зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1067145
- Make responsive design e10s-ready. r=ochameau
This commit is contained in:
Родитель
04ab8bfb89
Коммит
6ccd40c82a
|
@ -117,7 +117,7 @@ function checkDebuggerPort() {
|
|||
function initResponsiveDesign() {
|
||||
Cu.import('resource:///modules/devtools/responsivedesign.jsm');
|
||||
ResponsiveUIManager.on('on', function(event, {tab:tab}) {
|
||||
let responsive = tab.__responsiveUI;
|
||||
let responsive = ResponsiveUIManager.getResponsiveUIForTab(tab);
|
||||
let document = tab.ownerDocument;
|
||||
|
||||
// Only tweak reponsive mode for shell.html tabs.
|
||||
|
@ -137,7 +137,7 @@ function initResponsiveDesign() {
|
|||
}, true);
|
||||
|
||||
// Enable touch events
|
||||
browserWindow.gBrowser.selectedTab.__responsiveUI.enableTouch();
|
||||
responsive.enableTouch();
|
||||
});
|
||||
|
||||
// Automatically toggle responsive design mode
|
||||
|
|
|
@ -148,7 +148,8 @@ window.addEventListener('ContentStart', function() {
|
|||
let chromewidth = window.outerWidth - window.innerWidth;
|
||||
let chromeheight = window.outerHeight - window.innerHeight + controlsHeight;
|
||||
if (isMulet) {
|
||||
let responsive = browserWindow.gBrowser.selectedTab.__responsiveUI;
|
||||
let tab = browserWindow.gBrowser.selectedTab;
|
||||
let responsive = ResponsiveUIManager.getResponsiveUIForTab(tab);
|
||||
responsive.setSize((Math.round(width * scale) + 16*2),
|
||||
(Math.round(height * scale) + controlsHeight + 61));
|
||||
} else {
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
EXTRA_JS_MODULES.devtools += [
|
||||
'resize-commands.js',
|
||||
'responsivedesign.jsm',
|
||||
'responsivedesign-child.js',
|
||||
'responsivedesign.jsm'
|
||||
]
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const gDeviceSizeWasPageSize = docShell.deviceSizeIsPageSize;
|
||||
const gFloatingScrollbarsStylesheet = Services.io.newURI("chrome://browser/skin/devtools/floating-scrollbars.css", null, null);
|
||||
let gRequiresFloatingScrollbars;
|
||||
|
||||
let active = false;
|
||||
|
||||
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
|
||||
addMessageListener("ResponsiveMode:Start", startResponsiveMode);
|
||||
addMessageListener("ResponsiveMode:Stop", stopResponsiveMode);
|
||||
|
||||
function startResponsiveMode({data:data}) {
|
||||
if (active) {
|
||||
return;
|
||||
}
|
||||
addMessageListener("ResponsiveMode:RequestScreenshot", screenshot);
|
||||
addMessageListener("ResponsiveMode:NotifyOnResize", notifiyOnResize);
|
||||
webProgress.addProgressListener(WebProgressListener, Ci.nsIWebProgress.NOTIFY_ALL);
|
||||
docShell.deviceSizeIsPageSize = true;
|
||||
gRequiresFloatingScrollbars = data.requiresFloatingScrollbars;
|
||||
|
||||
// At this point, a content viewer might not be loaded for this
|
||||
// docshell. makeScrollbarsFloating will be triggered by onLocationChange.
|
||||
if (docShell.contentViewer) {
|
||||
makeScrollbarsFloating();
|
||||
}
|
||||
active = true;
|
||||
sendAsyncMessage("ResponsiveMode:Start:Done");
|
||||
}
|
||||
|
||||
function notifiyOnResize() {
|
||||
content.addEventListener("resize", () => {
|
||||
sendAsyncMessage("ResponsiveMode:OnContentResize");
|
||||
}, false);
|
||||
sendAsyncMessage("ResponsiveMode:NotifyOnResize:Done");
|
||||
}
|
||||
|
||||
function stopResponsiveMode() {
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
active = false;
|
||||
removeMessageListener("ResponsiveMode:RequestScreenshot", screenshot);
|
||||
removeMessageListener("ResponsiveMode:NotifyOnResize", notifiyOnResize);
|
||||
webProgress.removeProgressListener(WebProgressListener);
|
||||
docShell.deviceSizeIsPageSize = gDeviceSizeWasPageSize;
|
||||
restoreScrollbars();
|
||||
sendAsyncMessage("ResponsiveMode:Stop:Done");
|
||||
}
|
||||
|
||||
function makeScrollbarsFloating() {
|
||||
if (!gRequiresFloatingScrollbars) {
|
||||
return;
|
||||
}
|
||||
|
||||
let allDocShells = [docShell];
|
||||
|
||||
for (let i = 0; i < docShell.childCount; i++) {
|
||||
let child = docShell.getChildAt(i).QueryInterface(Ci.nsIDocShell);
|
||||
allDocShells.push(child);
|
||||
}
|
||||
|
||||
for (let d of allDocShells) {
|
||||
let win = d.contentViewer.DOMDocument.defaultView;
|
||||
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
try {
|
||||
winUtils.loadSheet(gFloatingScrollbarsStylesheet, win.AGENT_SHEET);
|
||||
} catch(e) { }
|
||||
}
|
||||
|
||||
flushStyle();
|
||||
}
|
||||
|
||||
function restoreScrollbars() {
|
||||
let allDocShells = [docShell];
|
||||
for (let i = 0; i < docShell.childCount; i++) {
|
||||
allDocShells.push(docShell.getChildAt(i).QueryInterface(Ci.nsIDocShell));
|
||||
}
|
||||
for (let d of allDocShells) {
|
||||
let win = d.contentViewer.DOMDocument.defaultView;
|
||||
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
try {
|
||||
winUtils.removeSheet(gFloatingScrollbarsStylesheet, win.AGENT_SHEET);
|
||||
} catch(e) { }
|
||||
}
|
||||
flushStyle();
|
||||
}
|
||||
|
||||
function flushStyle() {
|
||||
// Force presContext destruction
|
||||
let isSticky = docShell.contentViewer.sticky;
|
||||
docShell.contentViewer.sticky = false;
|
||||
docShell.contentViewer.hide();
|
||||
docShell.contentViewer.show();
|
||||
docShell.contentViewer.sticky = isSticky;
|
||||
}
|
||||
|
||||
function screenshot() {
|
||||
let canvas = content.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
let width = content.innerWidth;
|
||||
let height = content.innerHeight;
|
||||
canvas.mozOpaque = true;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.drawWindow(content, content.scrollX, content.scrollY, width, height, "#fff");
|
||||
sendAsyncMessage("ResponsiveMode:RequestScreenshot:Done", canvas.toDataURL());
|
||||
}
|
||||
|
||||
let WebProgressListener = {
|
||||
onLocationChange: function onLocationChange(aWebProgress) {
|
||||
makeScrollbarsFloating();
|
||||
},
|
||||
QueryInterface: function QueryInterface(aIID) {
|
||||
if (aIID.equals(Ci.nsIWebProgressListener) ||
|
||||
aIID.equals(Ci.nsISupportsWeakReference) ||
|
||||
aIID.equals(Ci.nsISupports)) {
|
||||
return this;
|
||||
}
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
};
|
||||
|
||||
sendAsyncMessage("ResponsiveMode:ChildScriptReady");
|
|
@ -10,8 +10,8 @@ const Cu = Components.utils;
|
|||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/devtools/gDevTools.jsm");
|
||||
Cu.import("resource:///modules/devtools/FloatingScrollbars.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/event-emitter.js");
|
||||
let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
|
||||
"resource://gre/modules/SystemAppProxy.jsm");
|
||||
|
||||
|
@ -33,6 +33,8 @@ const ROUND_RATIO = 10;
|
|||
|
||||
const INPUT_PARSER = /(\d+)[^\d]+(\d+)/;
|
||||
|
||||
let ActiveTabs = new Map();
|
||||
|
||||
this.ResponsiveUIManager = {
|
||||
/**
|
||||
* Check if the a tab is in a responsive mode.
|
||||
|
@ -43,8 +45,8 @@ this.ResponsiveUIManager = {
|
|||
* @param aTab the tab targeted.
|
||||
*/
|
||||
toggle: function(aWindow, aTab) {
|
||||
if (aTab.__responsiveUI) {
|
||||
aTab.__responsiveUI.close();
|
||||
if (this.isActiveForTab(aTab)) {
|
||||
ActiveTabs.get(aTab).close();
|
||||
} else {
|
||||
new ResponsiveUI(aWindow, aTab);
|
||||
}
|
||||
|
@ -56,7 +58,14 @@ this.ResponsiveUIManager = {
|
|||
* @param aTab the tab targeted.
|
||||
*/
|
||||
isActiveForTab: function(aTab) {
|
||||
return !!aTab.__responsiveUI;
|
||||
return ActiveTabs.has(aTab);
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the responsive UI controller for a tab.
|
||||
*/
|
||||
getResponsiveUIForTab: function(aTab) {
|
||||
return ActiveTabs.get(aTab);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -70,19 +79,19 @@ this.ResponsiveUIManager = {
|
|||
handleGcliCommand: function(aWindow, aTab, aCommand, aArgs) {
|
||||
switch (aCommand) {
|
||||
case "resize to":
|
||||
if (!aTab.__responsiveUI) {
|
||||
if (!this.isActiveForTab(aTab)) {
|
||||
new ResponsiveUI(aWindow, aTab);
|
||||
}
|
||||
aTab.__responsiveUI.setSize(aArgs.width, aArgs.height);
|
||||
ActiveTabs.get(aTab).setSize(aArgs.width, aArgs.height);
|
||||
break;
|
||||
case "resize on":
|
||||
if (!aTab.__responsiveUI) {
|
||||
if (!this.isActiveForTab(aTab)) {
|
||||
new ResponsiveUI(aWindow, aTab);
|
||||
}
|
||||
break;
|
||||
case "resize off":
|
||||
if (aTab.__responsiveUI) {
|
||||
aTab.__responsiveUI.close();
|
||||
if (this.isActiveForTab(aTab)) {
|
||||
ActiveTabs.get(aTab).close();
|
||||
}
|
||||
break;
|
||||
case "resize toggle":
|
||||
|
@ -115,13 +124,28 @@ function ResponsiveUI(aWindow, aTab)
|
|||
{
|
||||
this.mainWindow = aWindow;
|
||||
this.tab = aTab;
|
||||
this.mm = this.tab.linkedBrowser.messageManager;
|
||||
this.tabContainer = aWindow.gBrowser.tabContainer;
|
||||
this.browser = aTab.linkedBrowser;
|
||||
this.chromeDoc = aWindow.document;
|
||||
this.container = aWindow.gBrowser.getBrowserContainer(this.browser);
|
||||
this.stack = this.container.querySelector(".browserStack");
|
||||
this._telemetry = new Telemetry();
|
||||
this._floatingScrollbars = !this.mainWindow.matchMedia("(-moz-overlay-scrollbars)").matches;
|
||||
this.e10s = !this.browser.contentWindow;
|
||||
|
||||
let childOn = () => {
|
||||
this.mm.removeMessageListener("ResponsiveMode:Start:Done", childOn);
|
||||
ResponsiveUIManager.emit("on", { tab: this.tab });
|
||||
}
|
||||
this.mm.addMessageListener("ResponsiveMode:Start:Done", childOn);
|
||||
|
||||
let requiresFloatingScrollbars = !this.mainWindow.matchMedia("(-moz-overlay-scrollbars)").matches;
|
||||
this.mm.loadFrameScript("resource:///modules/devtools/responsivedesign-child.js", true);
|
||||
this.mm.addMessageListener("ResponsiveMode:ChildScriptReady", () => {
|
||||
this.mm.sendAsyncMessage("ResponsiveMode:Start", {
|
||||
requiresFloatingScrollbars: requiresFloatingScrollbars
|
||||
});
|
||||
});
|
||||
|
||||
// Try to load presets from prefs
|
||||
if (Services.prefs.prefHasUserValue("devtools.responsiveUI.presets")) {
|
||||
|
@ -163,8 +187,6 @@ function ResponsiveUI(aWindow, aTab)
|
|||
this.stack.setAttribute("responsivemode", "true");
|
||||
|
||||
// Let's bind some callbacks.
|
||||
this.bound_onPageLoad = this.onPageLoad.bind(this);
|
||||
this.bound_onPageUnload = this.onPageUnload.bind(this);
|
||||
this.bound_presetSelected = this.presetSelected.bind(this);
|
||||
this.bound_handleManualInput = this.handleManualInput.bind(this);
|
||||
this.bound_addPreset = this.addPreset.bind(this);
|
||||
|
@ -184,41 +206,22 @@ function ResponsiveUI(aWindow, aTab)
|
|||
this.buildUI();
|
||||
this.checkMenus();
|
||||
|
||||
this.docShell = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
|
||||
this._deviceSizeWasPageSize = this.docShell.deviceSizeIsPageSize;
|
||||
this.docShell.deviceSizeIsPageSize = true;
|
||||
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("devtools.responsiveUI.rotate")) {
|
||||
this.rotate();
|
||||
}
|
||||
} catch(e) {}
|
||||
|
||||
if (this._floatingScrollbars)
|
||||
switchToFloatingScrollbars(this.tab);
|
||||
|
||||
this.tab.__responsiveUI = this;
|
||||
ActiveTabs.set(aTab, this);
|
||||
|
||||
this._telemetry.toolOpened("responsive");
|
||||
|
||||
// Touch events support
|
||||
this.touchEnableBefore = false;
|
||||
this.touchEventHandler = new TouchEventHandler(this.browser);
|
||||
|
||||
this.browser.addEventListener("load", this.bound_onPageLoad, true);
|
||||
this.browser.addEventListener("unload", this.bound_onPageUnload, true);
|
||||
|
||||
if (this.browser.contentWindow.document &&
|
||||
this.browser.contentWindow.document.readyState == "complete") {
|
||||
this.onPageLoad();
|
||||
if (!this.e10s) {
|
||||
// Touch events support
|
||||
this.touchEnableBefore = false;
|
||||
this.touchEventHandler = new TouchEventHandler(this.browser);
|
||||
}
|
||||
|
||||
// E10S: We should be using target here. See bug 1028234
|
||||
ResponsiveUIManager.emit("on", { tab: this.tab });
|
||||
|
||||
// Hook to display promotional Developer Edition doorhanger. Only displayed once.
|
||||
showDoorhanger({
|
||||
window: this.mainWindow,
|
||||
|
@ -239,45 +242,14 @@ ResponsiveUI.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Window onload / onunload
|
||||
*/
|
||||
onPageLoad: function() {
|
||||
this.touchEventHandler = new TouchEventHandler(this.browser);
|
||||
if (this.touchEnableBefore) {
|
||||
this.enableTouch();
|
||||
}
|
||||
},
|
||||
|
||||
onPageUnload: function(evt) {
|
||||
// Ignore sub frames unload events
|
||||
if (evt.target != this.browser.contentDocument)
|
||||
return;
|
||||
if (this.closing)
|
||||
return;
|
||||
if (this.touchEventHandler) {
|
||||
this.touchEnableBefore = this.touchEventHandler.enabled;
|
||||
this.disableTouch();
|
||||
delete this.touchEventHandler;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the nodes. Remove listeners. Reset the style.
|
||||
*/
|
||||
close: function RUI_unload() {
|
||||
close: function RUI_close() {
|
||||
if (this.closing)
|
||||
return;
|
||||
this.closing = true;
|
||||
|
||||
this.docShell.deviceSizeIsPageSize = this._deviceSizeWasPageSize;
|
||||
|
||||
this.browser.removeEventListener("load", this.bound_onPageLoad, true);
|
||||
this.browser.removeEventListener("unload", this.bound_onPageUnload, true);
|
||||
|
||||
if (this._floatingScrollbars)
|
||||
switchToNativeScrollbars(this.tab);
|
||||
|
||||
this.unCheckMenus();
|
||||
// Reset style of the stack.
|
||||
let style = "max-width: none;" +
|
||||
|
@ -296,10 +268,12 @@ ResponsiveUI.prototype = {
|
|||
this.tabContainer.removeEventListener("TabSelect", this);
|
||||
this.rotatebutton.removeEventListener("command", this.bound_rotate, true);
|
||||
this.screenshotbutton.removeEventListener("command", this.bound_screenshot, true);
|
||||
this.touchbutton.removeEventListener("command", this.bound_touch, 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);
|
||||
if (!this.e10s) {
|
||||
this.touchbutton.removeEventListener("command", this.bound_touch, true);
|
||||
}
|
||||
|
||||
// Removed elements.
|
||||
this.container.removeChild(this.toolbar);
|
||||
|
@ -317,13 +291,40 @@ ResponsiveUI.prototype = {
|
|||
this.container.removeAttribute("responsivemode");
|
||||
this.stack.removeAttribute("responsivemode");
|
||||
|
||||
delete this.docShell;
|
||||
delete this.tab.__responsiveUI;
|
||||
if (this.touchEventHandler)
|
||||
ActiveTabs.delete(this.tab);
|
||||
if (!this.e10s && this.touchEventHandler) {
|
||||
this.touchEventHandler.stop();
|
||||
}
|
||||
this._telemetry.toolClosed("responsive");
|
||||
// E10S: We should be using target here. See bug 1028234
|
||||
ResponsiveUIManager.emit("off", { tab: this.tab });
|
||||
let childOff = () => {
|
||||
this.mm.removeMessageListener("ResponsiveMode:Stop:Done", childOff);
|
||||
ResponsiveUIManager.emit("off", { tab: this.tab });
|
||||
}
|
||||
this.mm.addMessageListener("ResponsiveMode:Stop:Done", childOff);
|
||||
this.tab.linkedBrowser.messageManager.sendAsyncMessage("ResponsiveMode:Stop");
|
||||
},
|
||||
|
||||
/**
|
||||
* Notify when the content has been resized. Only used in tests.
|
||||
*/
|
||||
_test_notifyOnResize: function() {
|
||||
let deferred = promise.defer();
|
||||
let mm = this.mm;
|
||||
|
||||
this.bound_onContentResize = this.onContentResize.bind(this);
|
||||
|
||||
mm.addMessageListener("ResponsiveMode:OnContentResize", this.bound_onContentResize);
|
||||
|
||||
mm.sendAsyncMessage("ResponsiveMode:NotifyOnResize");
|
||||
mm.addMessageListener("ResponsiveMode:NotifyOnResize:Done", function onListeningResize() {
|
||||
mm.removeMessageListener("ResponsiveMode:NotifyOnResize:Done", onListeningResize);
|
||||
deferred.resolve();
|
||||
});
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
onContentResize: function() {
|
||||
ResponsiveUIManager.emit("contentResize", { tab: this.tab });
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -427,12 +428,6 @@ ResponsiveUI.prototype = {
|
|||
this.screenshotbutton.className = "devtools-responsiveui-toolbarbutton devtools-responsiveui-screenshot";
|
||||
this.screenshotbutton.addEventListener("command", this.bound_screenshot, true);
|
||||
|
||||
this.touchbutton = this.chromeDoc.createElement("toolbarbutton");
|
||||
this.touchbutton.setAttribute("tabindex", "0");
|
||||
this.touchbutton.setAttribute("tooltiptext", this.strings.GetStringFromName("responsiveUI.touch"));
|
||||
this.touchbutton.className = "devtools-responsiveui-toolbarbutton devtools-responsiveui-touch";
|
||||
this.touchbutton.addEventListener("command", this.bound_touch, true);
|
||||
|
||||
this.closebutton = this.chromeDoc.createElement("toolbarbutton");
|
||||
this.closebutton.setAttribute("tabindex", "0");
|
||||
this.closebutton.className = "devtools-responsiveui-toolbarbutton devtools-responsiveui-close";
|
||||
|
@ -442,7 +437,16 @@ ResponsiveUI.prototype = {
|
|||
this.toolbar.appendChild(this.closebutton);
|
||||
this.toolbar.appendChild(this.menulist);
|
||||
this.toolbar.appendChild(this.rotatebutton);
|
||||
this.toolbar.appendChild(this.touchbutton);
|
||||
|
||||
if (!this.e10s) {
|
||||
this.touchbutton = this.chromeDoc.createElement("toolbarbutton");
|
||||
this.touchbutton.setAttribute("tabindex", "0");
|
||||
this.touchbutton.setAttribute("tooltiptext", this.strings.GetStringFromName("responsiveUI.touch"));
|
||||
this.touchbutton.className = "devtools-responsiveui-toolbarbutton devtools-responsiveui-touch";
|
||||
this.touchbutton.addEventListener("command", this.bound_touch, true);
|
||||
this.toolbar.appendChild(this.touchbutton);
|
||||
}
|
||||
|
||||
this.toolbar.appendChild(this.screenshotbutton);
|
||||
|
||||
// Resizers
|
||||
|
@ -583,8 +587,9 @@ ResponsiveUI.prototype = {
|
|||
this.selectedItem = menuitem;
|
||||
}
|
||||
|
||||
if (preset.custom)
|
||||
if (preset.custom) {
|
||||
this.customMenuitem = menuitem;
|
||||
}
|
||||
|
||||
this.setMenuLabel(menuitem, preset);
|
||||
fragment.appendChild(menuitem);
|
||||
|
@ -662,9 +667,7 @@ ResponsiveUI.prototype = {
|
|||
|
||||
if (!promptOk) {
|
||||
// Prompt has been cancelled
|
||||
let menuitem = this.customMenuitem;
|
||||
this.menulist.selectedItem = menuitem;
|
||||
this.currentPresetKey = this.customPreset.key;
|
||||
this.menulist.selectedItem = this.selectedItem;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -762,21 +765,7 @@ ResponsiveUI.prototype = {
|
|||
* @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);
|
||||
|
@ -785,12 +774,15 @@ ResponsiveUI.prototype = {
|
|||
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);
|
||||
});
|
||||
let mm = this.tab.linkedBrowser.messageManager;
|
||||
let chromeWindow = this.chromeDoc.defaultView;
|
||||
let doc = chromeWindow.document;
|
||||
function onScreenshot(aMessage) {
|
||||
mm.removeMessageListener("ResponsiveMode:RequestScreenshot:Done", onScreenshot);
|
||||
chromeWindow.saveURL(aMessage.data, filename + ".png", null, true, true, doc.documentURIObject, doc);
|
||||
}
|
||||
mm.addMessageListener("ResponsiveMode:RequestScreenshot:Done", onScreenshot);
|
||||
mm.sendAsyncMessage("ResponsiveMode:RequestScreenshot");
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[DEFAULT]
|
||||
skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
head.js
|
||||
|
@ -7,8 +6,11 @@ support-files =
|
|||
|
||||
[browser_responsive_cmd.js]
|
||||
[browser_responsivecomputedview.js]
|
||||
skip-if = e10s # Bug ??????
|
||||
[browser_responsiveruleview.js]
|
||||
skip-if = e10s # Bug ??????
|
||||
[browser_responsiveui.js]
|
||||
[browser_responsiveui_touch.js]
|
||||
skip-if = e10s # Bug ?????? - [e10s] re-introduce touch feature in responsive mode
|
||||
[browser_responsiveuiaddcustompreset.js]
|
||||
[browser_responsive_devicewidth.js]
|
||||
|
|
|
@ -10,10 +10,11 @@ thisTestLeaksUncaughtRejectionsAndShouldBeFixed("destroy");
|
|||
|
||||
function test() {
|
||||
function isOpen() {
|
||||
return !!gBrowser.selectedTab.__responsiveUI;
|
||||
return gBrowser.getBrowserContainer(gBrowser.selectedTab.linkedBrowser)
|
||||
.hasAttribute("responsivemode");
|
||||
}
|
||||
|
||||
helpers.addTabWithToolbar("about:blank", function(options) {
|
||||
helpers.addTabWithToolbar("data:text/html;charset=utf-8,hi", function(options) {
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
setup: "resize toggle",
|
||||
|
|
|
@ -7,21 +7,19 @@ function test() {
|
|||
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = gBrowser.addTab("about:logo");
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
waitForFocus(startTest, content);
|
||||
startTest();
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,mop";
|
||||
|
||||
function startTest() {
|
||||
mgr.once("on", function() {executeSoon(onUIOpen)});
|
||||
document.getElementById("Tools:ResponsiveUI").doCommand();
|
||||
}
|
||||
|
||||
function onUIOpen() {
|
||||
instance = gBrowser.selectedTab.__responsiveUI;
|
||||
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
|
||||
instance.stack.setAttribute("notransition", "true");
|
||||
ok(instance, "instance of the module is attached to the tab.");
|
||||
|
||||
|
|
|
@ -8,11 +8,12 @@ function test() {
|
|||
let inspector;
|
||||
|
||||
waitForExplicitFinish();
|
||||
let mgr = ResponsiveUI.ResponsiveUIManager;
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
waitForFocus(startTest, content);
|
||||
startTest();
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html;charset=utf-8,<html><style>" +
|
||||
|
@ -43,7 +44,7 @@ function test() {
|
|||
}
|
||||
|
||||
function onUIOpen() {
|
||||
instance = gBrowser.selectedTab.__responsiveUI;
|
||||
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
|
||||
ok(instance, "instance of the module is attached to the tab.");
|
||||
|
||||
instance.stack.setAttribute("notransition", "true");
|
||||
|
|
|
@ -11,10 +11,7 @@ function test() {
|
|||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
waitForFocus(startTest, content);
|
||||
}, true);
|
||||
gBrowser.selectedBrowser.addEventListener("load", startTest, true);
|
||||
|
||||
content.location = "data:text/html;charset=utf-8,<html><style>" +
|
||||
"div {" +
|
||||
|
@ -34,12 +31,13 @@ function test() {
|
|||
}
|
||||
|
||||
function startTest() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", startTest, true);
|
||||
document.getElementById("Tools:ResponsiveUI").doCommand();
|
||||
executeSoon(onUIOpen);
|
||||
}
|
||||
|
||||
function onUIOpen() {
|
||||
instance = gBrowser.selectedTab.__responsiveUI;
|
||||
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
|
||||
ok(instance, "instance of the module is attached to the tab.");
|
||||
|
||||
instance.stack.setAttribute("notransition", "true");
|
||||
|
|
|
@ -2,26 +2,33 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
let instance, widthBeforeClose, heightBeforeClose;
|
||||
let mgr = ResponsiveUI.ResponsiveUIManager;
|
||||
|
||||
waitForExplicitFinish();
|
||||
SimpleTest.requestCompleteLog();
|
||||
Task.spawn(function() {
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
waitForFocus(startTest, content);
|
||||
}, true);
|
||||
function extractSizeFromString(str) {
|
||||
let numbers = str.match(/(\d+)[^\d]*(\d+)/);
|
||||
if (numbers) {
|
||||
return [numbers[1], numbers[2]];
|
||||
} else {
|
||||
return [null, null];
|
||||
}
|
||||
}
|
||||
|
||||
content.location = "data:text/html,mop";
|
||||
function processStringAsKey(str) {
|
||||
for (let i = 0, l = str.length; i < l; i++) {
|
||||
EventUtils.synthesizeKey(str.charAt(i), {});
|
||||
}
|
||||
}
|
||||
|
||||
yield addTab("data:text/html,mop");
|
||||
|
||||
let mgr = ResponsiveUI.ResponsiveUIManager;
|
||||
|
||||
function startTest() {
|
||||
document.getElementById("Tools:ResponsiveUI").removeAttribute("disabled");
|
||||
mgr.once("on", function() {executeSoon(onUIOpen)});
|
||||
synthesizeKeyFromKeyTag("key_responsiveUI");
|
||||
}
|
||||
|
||||
function onUIOpen() {
|
||||
yield once(mgr, "on");
|
||||
|
||||
// Is it open?
|
||||
let container = gBrowser.getBrowserContainer();
|
||||
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
|
||||
|
@ -29,75 +36,58 @@ function test() {
|
|||
// Menus are correctly updated?
|
||||
is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), "true", "menus checked");
|
||||
|
||||
instance = gBrowser.selectedTab.__responsiveUI;
|
||||
let instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
|
||||
ok(instance, "instance of the module is attached to the tab.");
|
||||
|
||||
if (instance._floatingScrollbars) {
|
||||
ensureScrollbarsAreFloating();
|
||||
}
|
||||
let originalWidth = content.innerWidth;
|
||||
content.location = "data:text/html;charset=utf-8,mop<div style%3D'height%3A5000px'><%2Fdiv>";
|
||||
let newWidth = content.innerWidth;
|
||||
is(originalWidth, newWidth, "Floating scrollbars are presents");
|
||||
|
||||
yield instance._test_notifyOnResize();
|
||||
|
||||
yield nextTick();
|
||||
|
||||
instance.transitionsEnabled = false;
|
||||
|
||||
testPresets();
|
||||
}
|
||||
|
||||
function ensureScrollbarsAreFloating() {
|
||||
let body = gBrowser.contentDocument.body;
|
||||
let html = gBrowser.contentDocument.documentElement;
|
||||
|
||||
let originalWidth = body.getBoundingClientRect().width;
|
||||
|
||||
html.style.overflowY = "scroll"; // Force scrollbars
|
||||
// Flush. Should not be needed as getBoundingClientRect() should flush,
|
||||
// but just in case.
|
||||
gBrowser.contentWindow.getComputedStyle(html).overflowY;
|
||||
let newWidth = body.getBoundingClientRect().width;
|
||||
is(originalWidth, newWidth, "Floating scrollbars are presents");
|
||||
}
|
||||
|
||||
function testPresets() {
|
||||
function testOnePreset(c) {
|
||||
if (c == 0) {
|
||||
executeSoon(testCustom);
|
||||
return;
|
||||
}
|
||||
instance.menulist.selectedIndex = c;
|
||||
// Starting from length - 4 because last 3 items are not presets : separator, addbutton and removebutton
|
||||
for (let c = instance.menulist.firstChild.childNodes.length - 4; c >= 0; c--) {
|
||||
let item = instance.menulist.firstChild.childNodes[c];
|
||||
let [width, height] = extractSizeFromString(item.getAttribute("label"));
|
||||
let onContentResize = once(mgr, "contentResize");
|
||||
instance.menulist.selectedIndex = c;
|
||||
yield onContentResize;
|
||||
is(content.innerWidth, width, "preset " + c + ": dimension valid (width)");
|
||||
is(content.innerHeight, height, "preset " + c + ": dimension valid (height)");
|
||||
|
||||
testOnePreset(c - 1);
|
||||
}
|
||||
// Starting from length - 4 because last 3 items are not presets : separator, addbutton and removebutton
|
||||
testOnePreset(instance.menulist.firstChild.childNodes.length - 4);
|
||||
}
|
||||
|
||||
function extractSizeFromString(str) {
|
||||
let numbers = str.match(/(\d+)[^\d]*(\d+)/);
|
||||
if (numbers) {
|
||||
return [numbers[1], numbers[2]];
|
||||
} else {
|
||||
return [null, null];
|
||||
}
|
||||
}
|
||||
// test custom
|
||||
|
||||
instance.setSize(100, 100);
|
||||
|
||||
yield once(mgr, "contentResize");
|
||||
|
||||
function testCustom() {
|
||||
let initialWidth = content.innerWidth;
|
||||
let initialHeight = content.innerHeight;
|
||||
|
||||
is(initialWidth, 100, "Width reset to 100");
|
||||
is(initialHeight, 100, "Height reset to 100");
|
||||
|
||||
let x = 2, y = 2;
|
||||
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousedown"}, window);
|
||||
x += 20; y += 10;
|
||||
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousemove"}, window);
|
||||
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mouseup"}, window);
|
||||
|
||||
yield once(mgr, "contentResize");
|
||||
|
||||
let expectedWidth = initialWidth + 20;
|
||||
let expectedHeight = initialHeight + 10;
|
||||
info("initial width: " + initialWidth);
|
||||
info("initial height: " + initialHeight);
|
||||
is(content.innerWidth, expectedWidth, "Size correcty updated (width).");
|
||||
is(content.innerHeight, expectedHeight, "Size correcty updated (height).");
|
||||
is(content.innerWidth, expectedWidth, "Size correctly updated (width).");
|
||||
is(content.innerHeight, expectedHeight, "Size correctly updated (height).");
|
||||
|
||||
is(instance.menulist.selectedIndex, -1, "Custom menuitem cannot be selected");
|
||||
let label = instance.menulist.firstChild.firstChild.getAttribute("label");
|
||||
let value = instance.menulist.value;
|
||||
|
@ -108,71 +98,80 @@ function test() {
|
|||
[width, height] = extractSizeFromString(value);
|
||||
is(width, expectedWidth, "Value updated (width).");
|
||||
is(height, expectedHeight, "Value updated (height).");
|
||||
testCustom2();
|
||||
}
|
||||
|
||||
function testCustom2() {
|
||||
let initialWidth = content.innerWidth;
|
||||
let initialHeight = content.innerHeight;
|
||||
// With "shift" key pressed
|
||||
|
||||
let x = 2, y = 2;
|
||||
instance.setSize(100, 100);
|
||||
|
||||
yield once(mgr, "contentResize");
|
||||
|
||||
initialWidth = content.innerWidth;
|
||||
initialHeight = content.innerHeight;
|
||||
|
||||
x = 2; y = 2;
|
||||
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousedown"}, window);
|
||||
x += 23; y += 13;
|
||||
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousemove", shiftKey: true}, window);
|
||||
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mouseup"}, window);
|
||||
|
||||
let expectedWidth = initialWidth + 20;
|
||||
let expectedHeight = initialHeight + 10;
|
||||
is(content.innerWidth, expectedWidth, "with shift: Size correcty updated (width).");
|
||||
is(content.innerHeight, expectedHeight, "with shift: Size correcty updated (height).");
|
||||
yield once(mgr, "contentResize");
|
||||
|
||||
expectedWidth = initialWidth + 20;
|
||||
expectedHeight = initialHeight + 10;
|
||||
is(content.innerWidth, expectedWidth, "with shift: Size correctly updated (width).");
|
||||
is(content.innerHeight, expectedHeight, "with shift: Size correctly updated (height).");
|
||||
is(instance.menulist.selectedIndex, -1, "with shift: Custom menuitem cannot be selected");
|
||||
let label = instance.menulist.firstChild.firstChild.getAttribute("label");
|
||||
let value = instance.menulist.value;
|
||||
isnot(label, value, "Label from the menulist item is different than the value of the menulist")
|
||||
let [width, height] = extractSizeFromString(label);
|
||||
label = instance.menulist.firstChild.firstChild.getAttribute("label");
|
||||
value = instance.menulist.value;
|
||||
isnot(label, value, "Label from the menulist item is different than the value of the menulist");
|
||||
[width, height] = extractSizeFromString(label);
|
||||
is(width, expectedWidth, "Label updated (width).");
|
||||
is(height, expectedHeight, "Label updated (height).");
|
||||
[width, height] = extractSizeFromString(value);
|
||||
is(width, expectedWidth, "Value updated (width).");
|
||||
is(height, expectedHeight, "Value updated (height).");
|
||||
testCustom3();
|
||||
}
|
||||
|
||||
function testCustom3() {
|
||||
let initialWidth = content.innerWidth;
|
||||
let initialHeight = content.innerHeight;
|
||||
|
||||
let x = 2, y = 2;
|
||||
// With "ctrl" key pressed
|
||||
|
||||
instance.setSize(100, 100);
|
||||
|
||||
yield once(mgr, "contentResize");
|
||||
|
||||
initialWidth = content.innerWidth;
|
||||
initialHeight = content.innerHeight;
|
||||
|
||||
x = 2; y = 2;
|
||||
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousedown"}, window);
|
||||
x += 60; y += 30;
|
||||
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mousemove", ctrlKey: true}, window);
|
||||
EventUtils.synthesizeMouse(instance.resizer, x, y, {type: "mouseup"}, window);
|
||||
|
||||
let expectedWidth = initialWidth + 10;
|
||||
let expectedHeight = initialHeight + 5;
|
||||
is(content.innerWidth, expectedWidth, "with ctrl: Size correcty updated (width).");
|
||||
is(content.innerHeight, expectedHeight, "with ctrl: Size correcty updated (height).");
|
||||
yield once(mgr, "contentResize");
|
||||
|
||||
expectedWidth = initialWidth + 10;
|
||||
expectedHeight = initialHeight + 5;
|
||||
is(content.innerWidth, expectedWidth, "with ctrl: Size correctly updated (width).");
|
||||
is(content.innerHeight, expectedHeight, "with ctrl: Size correctly updated (height).");
|
||||
is(instance.menulist.selectedIndex, -1, "with ctrl: Custom menuitem cannot be selected");
|
||||
let label = instance.menulist.firstChild.firstChild.getAttribute("label");
|
||||
let value = instance.menulist.value;
|
||||
isnot(label, value, "Label from the menulist item is different than the value of the menulist")
|
||||
let [width, height] = extractSizeFromString(label);
|
||||
label = instance.menulist.firstChild.firstChild.getAttribute("label");
|
||||
value = instance.menulist.value;
|
||||
isnot(label, value, "Label from the menulist item is different than the value of the menulist");
|
||||
[width, height] = extractSizeFromString(label);
|
||||
is(width, expectedWidth, "Label updated (width).");
|
||||
is(height, expectedHeight, "Label updated (height).");
|
||||
[width, height] = extractSizeFromString(value);
|
||||
is(width, expectedWidth, "Value updated (width).");
|
||||
is(height, expectedHeight, "Value updated (height).");
|
||||
|
||||
testCustomInput();
|
||||
}
|
||||
|
||||
function testCustomInput() {
|
||||
let initialWidth = content.innerWidth;
|
||||
let initialHeight = content.innerHeight;
|
||||
let expectedWidth = initialWidth - 20;
|
||||
let expectedHeight = initialHeight - 10;
|
||||
// Test custom input
|
||||
|
||||
initialWidth = content.innerWidth;
|
||||
initialHeight = content.innerHeight;
|
||||
expectedWidth = initialWidth - 20;
|
||||
expectedHeight = initialHeight - 10;
|
||||
let index = instance.menulist.selectedIndex;
|
||||
let label, value, width, height;
|
||||
|
||||
let userInput = expectedWidth + " x " + expectedHeight;
|
||||
|
||||
|
@ -187,6 +186,8 @@ function test() {
|
|||
// Only the `change` event must change the size
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
|
||||
yield once(mgr, "contentResize");
|
||||
|
||||
is(content.innerWidth, expectedWidth, "Size correctly updated (width).");
|
||||
is(content.innerHeight, expectedHeight, "Size correctly updated (height).");
|
||||
is(instance.menulist.selectedIndex, -1, "Custom menuitem cannot be selected");
|
||||
|
@ -200,17 +201,17 @@ function test() {
|
|||
is(width, expectedWidth, "Value updated (width).");
|
||||
is(height, expectedHeight, "Value updated (height).");
|
||||
|
||||
testCustomInput2();
|
||||
}
|
||||
|
||||
function testCustomInput2() {
|
||||
let initialWidth = content.innerWidth;
|
||||
let initialHeight = content.innerHeight;
|
||||
let index = instance.menulist.selectedIndex;
|
||||
// Invalid input
|
||||
|
||||
|
||||
initialWidth = content.innerWidth;
|
||||
initialHeight = content.innerHeight;
|
||||
index = instance.menulist.selectedIndex;
|
||||
let expectedValue = initialWidth + "x" + initialHeight;
|
||||
let expectedLabel = instance.menulist.firstChild.firstChild.getAttribute("label");
|
||||
|
||||
let userInput = "I'm wrong";
|
||||
userInput = "I'm wrong";
|
||||
|
||||
instance.menulist.inputField.value = "";
|
||||
instance.menulist.focus();
|
||||
|
@ -221,93 +222,75 @@ function test() {
|
|||
is(content.innerHeight, initialHeight, "Size hasn't changed (height).");
|
||||
is(instance.menulist.selectedIndex, index, "Selected item hasn't changed.");
|
||||
is(instance.menulist.value, expectedValue, "Value has been reset")
|
||||
let label = instance.menulist.firstChild.firstChild.getAttribute("label");
|
||||
label = instance.menulist.firstChild.firstChild.getAttribute("label");
|
||||
is(label, expectedLabel, "Custom menuitem's label hasn't changed");
|
||||
|
||||
rotate();
|
||||
}
|
||||
|
||||
function rotate() {
|
||||
let initialWidth = content.innerWidth;
|
||||
let initialHeight = content.innerHeight;
|
||||
// Rotate
|
||||
|
||||
initialWidth = content.innerWidth;
|
||||
initialHeight = content.innerHeight;
|
||||
|
||||
info("rotate");
|
||||
instance.rotate();
|
||||
|
||||
yield once(mgr, "contentResize");
|
||||
|
||||
is(content.innerWidth, initialHeight, "The width is now the height.");
|
||||
is(content.innerHeight, initialWidth, "The height is now the width.");
|
||||
let [width, height] = extractSizeFromString(instance.menulist.firstChild.firstChild.getAttribute("label"));
|
||||
[width, height] = extractSizeFromString(instance.menulist.firstChild.firstChild.getAttribute("label"));
|
||||
is(width, initialHeight, "Label updated (width).");
|
||||
is(height, initialWidth, "Label updated (height).");
|
||||
|
||||
widthBeforeClose = content.innerWidth;
|
||||
heightBeforeClose = content.innerHeight;
|
||||
let widthBeforeClose = content.innerWidth;
|
||||
let heightBeforeClose = content.innerHeight;
|
||||
|
||||
info("XXX BUG 851296: instance.closing: " + !!instance.closing);
|
||||
// Restart
|
||||
|
||||
mgr.once("off", function() {
|
||||
info("XXX BUG 851296: 'off' received.");
|
||||
executeSoon(restart);
|
||||
});
|
||||
mgr.toggle(window, gBrowser.selectedTab);
|
||||
}
|
||||
|
||||
function restart() {
|
||||
info("XXX BUG 851296: restarting.");
|
||||
info("XXX BUG 851296: __responsiveUI: " + gBrowser.selectedTab.__responsiveUI);
|
||||
mgr.once("on", function() {
|
||||
info("XXX BUG 851296: 'on' received.");
|
||||
executeSoon(onUIOpen2);
|
||||
});
|
||||
//XXX BUG 851296: synthesizeKeyFromKeyTag("key_responsiveUI");
|
||||
yield once(mgr, "off");
|
||||
|
||||
mgr.toggle(window, gBrowser.selectedTab);
|
||||
info("XXX BUG 851296: restart() finished.");
|
||||
}
|
||||
|
||||
function onUIOpen2() {
|
||||
info("XXX BUG 851296: onUIOpen2.");
|
||||
let container = gBrowser.getBrowserContainer();
|
||||
yield once(mgr, "on");
|
||||
|
||||
container = gBrowser.getBrowserContainer();
|
||||
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
|
||||
|
||||
// Menus are correctly updated?
|
||||
|
||||
is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), "true", "menus checked");
|
||||
|
||||
is(content.innerWidth, widthBeforeClose, "width restored.");
|
||||
is(content.innerHeight, heightBeforeClose, "height restored.");
|
||||
|
||||
mgr.once("off", function() {executeSoon(testScreenshot)});
|
||||
mgr.toggle(window, gBrowser.selectedTab);
|
||||
}
|
||||
// Screenshot
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
if (!isWinXP) {
|
||||
info("screenshot");
|
||||
instance.screenshot("responsiveui");
|
||||
let FileUtils = (Cu.import("resource://gre/modules/FileUtils.jsm", {})).FileUtils;
|
||||
|
||||
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);
|
||||
while(true) {
|
||||
// while(true) until we find the file.
|
||||
// no need for a timeout, the test will get killed anyway.
|
||||
let file = FileUtils.getFile("DfltDwnld", [ "responsiveui.png" ]);
|
||||
if (file.exists()) {
|
||||
ok(true, "Screenshot file exists");
|
||||
file.remove(false);
|
||||
break;
|
||||
}
|
||||
info("checking if file exists in 200ms");
|
||||
yield wait(200);
|
||||
}
|
||||
}
|
||||
checkIfFileExist();
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
mgr.toggle(window, gBrowser.selectedTab);
|
||||
|
||||
yield once(mgr, "off");
|
||||
|
||||
// Menus are correctly updated?
|
||||
is(document.getElementById("Tools:ResponsiveUI").getAttribute("checked"), "false", "menu unchecked");
|
||||
|
@ -315,39 +298,6 @@ function test() {
|
|||
delete instance;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
|
||||
function synthesizeKeyFromKeyTag(aKeyId) {
|
||||
let key = document.getElementById(aKeyId);
|
||||
isnot(key, null, "Successfully retrieved the <key> node");
|
||||
|
||||
let modifiersAttr = key.getAttribute("modifiers");
|
||||
|
||||
let name = null;
|
||||
|
||||
if (key.getAttribute("keycode"))
|
||||
name = key.getAttribute("keycode");
|
||||
else if (key.getAttribute("key"))
|
||||
name = key.getAttribute("key");
|
||||
|
||||
isnot(name, null, "Successfully retrieved keycode/key");
|
||||
|
||||
let modifiers = {
|
||||
shiftKey: modifiersAttr.match("shift"),
|
||||
ctrlKey: modifiersAttr.match("ctrl"),
|
||||
altKey: modifiersAttr.match("alt"),
|
||||
metaKey: modifiersAttr.match("meta"),
|
||||
accelKey: modifiersAttr.match("accel")
|
||||
}
|
||||
|
||||
info("XXX BUG 851296: key name: " + name);
|
||||
info("XXX BUG 851296: key modifiers: " + JSON.stringify(modifiers));
|
||||
EventUtils.synthesizeKey(name, modifiers);
|
||||
}
|
||||
|
||||
function processStringAsKey(str) {
|
||||
for (let i = 0, l = str.length; i < l; i++) {
|
||||
EventUtils.synthesizeKey(str.charAt(i), {});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ function test() {
|
|||
}
|
||||
|
||||
function testWithTouch() {
|
||||
gBrowser.selectedTab.__responsiveUI.enableTouch();
|
||||
mgr.getResponsiveUIForTab(gBrowser.selectedTab).enableTouch();
|
||||
let div = content.document.querySelector("div");
|
||||
let x = 2, y = 2;
|
||||
EventUtils.synthesizeMouse(div, x, y, {type: "mousedown", isSynthesized: false}, content);
|
||||
|
@ -47,7 +47,7 @@ function test() {
|
|||
}
|
||||
|
||||
function testWithTouchAgain() {
|
||||
gBrowser.selectedTab.__responsiveUI.disableTouch();
|
||||
mgr.getResponsiveUIForTab(gBrowser.selectedTab).disableTouch();
|
||||
let div = content.document.querySelector("div");
|
||||
let x = 2, y = 2;
|
||||
EventUtils.synthesizeMouse(div, x, y, {type: "mousedown", isSynthesized: false}, content);
|
||||
|
|
|
@ -2,170 +2,10 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
let instance, deletedPresetA, deletedPresetB, oldPrompt;
|
||||
let mgr = ResponsiveUI.ResponsiveUIManager;
|
||||
|
||||
waitForExplicitFinish();
|
||||
SimpleTest.requestCompleteLog();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
waitForFocus(startTest, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html;charset=utf8,test custom presets in responsive mode";
|
||||
|
||||
// This test uses executeSoon() when responsive mode is initialized and when
|
||||
// it is destroyed such that we get out of the init/destroy loops. If we try
|
||||
// to init/destroy immediately, without waiting for the next loop, we get
|
||||
// intermittent test failures.
|
||||
|
||||
function startTest() {
|
||||
// Mocking prompt
|
||||
oldPrompt = Services.prompt;
|
||||
Services.prompt = {
|
||||
value: "",
|
||||
returnBool: true,
|
||||
prompt: function(aParent, aDialogTitle, aText, aValue, aCheckMsg, aCheckState) {
|
||||
aValue.value = this.value;
|
||||
return this.returnBool;
|
||||
}
|
||||
};
|
||||
|
||||
registerCleanupFunction(() => Services.prompt = oldPrompt);
|
||||
|
||||
info("test started, waiting for responsive mode to activate");
|
||||
|
||||
document.getElementById("Tools:ResponsiveUI").removeAttribute("disabled");
|
||||
mgr.once("on", onUIOpen);
|
||||
synthesizeKeyFromKeyTag("key_responsiveUI");
|
||||
}
|
||||
|
||||
function onUIOpen() {
|
||||
// Is it open?
|
||||
let container = gBrowser.getBrowserContainer();
|
||||
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
|
||||
|
||||
instance = gBrowser.selectedTab.__responsiveUI;
|
||||
ok(instance, "instance of the module is attached to the tab.");
|
||||
|
||||
instance.transitionsEnabled = false;
|
||||
|
||||
testAddCustomPreset();
|
||||
}
|
||||
|
||||
function testAddCustomPreset() {
|
||||
// Tries to add a custom preset and cancel the prompt
|
||||
let idx = instance.menulist.selectedIndex;
|
||||
let presetCount = instance.presets.length;
|
||||
|
||||
Services.prompt.value = "";
|
||||
Services.prompt.returnBool = false;
|
||||
instance.addbutton.doCommand();
|
||||
|
||||
is(idx, instance.menulist.selectedIndex, "selected item didn't change after add preset and cancel");
|
||||
is(presetCount, instance.presets.length, "number of presets didn't change after add preset and cancel");
|
||||
|
||||
let customHeight = 123, customWidth = 456;
|
||||
instance.setSize(customWidth, customHeight);
|
||||
|
||||
// Adds the custom preset with "Testing preset"
|
||||
Services.prompt.value = "Testing preset";
|
||||
Services.prompt.returnBool = true;
|
||||
instance.addbutton.doCommand();
|
||||
|
||||
instance.menulist.selectedIndex = 1;
|
||||
|
||||
info("waiting for responsive mode to turn off");
|
||||
mgr.once("off", restart);
|
||||
|
||||
// Force document reflow to avoid intermittent failures.
|
||||
info("document height " + document.height);
|
||||
|
||||
// We're still in the loop of initializing the responsive mode.
|
||||
// Let's wait next loop to stop it.
|
||||
executeSoon(function() {
|
||||
instance.close();
|
||||
});
|
||||
}
|
||||
|
||||
function restart() {
|
||||
info("Restarting Responsive Mode");
|
||||
mgr.once("on", function() {
|
||||
let container = gBrowser.getBrowserContainer();
|
||||
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
|
||||
|
||||
instance = gBrowser.selectedTab.__responsiveUI;
|
||||
|
||||
testCustomPresetInList();
|
||||
});
|
||||
|
||||
// We're still in the loop of destroying the responsive mode.
|
||||
// Let's wait next loop to start it.
|
||||
executeSoon(function() {
|
||||
synthesizeKeyFromKeyTag("key_responsiveUI");
|
||||
});
|
||||
}
|
||||
|
||||
function testCustomPresetInList() {
|
||||
let customPresetIndex = getPresetIndex("456x123 (Testing preset)");
|
||||
ok(customPresetIndex >= 0, "is the previously added preset (idx = " + customPresetIndex + ") in the list of items");
|
||||
|
||||
instance.menulist.selectedIndex = customPresetIndex;
|
||||
|
||||
is(content.innerWidth, 456, "add preset, and selected in the list, dimension valid (width)");
|
||||
is(content.innerHeight, 123, "add preset, and selected in the list, dimension valid (height)");
|
||||
|
||||
testDeleteCustomPresets();
|
||||
}
|
||||
|
||||
function testDeleteCustomPresets() {
|
||||
instance.removebutton.doCommand();
|
||||
|
||||
instance.menulist.selectedIndex = 2;
|
||||
deletedPresetA = instance.menulist.selectedItem.getAttribute("label");
|
||||
instance.removebutton.doCommand();
|
||||
|
||||
instance.menulist.selectedIndex = 2;
|
||||
deletedPresetB = instance.menulist.selectedItem.getAttribute("label");
|
||||
instance.removebutton.doCommand();
|
||||
|
||||
info("waiting for responsive mode to turn off");
|
||||
mgr.once("off", restartAgain);
|
||||
|
||||
// We're still in the loop of initializing the responsive mode.
|
||||
// Let's wait next loop to stop it.
|
||||
executeSoon(() => instance.close());
|
||||
}
|
||||
|
||||
function restartAgain() {
|
||||
info("waiting for responsive mode to turn on");
|
||||
mgr.once("on", () => {
|
||||
instance = gBrowser.selectedTab.__responsiveUI;
|
||||
testCustomPresetsNotInListAnymore();
|
||||
});
|
||||
|
||||
// We're still in the loop of destroying the responsive mode.
|
||||
// Let's wait next loop to start it.
|
||||
executeSoon(() => synthesizeKeyFromKeyTag("key_responsiveUI"));
|
||||
}
|
||||
|
||||
function testCustomPresetsNotInListAnymore() {
|
||||
let customPresetIndex = getPresetIndex(deletedPresetA);
|
||||
is(customPresetIndex, -1, "deleted preset " + deletedPresetA + " is not in the list anymore");
|
||||
|
||||
customPresetIndex = getPresetIndex(deletedPresetB);
|
||||
is(customPresetIndex, -1, "deleted preset " + deletedPresetB + " is not in the list anymore");
|
||||
|
||||
executeSoon(finishUp);
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
delete instance;
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
finish();
|
||||
}
|
||||
let instance, deletedPresetA, deletedPresetB, oldPrompt;
|
||||
|
||||
function getPresetIndex(presetLabel) {
|
||||
function testOnePreset(c) {
|
||||
|
@ -199,4 +39,121 @@ function test() {
|
|||
|
||||
key.doCommand();
|
||||
}
|
||||
|
||||
Task.spawn(function() {
|
||||
|
||||
yield addTab("data:text/html;charset=utf8,test custom presets in responsive mode");
|
||||
|
||||
let mgr = ResponsiveUI.ResponsiveUIManager;
|
||||
|
||||
synthesizeKeyFromKeyTag("key_responsiveUI");
|
||||
|
||||
yield once(mgr, "on");
|
||||
|
||||
oldPrompt = Services.prompt;
|
||||
Services.prompt = {
|
||||
value: "",
|
||||
returnBool: true,
|
||||
prompt: function(aParent, aDialogTitle, aText, aValue, aCheckMsg, aCheckState) {
|
||||
aValue.value = this.value;
|
||||
return this.returnBool;
|
||||
}
|
||||
};
|
||||
|
||||
registerCleanupFunction(() => Services.prompt = oldPrompt);
|
||||
|
||||
// Is it open?
|
||||
let container = gBrowser.getBrowserContainer();
|
||||
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
|
||||
|
||||
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
|
||||
ok(instance, "instance of the module is attached to the tab.");
|
||||
|
||||
instance.transitionsEnabled = false;
|
||||
|
||||
yield instance._test_notifyOnResize();
|
||||
|
||||
// Tries to add a custom preset and cancel the prompt
|
||||
let idx = instance.menulist.selectedIndex;
|
||||
let presetCount = instance.presets.length;
|
||||
|
||||
Services.prompt.value = "";
|
||||
Services.prompt.returnBool = false;
|
||||
instance.addbutton.doCommand();
|
||||
|
||||
is(idx, instance.menulist.selectedIndex, "selected item didn't change after add preset and cancel");
|
||||
is(presetCount, instance.presets.length, "number of presets didn't change after add preset and cancel");
|
||||
|
||||
// Adds the custom preset with "Testing preset"
|
||||
Services.prompt.value = "Testing preset";
|
||||
Services.prompt.returnBool = true;
|
||||
|
||||
let customHeight = 123, customWidth = 456;
|
||||
instance.startResizing({});
|
||||
instance.setSize(customWidth, customHeight);
|
||||
instance.stopResizing({});
|
||||
|
||||
instance.addbutton.doCommand();
|
||||
|
||||
// Force document reflow to avoid intermittent failures.
|
||||
info("document height " + document.height);
|
||||
|
||||
instance.close();
|
||||
|
||||
info("waiting for responsive mode to turn off");
|
||||
yield once(mgr, "off");
|
||||
|
||||
// We're still in the loop of initializing the responsive mode.
|
||||
// Let's wait next loop to stop it.
|
||||
yield nextTick();
|
||||
|
||||
synthesizeKeyFromKeyTag("key_responsiveUI");
|
||||
|
||||
yield once(mgr, "on");
|
||||
|
||||
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
|
||||
|
||||
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
|
||||
|
||||
let customPresetIndex = getPresetIndex("456x123 (Testing preset)");
|
||||
info(customPresetIndex);
|
||||
ok(customPresetIndex >= 0, "is the previously added preset (idx = " + customPresetIndex + ") in the list of items");
|
||||
|
||||
instance.menulist.selectedIndex = customPresetIndex;
|
||||
|
||||
is(content.innerWidth, 456, "add preset, and selected in the list, dimension valid (width)");
|
||||
is(content.innerHeight, 123, "add preset, and selected in the list, dimension valid (height)");
|
||||
|
||||
instance.removebutton.doCommand();
|
||||
|
||||
instance.menulist.selectedIndex = 2;
|
||||
deletedPresetA = instance.menulist.selectedItem.getAttribute("label");
|
||||
instance.removebutton.doCommand();
|
||||
|
||||
instance.menulist.selectedIndex = 2;
|
||||
deletedPresetB = instance.menulist.selectedItem.getAttribute("label");
|
||||
instance.removebutton.doCommand();
|
||||
|
||||
yield nextTick();
|
||||
instance.close();
|
||||
yield once(mgr, "off");
|
||||
|
||||
synthesizeKeyFromKeyTag("key_responsiveUI");
|
||||
|
||||
info("waiting for responsive mode to turn on");
|
||||
yield once(mgr, "on");
|
||||
|
||||
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
|
||||
|
||||
customPresetIndex = getPresetIndex(deletedPresetA);
|
||||
is(customPresetIndex, -1, "deleted preset " + deletedPresetA + " is not in the list anymore");
|
||||
|
||||
customPresetIndex = getPresetIndex(deletedPresetB);
|
||||
is(customPresetIndex, -1, "deleted preset " + deletedPresetB + " is not in the list anymore");
|
||||
|
||||
yield nextTick();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -123,3 +123,92 @@ function openComputedView() {
|
|||
function openRuleView() {
|
||||
return openInspectorSideBar("ruleview");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a new test tab in the browser and load the given url.
|
||||
* @param {String} url The url to be loaded in the new tab
|
||||
* @return a promise that resolves to the tab object when the url is loaded
|
||||
*/
|
||||
let addTab = Task.async(function* (url) {
|
||||
info("Adding a new tab with URL: '" + url + "'");
|
||||
|
||||
window.focus();
|
||||
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
yield once(browser, "load", true);
|
||||
info("URL '" + url + "' loading complete");
|
||||
|
||||
return tab;
|
||||
});
|
||||
|
||||
/**
|
||||
* Wait for eventName on target.
|
||||
* @param {Object} target An observable object that either supports on/off or
|
||||
* addEventListener/removeEventListener
|
||||
* @param {String} eventName
|
||||
* @param {Boolean} useCapture Optional, for addEventListener/removeEventListener
|
||||
* @return A promise that resolves when the event has been handled
|
||||
*/
|
||||
function once(target, eventName, useCapture=false) {
|
||||
info("Waiting for event: '" + eventName + "' on " + target + ".");
|
||||
|
||||
let deferred = promise.defer();
|
||||
|
||||
for (let [add, remove] of [
|
||||
["addEventListener", "removeEventListener"],
|
||||
["addListener", "removeListener"],
|
||||
["on", "off"]
|
||||
]) {
|
||||
if ((add in target) && (remove in target)) {
|
||||
target[add](eventName, function onEvent(...aArgs) {
|
||||
info("Got event: '" + eventName + "' on " + target + ".");
|
||||
target[remove](eventName, onEvent, useCapture);
|
||||
deferred.resolve.apply(deferred, aArgs);
|
||||
}, useCapture);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function wait(ms) {
|
||||
let def = promise.defer();
|
||||
setTimeout(def.resolve, ms);
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
function synthesizeKeyFromKeyTag(aKeyId) {
|
||||
let key = document.getElementById(aKeyId);
|
||||
isnot(key, null, "Successfully retrieved the <key> node");
|
||||
|
||||
let modifiersAttr = key.getAttribute("modifiers");
|
||||
|
||||
let name = null;
|
||||
|
||||
if (key.getAttribute("keycode"))
|
||||
name = key.getAttribute("keycode");
|
||||
else if (key.getAttribute("key"))
|
||||
name = key.getAttribute("key");
|
||||
|
||||
isnot(name, null, "Successfully retrieved keycode/key");
|
||||
|
||||
let modifiers = {
|
||||
shiftKey: modifiersAttr.match("shift"),
|
||||
ctrlKey: modifiersAttr.match("ctrl"),
|
||||
altKey: modifiersAttr.match("alt"),
|
||||
metaKey: modifiersAttr.match("meta"),
|
||||
accelKey: modifiersAttr.match("accel")
|
||||
}
|
||||
|
||||
EventUtils.synthesizeKey(name, modifiers);
|
||||
}
|
||||
|
||||
function nextTick() {
|
||||
let def = promise.defer();
|
||||
executeSoon(() => def.resolve())
|
||||
return def.promise;
|
||||
}
|
||||
|
|
|
@ -1,126 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ "switchToFloatingScrollbars", "switchToNativeScrollbars" ];
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let URL = Services.io.newURI("chrome://browser/skin/devtools/floating-scrollbars.css", null, null);
|
||||
|
||||
let trackedTabs = new WeakMap();
|
||||
|
||||
/**
|
||||
* Switch to floating scrollbars, à la mobile.
|
||||
*
|
||||
* @param aTab the targeted tab.
|
||||
*
|
||||
*/
|
||||
this.switchToFloatingScrollbars = function switchToFloatingScrollbars(aTab) {
|
||||
let mgr = trackedTabs.get(aTab);
|
||||
if (!mgr) {
|
||||
mgr = new ScrollbarManager(aTab);
|
||||
}
|
||||
mgr.switchToFloating();
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to original native scrollbars.
|
||||
*
|
||||
* @param aTab the targeted tab.
|
||||
*
|
||||
*/
|
||||
this.switchToNativeScrollbars = function switchToNativeScrollbars(aTab) {
|
||||
let mgr = trackedTabs.get(aTab);
|
||||
if (mgr) {
|
||||
mgr.reset();
|
||||
}
|
||||
}
|
||||
|
||||
function ScrollbarManager(aTab) {
|
||||
trackedTabs.set(aTab, this);
|
||||
|
||||
this.attachedTab = aTab;
|
||||
this.attachedBrowser = aTab.linkedBrowser;
|
||||
|
||||
this.reset = this.reset.bind(this);
|
||||
this.switchToFloating = this.switchToFloating.bind(this);
|
||||
|
||||
this.attachedTab.addEventListener("TabClose", this.reset, true);
|
||||
this.attachedBrowser.addEventListener("DOMContentLoaded", this.switchToFloating, true);
|
||||
}
|
||||
|
||||
ScrollbarManager.prototype = {
|
||||
get win() {
|
||||
return this.attachedBrowser.contentWindow;
|
||||
},
|
||||
|
||||
/*
|
||||
* Change the look of the scrollbars.
|
||||
*/
|
||||
switchToFloating: function() {
|
||||
let windows = this.getInnerWindows(this.win);
|
||||
windows.forEach(this.injectStyleSheet);
|
||||
this.forceStyle();
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* Reset the look of the scrollbars.
|
||||
*/
|
||||
reset: function() {
|
||||
let windows = this.getInnerWindows(this.win);
|
||||
windows.forEach(this.removeStyleSheet);
|
||||
this.forceStyle(this.attachedBrowser);
|
||||
this.attachedBrowser.removeEventListener("DOMContentLoaded", this.switchToFloating, true);
|
||||
this.attachedTab.removeEventListener("TabClose", this.reset, true);
|
||||
trackedTabs.delete(this.attachedTab);
|
||||
},
|
||||
|
||||
/*
|
||||
* Toggle the display property of the window to force the style to be applied.
|
||||
*/
|
||||
forceStyle: function() {
|
||||
let parentWindow = this.attachedBrowser.ownerDocument.defaultView;
|
||||
let display = parentWindow.getComputedStyle(this.attachedBrowser).display; // Save display value
|
||||
this.attachedBrowser.style.display = "none";
|
||||
parentWindow.getComputedStyle(this.attachedBrowser).display; // Flush
|
||||
this.attachedBrowser.style.display = display; // Restore
|
||||
},
|
||||
|
||||
/*
|
||||
* return all the window objects present in the hiearchy of a window.
|
||||
*/
|
||||
getInnerWindows: function(win) {
|
||||
let iframes = win.document.querySelectorAll("iframe");
|
||||
let innerWindows = [];
|
||||
for (let iframe of iframes) {
|
||||
innerWindows = innerWindows.concat(this.getInnerWindows(iframe.contentWindow));
|
||||
}
|
||||
return [win].concat(innerWindows);
|
||||
},
|
||||
|
||||
/*
|
||||
* Append the new scrollbar style.
|
||||
*/
|
||||
injectStyleSheet: function(win) {
|
||||
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
try {
|
||||
winUtils.loadSheet(URL, win.AGENT_SHEET);
|
||||
}catch(e) {}
|
||||
},
|
||||
|
||||
/*
|
||||
* Remove the injected stylesheet.
|
||||
*/
|
||||
removeStyleSheet: function(win) {
|
||||
let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
try {
|
||||
winUtils.removeSheet(URL, win.AGENT_SHEET);
|
||||
}catch(e) {}
|
||||
},
|
||||
}
|
|
@ -12,7 +12,6 @@ EXTRA_JS_MODULES.devtools += [
|
|||
'Curl.jsm',
|
||||
'DeveloperToolbar.jsm',
|
||||
'DOMHelpers.jsm',
|
||||
'FloatingScrollbars.jsm',
|
||||
'Jsbeautify.jsm',
|
||||
'Parser.jsm',
|
||||
'SplitView.jsm',
|
||||
|
|
Загрузка…
Ссылка в новой задаче