mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Merge m-c to inbound, a=merge
MozReview-Commit-ID: 9YZdlIARozU
This commit is contained in:
commit
dfc7e5253f
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
},
|
||||
|
@ -698,7 +698,7 @@
|
||||
showcommentcolumn="true"
|
||||
showimagecolumn="true"
|
||||
enablehistory="true"
|
||||
maxrows="6"
|
||||
maxrows="10"
|
||||
newlines="stripsurroundingwhitespace"
|
||||
ontextentered="this.handleCommand(param);"
|
||||
ontextreverted="return this.handleRevert();"
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -147,6 +147,7 @@ var Change = {
|
||||
return this.doChangePassword();
|
||||
break;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
doGeneratePassphrase: function () {
|
||||
|
@ -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.
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -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 => {
|
||||
|
@ -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();
|
||||
});
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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) {
|
||||
|
@ -478,6 +478,7 @@ ESEDB.prototype = {
|
||||
systemTime.wSecond,
|
||||
systemTime.wMilliseconds));
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
_getColumnInfo(tableName, columns) {
|
||||
|
@ -872,6 +872,7 @@ WindowsVaultFormPasswords.prototype = {
|
||||
if (aOnlyCheckExists) {
|
||||
return false;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -161,6 +161,7 @@ var MigrationWizard = {
|
||||
else
|
||||
this._selectedProfile = null;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
// 2 - [Profile Selection]
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -1822,6 +1822,7 @@ Experiments.ExperimentEntry.prototype = {
|
||||
this._log.error("_installAddon() - onInstallStarted, wrong addon type");
|
||||
return false;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
onInstallEnded: install => {
|
||||
|
@ -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
|
||||
|
@ -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
5127
browser/extensions/pdfjs/content/build/pdf.worker.js
vendored
5127
browser/extensions/pdfjs/content/build/pdf.worker.js
vendored
File diff suppressed because it is too large
Load Diff
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
5
browser/extensions/pocket/bootstrap.js
vendored
5
browser/extensions/pocket/bootstrap.js
vendored
@ -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));
|
||||
},
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}),
|
||||
},
|
||||
|
||||
|
@ -37,6 +37,7 @@ this.Toolbars = {
|
||||
if (browserWindow.fullScreen) {
|
||||
return Promise.reject("The bookmark toolbar and menubar are not shown in fullscreen.");
|
||||
}
|
||||
return undefined;
|
||||
}),
|
||||
},
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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({
|
||||
|
@ -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 });
|
||||
});
|
||||
},
|
||||
});
|
||||
|
@ -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));
|
||||
}
|
||||
});
|
@ -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',
|
||||
|
@ -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;
|
||||
},
|
||||
});
|
@ -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;
|
||||
},
|
||||
});
|
||||
|
@ -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 };
|
||||
}),
|
||||
});
|
||||
|
7
devtools/client/aboutdebugging/modules/moz.build
Normal file
7
devtools/client/aboutdebugging/modules/moz.build
Normal 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',
|
||||
)
|
77
devtools/client/aboutdebugging/modules/worker.js
Normal file
77
devtools/client/aboutdebugging/modules/worker.js
Normal 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 };
|
||||
});
|
@ -6,6 +6,7 @@
|
||||
|
||||
DIRS += [
|
||||
'components',
|
||||
'modules',
|
||||
]
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
|
@ -0,0 +1 @@
|
||||
this is not valid json
|
@ -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
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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);
|
||||
});
|
@ -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();
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -9,3 +9,4 @@ skip-if = toolkit == 'android' || toolkit == 'gonk'
|
||||
[test_formatStopwatchTime.js]
|
||||
[test_getCssPropertyName.js]
|
||||
[test_timeScale.js]
|
||||
[test_timeScale_dimensions.js]
|
||||
|
@ -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};
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 });
|
||||
});
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
|
||||
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -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*() {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -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 })
|
||||
]));
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -141,6 +141,7 @@ Tools.webConsole = {
|
||||
}
|
||||
|
||||
panel.focusInput();
|
||||
return undefined;
|
||||
},
|
||||
|
||||
isTargetSupported: function() {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
|
@ -874,6 +874,7 @@ CssRuleView.prototype = {
|
||||
if (this._elementStyle === elementStyle) {
|
||||
return this._populate();
|
||||
}
|
||||
return undefined;
|
||||
}).then(() => {
|
||||
if (this._elementStyle === elementStyle) {
|
||||
if (!refresh) {
|
||||
|
@ -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) {
|
||||
|
@ -75,6 +75,7 @@ function* getContainerStyleAttrValue(id, {walker, markup}) {
|
||||
}
|
||||
attrIndex++;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function* assertRuleAndMarkupViewWidth(id, value, ruleView, inspector) {
|
||||
|
@ -251,6 +251,7 @@ TextPropertyEditor.prototype = {
|
||||
if (domRule) {
|
||||
return domRule.href || domRule.nodeHref;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -406,6 +406,8 @@ TooltipsOverlay.prototype = {
|
||||
return this.previewTooltip.setFontFamilyContent(nodeInfo.value.value,
|
||||
inspector.selection.nodeFront);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
|
||||
_onNewSelection: function() {
|
||||
|
@ -132,6 +132,7 @@ let Converter = Class({
|
||||
return jsonViewStrings.GetStringFromName(key);
|
||||
} catch (err) {
|
||||
Cu.reportError(err);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user