From ed4f1f25ef4ae9429f1f87e332b96a67caec4af5 Mon Sep 17 00:00:00 2001 From: Paul Rouget Date: Tue, 3 Sep 2013 09:15:51 +0200 Subject: [PATCH] Bug 849236 - Add a screenshot button to the responsive mode. r=mratcliffe --- .../responsivedesign/responsivedesign.jsm | 57 ++++++++++++++++-- .../test/browser_responsiveui.js | 30 ++++++++- .../browser_responsiveuiaddcustompreset.js | 4 +- .../browser/devtools/responsiveUI.properties | 12 +++- browser/themes/linux/jar.mn | 2 + browser/themes/osx/jar.mn | 2 + .../shared/devtools/responsivedesign.inc.css | 12 ++++ .../shared/devtools/responsiveui-rotate.png | Bin 0 -> 498 bytes .../devtools/responsiveui-screenshot.png | Bin 0 -> 528 bytes browser/themes/windows/jar.mn | 4 ++ 10 files changed, 113 insertions(+), 10 deletions(-) create mode 100644 browser/themes/shared/devtools/responsiveui-rotate.png create mode 100644 browser/themes/shared/devtools/responsiveui-screenshot.png diff --git a/browser/devtools/responsivedesign/responsivedesign.jsm b/browser/devtools/responsivedesign/responsivedesign.jsm index 7bc2a4b21f6..b745b0a6846 100644 --- a/browser/devtools/responsivedesign/responsivedesign.jsm +++ b/browser/devtools/responsivedesign/responsivedesign.jsm @@ -157,6 +157,7 @@ function ResponsiveUI(aWindow, aTab) this.bound_addPreset = this.addPreset.bind(this); this.bound_removePreset = this.removePreset.bind(this); this.bound_rotate = this.rotate.bind(this); + this.bound_screenshot = () => this.screenshot(); this.bound_close = this.close.bind(this); this.bound_startResizing = this.startResizing.bind(this); this.bound_stopResizing = this.stopResizing.bind(this); @@ -228,6 +229,7 @@ ResponsiveUI.prototype = { this.tab.removeEventListener("TabClose", this); this.tabContainer.removeEventListener("TabSelect", this); this.rotatebutton.removeEventListener("command", this.bound_rotate, true); + this.screenshotbutton.removeEventListener("command", this.bound_screenshot, true); this.closebutton.removeEventListener("command", this.bound_close, true); this.addbutton.removeEventListener("command", this.bound_addPreset, true); this.removebutton.removeEventListener("command", this.bound_removePreset, true); @@ -300,8 +302,9 @@ ResponsiveUI.prototype = { * From tabbrowser.xml * * // presets - * // rotate - * // close + * // rotate + * // screenshot + * // close * * From tabbrowser.xml * @@ -341,19 +344,26 @@ ResponsiveUI.prototype = { this.rotatebutton = this.chromeDoc.createElement("toolbarbutton"); this.rotatebutton.setAttribute("tabindex", "0"); - this.rotatebutton.setAttribute("label", this.strings.GetStringFromName("responsiveUI.rotate")); - this.rotatebutton.className = "devtools-toolbarbutton"; + this.rotatebutton.setAttribute("tooltiptext", this.strings.GetStringFromName("responsiveUI.rotate2")); + this.rotatebutton.className = "devtools-toolbarbutton devtools-responsiveui-rotate"; this.rotatebutton.addEventListener("command", this.bound_rotate, true); + this.screenshotbutton = this.chromeDoc.createElement("toolbarbutton"); + this.screenshotbutton.setAttribute("tabindex", "0"); + this.screenshotbutton.setAttribute("tooltiptext", this.strings.GetStringFromName("responsiveUI.screenshot")); + this.screenshotbutton.className = "devtools-toolbarbutton devtools-responsiveui-screenshot"; + this.screenshotbutton.addEventListener("command", this.bound_screenshot, true); + this.closebutton = this.chromeDoc.createElement("toolbarbutton"); this.closebutton.setAttribute("tabindex", "0"); - this.closebutton.className = "devtools-toolbarbutton devtools-closebutton"; + this.closebutton.className = "devtools-toolbarbutton devtools-responsiveui-close"; this.closebutton.setAttribute("tooltiptext", this.strings.GetStringFromName("responsiveUI.close")); this.closebutton.addEventListener("command", this.bound_close, true); this.toolbar.appendChild(this.closebutton); this.toolbar.appendChild(this.menulist); this.toolbar.appendChild(this.rotatebutton); + this.toolbar.appendChild(this.screenshotbutton); // Resizers this.resizer = this.chromeDoc.createElement("box"); @@ -568,6 +578,43 @@ ResponsiveUI.prototype = { } }, + /** + * Take a screenshot of the page. + * + * @param aFileName name of the screenshot file (used for tests). + */ + screenshot: function RUI_screenshot(aFileName) { + let window = this.browser.contentWindow; + let document = window.document; + let canvas = this.chromeDoc.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); + + let width = window.innerWidth; + let height = window.innerHeight; + + canvas.width = width; + canvas.height = height; + + let ctx = canvas.getContext("2d"); + ctx.drawWindow(window, window.scrollX, window.scrollY, width, height, "#fff"); + + let filename = aFileName; + + if (!filename) { + let date = new Date(); + let month = ("0" + (date.getMonth() + 1)).substr(-2, 2); + let day = ("0" + (date.getDay() + 1)).substr(-2, 2); + let dateString = [date.getFullYear(), month, day].join("-"); + let timeString = date.toTimeString().replace(/:/g, ".").split(" ")[0]; + filename = this.strings.formatStringFromName("responsiveUI.screenshotGeneratedFilename", [dateString, timeString], 2); + } + + canvas.toBlob(blob => { + let chromeWindow = this.chromeDoc.defaultView; + let url = chromeWindow.URL.createObjectURL(blob); + chromeWindow.saveURL(url, filename + ".png", null, true, true, document.documentURIObject, document); + }); + }, + /** * Change the size of the browser. * diff --git a/browser/devtools/responsivedesign/test/browser_responsiveui.js b/browser/devtools/responsivedesign/test/browser_responsiveui.js index 47cebfd397e..e3bbcb51b30 100644 --- a/browser/devtools/responsivedesign/test/browser_responsiveui.js +++ b/browser/devtools/responsivedesign/test/browser_responsiveui.js @@ -153,10 +153,38 @@ function test() { is(content.innerWidth, widthBeforeClose, "width restored."); is(content.innerHeight, heightBeforeClose, "height restored."); - mgr.once("off", function() {executeSoon(finishUp)}); + mgr.once("off", function() {executeSoon(testScreenshot)}); EventUtils.synthesizeKey("VK_ESCAPE", {}); } + function testScreenshot() { + let isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1; + if (isWinXP) { + // We have issues testing this on Windows XP. + // See https://bugzilla.mozilla.org/show_bug.cgi?id=848760#c17 + return finishUp(); + } + + info("screenshot"); + instance.screenshot("responsiveui"); + let FileUtils = (Cu.import("resource://gre/modules/FileUtils.jsm", {})).FileUtils; + + // while(1) until we find the file. + // no need for a timeout, the test will get killed anyway. + info("checking if file exists in 200ms"); + function checkIfFileExist() { + let file = FileUtils.getFile("DfltDwnld", [ "responsiveui.png" ]); + if (file.exists()) { + ok(true, "Screenshot file exists"); + file.remove(false); + finishUp(); + } else { + setTimeout(checkIfFileExist, 200); + } + } + checkIfFileExist(); + } + function finishUp() { // Menus are correctly updated? diff --git a/browser/devtools/responsivedesign/test/browser_responsiveuiaddcustompreset.js b/browser/devtools/responsivedesign/test/browser_responsiveuiaddcustompreset.js index cba6f4fe73c..75487f0893c 100644 --- a/browser/devtools/responsivedesign/test/browser_responsiveuiaddcustompreset.js +++ b/browser/devtools/responsivedesign/test/browser_responsiveuiaddcustompreset.js @@ -85,7 +85,7 @@ function test() { // We're still in the loop of initializing the responsive mode. // Let's wait next loop to stop it. executeSoon(function() { - EventUtils.synthesizeKey("VK_ESCAPE", {}); + instance.close(); }); } @@ -135,7 +135,7 @@ function test() { // We're still in the loop of initializing the responsive mode. // Let's wait next loop to stop it. - executeSoon(() => EventUtils.synthesizeKey("VK_ESCAPE", {})); + executeSoon(() => instance.close()); } function restartAgain() { diff --git a/browser/locales/en-US/chrome/browser/devtools/responsiveUI.properties b/browser/locales/en-US/chrome/browser/devtools/responsiveUI.properties index 85a93beaf0f..348c7f2a73a 100644 --- a/browser/locales/en-US/chrome/browser/devtools/responsiveUI.properties +++ b/browser/locales/en-US/chrome/browser/devtools/responsiveUI.properties @@ -12,8 +12,16 @@ # documentation on web development on the web. -# LOCALIZATION NOTE (responsiveUI.rotate): label of the rotate button. -responsiveUI.rotate=rotate +# LOCALIZATION NOTE (responsiveUI.rotate2): tooltip of the rotate button. +responsiveUI.rotate2=Rotate + +# LOCALIZATION NOTE (responsiveUI.screenshot): tooltip of the screenshot button. +responsiveUI.screenshot=Screenshot + +# LOCALIZATION NOTE (responsiveUI.screenshotGeneratedFilename): The auto generated filename. +# The first argument (%1$S) is the date string in yyyy-mm-dd format and the second +# argument (%2$S) is the time string in HH.MM.SS format. +responsiveUI.screenshotGeneratedFilename=Screen Shot %1$S at %2$S # LOCALIZATION NOTE (responsiveUI.addPreset): label of the add preset button. responsiveUI.addPreset=Add Preset diff --git a/browser/themes/linux/jar.mn b/browser/themes/linux/jar.mn index f062e91e3d5..f5a9cebb92c 100644 --- a/browser/themes/linux/jar.mn +++ b/browser/themes/linux/jar.mn @@ -222,6 +222,8 @@ browser.jar: skin/classic/browser/devtools/font-inspector.css (devtools/font-inspector.css) skin/classic/browser/devtools/computedview.css (devtools/computedview.css) skin/classic/browser/devtools/arrow-e.png (devtools/arrow-e.png) + skin/classic/browser/devtools/responsiveui-rotate.png (../shared/devtools/responsiveui-rotate.png) + skin/classic/browser/devtools/responsiveui-screenshot.png (../shared/devtools/responsiveui-screenshot.png) #ifdef MOZ_SERVICES_SYNC skin/classic/browser/sync-16-throbber.png skin/classic/browser/sync-16.png diff --git a/browser/themes/osx/jar.mn b/browser/themes/osx/jar.mn index e325f771d0e..2687007bc9c 100644 --- a/browser/themes/osx/jar.mn +++ b/browser/themes/osx/jar.mn @@ -312,6 +312,8 @@ browser.jar: skin/classic/browser/devtools/font-inspector.css (devtools/font-inspector.css) skin/classic/browser/devtools/computedview.css (devtools/computedview.css) skin/classic/browser/devtools/arrow-e.png (devtools/arrow-e.png) + skin/classic/browser/devtools/responsiveui-rotate.png (../shared/devtools/responsiveui-rotate.png) + skin/classic/browser/devtools/responsiveui-screenshot.png (../shared/devtools/responsiveui-screenshot.png) #ifdef MOZ_SERVICES_SYNC skin/classic/browser/sync-throbber.png skin/classic/browser/sync-16.png diff --git a/browser/themes/shared/devtools/responsivedesign.inc.css b/browser/themes/shared/devtools/responsivedesign.inc.css index 1df673bc385..3ca3beecd0f 100644 --- a/browser/themes/shared/devtools/responsivedesign.inc.css +++ b/browser/themes/shared/devtools/responsivedesign.inc.css @@ -34,6 +34,18 @@ margin-left: 0; } +.devtools-responsiveui-close { + list-style-image: url("chrome://browser/skin/devtools/close.png"); +} + +.devtools-responsiveui-rotate { + list-style-image: url("chrome://browser/skin/devtools/responsiveui-rotate.png"); +} + +.devtools-responsiveui-screenshot { + list-style-image: url("chrome://browser/skin/devtools/responsiveui-screenshot.png"); +} + .devtools-responsiveui-resizebarV { width: 7px; height: 24px; diff --git a/browser/themes/shared/devtools/responsiveui-rotate.png b/browser/themes/shared/devtools/responsiveui-rotate.png new file mode 100644 index 0000000000000000000000000000000000000000..1e30f708697532e260694d36d6d0ae50cd491ef7 GIT binary patch literal 498 zcmV7K9)h$bkwp z(kQ2SAr&jV{=foad9+vz6aym@)BZrv`TF)A3WvkjB$7SJqh1RdR*j}z9RC{YmLG9; zK}Cbb=CGh}1unoj2+?>!^7~f%!P>@_8S6_@gRYZ5c9qTHKA?i&FNC6dpwke899{qL z3=*dxK)8Q+^q-uCyf?RZKC({)Z&2y-_{iOTPtPx2ZBM^RC}l^14(PeIuAPt1uVYe= zg*V_ZC^rV?Zc=NOgc7z{AYls;^I_1sxU@nB<^e~s@CNPJIL(&BJqS7=&ZKWdxxBKz zNt+$<;0@F-uWy#|skv1cC}5C6=3=$G47Aaj2=sFdE-K8xI5s(Jz`6`#l9PZs&`swt z76&aTCCw$hgZd$(X?tFT1YmFq0muNkATI$jkj7wGVwhCn>*_-+NcO*A$TP!4S}dA*--;FPDkiIUhB>WGcNPv+SyYsG{%w za0G?+(MOZhg@c0_K4^@Z9&a)$2VN>JyX!_yoIcx<%jcJsm(Asu;9ciUX63-VqN>g_ z0IwyL{`tqFrgyETaX@C}Kv*&S@No!U)6MSQU?Q1{5Ndc{-egt|JXieM-HYHq5AmHr zfKa=t8wPokSvAmvhgrc>1jAz!!I^qb+dV=}k2jfRSHrq{E&eXFyO)tX$z*fSz#O5b zCo`)XZ$s>AdZ|$k;ROM32iyj|zz@0zH9g*#VU`_sHA|_X0~@dd$3J2>JNj>ErW>=K S?OJXC0000