Merge m-c to inbound, a=merge

MozReview-Commit-ID: 9YZdlIARozU
This commit is contained in:
Wes Kocher 2016-04-08 16:47:03 -07:00
commit dfc7e5253f
538 changed files with 6769 additions and 5684 deletions

View File

@ -193,6 +193,7 @@ toolkit/modules/tests/xpcshell/test_task.js
toolkit/components/osfile/**
# External code:
toolkit/components/microformats/test/**
toolkit/components/reader/Readability.js
toolkit/components/reader/JSDOMParser.js

View File

@ -304,7 +304,7 @@ pref("browser.urlbar.matchBehavior", 1);
pref("browser.urlbar.filter.javascript", true);
// the maximum number of results to show in autocomplete when doing richResults
pref("browser.urlbar.maxRichResults", 12);
pref("browser.urlbar.maxRichResults", 10);
// The amount of time (ms) to wait after the user has stopped typing
// before starting to perform autocomplete. 50 is the default set in
// autocomplete.xml.

View File

@ -660,6 +660,7 @@ var LightweightThemeListener = {
if (sheet.href == "chrome://browser/skin/browser-lightweightTheme.css")
return sheet;
}
return undefined;
});
Services.obs.addObserver(this, "lightweight-theme-styling-update", false);

View File

@ -11,7 +11,6 @@ var gPluginHandler = {
"PluginContent:RemoveNotification",
"PluginContent:UpdateHiddenPluginUI",
"PluginContent:HideNotificationBar",
"PluginContent:ShowInstallNotification",
"PluginContent:InstallSinglePlugin",
"PluginContent:ShowPluginCrashedNotification",
"PluginContent:SubmitReport",
@ -56,8 +55,6 @@ var gPluginHandler = {
case "PluginContent:HideNotificationBar":
this.hideNotificationBar(msg.target, msg.data.name);
break;
case "PluginContent:ShowInstallNotification":
return this.showInstallNotification(msg.target, msg.data.pluginInfo);
case "PluginContent:InstallSinglePlugin":
this.installSinglePlugin(msg.data.pluginInfo);
break;

View File

@ -251,7 +251,7 @@ var gSyncUI = {
if (needsSetup || this._loginFailed()) {
this.openSetup();
} else {
return this.doSync();
this.doSync();
}
}).catch(err => {
this.log.error("Failed to handle toolbar button command", err);

View File

@ -3387,7 +3387,7 @@ const DOMLinkHandler = {
addSearch: function(aBrowser, aEngine, aURL) {
let tab = gBrowser.getTabForBrowser(aBrowser);
if (!tab)
return false;
return;
BrowserSearch.addEngine(aBrowser, aEngine, makeURI(aURL));
},

View File

@ -698,7 +698,7 @@
showcommentcolumn="true"
showimagecolumn="true"
enablehistory="true"
maxrows="6"
maxrows="10"
newlines="stripsurroundingwhitespace"
ontextentered="this.handleCommand(param);"
ontextreverted="return this.handleRevert();"

View File

@ -268,6 +268,7 @@ function getClipboardHelper() {
return Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);
} catch(e) {
// do nothing, later code will handle the error
return null;
}
}
const gClipboardHelper = getClipboardHelper();

View File

@ -603,6 +603,7 @@ Sanitizer.prototype = {
aWindow.skipNextCanClose = true;
return true;
}
return false;
},
_resetAllWindowClosures: function(aWindowList) {
for (let win of aWindowList) {
@ -665,6 +666,7 @@ Sanitizer.prototype = {
e.stopPropagation();
return false;
}
return undefined;
}
newWindow.addEventListener("fullscreen", onFullScreen);
}

View File

@ -147,6 +147,7 @@ var Change = {
return this.doChangePassword();
break;
}
return undefined;
},
doGeneratePassphrase: function () {

View File

@ -123,14 +123,14 @@ var gSyncSetup = {
startNewAccountSetup: function () {
if (!Weave.Utils.ensureMPUnlocked())
return false;
return;
this._settingUpNew = true;
this.wizard.pageIndex = NEW_ACCOUNT_START_PAGE;
},
useExistingAccount: function () {
if (!Weave.Utils.ensureMPUnlocked())
return false;
return;
this._settingUpNew = false;
if (this.wizardType == "pair") {
// We're already pairing, so there's no point in pairing again.

View File

@ -1824,6 +1824,99 @@
</body>
</method>
<method name="_linkBrowserToTab">
<parameter name="aTab"/>
<parameter name="aURI"/>
<parameter name="aParams"/>
<body>
<![CDATA[
"use strict";
let aReferrerURI = aParams.referrerURI;
let aReferrerPolicy = aParams.referrerPolicy;
let aCharset = aParams.charset;
let aPostData = aParams.postData;
let aAllowThirdPartyFixup = aParams.allowThirdPartyFixup;
let aFromExternal = aParams.fromExternal;
let aAllowMixedContent = aParams.allowMixedContent;
let aForceNotRemote = aParams.forceNotRemote;
let aNoReferrer = aParams.noReferrer;
let aUserContextId = aParams.userContextId;
let uriIsAboutBlank = !aURI || aURI == "about:blank";
// The new browser should be remote if this is an e10s window and
// the uri to load can be loaded remotely.
let remote = gMultiProcessBrowser &&
!aForceNotRemote &&
E10SUtils.canLoadURIInProcess(aURI, Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT);
let browser;
let usingPreloadedContent = false;
// If we open a new tab with the newtab URL in the default
// userContext, check if there is a preloaded browser ready.
// Private windows are not included because both the label and the
// icon for the tab would be set incorrectly (see bug 1195981).
if (aURI == BROWSER_NEW_TAB_URL && !aUserContextId &&
!PrivateBrowsingUtils.isWindowPrivate(window)) {
browser = this._getPreloadedBrowser();
usingPreloadedContent = !!browser;
}
if (!browser) {
// No preloaded browser found, create one.
browser = this._createBrowser({remote: remote,
uriIsAboutBlank: uriIsAboutBlank,
userContextId: aUserContextId});
}
let notificationbox = this.getNotificationBox(browser);
let uniqueId = this._generateUniquePanelID();
notificationbox.id = uniqueId;
aTab.linkedPanel = uniqueId;
aTab.linkedBrowser = browser;
this._tabForBrowser.set(browser, aTab);
// Inject the <browser> into the DOM if necessary.
if (!notificationbox.parentNode) {
// NB: this appendChild call causes us to run constructors for the
// browser element, which fires off a bunch of notifications. Some
// of those notifications can cause code to run that inspects our
// state, so it is important that the tab element is fully
// initialized by this point.
this.mPanelContainer.appendChild(notificationbox);
}
// wire up a progress listener for the new browser object.
let tabListener = this.mTabProgressListener(aTab, browser, uriIsAboutBlank, usingPreloadedContent);
const filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
.createInstance(Ci.nsIWebProgress);
filter.addProgressListener(tabListener, Ci.nsIWebProgress.NOTIFY_ALL);
browser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);
this._tabListeners.set(aTab, tabListener);
this._tabFilters.set(aTab, filter);
browser.droppedLinkHandler = handleDroppedLink;
// We start our browsers out as inactive, and then maintain
// activeness in the tab switcher.
browser.docShellIsActive = false;
// When addTab() is called with an URL that is not "about:blank" we
// set the "nodefaultsrc" attribute that prevents a frameLoader
// from being created as soon as the linked <browser> is inserted
// into the DOM. We thus have to register the new outerWindowID
// for non-remote browsers after we have called browser.loadURI().
if (!remote) {
this._outerWindowIDBrowserMap.set(browser.outerWindowID, browser);
}
return { usingPreloadedContent: usingPreloadedContent };
]]>
</body>
</method>
<method name="addTab">
<parameter name="aURI"/>
<parameter name="aReferrerURI"/>
@ -1833,6 +1926,8 @@
<parameter name="aAllowThirdPartyFixup"/>
<body>
<![CDATA[
"use strict";
const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var aReferrerPolicy;
var aFromExternal;
@ -1884,12 +1979,6 @@
t.setAttribute("onerror", "this.removeAttribute('image');");
t.className = "tabbrowser-tab";
// The new browser should be remote if this is an e10s window and
// the uri to load can be loaded remotely.
let remote = gMultiProcessBrowser &&
!aForceNotRemote &&
E10SUtils.canLoadURIInProcess(aURI, Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT);
this.tabContainer._unlockTabSizing();
// When overflowing, new tabs are scrolled into view smoothly, which
@ -1914,59 +2003,35 @@
if (aOwner)
t.owner = aOwner;
let b;
let usingPreloadedContent = false;
// If we open a new tab with the newtab URL in the default
// userContext, check if there is a preloaded browser ready.
// Private windows are not included because both the label and the
// icon for the tab would be set incorrectly (see bug 1195981).
if (aURI == BROWSER_NEW_TAB_URL && !aUserContextId &&
!PrivateBrowsingUtils.isWindowPrivate(window)) {
b = this._getPreloadedBrowser();
usingPreloadedContent = !!b;
}
if (!b) {
// No preloaded browser found, create one.
b = this._createBrowser({remote: remote,
uriIsAboutBlank: uriIsAboutBlank,
userContextId: aUserContextId});
}
let notificationbox = this.getNotificationBox(b);
var position = this.tabs.length - 1;
var uniqueId = this._generateUniquePanelID();
notificationbox.id = uniqueId;
t.linkedPanel = uniqueId;
t.linkedBrowser = b;
this._tabForBrowser.set(b, t);
t._tPos = position;
t.lastAccessed = Date.now();
this.tabContainer._setPositionalAttributes();
// Inject the <browser> into the DOM if necessary.
if (!notificationbox.parentNode) {
// NB: this appendChild call causes us to run constructors for the
// browser element, which fires off a bunch of notifications. Some
// of those notifications can cause code to run that inspects our
// state, so it is important that the tab element is fully
// initialized by this point.
this.mPanelContainer.appendChild(notificationbox);
}
this.tabContainer.updateVisibility();
// wire up a progress listener for the new browser object.
var tabListener = this.mTabProgressListener(t, b, uriIsAboutBlank, usingPreloadedContent);
const filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"]
.createInstance(Components.interfaces.nsIWebProgress);
filter.addProgressListener(tabListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
b.webProgress.addProgressListener(filter, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
this._tabListeners.set(t, tabListener);
this._tabFilters.set(t, filter);
let options = {
referrerURI : aReferrerURI,
referrerPolicy : aReferrerPolicy,
charset : aCharset,
postData : aPostData,
allowThirdPartyFixup : aAllowThirdPartyFixup,
fromExternal : aFromExternal,
allowMixedContent : aAllowMixedContent,
forceNotRemote : aForceNotRemote,
noReferrer : aNoReferrer,
userContextId : aUserContextId
};
b.droppedLinkHandler = handleDroppedLink;
// Currently in this incarnation of bug 906076, we are forcing the
// browser to immediately be linked. In future incarnations of this
// bug this will be removed so we can leave the tab in its "lazy"
// state to be exploited for startup optimization. Note that for
// now this must occur before "TabOpen" event is fired, as that will
// trigger SessionStore.jsm to run code that expects the existence
// of tab.linkedBrowser.
let { usingPreloadedContent } = this._linkBrowserToTab(t, aURI, options);
let b = t.linkedBrowser;
// Dispatch a new tab notification. We do this once we're
// entirely done, so that things are in a consistent state
@ -2005,23 +2070,6 @@
}
}
// We start our browsers out as inactive, and then maintain
// activeness in the tab switcher.
b.docShellIsActive = false;
// When addTab() is called with an URL that is not "about:blank" we
// set the "nodefaultsrc" attribute that prevents a frameLoader
// from being created as soon as the linked <browser> is inserted
// into the DOM. We thus have to register the new outerWindowID
// for non-remote browsers after we have called browser.loadURI().
//
// Note: Only do this of we still have a docShell. The TabOpen
// event was dispatched above and a gBrowser.removeTab() call from
// one of its listeners could cause us to fail here.
if (!remote && b.docShell) {
this._outerWindowIDBrowserMap.set(b.outerWindowID, b);
}
// Check if we're opening a tab related to the current tab and
// move it to after the current tab.
// aReferrerURI is null or undefined if the tab is opened from
@ -4266,6 +4314,7 @@
}
}
return undefined;
]]></body>
</method>

View File

@ -321,7 +321,7 @@ skip-if = !datareporting
[browser_devices_get_user_media.js]
skip-if = buildapp == 'mulet' || (os == "linux" && debug) # linux: bug 976544
[browser_devices_get_user_media_about_urls.js]
skip-if = e10s # Bug 1071623
skip-if = e10s && debug
[browser_devices_get_user_media_in_frame.js]
[browser_discovery.js]
[browser_double_close_tab.js]

View File

@ -16,12 +16,14 @@ add_task(function*() {
Services.prefs.setBoolPref("browser.urlbar.unifiedcomplete", ucpref);
});
let maxResults = Services.prefs.getIntPref("browser.urlbar.maxRichResults");
registerCleanupFunction(function* () {
yield PlacesTestUtils.clearHistory();
});
let visits = [];
repeat(10, i => {
repeat(maxResults, i => {
visits.push({
uri: makeURI("http://example.com/autocomplete/?" + i),
});
@ -34,20 +36,20 @@ add_task(function*() {
let popup = gURLBar.popup;
let results = popup.richlistbox.children;
// 1 extra for the current search engine match
is(results.length, 11, "Should get 11 results");
is(results.length, maxResults,
"Should get maxResults=" + maxResults + " results");
is_selected(0);
info("Key Down to select the next item");
EventUtils.synthesizeKey("VK_DOWN", {});
is_selected(1);
info("Key Down 11 times should wrap around all the way around");
repeat(11, () => EventUtils.synthesizeKey("VK_DOWN", {}));
info("Key Down maxResults times should wrap around all the way around");
repeat(maxResults, () => EventUtils.synthesizeKey("VK_DOWN", {}));
is_selected(1);
info("Key Up 11 times should wrap around the other way");
repeat(11, () => EventUtils.synthesizeKey("VK_UP", {}));
info("Key Up maxResults times should wrap around the other way");
repeat(maxResults, () => EventUtils.synthesizeKey("VK_UP", {}));
is_selected(1);
info("Page Up will go up the list, but not wrap");
@ -56,7 +58,7 @@ add_task(function*() {
info("Page Up again will wrap around to the end of the list");
EventUtils.synthesizeKey("VK_PAGE_UP", {})
is_selected(10);
is_selected(maxResults - 1);
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promisePopupHidden(gURLBar.popup);

View File

@ -11,6 +11,8 @@ let LOGIN_FILL_ITEMS = [
], null,
];
let hasPocket = Services.prefs.getBoolPref("extensions.pocket.enabled");
add_task(function* test_setup() {
const example_base = "http://example.com/browser/browser/base/content/test/general/";
const url = example_base + "subtst_contextmenu.html";
@ -38,6 +40,7 @@ add_task(function* test_plaintext() {
"context-bookmarkpage", true], null,
"---", null,
"context-savepage", true,
...(hasPocket ? ["context-pocket", true] : []),
"---", null,
"context-viewbgimage", false,
"context-selectall", true,
@ -56,6 +59,7 @@ add_task(function* test_link() {
"---", null,
"context-bookmarklink", true,
"context-savelink", true,
...(hasPocket ? ["context-savelinktopocket", true] : []),
"context-copylink", true,
"context-searchselect", true
]
@ -196,6 +200,7 @@ add_task(function* test_iframe() {
"context-bookmarkpage", true], null,
"---", null,
"context-savepage", true,
...(hasPocket ? ["context-pocket", true] : []),
"---", null,
"context-viewbgimage", false,
"context-selectall", true,
@ -460,6 +465,7 @@ add_task(function* test_pagemenu() {
"+Checkbox", {type: "checkbox", icon: "", checked: false, disabled: false}], null,
"---", null,
"context-savepage", true,
...(hasPocket ? ["context-pocket", true] : []),
"---", null,
"context-viewbgimage", false,
"context-selectall", true,
@ -490,6 +496,7 @@ add_task(function* test_dom_full_screen() {
"context-leave-dom-fullscreen", true,
"---", null,
"context-savepage", true,
...(hasPocket ? ["context-pocket", true] : []),
"---", null,
"context-viewbgimage", false,
"context-selectall", true,
@ -535,6 +542,7 @@ add_task(function* test_pagemenu2() {
"context-bookmarkpage", true], null,
"---", null,
"context-savepage", true,
...(hasPocket ? ["context-pocket", true] : []),
"---", null,
"context-viewbgimage", false,
"context-selectall", true,
@ -603,6 +611,7 @@ add_task(function* test_imagelink() {
"---", null,
"context-bookmarklink", true,
"context-savelink", true,
...(hasPocket ? ["context-savelinktopocket", true] : []),
"context-copylink", true,
"---", null,
"context-viewimage", true,
@ -701,6 +710,7 @@ add_task(function* test_click_to_play_blocked_plugin() {
"context-ctp-hide", true,
"---", null,
"context-savepage", true,
...(hasPocket ? ["context-pocket", true] : []),
"---", null,
"context-viewbgimage", false,
"context-selectall", true,
@ -744,6 +754,7 @@ add_task(function* test_srcdoc() {
"context-bookmarkpage", true], null,
"---", null,
"context-savepage", true,
...(hasPocket ? ["context-pocket", true] : []),
"---", null,
"context-viewbgimage", false,
"context-selectall", true,

View File

@ -1,6 +1,8 @@
"use strict";
let contextMenu;
let hasPocket = Services.prefs.getBoolPref("extensions.pocket.enabled");
add_task(function* test_setup() {
const example_base = "http://example.com/browser/browser/base/content/test/general/";
const url = example_base + "subtst_contextmenu_input.html";
@ -187,6 +189,7 @@ add_task(function* test_date_time_color_range_input() {
"context-bookmarkpage", true], null,
"---", null,
"context-savepage", true,
...(hasPocket ? ["context-pocket", true] : []),
"---", null,
"context-viewbgimage", false,
"context-selectall", null,

View File

@ -58,37 +58,8 @@ function loadPage(aUrl) {
return deferred.promise;
}
// A fake about module to map get_user_media.html to different about urls.
function fakeLoopAboutModule() {
}
fakeLoopAboutModule.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
newChannel: function (aURI, aLoadInfo) {
let rootDir = getRootDirectory(gTestPath);
let uri = Services.io.newURI(rootDir + "get_user_media.html", null, null);
let chan = Services.io.newChannelFromURIWithLoadInfo(uri, aLoadInfo);
chan.owner = Services.scriptSecurityManager.getSystemPrincipal();
return chan;
},
getURIFlags: function (aURI) {
return Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT |
Ci.nsIAboutModule.ALLOW_SCRIPT |
Ci.nsIAboutModule.URI_CAN_LOAD_IN_CHILD |
Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT;
}
};
var factory = XPCOMUtils._getFactory(fakeLoopAboutModule);
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
var classIDLoopconversation, classIDEvil;
registerCleanupFunction(function() {
gBrowser.removeCurrentTab();
registrar.unregisterFactory(classIDLoopconversation, factory);
registrar.unregisterFactory(classIDEvil, factory);
});
const permissionError = "error: SecurityError: The operation is insecure.";
@ -181,19 +152,46 @@ function test() {
gTab.linkedBrowser.messageManager.loadFrameScript(CONTENT_SCRIPT_HELPER, true);
classIDLoopconversation = Cc["@mozilla.org/uuid-generator;1"]
.getService(Ci.nsIUUIDGenerator).generateUUID();
registrar.registerFactory(classIDLoopconversation, "",
Task.spawn(function () {
yield ContentTask.spawn(gBrowser.selectedBrowser,
getRootDirectory(gTestPath) + "get_user_media.html",
function* (url) {
const Ci = Components.interfaces;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
/* A fake about module to map get_user_media.html to different about urls. */
function fakeLoopAboutModule() {
}
fakeLoopAboutModule.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
newChannel: function (aURI, aLoadInfo) {
let uri = Services.io.newURI(url, null, null);
let chan = Services.io.newChannelFromURIWithLoadInfo(uri, aLoadInfo);
chan.owner = Services.scriptSecurityManager.getSystemPrincipal();
return chan;
},
getURIFlags: function (aURI) {
return Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT |
Ci.nsIAboutModule.ALLOW_SCRIPT |
Ci.nsIAboutModule.URI_CAN_LOAD_IN_CHILD |
Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT;
}
};
var factory = XPCOMUtils._getFactory(fakeLoopAboutModule);
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
let UUIDGenerator = Components.classes["@mozilla.org/uuid-generator;1"]
.getService(Ci.nsIUUIDGenerator);
registrar.registerFactory(UUIDGenerator.generateUUID(), "",
"@mozilla.org/network/protocol/about;1?what=loopconversation",
factory);
classIDEvil = Cc["@mozilla.org/uuid-generator;1"]
.getService(Ci.nsIUUIDGenerator).generateUUID();
registrar.registerFactory(classIDEvil, "",
registrar.registerFactory(UUIDGenerator.generateUUID(), "",
"@mozilla.org/network/protocol/about;1?what=evil",
factory);
});
Task.spawn(function () {
yield new Promise(resolve => SpecialPowers.pushPrefEnv({
"set": [[PREF_PERMISSION_FAKE, true],
["media.getusermedia.screensharing.enabled", true]],
@ -206,6 +204,19 @@ function test() {
// Cleanup before the next test
expectNoObserverCalled();
}
yield ContentTask.spawn(gBrowser.selectedBrowser, null,
function* () {
const Ci = Components.interfaces;
const Cc = Components.classes;
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
let cid = Cc["@mozilla.org/network/protocol/about;1?what=loopconversation"];
registrar.unregisterFactory(cid,
registrar.getClassObject(cid, Ci.nsIFactory));
cid = Cc["@mozilla.org/network/protocol/about;1?what=evil"];
registrar.unregisterFactory(cid,
registrar.getClassObject(cid, Ci.nsIFactory));
});
}).then(finish, ex => {
ok(false, "Unexpected Exception: " + ex);
finish();

View File

@ -15,6 +15,8 @@ function is_selected(index) {
is(gURLBar.popup.richlistbox.selectedIndex, index, `Item ${index + 1} should be selected`);
}
let gMaxResults;
add_task(function*() {
registerCleanupFunction(function* () {
yield PlacesTestUtils.clearHistory();
@ -23,8 +25,10 @@ add_task(function*() {
yield PlacesTestUtils.clearHistory();
let tabCount = gBrowser.tabs.length;
gMaxResults = Services.prefs.getIntPref("browser.urlbar.maxRichResults");
let visits = [];
repeat(10, i => {
repeat(gMaxResults, i => {
visits.push({
uri: makeURI("http://example.com/autocomplete/?" + i),
});
@ -44,7 +48,8 @@ function* do_test() {
let popup = gURLBar.popup;
let results = popup.richlistbox.children;
is(results.length, 11, "Should get 11 results");
is(results.length, gMaxResults,
"Should get gMaxResults=" + gMaxResults + " results");
let initiallySelected = gURLBar.popup.richlistbox.selectedIndex;

View File

@ -62,6 +62,7 @@ function getVisibleMenuItems(aMenu, aData) {
} else if (item.id.indexOf("spell-check-dictionary-") != 0 &&
item.id != "spell-no-suggestions" &&
item.id != "spell-add-dictionaries-main" &&
item.id != "context-savelinktopocket" &&
item.id != "fill-login-saved-passwords" &&
item.id != "fill-login-no-logins") {
ok(key, "menuitem " + item.id + " has an access key");

View File

@ -1360,9 +1360,16 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
var popupDirection = aElement.ownerDocument.defaultView.getComputedStyle(aElement).direction;
this.style.direction = popupDirection;
// Move left margin to the window border.
// Make the popup's starting margin negaxtive so that the start of the
// popup aligns with the window border.
let elementRect = aElement.getBoundingClientRect();
this.style.marginLeft = "-" + (elementRect.left - rect.left) + "px";
if (popupDirection == "rtl") {
let offset = elementRect.right - rect.right
this.style.marginRight = offset + "px";
} else {
let offset = rect.left - elementRect.left;
this.style.marginLeft = offset + "px";
}
// Position the popup below the navbar. To get the y-coordinate,
// which is an offset from the bottom of the input, subtract the

View File

@ -2134,7 +2134,8 @@ var CustomizableUIInternal = {
dispatchToolboxEvent: function(aEventType, aDetails={}, aWindow=null) {
if (aWindow) {
return this._dispatchToolboxEventToWindow(aEventType, aDetails, aWindow);
this._dispatchToolboxEventToWindow(aEventType, aDetails, aWindow);
return;
}
for (let [win, ] of gBuildWindows) {
this._dispatchToolboxEventToWindow(aEventType, aDetails, win);
@ -2418,6 +2419,7 @@ var CustomizableUIInternal = {
aArgs);
} catch (e) {
Cu.reportError(e);
return undefined;
}
};
},
@ -3912,7 +3914,7 @@ function XULWidgetGroupWrapper(aWidgetId) {
});
this.__defineGetter__("instances", function() {
return Array.from(gBuildWindows, ([win,]) => this.forWindow(win));
return Array.from(gBuildWindows, (wins) => this.forWindow(wins[0]));
});
Object.freeze(this);

View File

@ -128,6 +128,7 @@ function checkBookmarksItemsChevronContextMenu() {
if (child.style.visibility != "hidden")
return true;
}
return false;
});
yield checkPlacesContextMenu(chevronPopup);
info("Waiting for bookmark toolbar item chevron popup to close");

View File

@ -58,6 +58,7 @@ support-files =
[browser_ext_windows_create.js]
tags = fullscreen
[browser_ext_windows_create_tabId.js]
[browser_ext_windows_events.js]
[browser_ext_windows.js]
[browser_ext_windows_size.js]
skip-if = os == 'mac' # Fails when windows are randomly opened in fullscreen mode

View File

@ -226,3 +226,34 @@ add_task(function* test_tab_options() {
yield BrowserTestUtils.removeTab(tab);
});
add_task(function* test_options_no_manifest() {
let extension = yield loadExtension({
manifest: {},
background: function() {
browser.test.log("Try to open options page when not specified in the manifest.");
browser.runtime.openOptionsPage().then(
() => {
browser.test.fail("Opening options page without one specified in the manifest generated an error");
browser.test.notifyFail("options-no-manifest");
},
error => {
let expected = "No `options_ui` declared";
browser.test.assertTrue(
error.message.includes(expected),
`Got expected error (got: '${error.message}', expected: '${expected}'`);
}
).then(() => {
browser.test.notifyPass("options-no-manifest");
}).catch(error => {
browser.test.log(`Error: ${error} :: ${error.stack}`);
browser.test.notifyFail("options-no-manifest");
});
},
});
yield extension.awaitFinish("options-no-manifest");
yield extension.unload();
});

View File

@ -13,6 +13,17 @@ add_task(function* testWindowCreate() {
});
};
let promiseTabUpdated = (expected) => {
return new Promise(resolve => {
browser.tabs.onUpdated.addListener(function listener(tabId, changeInfo, tab) {
if (changeInfo.url === expected) {
browser.tabs.onUpdated.removeListener(listener);
resolve();
}
});
});
};
let windowId;
browser.windows.getCurrent().then(window => {
windowId = window.id;
@ -85,6 +96,35 @@ add_task(function* testWindowCreate() {
browser.test.assertTrue(/`incognito` property must match the incognito state of tab/.test(error.message),
"Create call failed as expected");
});
}).then(() => {
browser.test.log("Try to create a window with an invalid tabId");
return browser.windows.create({tabId: 0}).then(
window => {
browser.test.fail("Create call should have failed");
},
error => {
browser.test.assertTrue(/Invalid tab ID: 0/.test(error.message),
"Create call failed as expected");
}
);
}).then(() => {
browser.test.log("Try to create a window with two URLs");
return browser.windows.create({url: ["http://example.com/", "http://example.org/"]});
}).then(window => {
return Promise.all([
promiseTabUpdated("http://example.com/"),
promiseTabUpdated("http://example.org/"),
Promise.resolve(window),
]);
}).then(([, , window]) => {
return browser.windows.get(window.id, {populate: true});
}).then(window => {
browser.test.assertEq(2, window.tabs.length, "2 tabs were opened in new window");
browser.test.assertEq("http://example.com/", window.tabs[0].url, "Correct URL was loaded in tab 1");
browser.test.assertEq("http://example.org/", window.tabs[1].url, "Correct URL was loaded in tab 2");
return browser.windows.remove(window.id);
}).then(() => {
browser.test.notifyPass("window-create");
}).catch(e => {

View File

@ -0,0 +1,39 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
add_task(function* testWindowsEvents() {
function background() {
browser.windows.onCreated.addListener(function listener(window) {
browser.windows.onCreated.removeListener(listener);
browser.test.assertTrue(Number.isInteger(window.id),
"Window object's id is an integer");
browser.test.assertEq("normal", window.type,
"Window object returned with the correct type");
browser.test.sendMessage("window-created", window.id);
});
browser.windows.onRemoved.addListener(function listener(windowId) {
browser.windows.onRemoved.removeListener(listener);
browser.test.assertTrue(Number.isInteger(windowId),
"windowId is an integer");
browser.test.sendMessage(`window-removed-${windowId}`);
browser.test.notifyPass("windows.events");
});
browser.test.sendMessage("ready");
}
let extension = ExtensionTestUtils.loadExtension({
background: `(${background})()`,
});
yield extension.startup();
yield extension.awaitMessage("ready");
let win1 = yield BrowserTestUtils.openNewBrowserWindow();
let windowId = yield extension.awaitMessage("window-created");
yield BrowserTestUtils.closeWindow(win1);
yield extension.awaitMessage(`window-removed-${windowId}`);
yield extension.awaitFinish("windows.events");
yield extension.unload();
});

View File

@ -3,6 +3,7 @@
<head>
<meta charset="utf-8">
<script type="application/javascript">
"use strict";
throw new Error(`WebExt Privilege Escalation: BrowserAction: typeof(browser) = ${typeof(browser)}`);
</script>
</head>

View File

@ -3,6 +3,7 @@
<head>
<meta charset="utf-8">
<script type="application/javascript">
"use strict";
throw new Error(`WebExt Privilege Escalation: PageAction: typeof(browser) = ${typeof(browser)}`);
</script>
</head>

View File

@ -78,10 +78,8 @@ function getBrowserActionPopup(extension, win = window) {
if (group.areaType == CustomizableUI.TYPE_TOOLBAR) {
return win.document.getElementById("customizationui-widget-panel");
} else {
return win.PanelUI.panel;
}
return null;
return win.PanelUI.panel;
}
var clickBrowserAction = Task.async(function* (extension, win = window) {

View File

@ -478,6 +478,7 @@ ESEDB.prototype = {
systemTime.wSecond,
systemTime.wMilliseconds));
}
return undefined;
},
_getColumnInfo(tableName, columns) {

View File

@ -872,6 +872,7 @@ WindowsVaultFormPasswords.prototype = {
if (aOnlyCheckExists) {
return false;
}
return undefined;
}
};

View File

@ -161,6 +161,7 @@ var MigrationWizard = {
else
this._selectedProfile = null;
}
return undefined;
},
// 2 - [Profile Selection]

View File

@ -1436,7 +1436,22 @@
BrowserSearch.searchBar.openSuggestionsPanel();
},
onError: function(errorCode) {
Components.utils.reportError("Error adding search engine: " + errorCode);
if (errorCode != Ci.nsISearchInstallCallback.ERROR_DUPLICATE_ENGINE) {
// Download error is shown by the search service
return;
}
const kSearchBundleURI = "chrome://global/locale/search/search.properties";
let searchBundle = Services.strings.createBundle(kSearchBundleURI);
let brandBundle = document.getElementById("bundle_brand");
let brandName = brandBundle.getString("brandShortName");
let title = searchBundle.GetStringFromName("error_invalid_engine_title");
let text = searchBundle.formatStringFromName("error_duplicate_engine_msg",
[brandName, target.getAttribute("uri")], 2);
Services.prompt.QueryInterface(Ci.nsIPromptFactory);
let prompt = Services.prompt.getPrompt(gBrowser.contentWindow, Ci.nsIPrompt);
prompt.QueryInterface(Ci.nsIWritablePropertyBag2);
prompt.setPropertyAsBool("allowTabModal", true);
prompt.alert(title, text);
}
}
Services.search.addEngine(target.getAttribute("uri"), null,

View File

@ -27,6 +27,7 @@ function waitForConditionPromise(condition, timeoutMsg, tryCount=NUMBER_OF_TRIES
}
tries++;
setTimeout(checkCondition, SINGLE_TRY_TIMEOUT);
return undefined;
}
setTimeout(checkCondition, SINGLE_TRY_TIMEOUT);
return defer.promise;

View File

@ -1822,6 +1822,7 @@ Experiments.ExperimentEntry.prototype = {
this._log.error("_installAddon() - onInstallStarted, wrong addon type");
return false;
}
return undefined;
},
onInstallEnded: install => {

View File

@ -1,3 +1,3 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 1.4.185
Current extension version is: 1.4.213

View File

@ -1023,14 +1023,18 @@ PdfStreamConverter.prototype = {
// Keep the URL the same so the browser sees it as the same.
channel.originalURI = aRequest.URI;
channel.loadGroup = aRequest.loadGroup;
channel.loadInfo.originAttributes = aRequest.loadInfo.originAttributes;
// We can use resource principal when data is fetched by the chrome
// make sure we reuse the origin attributes from the request channel to keep
// isolation consistent.
// e.g. useful for NoScript
var ssm = Cc['@mozilla.org/scriptsecuritymanager;1']
.getService(Ci.nsIScriptSecurityManager);
var uri = NetUtil.newURI(PDF_VIEWER_WEB_PAGE, null, null);
var attrs = aRequest.loadInfo.originAttributes;
var resourcePrincipal;
resourcePrincipal = ssm.createCodebasePrincipal(uri, {});
resourcePrincipal = ssm.createCodebasePrincipal(uri, attrs);
aRequest.owner = resourcePrincipal;
channel.asyncOpen(proxy, aContext);
},

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals PDFJS */
/* globals pdfjsLib */
'use strict';
@ -307,8 +307,8 @@ var Stepper = (function StepperClosure() {
this.table = table;
if (!opMap) {
opMap = Object.create(null);
for (var key in PDFJS.OPS) {
opMap[PDFJS.OPS[key]] = key;
for (var key in pdfjsLib.OPS) {
opMap[pdfjsLib.OPS[key]] = key;
}
}
},
@ -460,7 +460,7 @@ var Stats = (function Stats() {
manager: null,
init: function init() {
this.panel.setAttribute('style', 'padding: 5px;');
PDFJS.enableStats = true;
pdfjsLib.PDFJS.enableStats = true;
},
enabled: false,
active: false,

View File

@ -1,4 +1,4 @@
/* Copyright 2012 Mozilla Foundation
/* Copyright 2016 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -12,20 +12,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals PDFJS, PDFBug, FirefoxCom, Stats, ProgressBar, DownloadManager,
getPDFFileNameFromURL, PDFHistory, Preferences, SidebarView,
ViewHistory, Stats, PDFThumbnailViewer, URL, noContextMenuHandler,
SecondaryToolbar, PasswordPrompt, PDFPresentationMode, PDFSidebar,
PDFDocumentProperties, HandTool, Promise, PDFLinkService,
PDFOutlineViewer, PDFAttachmentViewer, OverlayManager,
PDFFindController, PDFFindBar, PDFViewer, PDFRenderingQueue,
PresentationModeState, parseQueryString, RenderingStates,
UNKNOWN_SCALE, DEFAULT_SCALE_VALUE,
IGNORE_CURRENT_POSITION_ON_ZOOM: true */
/*globals require, parseQueryString, chrome, PDFViewerApplication */
'use strict';
var DEFAULT_URL = 'compressed.tracemonkey-pldi-09.pdf';
var DEFAULT_SCALE_DELTA = 1.1;
var MIN_SCALE = 0.25;
var MAX_SCALE = 10.0;
@ -41,8 +34,6 @@ function configure(PDFJS) {
PDFJS.cMapPacked = true;
}
var mozL10n = document.mozL10n || document.webL10n;
var CSS_UNITS = 96.0 / 72.0;
var DEFAULT_SCALE_VALUE = 'auto';
@ -52,6 +43,56 @@ var MAX_AUTO_SCALE = 1.25;
var SCROLLBAR_PADDING = 40;
var VERTICAL_PADDING = 5;
var mozL10n = document.mozL10n || document.webL10n;
if (typeof PDFJS === 'undefined') {
(typeof window !== 'undefined' ? window : this).PDFJS = {};
}
/**
* Disables fullscreen support, and by extension Presentation Mode,
* in browsers which support the fullscreen API.
* @var {boolean}
*/
PDFJS.disableFullscreen = (PDFJS.disableFullscreen === undefined ?
false : PDFJS.disableFullscreen);
/**
* Enables CSS only zooming.
* @var {boolean}
*/
PDFJS.useOnlyCssZoom = (PDFJS.useOnlyCssZoom === undefined ?
false : PDFJS.useOnlyCssZoom);
/**
* The maximum supported canvas size in total pixels e.g. width * height.
* The default value is 4096 * 4096. Use -1 for no limit.
* @var {number}
*/
PDFJS.maxCanvasPixels = (PDFJS.maxCanvasPixels === undefined ?
16777216 : PDFJS.maxCanvasPixels);
/**
* Disables saving of the last position of the viewed PDF.
* @var {boolean}
*/
PDFJS.disableHistory = (PDFJS.disableHistory === undefined ?
false : PDFJS.disableHistory);
/**
* Disables creation of the text layer that used for text selection and search.
* @var {boolean}
*/
PDFJS.disableTextLayer = (PDFJS.disableTextLayer === undefined ?
false : PDFJS.disableTextLayer);
/**
* Disables maintaining the current position in the document when zooming.
*/
PDFJS.ignoreCurrentPositionOnZoom = (PDFJS.ignoreCurrentPositionOnZoom ===
undefined ? false : PDFJS.ignoreCurrentPositionOnZoom);
/**
* Returns scale factor for the canvas. It makes sense for the HiDPI displays.
* @return {Object} The object with horizontal (sx) and vertical (sy)
@ -585,9 +626,6 @@ var Preferences = {
var FirefoxCom = (function FirefoxComClosure() {
return {
/**
@ -659,7 +697,7 @@ var DownloadManager = (function DownloadManagerClosure() {
downloadData: function DownloadManager_downloadData(data, filename,
contentType) {
var blobUrl = PDFJS.createObjectURL(data, contentType);
var blobUrl = pdfjsLib.createObjectURL(data, contentType, false);
FirefoxCom.request('download', {
blobUrl: blobUrl,
@ -3000,7 +3038,7 @@ var PasswordPrompt = {
var promptString = mozL10n.get('password_label', null,
'Enter the password to open this PDF file.');
if (this.reason === PDFJS.PasswordResponses.INCORRECT_PASSWORD) {
if (this.reason === pdfjsLib.PasswordResponses.INCORRECT_PASSWORD) {
promptString = mozL10n.get('password_invalid', null,
'Invalid password. Please try again.');
}
@ -3241,7 +3279,6 @@ var PresentationModeState = {
FULLSCREEN: 3,
};
var IGNORE_CURRENT_POSITION_ON_ZOOM = false;
var DEFAULT_CACHE_SIZE = 10;
@ -3552,19 +3589,18 @@ var PDFPageView = (function PDFPageViewClosure() {
});
var isScalingRestricted = false;
if (this.canvas && PDFJS.maxCanvasPixels > 0) {
if (this.canvas && pdfjsLib.PDFJS.maxCanvasPixels > 0) {
var outputScale = this.outputScale;
var pixelsInViewport = this.viewport.width * this.viewport.height;
var maxScale = Math.sqrt(PDFJS.maxCanvasPixels / pixelsInViewport);
if (((Math.floor(this.viewport.width) * outputScale.sx) | 0) *
((Math.floor(this.viewport.height) * outputScale.sy) | 0) >
PDFJS.maxCanvasPixels) {
pdfjsLib.PDFJS.maxCanvasPixels) {
isScalingRestricted = true;
}
}
if (this.canvas) {
if (PDFJS.useOnlyCssZoom ||
if (pdfjsLib.PDFJS.useOnlyCssZoom ||
(this.hasRestrictedScaling && isScalingRestricted)) {
this.cssTransform(this.canvas, true);
@ -3598,7 +3634,7 @@ var PDFPageView = (function PDFPageViewClosure() {
},
cssTransform: function PDFPageView_transform(canvas, redrawAnnotations) {
var CustomStyle = PDFJS.CustomStyle;
var CustomStyle = pdfjsLib.CustomStyle;
// Scale canvas, canvas wrapper, and page container.
var width = this.viewport.width;
@ -3718,7 +3754,7 @@ var PDFPageView = (function PDFPageViewClosure() {
var outputScale = getOutputScale(ctx);
this.outputScale = outputScale;
if (PDFJS.useOnlyCssZoom) {
if (pdfjsLib.PDFJS.useOnlyCssZoom) {
var actualSizeViewport = viewport.clone({scale: CSS_UNITS});
// Use a scale that will make the canvas be the original intended size
// of the page.
@ -3727,9 +3763,10 @@ var PDFPageView = (function PDFPageViewClosure() {
outputScale.scaled = true;
}
if (PDFJS.maxCanvasPixels > 0) {
if (pdfjsLib.PDFJS.maxCanvasPixels > 0) {
var pixelsInViewport = viewport.width * viewport.height;
var maxScale = Math.sqrt(PDFJS.maxCanvasPixels / pixelsInViewport);
var maxScale =
Math.sqrt(pdfjsLib.PDFJS.maxCanvasPixels / pixelsInViewport);
if (outputScale.sx > maxScale || outputScale.sy > maxScale) {
outputScale.sx = maxScale;
outputScale.sy = maxScale;
@ -3896,7 +3933,7 @@ var PDFPageView = (function PDFPageViewClosure() {
},
beforePrint: function PDFPageView_beforePrint() {
var CustomStyle = PDFJS.CustomStyle;
var CustomStyle = pdfjsLib.CustomStyle;
var pdfPage = this.pdfPage;
var viewport = pdfPage.getViewport(1);
@ -4020,7 +4057,7 @@ var TextLayerBuilder = (function TextLayerBuilderClosure() {
this.textDivs = [];
var textLayerFrag = document.createDocumentFragment();
this.textLayerRenderTask = PDFJS.renderTextLayer({
this.textLayerRenderTask = pdfjsLib.renderTextLayer({
textContent: this.textContent,
container: textLayerFrag,
viewport: this.viewport,
@ -4323,7 +4360,7 @@ var AnnotationLayerBuilder = (function AnnotationLayerBuilderClosure() {
if (self.div) {
// If an annotationLayer already exists, refresh its children's
// transformation matrices.
PDFJS.AnnotationLayer.update(parameters);
pdfjsLib.AnnotationLayer.update(parameters);
} else {
// Create an annotation layer div and render the annotations
// if there is at least one annotation.
@ -4336,7 +4373,7 @@ var AnnotationLayerBuilder = (function AnnotationLayerBuilderClosure() {
self.pageDiv.appendChild(self.div);
parameters.div = self.div;
PDFJS.AnnotationLayer.render(parameters);
pdfjsLib.AnnotationLayer.render(parameters);
if (typeof mozL10n !== 'undefined') {
mozL10n.translate(self.div);
}
@ -4628,7 +4665,7 @@ var PDFViewer = (function pdfViewer() {
var viewport = pdfPage.getViewport(scale * CSS_UNITS);
for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
var textLayerFactory = null;
if (!PDFJS.disableTextLayer) {
if (!pdfjsLib.PDFJS.disableTextLayer) {
textLayerFactory = this;
}
var pageView = new PDFPageView({
@ -4650,7 +4687,7 @@ var PDFViewer = (function pdfViewer() {
// starts to create the correct size canvas. Wait until one page is
// rendered so we don't tie up too many resources early on.
onePageRendered.then(function () {
if (!PDFJS.disableAutoFetch) {
if (!pdfjsLib.PDFJS.disableAutoFetch) {
var getPagesLeft = pagesCount;
for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
pdfDocument.getPage(pageNum).then(function (pageNum, pdfPage) {
@ -4740,7 +4777,7 @@ var PDFViewer = (function pdfViewer() {
if (!noScroll) {
var page = this._currentPageNumber, dest;
if (this._location && !IGNORE_CURRENT_POSITION_ON_ZOOM &&
if (this._location && !pdfjsLib.PDFJS.ignoreCurrentPositionOnZoom &&
!(this.isInPresentationMode || this.isChangingPresentationMode)) {
page = this._location.pageNumber;
dest = [null, { name: 'XYZ' }, this._location.left,
@ -6074,7 +6111,7 @@ var PDFOutlineViewer = (function PDFOutlineViewerClosure() {
*/
_bindLink: function PDFOutlineViewer_bindLink(element, item) {
if (item.url) {
PDFJS.addLinkAttributes(element, { url: item.url });
pdfjsLib.addLinkAttributes(element, { url: item.url });
return;
}
var linkService = this.linkService;
@ -6183,7 +6220,7 @@ var PDFOutlineViewer = (function PDFOutlineViewerClosure() {
this._bindLink(element, item);
this._setStyles(element, item);
element.textContent =
PDFJS.removeNullCharacters(item.title) || DEFAULT_TITLE;
pdfjsLib.removeNullCharacters(item.title) || DEFAULT_TITLE;
div.appendChild(element);
@ -6297,12 +6334,12 @@ var PDFAttachmentViewer = (function PDFAttachmentViewerClosure() {
for (var i = 0; i < attachmentsCount; i++) {
var item = attachments[names[i]];
var filename = PDFJS.getFilenameFromUrl(item.filename);
var filename = pdfjsLib.getFilenameFromUrl(item.filename);
var div = document.createElement('div');
div.className = 'attachmentsItem';
var button = document.createElement('button');
this._bindLink(button, item.content, filename);
button.textContent = PDFJS.removeNullCharacters(filename);
button.textContent = pdfjsLib.removeNullCharacters(filename);
div.appendChild(button);
this.container.appendChild(div);
}
@ -6355,6 +6392,8 @@ var PDFViewerApplication = {
// called once when the document is loaded
initialize: function pdfViewInitialize() {
configure(pdfjsLib.PDFJS);
var pdfRenderingQueue = new PDFRenderingQueue();
pdfRenderingQueue.onIdle = this.cleanup.bind(this);
this.pdfRenderingQueue = pdfRenderingQueue;
@ -6508,6 +6547,7 @@ var PDFViewerApplication = {
this.pdfSidebar.onToggled = this.forceRendering.bind(this);
var self = this;
var PDFJS = pdfjsLib.PDFJS;
var initializedPromise = Promise.all([
Preferences.get('enableWebGL').then(function resolved(value) {
PDFJS.disableWebGL = !value;
@ -6574,6 +6614,10 @@ var PDFViewerApplication = {
});
},
run: function pdfViewRun() {
this.initialize().then(webViewerInitialized);
},
zoomIn: function pdfViewZoomIn(ticks) {
var newScale = this.pdfViewer.currentScale;
do {
@ -6610,7 +6654,7 @@ var PDFViewerApplication = {
var canvas = document.createElement('canvas');
var value = 'mozPrintCallback' in canvas;
return PDFJS.shadow(this, 'supportsPrinting', value);
return pdfjsLib.shadow(this, 'supportsPrinting', value);
},
get supportsFullscreen() {
@ -6624,38 +6668,38 @@ var PDFViewerApplication = {
document.msFullscreenEnabled === false) {
support = false;
}
if (support && PDFJS.disableFullscreen === true) {
if (support && pdfjsLib.PDFJS.disableFullscreen === true) {
support = false;
}
return PDFJS.shadow(this, 'supportsFullscreen', support);
return pdfjsLib.shadow(this, 'supportsFullscreen', support);
},
get supportsIntegratedFind() {
var support = false;
support = FirefoxCom.requestSync('supportsIntegratedFind');
return PDFJS.shadow(this, 'supportsIntegratedFind', support);
return pdfjsLib.shadow(this, 'supportsIntegratedFind', support);
},
get supportsDocumentFonts() {
var support = true;
support = FirefoxCom.requestSync('supportsDocumentFonts');
return PDFJS.shadow(this, 'supportsDocumentFonts', support);
return pdfjsLib.shadow(this, 'supportsDocumentFonts', support);
},
get supportsDocumentColors() {
var support = true;
support = FirefoxCom.requestSync('supportsDocumentColors');
return PDFJS.shadow(this, 'supportsDocumentColors', support);
return pdfjsLib.shadow(this, 'supportsDocumentColors', support);
},
get loadingBar() {
var bar = new ProgressBar('#loadingBar', {});
return PDFJS.shadow(this, 'loadingBar', bar);
return pdfjsLib.shadow(this, 'loadingBar', bar);
},
get supportedMouseWheelZoomModifierKeys() {
@ -6665,15 +6709,16 @@ var PDFViewerApplication = {
};
support = FirefoxCom.requestSync('supportedMouseWheelZoomModifierKeys');
return PDFJS.shadow(this, 'supportedMouseWheelZoomModifierKeys', support);
return pdfjsLib.shadow(this, 'supportedMouseWheelZoomModifierKeys',
support);
},
initPassiveLoading: function pdfViewInitPassiveLoading() {
function FirefoxComDataRangeTransport(length, initialData) {
PDFJS.PDFDataRangeTransport.call(this, length, initialData);
pdfjsLib.PDFDataRangeTransport.call(this, length, initialData);
}
FirefoxComDataRangeTransport.prototype =
Object.create(PDFJS.PDFDataRangeTransport.prototype);
Object.create(pdfjsLib.PDFDataRangeTransport.prototype);
FirefoxComDataRangeTransport.prototype.requestDataRange =
function FirefoxComDataRangeTransport_requestDataRange(begin, end) {
FirefoxCom.request('requestDataRange', { begin: begin, end: end });
@ -6738,7 +6783,8 @@ var PDFViewerApplication = {
setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
this.url = url;
try {
this.setTitle(decodeURIComponent(PDFJS.getFilenameFromUrl(url)) || url);
this.setTitle(decodeURIComponent(
pdfjsLib.getFilenameFromUrl(url)) || url);
} catch (e) {
// decodeURIComponent may throw URIError,
// fall back to using the unprocessed url in that case
@ -6849,7 +6895,7 @@ var PDFViewerApplication = {
var self = this;
self.downloadComplete = false;
var loadingTask = PDFJS.getDocument(parameters);
var loadingTask = pdfjsLib.getDocument(parameters);
this.pdfLoadingTask = loadingTask;
loadingTask.onPassword = function passwordNeeded(updatePassword, reason) {
@ -6874,15 +6920,15 @@ var PDFViewerApplication = {
var loadingErrorMessage = mozL10n.get('loading_error', null,
'An error occurred while loading the PDF.');
if (exception instanceof PDFJS.InvalidPDFException) {
if (exception instanceof pdfjsLib.InvalidPDFException) {
// change error message also for other builds
loadingErrorMessage = mozL10n.get('invalid_file_error', null,
'Invalid or corrupted PDF file.');
} else if (exception instanceof PDFJS.MissingPDFException) {
} else if (exception instanceof pdfjsLib.MissingPDFException) {
// special message for missing PDF's
loadingErrorMessage = mozL10n.get('missing_file_error', null,
'Missing PDF file.');
} else if (exception instanceof PDFJS.UnexpectedResponseException) {
} else if (exception instanceof pdfjsLib.UnexpectedResponseException) {
loadingErrorMessage = mozL10n.get('unexpected_response_error', null,
'Unexpected server response.');
}
@ -6928,7 +6974,7 @@ var PDFViewerApplication = {
this.pdfDocument.getData().then(
function getDataSuccess(data) {
var blob = PDFJS.createBlob(data, 'application/pdf');
var blob = pdfjsLib.createBlob(data, 'application/pdf');
downloadManager.download(blob, url, filename);
},
downloadByUrl // Error occurred try downloading with just the url.
@ -6961,7 +7007,7 @@ var PDFViewerApplication = {
*/
error: function pdfViewError(message, moreInfo) {
var moreInfoText = mozL10n.get('error_version_info',
{version: PDFJS.version || '?', build: PDFJS.build || '?'},
{version: pdfjsLib.version || '?', build: pdfjsLib.build || '?'},
'PDF.js v{{version}} (build: {{build}})') + '\n';
if (moreInfo) {
moreInfoText +=
@ -7003,7 +7049,7 @@ var PDFViewerApplication = {
// the loading bar will not be completely filled, nor will it be hidden.
// To prevent displaying a partially filled loading bar permanently, we
// hide it when no data has been loaded during a certain amount of time.
if (PDFJS.disableAutoFetch && percent) {
if (pdfjsLib.PDFJS.disableAutoFetch && percent) {
if (this.disableAutoFetchLoadingBarTimeout) {
clearTimeout(this.disableAutoFetchLoadingBarTimeout);
this.disableAutoFetchLoadingBarTimeout = null;
@ -7063,7 +7109,7 @@ var PDFViewerApplication = {
self.loadingBar.setWidth(document.getElementById('viewer'));
if (!PDFJS.disableHistory && !self.isViewerEmbedded) {
if (!pdfjsLib.PDFJS.disableHistory && !self.isViewerEmbedded) {
// The browsing history is only enabled when the viewer is standalone,
// i.e. not when it is embedded in a web page.
if (!self.preferenceShowPreviousViewOnLoad) {
@ -7136,7 +7182,7 @@ var PDFViewerApplication = {
pdfDocument.getJavaScript().then(function(javaScript) {
if (javaScript.length) {
console.warn('Warning: JavaScript is not supported');
self.fallback(PDFJS.UNSUPPORTED_FEATURES.javaScript);
self.fallback(pdfjsLib.UNSUPPORTED_FEATURES.javaScript);
}
// Hack to support auto printing.
var regex = /\bprint\s*\(/;
@ -7173,8 +7219,8 @@ var PDFViewerApplication = {
console.log('PDF ' + pdfDocument.fingerprint + ' [' +
info.PDFFormatVersion + ' ' + (info.Producer || '-').trim() +
' / ' + (info.Creator || '-').trim() + ']' +
' (PDF.js: ' + (PDFJS.version || '-') +
(!PDFJS.disableWebGL ? ' [WebGL]' : '') + ')');
' (PDF.js: ' + (pdfjsLib.version || '-') +
(!pdfjsLib.PDFJS.disableWebGL ? ' [WebGL]' : '') + ')');
var pdfTitle;
if (metadata && metadata.has('dc:title')) {
@ -7195,7 +7241,7 @@ var PDFViewerApplication = {
if (info.IsAcroFormPresent) {
console.warn('Warning: AcroForm/XFA is not supported');
self.fallback(PDFJS.UNSUPPORTED_FEATURES.forms);
self.fallback(pdfjsLib.UNSUPPORTED_FEATURES.forms);
}
var versionId = String(info.PDFFormatVersion).slice(-1) | 0;
@ -7398,18 +7444,13 @@ var PDFViewerApplication = {
};
function webViewerLoad(evt) {
configure(PDFJS);
PDFViewerApplication.initialize().then(webViewerInitialized);
}
function webViewerInitialized() {
var file = window.location.href.split('#')[0];
document.getElementById('openFile').setAttribute('hidden', 'true');
document.getElementById('secondaryOpenFile').setAttribute('hidden', 'true');
var PDFJS = pdfjsLib.PDFJS;
if (PDFViewerApplication.preferencePdfBugEnabled) {
// Special debugging flags in the hash section of the URL.
@ -7444,7 +7485,7 @@ function webViewerInitialized() {
PDFJS.verbosity = hashParams['verbosity'] | 0;
}
if ('ignorecurrentpositiononzoom' in hashParams) {
IGNORE_CURRENT_POSITION_ON_ZOOM =
PDFJS.ignoreCurrentPositionOnZoom =
(hashParams['ignorecurrentpositiononzoom'] === 'true');
}
if ('textlayer' in hashParams) {
@ -7565,8 +7606,6 @@ function webViewerInitialized() {
}
document.addEventListener('DOMContentLoaded', webViewerLoad, true);
document.addEventListener('pagerendered', function (e) {
var pageNumber = e.detail.pageNumber;
var pageIndex = pageNumber - 1;
@ -7579,7 +7618,7 @@ document.addEventListener('pagerendered', function (e) {
thumbnailView.setImage(pageView);
}
if (PDFJS.pdfBug && Stats.enabled && pageView.stats) {
if (pdfjsLib.PDFJS.pdfBug && Stats.enabled && pageView.stats) {
Stats.add(pageNumber, pageView.stats);
}
@ -7830,7 +7869,7 @@ window.addEventListener('pagechange', function pagechange(evt) {
document.getElementById('lastPage').disabled = (page >= numPages);
// we need to update stats
if (PDFJS.pdfBug && Stats.enabled) {
if (pdfjsLib.PDFJS.pdfBug && Stats.enabled) {
var pageView = PDFViewerApplication.pdfViewer.getPageView(page - 1);
if (pageView.stats) {
Stats.add(page, pageView.stats);
@ -7838,6 +7877,7 @@ window.addEventListener('pagechange', function pagechange(evt) {
}
}, true);
var zoomDisabled = false, zoomDisabledTimeout;
function handleMouseWheel(evt) {
var MOUSE_WHEEL_DELTA_FACTOR = 40;
var ticks = (evt.type === 'DOMMouseScroll') ? -evt.detail :
@ -7857,6 +7897,10 @@ function handleMouseWheel(evt) {
}
// Only zoom the pages, not the entire viewer.
evt.preventDefault();
// NOTE: this check must be placed *after* preventDefault.
if (zoomDisabled) {
return;
}
var previousScale = pdfViewer.currentScale;
@ -7874,6 +7918,12 @@ function handleMouseWheel(evt) {
pdfViewer.container.scrollLeft += dx * scaleCorrectionFactor;
pdfViewer.container.scrollTop += dy * scaleCorrectionFactor;
}
} else {
zoomDisabled = true;
clearTimeout(zoomDisabledTimeout);
zoomDisabledTimeout = setTimeout(function () {
zoomDisabled = false;
}, 1000);
}
}
@ -8138,3 +8188,12 @@ window.addEventListener('afterprint', function afterPrint(evt) {
});
})();
function webViewerLoad() {
window.pdfjsLib = window.pdfjsDistBuildPdf;
PDFViewerApplication.run();
}
document.addEventListener('DOMContentLoaded', webViewerLoad, true);

View File

@ -273,7 +273,7 @@ var PocketContextMenu = {
"accesskey": gPocketBundle.GetStringFromName("saveLinkToPocketCmd.accesskey"),
"oncommand": "Pocket.savePage(gContextMenu.browser, gContextMenu.linkURL);"
});
sibling = document.getElementById("context-savelink");
let sibling = document.getElementById("context-savelink");
if (sibling.nextSibling) {
sibling.parentNode.insertBefore(menu, sibling.nextSibling);
} else {
@ -360,6 +360,7 @@ function pktUIGetter(prop, window) {
get: function() {
// delete any getters for properties loaded from main.js so we only load main.js once
delete window.pktUI;
delete window.pktApi;
delete window.pktUIMessaging;
Services.scriptloader.loadSubScript("chrome://pocket/content/main.js", window);
return window[prop];
@ -402,6 +403,7 @@ var PocketOverlay = {
this.removeStyles(window);
// remove script getters/objects
delete window.Pocket;
delete window.pktApi;
delete window.pktUI;
delete window.pktUIMessaging;
}
@ -421,6 +423,7 @@ var PocketOverlay = {
"chrome://pocket/content/Pocket.jsm");
// Can't use XPCOMUtils for these because the scripts try to define the variables
// on window, and so the defineProperty inside defineLazyGetter fails.
Object.defineProperty(window, "pktApi", pktUIGetter("pktApi", window));
Object.defineProperty(window, "pktUI", pktUIGetter("pktUI", window));
Object.defineProperty(window, "pktUIMessaging", pktUIGetter("pktUIMessaging", window));
},

View File

@ -11,13 +11,20 @@ function checkElements(expectPresent, l) {
}
}
add_task(function*() {
let enabledOnStartup = yield promisePocketEnabled();
add_task(function* test_setup() {
let clearValue = Services.prefs.prefHasUserValue("extensions.pocket.enabled");
let enabledOnStartup = Services.prefs.getBoolPref("extensions.pocket.enabled");
registerCleanupFunction(() => {
// Extra insurance that this is disabled again, but it should have been set
// in promisePocketReset.
if (clearValue) {
Services.prefs.clearUserPref("extensions.pocket.enabled");
} else {
Services.prefs.setBoolPref("extensions.pocket.enabled", enabledOnStartup);
}
});
});
add_task(function*() {
yield promisePocketEnabled();
checkWindowProperties(true, ["Pocket", "pktUI", "pktUIMessaging"]);
checkElements(true, ["pocket-button", "panelMenu_pocket", "menu_pocket", "BMB_pocket",

View File

@ -21,6 +21,7 @@ function waitForConditionPromise(condition, timeoutMsg, tryCount=NUMBER_OF_TRIES
}
tries++;
setTimeout(checkCondition, SINGLE_TRY_TIMEOUT);
return undefined;
}
setTimeout(checkCondition, SINGLE_TRY_TIMEOUT);
return defer.promise;

View File

@ -69,6 +69,10 @@
background-image: linear-gradient(@toolbarHighlight@, @toolbarHighlight@);
}
#navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar):-moz-lwtheme {
background-image: linear-gradient(@toolbarHighlightLWT@, @toolbarHighlightLWT@);
}
#navigator-toolbox > toolbar:not(:-moz-lwtheme):not(#toolbar-menubar):not(#TabsToolbar) {
-moz-appearance: none;
border-style: none;
@ -108,6 +112,10 @@
padding-bottom: 2px;
}
#nav-bar:-moz-lwtheme {
box-shadow: 0 1px 0 @toolbarHighlightLWT@ inset;
}
#nav-bar-overflow-button {
-moz-image-region: rect(-5px, 12px, 11px, -4px);
}
@ -1789,7 +1797,13 @@ toolbarbutton.chevron > .toolbarbutton-icon {
%include ../shared/fullscreen/warning.inc.css
%include ../../../devtools/client/themes/responsivedesign.inc.css
%include ../../../devtools/client/themes/commandline.inc.css
%include ../shared/plugin-doorhanger.inc.css
notification.pluginVulnerable > .notification-inner > .messageCloseButton:not(:hover) {
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 80, 16, 64);
}
%include ../shared/login-doorhanger.inc.css
%include downloads/indicator.css

View File

@ -4,7 +4,8 @@
%filter substitution
%define toolbarHighlight rgba(255,255,255,.4)
%define toolbarHighlight hsla(0,0%,100%,.05)
%define toolbarHighlightLWT rgba(255,255,255,.4)
%define fgTabTexture linear-gradient(transparent 2px, @toolbarHighlight@ 2px, @toolbarHighlight@)
%define fgTabTextureLWT @fgTabTexture@
%define fgTabTextureLWT linear-gradient(transparent 2px, @toolbarHighlightLWT@ 2px, @toolbarHighlightLWT@)
%define fgTabBackgroundColor -moz-dialog

View File

@ -2501,7 +2501,19 @@ notification[value="translation"] {
%include ../shared/fullscreen/warning.inc.css
%include ../../../devtools/client/themes/responsivedesign.inc.css
%include ../../../devtools/client/themes/commandline.inc.css
%include ../shared/plugin-doorhanger.inc.css
notification.pluginVulnerable > .notification-inner > .messageCloseButton {
list-style-image: url("chrome://global/skin/icons/close-inverted.png");
}
@media (min-resolution: 1.1dppx) {
notification.pluginVulnerable > .notification-inner > .messageCloseButton {
list-style-image: url("chrome://global/skin/icons/close-inverted@2x.png");
}
}
%include ../shared/login-doorhanger.inc.css
%include downloads/indicator.css

View File

@ -24,6 +24,7 @@ this.TabsInTitlebar = {
return Promise.reject("TabsInTitlebar isn't supported on Linux");
}
Services.prefs.setBoolPref(PREF_TABS_IN_TITLEBAR, true);
return undefined;
}),
},

View File

@ -37,6 +37,7 @@ this.Toolbars = {
if (browserWindow.fullScreen) {
return Promise.reject("The bookmark toolbar and menubar are not shown in fullscreen.");
}
return undefined;
}),
},

View File

@ -71,7 +71,7 @@
// Enforce one true comma style.
"comma-style": [2, "last"],
// Warn about cyclomatic complexity in functions.
"complexity": 2,
"complexity": [2, 35],
// Require return statements to either always or never specify values.
"consistent-return": 2,
// Don't warn for inconsistent naming when capturing this (not so important
@ -177,8 +177,6 @@
"no-empty": 2,
// Disallow the use of empty character classes in regular expressions.
"no-empty-character-class": 2,
// Disallow use of labels for anything other then loops and switches.
"no-empty-label": 2,
// Disallow use of eval(). We have other APIs to evaluate code in content.
"no-eval": 2,
// Disallow assigning to the exception in a catch block.
@ -324,8 +322,8 @@
"sort-vars": 0,
// Deprecated, will be removed in 1.0.
"space-after-function-name": 0,
// Require a space after keywords.
"space-after-keywords": [2, "always"],
// Require a space around all keywords.
"keyword-spacing": 2,
// Require a space before the start brace of a block.
"space-before-blocks": [2, "always"],
// Deprecated, will be removed in 1.0.
@ -340,8 +338,6 @@
"space-in-parens": [2, "never"],
// Require spaces around operators, except for a|0.
"space-infix-ops": [2, {"int32Hint": true}],
// Require a space after return, throw, and case.
"space-return-throw-case": 2,
// Require spaces before/after unary operators (words on by default,
// nonwords off by default).
"space-unary-ops": [2, { "words": true, "nonwords": false }],
@ -396,7 +392,7 @@
// disallow labels that share a name with a variable
"no-label-var": 0,
// disallow use of labeled statements
"no-labels": 0,
"no-labels": 2,
// disallow unnecessary nested blocks
"no-lone-blocks": 0,
// disallow creation of functions within loops

View File

@ -47,20 +47,22 @@ button {
/* Targets */
.targets {
margin-bottom: 25px;
margin-bottom: 35px;
}
.target {
.target-container {
margin-top: 5px;
min-height: 34px;
display: flex;
flex-direction: row;
align-items: center;
align-items: baseline;
}
.target-icon {
height: 24px;
margin-right: 5px;
margin: 6px 5px 0 0;
/* override the icon alignment and center it using margin-top */
align-self: flex-start;
}
.target-icon:not([src]) {
@ -71,15 +73,55 @@ button {
filter: invert(30%);
}
.target-details {
.target {
flex: 1;
}
.target-details {
margin: 0;
padding: 0;
list-style-type: none
}
.target-detail {
font-size: 12px;
margin-top: 7px;
}
.target-detail a {
cursor: pointer;
}
.target-detail > :not(:first-child) {
margin-left: 8px;
}
.addons-controls {
display: flex;
flex-direction: row;
}
.addons-install-error {
background-color: #f3b0b0;
padding: 5px 10px;
margin: 5px 4px 5px 0px;
}
.addons-install-error .warning {
background-image: url(chrome://devtools/skin/images/alerticon-warning.png);
background-size: 13px 12px;
margin-right: 10px;
display: inline-block;
width: 13px;
height: 12px;
}
@media (min-resolution: 1.1dppx) {
.addons-install-error .warning {
background-image: url(chrome://devtools/skin/images/alerticon-warning@2x.png);
}
}
.addons-options {
flex: 1;
}

View File

@ -23,13 +23,13 @@ module.exports = createClass({
render() {
let { target, debugDisabled } = this.props;
return dom.div({ className: "target" },
return dom.div({ className: "target-container" },
dom.img({
className: "target-icon",
role: "presentation",
src: target.icon
}),
dom.div({ className: "target-details" },
dom.div({ className: "target" },
dom.div({ className: "target-name" }, target.name)
),
dom.button({

View File

@ -11,10 +11,12 @@ loader.lazyImporter(this, "AddonManager",
"resource://gre/modules/AddonManager.jsm");
const { Cc, Ci } = require("chrome");
const { createClass, DOM: dom } =
const { createFactory, createClass, DOM: dom } =
require("devtools/client/shared/vendor/react");
const Services = require("Services");
const AddonsInstallError = createFactory(require("./addons-install-error"));
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
@ -24,10 +26,17 @@ const MORE_INFO_URL = "https://developer.mozilla.org/docs/Tools" +
module.exports = createClass({
displayName: "AddonsControls",
getInitialState() {
return {
installError: null,
};
},
render() {
let { debugDisabled } = this.props;
return dom.div({ className: "addons-controls" },
return dom.div({ className: "addons-top" },
dom.div({ className: "addons-controls" },
dom.div({ className: "addons-options" },
dom.input({
id: "enable-addon-debugging",
@ -49,7 +58,8 @@ module.exports = createClass({
id: "load-addon-from-file",
onClick: this.loadAddonFromFile,
}, Strings.GetStringFromName("loadTemporaryAddon"))
);
),
AddonsInstallError({ error: this.state.installError }));
},
onEnableAddonDebuggingChange(event) {
@ -59,6 +69,7 @@ module.exports = createClass({
},
loadAddonFromFile() {
this.setState({ installError: null });
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(window,
Strings.GetStringFromName("selectAddonFromFile2"),
@ -73,11 +84,10 @@ module.exports = createClass({
if (!file.isDirectory() && !file.leafName.endsWith(".xpi")) {
file = file.parent;
}
try {
AddonManager.installTemporaryAddon(file);
} catch (e) {
window.alert("Error while installing the addon:\n" + e.message + "\n");
throw e;
}
AddonManager.installTemporaryAddon(file)
.catch(e => {
this.setState({ installError: e.message });
});
},
});

View File

@ -0,0 +1,22 @@
/* 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/. */
/* eslint-env browser */
"use strict";
const { createClass, DOM: dom } = require("devtools/client/shared/vendor/react");
module.exports = createClass({
displayName: "AddonsInstallError",
render() {
if (!this.props.error) {
return null;
}
let text = `There was an error during installation: ${this.props.error}`;
return dom.div({ className: "addons-install-error" },
dom.div({ className: "warning" }),
dom.span({}, text));
}
});

View File

@ -6,7 +6,9 @@ DevToolsModules(
'aboutdebugging.js',
'addon-target.js',
'addons-controls.js',
'addons-install-error.js',
'addons-tab.js',
'service-worker-target.js',
'tab-header.js',
'tab-menu-entry.js',
'tab-menu.js',

View File

@ -0,0 +1,111 @@
/* 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/. */
/* eslint-env browser */
"use strict";
const { createClass, DOM: dom } =
require("devtools/client/shared/vendor/react");
const { debugWorker } = require("../modules/worker");
const Services = require("Services");
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
module.exports = createClass({
displayName: "ServiceWorkerTarget",
render() {
let { target, debugDisabled } = this.props;
let isRunning = this.isRunning();
return dom.div({ className: "target-container" },
dom.img({
className: "target-icon",
role: "presentation",
src: target.icon
}),
dom.div({ className: "target" },
dom.div({ className: "target-name" }, target.name),
dom.ul({ className: "target-details" },
dom.li({ className: "target-detail" },
dom.strong(null, Strings.GetStringFromName("scope")),
dom.span({ className: "service-worker-scope" }, target.scope),
dom.a({
onClick: this.unregister,
className: "unregister-link"
}, Strings.GetStringFromName("unregister"))
)
)
),
(isRunning ?
[
dom.button({
className: "push-button",
onClick: this.push
}, Strings.GetStringFromName("push")),
dom.button({
className: "debug-button",
onClick: this.debug,
disabled: debugDisabled
}, Strings.GetStringFromName("debug"))
] :
dom.button({
className: "start-button",
onClick: this.start
}, Strings.GetStringFromName("start"))
)
);
},
debug() {
if (!this.isRunning()) {
// If the worker is not running, we can't debug it.
return;
}
let { client, target } = this.props;
debugWorker(client, target.workerActor);
},
push() {
if (!this.isRunning()) {
// If the worker is not running, we can't push to it.
return;
}
let { client, target } = this.props;
client.request({
to: target.workerActor,
type: "push"
});
},
start() {
if (this.isRunning()) {
// If the worker is already running, we can't start it.
return;
}
let { client, target } = this.props;
client.request({
to: target.registrationActor,
type: "start"
});
},
unregister() {
let { client, target } = this.props;
client.request({
to: target.registrationActor,
type: "unregister"
});
},
isRunning() {
// We know the target is running if it has a worker actor.
return !!this.props.target.workerActor;
},
});

View File

@ -3,19 +3,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-env browser */
/* globals gDevTools, TargetFactory, Toolbox */
"use strict";
loader.lazyRequireGetter(this, "gDevTools",
"devtools/client/framework/devtools", true);
loader.lazyRequireGetter(this, "TargetFactory",
"devtools/client/framework/target", true);
loader.lazyRequireGetter(this, "Toolbox",
"devtools/client/framework/toolbox", true);
const { createClass, DOM: dom } =
require("devtools/client/shared/vendor/react");
const { debugWorker } = require("../modules/worker");
const Services = require("Services");
const Strings = Services.strings.createBundle(
@ -26,86 +19,26 @@ module.exports = createClass({
render() {
let { target, debugDisabled } = this.props;
let isRunning = this.isRunning();
let isServiceWorker = this.isServiceWorker();
return dom.div({ className: "target" },
return dom.div({ className: "target-container" },
dom.img({
className: "target-icon",
role: "presentation",
src: target.icon
}),
dom.div({ className: "target-details" },
dom.div({ className: "target" },
dom.div({ className: "target-name" }, target.name)
),
(isRunning && isServiceWorker ?
dom.button({
className: "push-button",
onClick: this.push
}, Strings.GetStringFromName("push")) :
null
),
(isRunning ?
dom.button({
className: "debug-button",
onClick: this.debug,
disabled: debugDisabled
}, Strings.GetStringFromName("debug")) :
dom.button({
className: "start-button",
onClick: this.start
}, Strings.GetStringFromName("start"))
)
}, Strings.GetStringFromName("debug"))
);
},
debug() {
let { client, target } = this.props;
if (!this.isRunning()) {
// If the worker is not running, we can't debug it.
return;
debugWorker(client, target.workerActor);
}
client.attachWorker(target.workerActor, (response, workerClient) => {
let workerTarget = TargetFactory.forWorker(workerClient);
gDevTools.showToolbox(workerTarget, "jsdebugger", Toolbox.HostType.WINDOW)
.then(toolbox => {
toolbox.once("destroy", () => workerClient.detach());
});
});
},
push() {
let { client, target } = this.props;
if (!this.isRunning()) {
// If the worker is not running, we can't push to it.
return;
}
client.request({
to: target.workerActor,
type: "push"
});
},
start() {
let { client, target } = this.props;
if (!this.isServiceWorker() || this.isRunning()) {
// Either the worker is already running, or it's not a service worker, in
// which case we don't know how to start it.
return;
}
client.request({
to: target.registrationActor,
type: "start"
});
},
isRunning() {
// We know the target is running if it has a worker actor.
return !!this.props.target.workerActor;
},
isServiceWorker() {
// We know the target is a service worker if it has a registration actor.
return !!this.props.target.registrationActor;
},
});

View File

@ -7,12 +7,13 @@
const { Ci } = require("chrome");
const { createClass, createFactory, DOM: dom } =
require("devtools/client/shared/vendor/react");
const { Task } = require("resource://gre/modules/Task.jsm");
const { getWorkerForms } = require("../modules/worker");
const Services = require("Services");
const TabHeader = createFactory(require("./tab-header"));
const TargetList = createFactory(require("./target-list"));
const WorkerTarget = createFactory(require("./worker-target"));
const ServiceWorkerTarget = createFactory(require("./service-worker-target"));
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
@ -50,7 +51,6 @@ module.exports = createClass({
render() {
let { client } = this.props;
let { workers } = this.state;
let targetClass = WorkerTarget;
return dom.div({
id: "tab-workers",
@ -67,21 +67,21 @@ module.exports = createClass({
client,
id: "service-workers",
name: Strings.GetStringFromName("serviceWorkers"),
targetClass,
targetClass: ServiceWorkerTarget,
targets: workers.service
}),
TargetList({
client,
id: "shared-workers",
name: Strings.GetStringFromName("sharedWorkers"),
targetClass,
targetClass: WorkerTarget,
targets: workers.shared
}),
TargetList({
client,
id: "other-workers",
name: Strings.GetStringFromName("otherWorkers"),
targetClass,
targetClass: WorkerTarget,
targets: workers.other
})
));
@ -90,7 +90,7 @@ module.exports = createClass({
update() {
let workers = this.getInitialState().workers;
this.getWorkerForms().then(forms => {
getWorkerForms(this.props.client).then(forms => {
forms.registrations.forEach(form => {
workers.service.push({
icon: WorkerIcon,
@ -136,40 +136,5 @@ module.exports = createClass({
this.setState({ workers });
});
},
getWorkerForms: Task.async(function*() {
let client = this.props.client;
let registrations = [];
let workers = [];
try {
// List service worker registrations
({ registrations } =
yield client.mainRoot.listServiceWorkerRegistrations());
// List workers from the Parent process
({ workers } = yield client.mainRoot.listWorkers());
// And then from the Child processes
let { processes } = yield client.mainRoot.listProcesses();
for (let process of processes) {
// Ignore parent process
if (process.parent) {
continue;
}
let { form } = yield client.getProcess(process.id);
let processActor = form.actor;
let response = yield client.request({
to: processActor,
type: "listWorkers"
});
workers = workers.concat(response.workers);
}
} catch (e) {
// Something went wrong, maybe our client is disconnected?
}
return { registrations, workers };
}),
});

View File

@ -0,0 +1,7 @@
# 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/.
DevToolsModules(
'worker.js',
)

View File

@ -0,0 +1,77 @@
/* 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 { Task } = require("resource://gre/modules/Task.jsm");
loader.lazyRequireGetter(this, "gDevTools",
"devtools/client/framework/devtools", true);
loader.lazyRequireGetter(this, "TargetFactory",
"devtools/client/framework/target", true);
loader.lazyRequireGetter(this, "Toolbox",
"devtools/client/framework/toolbox", true);
/**
* Open a window-hosted toolbox to debug the worker associated to the provided
* worker actor.
*
* @param {DebuggerClient} client
* @param {Object} workerActor
* worker actor form to debug
*/
exports.debugWorker = function(client, workerActor) {
client.attachWorker(workerActor, (response, workerClient) => {
let workerTarget = TargetFactory.forWorker(workerClient);
gDevTools.showToolbox(workerTarget, "jsdebugger", Toolbox.HostType.WINDOW)
.then(toolbox => {
toolbox.once("destroy", () => workerClient.detach());
});
});
};
/**
* Retrieve all service worker registrations as well as workers from the parent
* and child processes.
*
* @param {DebuggerClient} client
* @return {Object}
* - {Array} registrations
* Array of ServiceWorkerRegistrationActor forms
* - {Array} workers
* Array of WorkerActor forms
*/
exports.getWorkerForms = Task.async(function* (client) {
let registrations = [];
let workers = [];
try {
// List service worker registrations
({ registrations } =
yield client.mainRoot.listServiceWorkerRegistrations());
// List workers from the Parent process
({ workers } = yield client.mainRoot.listWorkers());
// And then from the Child processes
let { processes } = yield client.mainRoot.listProcesses();
for (let process of processes) {
// Ignore parent process
if (process.parent) {
continue;
}
let { form } = yield client.getProcess(process.id);
let processActor = form.actor;
let response = yield client.request({
to: processActor,
type: "listWorkers"
});
workers = workers.concat(response.workers);
}
} catch (e) {
// Something went wrong, maybe our client is disconnected?
}
return { registrations, workers };
});

View File

@ -6,6 +6,7 @@
DIRS += [
'components',
'modules',
]
BROWSER_CHROME_MANIFESTS += [

View File

@ -0,0 +1 @@
this is not valid json

View File

@ -5,6 +5,7 @@ support-files =
head.js
addons/unpacked/bootstrap.js
addons/unpacked/install.rdf
addons/bad/manifest.json
service-workers/empty-sw.html
service-workers/empty-sw.js
service-workers/push-sw.html
@ -17,4 +18,5 @@ support-files =
[browser_service_workers_push.js]
[browser_service_workers_start.js]
[browser_service_workers_timeout.js]
[browser_service_workers_unregister.js]
skip-if = true # Bug 1232931

View File

@ -28,3 +28,30 @@ add_task(function* () {
yield closeAboutDebugging(tab);
});
add_task(function* () {
let { tab, document } = yield openAboutDebugging("addons");
// Start an observer that looks for the install error before
// actually doing the install
let top = document.querySelector(".addons-top");
let promise = waitForMutation(top, { childList: true });
// Mock the file picker to select a test addon
let MockFilePicker = SpecialPowers.MockFilePicker;
MockFilePicker.init(null);
let file = getSupportsFile("addons/bad/manifest.json");
MockFilePicker.returnFiles = [file.file];
// Trigger the file picker by clicking on the button
document.getElementById("load-addon-from-file").click();
// Now wait for the install error to appear.
yield promise;
// And check that it really is there.
let err = document.querySelector(".addons-install-error");
isnot(err, null, "Addon install error message appeared");
yield closeAboutDebugging(tab);
});

View File

@ -0,0 +1,77 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-disable mozilla/no-cpows-in-tests */
/* global sendAsyncMessage */
"use strict";
// Test that clicking on the unregister link in the Service Worker details works
// as intended in about:debugging.
// It should unregister the service worker, which should trigger an update of
// the displayed list of service workers.
// Service workers can't be loaded from chrome://, but http:// is ok with
// dom.serviceWorkers.testing.enabled turned on.
const HTTP_ROOT = CHROME_ROOT.replace(
"chrome://mochitests/content/", "http://mochi.test:8888/");
const SCOPE = HTTP_ROOT + "service-workers/";
const SERVICE_WORKER = SCOPE + "empty-sw.js";
const TAB_URL = SCOPE + "empty-sw.html";
add_task(function* () {
info("Turn on workers via mochitest http.");
yield new Promise(done => {
let options = { "set": [
// Accept workers from mochitest's http.
["dom.serviceWorkers.testing.enabled", true],
]};
SpecialPowers.pushPrefEnv(options, done);
});
let { tab, document } = yield openAboutDebugging("workers");
// Listen for mutations in the service-workers list.
let serviceWorkersElement = document.getElementById("service-workers");
let onMutation = waitForMutation(serviceWorkersElement, { childList: true });
// Open a tab that registers an empty service worker.
let swTab = yield addTab(TAB_URL);
// Wait for the service workers-list to update.
yield onMutation;
// Check that the service worker appears in the UI.
assertHasTarget(true, document, "service-workers", SERVICE_WORKER);
info("Ensure that the registration resolved before trying to interact with " +
"the service worker.");
yield waitForServiceWorkerRegistered(swTab);
ok(true, "Service worker registration resolved");
let targets = document.querySelectorAll("#service-workers .target");
is(targets.length, 1, "One service worker is now displayed.");
let target = targets[0];
let name = target.querySelector(".target-name");
is(name.textContent, SERVICE_WORKER, "Found the service worker in the list");
info("Check the scope displayed scope is correct");
let scope = target.querySelector(".service-worker-scope");
is(scope.textContent, SCOPE,
"The expected scope is displayed in the service worker info.");
info("Unregister the service worker via the unregister link.");
let unregisterLink = target.querySelector(".unregister-link");
ok(unregisterLink, "Found the unregister link");
onMutation = waitForMutation(serviceWorkersElement, { childList: true });
unregisterLink.click();
yield onMutation;
is(document.querySelector("#service-workers .target"), null,
"No service worker displayed anymore.");
yield removeTab(swTab);
yield closeAboutDebugging(tab);
});

View File

@ -280,7 +280,9 @@ var AnimationsPanel = {
this.setCurrentTimeAllPromise =
AnimationsController.setCurrentTimeAll(time, true)
.catch(error => console.error(error))
.then(() => this.setCurrentTimeAllPromise = null);
.then(() => {
this.setCurrentTimeAllPromise = null;
});
}
this.displayTimelineCurrentTime();

View File

@ -16,45 +16,54 @@
<div id="target3" class="target"></div>
<div id="target4" class="target"></div>
<script>
/* globals KeyframeEffect, Animation */
"use strict";
var el = document.getElementById("target1");
el.animate(
{ opacity: [ 0, 1 ] },
{ id: "endDelay_animation1",
let animations = [{
id: "target1",
frames: [{ opacity: 0, offset: 0 }, { opacity: 1, offset: 1 }],
timing: {
id: "endDelay_animation1",
duration: 1000000,
endDelay: 500000,
fill: "none" }
);
el = document.getElementById("target2");
el.animate(
{ opacity: [ 0, 1 ] },
{ id: "endDelay_animation2",
fill: "none"
}
}, {
id: "target2",
frames: [{ opacity: 0, offset: 0 }, { opacity: 1, offset: 1 }],
timing: {
id: "endDelay_animation2",
duration: 1000000,
endDelay: -500000,
fill: "none" }
);
el = document.getElementById("target3");
el.animate(
{ opacity: [ 0, 1 ] },
{ id: "endDelay_animation3",
fill: "none"
}
}, {
id: "target3",
frames: [{ opacity: 0, offset: 0 }, { opacity: 1, offset: 1 }],
timing: {
id: "endDelay_animation3",
duration: 1000000,
endDelay: -1500000,
fill: "forwards" }
);
el = document.getElementById("target4");
el.animate(
{ opacity: [ 0, 1 ] },
{ id: "endDelay_animation4",
fill: "forwards"
}
}, {
id: "target4",
frames: [{ opacity: 0, offset: 0 }, { opacity: 1, offset: 1 }],
timing: {
id: "endDelay_animation4",
duration: 100000,
delay: 100000,
endDelay: -1500000,
fill: "forwards" }
);
fill: "forwards"
}
}];
for (let {id, frames, timing} of animations) {
let effect = new KeyframeEffect(document.getElementById(id),
frames, timing);
let animation = new Animation(effect, document.timeline);
animation.play();
}
</script>
</body>
</html>

View File

@ -42,19 +42,20 @@
<div class="ball css-transition"></div>
<script>
/* globals KeyframeEffect, Animation */
"use strict";
setTimeout(function() {
document.querySelector(".css-transition").style.backgroundColor = "yellow";
}, 0);
document.querySelector(".script-animation").animate([
let effect = new KeyframeEffect(
document.querySelector(".script-animation"), [
{opacity: 1, offset: 0},
{opacity: .1, offset: 1}
], {
duration: 10000,
fill: "forwards"
});
], { duration: 10000, fill: "forwards" });
let animation = new Animation(effect, document.timeline);
animation.play();
</script>
</body>
</html>

View File

@ -28,28 +28,44 @@
<div id="target3"></div>
<script>
/* globals KeyframeEffect, Animation */
"use strict";
document.getElementById("target1").animate([{ opacity: 0 }, { opacity: 1 }],
{ duration: 100,
let animations = [{
id: "target1",
frames: [{ opacity: 0, offset: 0 }, { opacity: 1, offset: 1 }],
timing: {
duration: 100,
iterations: 2,
iterationStart: 0.25,
fill: "both" }
);
document.getElementById("target2").animate([{ opacity: 0 }, { opacity: 1 }],
{ duration: 100,
fill: "both"
}
}, {
id: "target2",
frames: [{ opacity: 0, offset: 0 }, { opacity: 1, offset: 1 }],
timing: {
duration: 100,
iterations: 1,
iterationStart: 0.25,
fill: "both" }
);
document.getElementById("target3").animate([{ opacity: 0 }, { opacity: 1 }],
{ duration: 100,
fill: "both"
}
}, {
id: "target3",
frames: [{ opacity: 0, offset: 0 }, { opacity: 1, offset: 1 }],
timing: {
duration: 100,
iterations: 1.5,
iterationStart: 2.5,
fill: "both" }
);
fill: "both"
}
}];
for (let {id, frames, timing} of animations) {
let effect = new KeyframeEffect(document.getElementById(id),
frames, timing);
let animation = new Animation(effect, document.timeline);
animation.play();
}
</script>
</body>
</html>

View File

@ -114,15 +114,16 @@
<div class="ball no-compositor"></div>
<div class="ball" id="endDelayed"></div>
<script>
/* globals KeyframeEffect, Animation */
"use strict";
var el = document.getElementById("endDelayed");
el.animate(
{ opacity: [ 0, 1 ] },
{ duration: 1000000,
endDelay: 500000,
fill: "none" }
);
let effect = new KeyframeEffect(el, [
{ opacity: 0, offset: 0 },
{ opacity: 1, offset: 1 }
], { duration: 1000000, endDelay: 500000, fill: "none" });
let animation = new Animation(effect, document.timeline);
animation.play();
</script>
</body>
</html>

View File

@ -265,7 +265,9 @@ function* assertScrubberMoving(panel, isMoving) {
// If instead we expect the scrubber to remain at its position, just wait
// for some time and make sure timeline-data-changed isn't emitted.
let hasMoved = false;
timeline.once("timeline-data-changed", () => hasMoved = true);
timeline.once("timeline-data-changed", () => {
hasMoved = true;
});
yield new Promise(r => setTimeout(r, 500));
ok(!hasMoved, "The scrubber is not moving");
}

View File

@ -0,0 +1,54 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
https://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const Cu = Components.utils;
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
const {TimeScale} = require("devtools/client/animationinspector/utils");
const TEST_ENDDELAY_X = [{
desc: "Testing positive-endDelay animations",
animations: [{
previousStartTime: 0,
duration: 500,
playbackRate: 1,
iterationCount: 3,
delay: 500,
endDelay: 500
}],
expectedEndDelayX: 80
}, {
desc: "Testing negative-endDelay animations",
animations: [{
previousStartTime: 0,
duration: 500,
playbackRate: 1,
iterationCount: 9,
delay: 500,
endDelay: -500
}],
expectedEndDelayX: 90
}];
function run_test() {
do_print("Test calculating endDelayX");
// Be independent of possible prior tests
TimeScale.reset();
for (let {desc, animations, expectedEndDelayX} of TEST_ENDDELAY_X) {
do_print(`Adding animations: ${desc}`);
for (let state of animations) {
TimeScale.addAnimation(state);
let {endDelayX} = TimeScale.getAnimationDimensions({state});
equal(endDelayX, expectedEndDelayX);
TimeScale.reset();
}
}
}

View File

@ -9,3 +9,4 @@ skip-if = toolkit == 'android' || toolkit == 'gonk'
[test_formatStopwatchTime.js]
[test_getCssPropertyName.js]
[test_timeScale.js]
[test_timeScale_dimensions.js]

View File

@ -328,7 +328,8 @@ var TimeScale = {
// The width of the endDelay.
let endDelayW = this.durationToDistance(Math.abs(endDelay) / rate);
// The start position of the endDelay.
let endDelayX = endDelay < 0 ? x + w - endDelayW : x + w;
let endDelayX = endDelay < 0 ? x + iterationW - endDelayW
: x + iterationW;
return {x, w, iterationW, delayX, delayW, negativeDelayW,
endDelayX, endDelayW};

View File

@ -431,7 +431,6 @@ var DebuggerView = {
this.editor.clearDebugLocation();
this.editor.clearHistory();
this.editor.setCursor({ line: 0, ch: 0});
this.editor.removeBreakpoints();
// Only set editor's text and mode if it is a new document

View File

@ -336,6 +336,9 @@ skip-if = e10s && debug
[browser_dbg_parser-10.js]
skip-if = e10s && debug
[browser_dbg_parser-11.js]
[browser_dbg_parser-function-defaults.js]
[browser_dbg_parser-spread-expression.js]
[browser_dbg_parser-template-strings.js]
skip-if = e10s && debug
[browser_dbg_pause-exceptions-01.js]
skip-if = e10s && debug
@ -608,4 +611,4 @@ skip-if = e10s && debug
[browser_dbg_WorkerActor.attachThread.js]
skip-if = e10s && debug
[browser_dbg_split-console-keypress.js]
skip-if = e10s && debug
skip-if = e10s && (debug || os == "linux") # Bug 1214439

View File

@ -79,7 +79,7 @@ function test() {
yield verifyView({ disabled: false });
executeSoon(() => gDebugger.gThreadClient.resume());
yield waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1);
yield waitForSourceAndCaretAndScopes(gPanel, "-02.js", 6);
yield verifyView({ disabled: false });
});
}
@ -94,7 +94,7 @@ function test() {
yield verifyView({ disabled: false });
executeSoon(() => gDebugger.gThreadClient.resume());
yield waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1);
yield waitForSourceAndCaretAndScopes(gPanel, "-02.js", 6);
yield verifyView({ disabled: false });
});
}

View File

@ -152,10 +152,7 @@ function test() {
is(gEditor.getBreakpoints().length, 1,
"One breakpoint should be shown for the first source.");
//yield waitForTime(2000);
yield ensureCaretAt(gPanel, 1, 1, true);
//yield waitForTime(50000);
yield ensureCaretAt(gPanel, 6, 1, true);
resumeDebuggerThenCloseAndFinish(gPanel);
});

View File

@ -0,0 +1,31 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that function default arguments are correctly processed.
*/
"use strict";
function test() {
let { Parser, ParserHelpers, SyntaxTreeVisitor } =
Cu.import("resource://devtools/shared/Parser.jsm", {});
function verify(source, predicate, string) {
let ast = Parser.reflectionAPI.parse(source);
let node = SyntaxTreeVisitor.filter(ast, predicate).pop();
let info = ParserHelpers.getIdentifierEvalString(node);
is(info, string, "The identifier evaluation string is correct.");
}
// FunctionDeclaration
verify("function foo(a, b='b') {}", e => e.type == "Literal", "\"b\"");
// FunctionExpression
verify("let foo=function(a, b='b') {}", e => e.type == "Literal", "\"b\"");
// ArrowFunctionExpression
verify("let foo=(a, b='b')=> {}", e => e.type == "Literal", "\"b\"");
finish();
}

View File

@ -0,0 +1,32 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that spread expressions work both in arrays and function calls.
*/
"use strict";
function test() {
let { Parser, SyntaxTreeVisitor } =
Cu.import("resource://devtools/shared/Parser.jsm", {});
const SCRIPTS = ["[...a]", "foo(...a)"];
for (let script of SCRIPTS) {
info(`Testing spread expression in '${script}'`);
let ast = Parser.reflectionAPI.parse(script);
let nodes = SyntaxTreeVisitor.filter(ast,
e => e.type == "SpreadExpression");
ok(nodes && nodes.length === 1, "Found the SpreadExpression node");
let expr = nodes[0].expression;
ok(expr, "The SpreadExpression node has the sub-expression");
is(expr.type, "Identifier", "The sub-expression is an Identifier");
is(expr.name, "a", "The sub-expression identifier has a correct name");
}
finish();
}

View File

@ -0,0 +1,29 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that template strings are correctly processed.
*/
"use strict";
function test() {
let { Parser, SyntaxTreeVisitor } =
Cu.import("resource://devtools/shared/Parser.jsm", {});
let ast = Parser.reflectionAPI.parse("`foo${i}bar`");
let nodes = SyntaxTreeVisitor.filter(ast, e => e.type == "TemplateLiteral");
ok(nodes && nodes.length === 1, "Found the TemplateLiteral node");
let elements = nodes[0].elements;
ok(elements, "The TemplateLiteral node has elements");
is(elements.length, 3, "There are 3 elements in the literal");
["Literal", "Identifier", "Literal"].forEach((type, i) => {
is(elements[i].type, type, `Element at index ${i} is '${type}'`);
});
finish();
}

View File

@ -24,44 +24,44 @@ function test() {
let deferred = promise.defer();
is(gSources.itemCount, 2,
"Found the expected number of sources.");
"Found the expected number of sources. (1)");
is(gSources.items[0].target.querySelector(".dbg-source-item").getAttribute("tooltiptext"),
EXAMPLE_URL + "code_script-switching-01.js",
"The correct tooltip text is displayed for the first source.");
"The correct tooltip text is displayed for the first source. (1)");
is(gSources.items[1].target.querySelector(".dbg-source-item").getAttribute("tooltiptext"),
EXAMPLE_URL + "code_script-switching-02.js",
"The correct tooltip text is displayed for the second source.");
"The correct tooltip text is displayed for the second source. (1)");
ok(getSourceActor(gSources, EXAMPLE_URL + gLabel1),
"First source url is incorrect.");
"First source url is incorrect. (1)");
ok(getSourceActor(gSources, EXAMPLE_URL + gLabel2),
"Second source url is incorrect.");
"Second source url is incorrect. (1)");
ok(gSources.getItemForAttachment(e => e.label == gLabel1),
"First source label is incorrect.");
"First source label is incorrect. (1)");
ok(gSources.getItemForAttachment(e => e.label == gLabel2),
"Second source label is incorrect.");
"Second source label is incorrect. (1)");
ok(gSources.selectedItem,
"There should be a selected item in the sources pane.");
"There should be a selected item in the sources pane. (1)");
is(getSelectedSourceURL(gSources), EXAMPLE_URL + gLabel2,
"The selected value is the sources pane is incorrect.");
"The selected value is the sources pane is incorrect. (1)");
is(gEditor.getText().search(/firstCall/), -1,
"The first source is not displayed.");
"The first source is not displayed. (1)");
is(gEditor.getText().search(/debugger/), 166,
"The second source is displayed.");
"The second source is displayed. (1)");
ok(gDebugger.document.title.endsWith(EXAMPLE_URL + gLabel2),
"Title with second source is correct.");
"Title with second source is correct. (1)");
ok(isCaretPos(gPanel, 6),
"Editor caret location is correct.");
"Editor caret location is correct. (1)");
// The editor's debug location takes a tick to update.
is(gEditor.getDebugLocation(), 5,
"Editor debugger location is correct.");
"Editor debugger location is correct. (1)");
ok(gEditor.hasLineClass(5, "debug-line"),
"The debugged line is highlighted appropriately (1).");
@ -75,22 +75,22 @@ function test() {
let deferred = promise.defer();
ok(gSources.selectedItem,
"There should be a selected item in the sources pane.");
"There should be a selected item in the sources pane. (2)");
is(getSelectedSourceURL(gSources), EXAMPLE_URL + gLabel1,
"The selected value is the sources pane is incorrect.");
"The selected value is the sources pane is incorrect. (2)");
is(gEditor.getText().search(/firstCall/), 118,
"The first source is displayed.");
"The first source is displayed. (2)");
is(gEditor.getText().search(/debugger/), -1,
"The second source is not displayed.");
"The second source is not displayed. (2)");
// The editor's debug location takes a tick to update.
ok(isCaretPos(gPanel, 1),
"Editor caret location is correct.");
"Editor caret location is correct. (2)");
is(gEditor.getDebugLocation(), null,
"Editor debugger location is correct.");
"Editor debugger location is correct. (2)");
ok(!gEditor.hasLineClass(5, "debug-line"),
"The debugged line highlight was removed.");
"The debugged line highlight was removed. (2)");
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_SHOWN).then(deferred.resolve);
gSources.selectedIndex = 1;
@ -101,21 +101,21 @@ function test() {
let deferred = promise.defer();
ok(gSources.selectedItem,
"There should be a selected item in the sources pane.");
"There should be a selected item in the sources pane. (3)");
is(getSelectedSourceURL(gSources), EXAMPLE_URL + gLabel2,
"The selected value is the sources pane is incorrect.");
"The selected value is the sources pane is incorrect. (3)");
is(gEditor.getText().search(/firstCall/), -1,
"The first source is not displayed.");
"The first source is not displayed. (3)");
is(gEditor.getText().search(/debugger/), 166,
"The second source is displayed.");
"The second source is displayed. (3)");
ok(isCaretPos(gPanel, 1),
"Editor caret location is correct.");
ok(isCaretPos(gPanel, 6),
"Editor caret location is correct. (3)");
is(gEditor.getDebugLocation(), 5,
"Editor debugger location is correct.");
"Editor debugger location is correct. (3)");
ok(gEditor.hasLineClass(5, "debug-line"),
"The debugged line is highlighted appropriately (2).");
"The debugged line is highlighted appropriately (3).");
// Step out twice.
waitForThreadEvents(gPanel, "paused").then(() => {
@ -129,21 +129,21 @@ function test() {
function testSwitchRunning() {
ok(gSources.selectedItem,
"There should be a selected item in the sources pane.");
"There should be a selected item in the sources pane. (4)");
is(getSelectedSourceURL(gSources), EXAMPLE_URL + gLabel1,
"The selected value is the sources pane is incorrect.");
"The selected value is the sources pane is incorrect. (4)");
is(gEditor.getText().search(/firstCall/), 118,
"The first source is displayed.");
"The first source is displayed. (4)");
is(gEditor.getText().search(/debugger/), -1,
"The second source is not displayed.");
"The second source is not displayed. (4)");
ok(isCaretPos(gPanel, 6),
"Editor caret location is correct.");
"Editor caret location is correct. (4)");
is(gEditor.getDebugLocation(), 5,
"Editor debugger location is correct.");
"Editor debugger location is correct. (4)");
ok(gEditor.hasLineClass(5, "debug-line"),
"The debugged line is highlighted appropriately (3).");
"The debugged line is highlighted appropriately (3). (4)");
}
Task.spawn(function*() {

View File

@ -25,34 +25,34 @@ function test() {
let deferred = promise.defer();
is(gSources.itemCount, 2,
"Found the expected number of sources.");
"Found the expected number of sources. (1)");
ok(getSourceActor(gSources, EXAMPLE_URL + gLabel1),
"First source url is incorrect.");
"First source url is incorrect. (1)");
ok(getSourceActor(gSources, EXAMPLE_URL + gLabel2 + gParams),
"Second source url is incorrect.");
"Second source url is incorrect. (1)");
ok(gSources.getItemForAttachment(e => e.label == gLabel1),
"First source label is incorrect.");
"First source label is incorrect. (1)");
ok(gSources.getItemForAttachment(e => e.label == gLabel2),
"Second source label is incorrect.");
"Second source label is incorrect. (1)");
ok(gSources.selectedItem,
"There should be a selected item in the sources pane.");
"There should be a selected item in the sources pane. (1)");
is(getSelectedSourceURL(gSources), EXAMPLE_URL + gLabel2 + gParams,
"The selected value is the sources pane is incorrect.");
"The selected value is the sources pane is incorrect. (1)");
is(gEditor.getText().search(/firstCall/), -1,
"The first source is not displayed.");
"The first source is not displayed. (1)");
is(gEditor.getText().search(/debugger/), 166,
"The second source is displayed.");
"The second source is displayed. (1)");
ok(isCaretPos(gPanel, 6),
"Editor caret location is correct.");
"Editor caret location is correct. (1)");
is(gEditor.getDebugLocation(), 5,
"Editor debugger location is correct.");
"Editor debugger location is correct. (1)");
ok(gEditor.hasLineClass(5, "debug-line"),
"The debugged line is highlighted appropriately.");
"The debugged line is highlighted appropriately. (1)");
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_SHOWN).then(deferred.resolve);
gSources.selectedItem = e => e.attachment.label == gLabel1;
@ -64,23 +64,23 @@ function test() {
let deferred = promise.defer();
ok(gSources.selectedItem,
"There should be a selected item in the sources pane.");
"There should be a selected item in the sources pane. (2)");
is(getSelectedSourceURL(gSources), EXAMPLE_URL + gLabel1,
"The selected value is the sources pane is incorrect.");
"The selected value is the sources pane is incorrect. (2)");
is(gEditor.getText().search(/firstCall/), 118,
"The first source is displayed.");
"The first source is displayed. (2)");
is(gEditor.getText().search(/debugger/), -1,
"The second source is not displayed.");
"The second source is not displayed. (2)");
// The editor's debug location takes a tick to update.
ok(isCaretPos(gPanel, 1),
"Editor caret location is correct.");
"Editor caret location is correct. (2)");
is(gEditor.getDebugLocation(), null,
"Editor debugger location is correct.");
"Editor debugger location is correct. (2)");
ok(!gEditor.hasLineClass(5, "debug-line"),
"The debugged line highlight was removed.");
"The debugged line highlight was removed. (2)");
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_SHOWN).then(deferred.resolve);
gSources.selectedItem = e => e.attachment.label == gLabel2;
@ -92,22 +92,22 @@ function test() {
let deferred = promise.defer();
ok(gSources.selectedItem,
"There should be a selected item in the sources pane.");
"There should be a selected item in the sources pane. (3)");
is(getSelectedSourceURL(gSources), EXAMPLE_URL + gLabel2 + gParams,
"The selected value is the sources pane is incorrect.");
"The selected value is the sources pane is incorrect. (3)");
is(gEditor.getText().search(/firstCall/), -1,
"The first source is not displayed.");
"The first source is not displayed. (3)");
is(gEditor.getText().search(/debugger/), 166,
"The second source is displayed.");
"The second source is displayed. (3)");
// The editor's debug location takes a tick to update.
ok(isCaretPos(gPanel, 1),
"Editor caret location is correct.");
ok(isCaretPos(gPanel, 6),
"Editor caret location is correct. (3)");
is(gEditor.getDebugLocation(), 5,
"Editor debugger location is correct.");
"Editor debugger location is correct. (3)");
ok(gEditor.hasLineClass(5, "debug-line"),
"The debugged line is highlighted appropriately.");
"The debugged line is highlighted appropriately. (3)");
// Step out three times.
waitForThreadEvents(gPanel, "paused").then(() => {
@ -123,22 +123,22 @@ function test() {
let deferred = promise.defer();
ok(gSources.selectedItem,
"There should be a selected item in the sources pane.");
"There should be a selected item in the sources pane. (4)");
is(getSelectedSourceURL(gSources), EXAMPLE_URL + gLabel1,
"The selected value is the sources pane is incorrect.");
"The selected value is the sources pane is incorrect. (4)");
is(gEditor.getText().search(/firstCall/), 118,
"The first source is displayed.");
"The first source is displayed. (4)");
is(gEditor.getText().search(/debugger/), -1,
"The second source is not displayed.");
"The second source is not displayed. (4)");
// The editor's debug location takes a tick to update.
ok(isCaretPos(gPanel, 6),
"Editor caret location is correct.");
"Editor caret location is correct. (4)");
is(gEditor.getDebugLocation(), 5,
"Editor debugger location is correct.");
"Editor debugger location is correct. (4)");
ok(gEditor.hasLineClass(5, "debug-line"),
"The debugged line is highlighted appropriately.");
"The debugged line is highlighted appropriately. (4)");
deferred.resolve();

View File

@ -49,11 +49,11 @@ function doSearch() {
info("Debugger editor text:\n" + gEditor.getText());
ok(isCaretPos(gPanel, 6),
"The editor shouldn't have jumped to a matching line yet.");
"The editor shouldn't have jumped to a matching line yet. (1)");
ok(getSelectedSourceURL(gSources).includes("-02.js"),
"The current source shouldn't have changed after a global search.");
"The current source shouldn't have changed after a global search. (2)");
is(gSources.visibleItems.length, 2,
"Not all the sources are shown after the global search.");
"Not all the sources are shown after the global search. (3)");
deferred.resolve();
});
@ -75,17 +75,17 @@ function testExpandCollapse() {
EventUtils.sendMouseEvent({ type: "click" }, secondHeader);
is(item0.instance.expanded, false,
"The first source results should be collapsed on click.")
"The first source results should be collapsed on click. (2)")
is(item1.instance.expanded, false,
"The second source results should be collapsed on click.")
"The second source results should be collapsed on click. (2)")
EventUtils.sendMouseEvent({ type: "click" }, firstHeader);
EventUtils.sendMouseEvent({ type: "click" }, secondHeader);
is(item0.instance.expanded, true,
"The first source results should be expanded on an additional click.");
"The first source results should be expanded on an additional click. (3)");
is(item1.instance.expanded, true,
"The second source results should be expanded on an additional click.");
"The second source results should be expanded on an additional click. (3)");
}
function testClickLineToJump() {
@ -100,13 +100,13 @@ function testClickLineToJump() {
info("Debugger editor text:\n" + gEditor.getText());
ok(isCaretPos(gPanel, 1, 5),
"The editor didn't jump to the correct line (1).");
"The editor didn't jump to the correct line (4).");
is(gEditor.getSelection(), "A",
"The editor didn't select the correct text (1).");
"The editor didn't select the correct text (4).");
ok(getSelectedSourceURL(gSources).includes("-01.js"),
"The currently shown source is incorrect (1).");
"The currently shown source is incorrect (4).");
is(gSources.visibleItems.length, 2,
"Not all the sources are shown after the global search (1).");
"Not all the sources are shown after the global search (4).");
deferred.resolve();
});
@ -124,18 +124,18 @@ function testClickMatchToJump() {
let secondMatches = sourceResults[1].querySelectorAll(".dbg-results-line-contents-string[match=true]");
let lastMatch = Array.slice(secondMatches).pop();
waitForSourceAndCaret(gPanel, "-02.js", 1, 1).then(() => {
waitForSourceAndCaret(gPanel, "-02.js", 13, 3).then(() => {
info("Current source url:\n" + getSelectedSourceURL(gSources));
info("Debugger editor text:\n" + gEditor.getText());
ok(isCaretPos(gPanel, 13, 3),
"The editor didn't jump to the correct line (2).");
"The editor didn't jump to the correct line (5).");
is(gEditor.getSelection(), "a",
"The editor didn't select the correct text (2).");
"The editor didn't select the correct text (5).");
ok(getSelectedSourceURL(gSources).includes("-02.js"),
"The currently shown source is incorrect (2).");
"The currently shown source is incorrect (5).");
is(gSources.visibleItems.length, 2,
"Not all the sources are shown after the global search (2).");
"Not all the sources are shown after the global search (5).");
deferred.resolve();
});

View File

@ -212,7 +212,7 @@ function test() {
return finished.then(() => promise.all([
ensureSourceIs(gPanel, "-01.js"),
ensureCaretAt(gPanel, 1),
ensureCaretAt(gPanel, 2, 9),
verifyContents({ itemCount: 2, hidden: false })
]));
}

View File

@ -40,7 +40,7 @@ function performTest() {
is(gEditor.getText().search(/debugger/), 166,
"The second source is displayed.");
waitForSourceAndCaret(gPanel, "-01.js", 1).then(waitForTick).then(() => {
waitForSourceAndCaret(gPanel, "-01.js", 5).then(waitForTick).then(() => {
is(gFrames.selectedIndex, 0,
"Oldest frame should be selected after click.");
is(gClassicFrames.selectedIndex, 1,
@ -52,7 +52,7 @@ function performTest() {
is(gEditor.getText().search(/debugger/), -1,
"The second source is not displayed.");
waitForSourceAndCaret(gPanel, "-02.js", 1).then(waitForTick).then(() => {
waitForSourceAndCaret(gPanel, "-02.js", 6).then(waitForTick).then(() => {
is(gFrames.selectedIndex, 1,
"Newest frame should be selected again after click.");
is(gClassicFrames.selectedIndex, 0,

View File

@ -141,6 +141,7 @@ Tools.webConsole = {
}
panel.focusInput();
return undefined;
},
isTargetSupported: function() {

View File

@ -604,6 +604,7 @@ LayoutView.prototype = {
this.elementRules = styleEntries.map(e => e.rule);
this.inspector.emit("layoutview-updated");
return undefined;
}).bind(this)).catch(console.error);
this._lastRequest = lastRequest;

View File

@ -468,6 +468,8 @@ MarkupView.prototype = {
// and decision to show or not the tooltip
return container.isImagePreviewTarget(target, this.tooltip);
}
return undefined;
},
/**
@ -534,6 +536,7 @@ MarkupView.prototype = {
// Make sure the new selection receives focus so the keyboard can be used.
this.maybeFocusNewSelection();
return undefined;
}).catch(e => {
if (!this._destroyer) {
console.error(e);
@ -707,6 +710,7 @@ MarkupView.prototype = {
this.cancelDragging();
break;
}
// falls through
}
default:
handled = false;
@ -2298,6 +2302,7 @@ MarkupElementContainer.prototype = Heritage.extend(MarkupContainer.prototype, {
});
return true;
}
return undefined;
},
/**

View File

@ -7,7 +7,7 @@
// Tests that attributes can be deleted from the markup-view with the delete key
// when they are focused.
const HTML = `<div id="id" class="class" data-id="id"></div>`;
const HTML = '<div id="id" class="class" data-id="id"></div>';
const TEST_URL = "data:text/html;charset=utf-8," + encodeURIComponent(HTML);
// List of all the test cases. Each item is an object with the following props:

View File

@ -20,7 +20,9 @@ SimpleTest.requestCompleteLog();
// Set the testing flag on DevToolsUtils and reset it when the test ends
DevToolsUtils.testing = true;
registerCleanupFunction(() => DevToolsUtils.testing = false);
registerCleanupFunction(() => {
DevToolsUtils.testing = false;
});
// Clear preferences that may be set during the course of tests.
registerCleanupFunction(() => {
@ -440,6 +442,7 @@ function* waitForMultipleChildrenUpdates(inspector) {
yield waitForChildrenUpdated(inspector);
return yield waitForMultipleChildrenUpdates(inspector);
}
return undefined;
}
/**

View File

@ -130,6 +130,8 @@ ElementStyle.prototype = {
r.editor.destroy();
}
}
return undefined;
}).then(null, e => {
// populate is often called after a setTimeout,
// the connection may already be closed.

View File

@ -874,6 +874,7 @@ CssRuleView.prototype = {
if (this._elementStyle === elementStyle) {
return this._populate();
}
return undefined;
}).then(() => {
if (this._elementStyle === elementStyle) {
if (!refresh) {

View File

@ -59,12 +59,11 @@ function* addNewRuleFromContextMenu(inspector, view) {
ok(!view._contextmenu.menuitemAddRule.hidden, "Add rule is visible");
info("Adding the new rule");
info("Adding the new rule and expecting a ruleview-changed event");
let onRuleViewChanged = view.once("ruleview-changed");
view._contextmenu.menuitemAddRule.click();
view._contextmenu._menupopup.hidePopup();
info("Waiting for rule view to change");
yield view.once("ruleview-changed");
yield onRuleViewChanged;
}
function* testNewRule(view, expected, index) {

View File

@ -75,6 +75,7 @@ function* getContainerStyleAttrValue(id, {walker, markup}) {
}
attrIndex++;
}
return undefined;
}
function* assertRuleAndMarkupViewWidth(id, value, ruleView, inspector) {

View File

@ -251,6 +251,7 @@ TextPropertyEditor.prototype = {
if (domRule) {
return domRule.href || domRule.nodeHref;
}
return undefined;
},
/**

View File

@ -406,6 +406,8 @@ TooltipsOverlay.prototype = {
return this.previewTooltip.setFontFamilyContent(nodeInfo.value.value,
inspector.selection.nodeFront);
}
return undefined;
},
_onNewSelection: function() {

View File

@ -132,6 +132,7 @@ let Converter = Class({
return jsonViewStrings.GetStringFromName(key);
} catch (err) {
Cu.reportError(err);
return undefined;
}
}
};

View File

@ -6,6 +6,9 @@ debug = Debug
push = Push
start = Start
scope = Scope
unregister = unregister
addons = Add-ons
addonDebugging.label = Enable add-on debugging
addonDebugging.tooltip = Turning this on will allow you to debug add-ons and various other parts of the browser chrome

View File

@ -241,41 +241,27 @@ function setScrollHandlers(container, dragZoom, emitChanged, update) {
let deltaZoom = dragZoom.zoom - prevZoom;
// Calculate the updated width and height
let prevWidth = container.offsetWidth * (1 + prevZoom);
let prevHeight = container.offsetHeight * (1 + prevZoom);
let prevZoomedWidth = container.offsetWidth * (1 + prevZoom);
let prevZoomedHeight = container.offsetHeight * (1 + prevZoom);
dragZoom.zoomedWidth = container.offsetWidth * (1 + dragZoom.zoom);
dragZoom.height = container.offsetHeight * (1 + dragZoom.zoom);
let deltaWidth = dragZoom.zoomedWidth - prevWidth;
let deltaHeight = dragZoom.height - prevHeight;
dragZoom.zoomedHeight = container.offsetHeight * (1 + dragZoom.zoom);
let deltaWidth = dragZoom.zoomedWidth - prevZoomedWidth;
let deltaHeight = dragZoom.zoomedHeight - prevZoomedHeight;
// The ratio of where the center of the zoom is in regards to the total
let mouseOffsetX = dragZoom.mouseX - container.offsetWidth / 2
let mouseOffsetY = dragZoom.mouseY - container.offsetHeight / 2
// The ratio of where the center of the mouse is in regards to the total
// zoomed width/height
let ratioZoomX = (dragZoom.zoomedWidth / 2 - dragZoom.translateX)
let ratioZoomX = (dragZoom.zoomedWidth / 2 + mouseOffsetX - dragZoom.translateX)
/ dragZoom.zoomedWidth;
let ratioZoomY = (dragZoom.height / 2 - dragZoom.translateY)
/ dragZoom.height;
let ratioZoomY = (dragZoom.zoomedHeight / 2 + mouseOffsetY - dragZoom.translateY)
/ dragZoom.zoomedHeight;
// Distribute the change in width and height based on the above ratio
dragZoom.translateX -= lerp(-deltaWidth / 2, deltaWidth / 2, ratioZoomX);
dragZoom.translateY -= lerp(-deltaHeight / 2, deltaHeight / 2, ratioZoomY);
// The ratio of mouse position to total zoomeed width/height, ranged [-1, 1]
let mouseRatioX, mouseRatioY;
if (deltaZoom > 0) {
// Zoom in towards the mouse
mouseRatioX = 2 * (dragZoom.mouseX - container.offsetWidth / 2)
/ dragZoom.zoomedWidth;
mouseRatioY = 2 * (dragZoom.mouseY - container.offsetHeight / 2)
/ dragZoom.height;
} else {
// Zoom out centering the screen
mouseRatioX = 0;
mouseRatioY = 0;
}
// Adjust the translate to zoom towards the mouse
dragZoom.translateX -= deltaWidth * mouseRatioX;
dragZoom.translateY -= deltaHeight * mouseRatioY;
// Keep the canvas in range of the container
keepInView(container, dragZoom);
emitChanged();
@ -314,7 +300,7 @@ function getScrollDelta(event, window) {
function keepInView(container, dragZoom) {
let { devicePixelRatio } = container.ownerDocument.defaultView;
let overdrawX = (dragZoom.zoomedWidth - container.offsetWidth) / 2;
let overdrawY = (dragZoom.height - container.offsetHeight) / 2;
let overdrawY = (dragZoom.zoomedHeight - container.offsetHeight) / 2;
dragZoom.translateX = Math.max(-overdrawX,
Math.min(overdrawX, dragZoom.translateX));
@ -325,6 +311,6 @@ function keepInView(container, dragZoom) {
(dragZoom.zoomedWidth - container.offsetWidth) / 2 - dragZoom.translateX
);
dragZoom.offsetY = devicePixelRatio * (
(dragZoom.height - container.offsetHeight) / 2 - dragZoom.translateY
(dragZoom.zoomedHeight - container.offsetHeight) / 2 - dragZoom.translateY
);
}

Some files were not shown because too many files have changed in this diff Show More