mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Merge inbound to mozilla-central r=merge a=merge
This commit is contained in:
commit
5ba2665757
3
.arcconfig
Normal file
3
.arcconfig
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"phabricator.uri" : "https://phabricator.services.mozilla.com/"
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
* 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/. */
|
||||
|
||||
/* globals windowTracker */
|
||||
/* globals windowTracker */
|
||||
|
||||
"use strict";
|
||||
|
||||
@ -170,8 +170,9 @@ this.chrome_settings_overrides = class extends ExtensionAPI {
|
||||
// Needs to be called every time to handle reenabling, but
|
||||
// only sets default for install or enable.
|
||||
await this.setDefault(engineName);
|
||||
} else if (ExtensionSettingsStore.hasSetting(
|
||||
extension.id, DEFAULT_SEARCH_STORE_TYPE, DEFAULT_SEARCH_SETTING_NAME)) {
|
||||
} else if (ExtensionSettingsStore.hasSetting(extension.id,
|
||||
DEFAULT_SEARCH_STORE_TYPE,
|
||||
DEFAULT_SEARCH_SETTING_NAME)) {
|
||||
// is_default has been removed, but we still have a setting. Remove it.
|
||||
chrome_settings_overrides.processDefaultSearchSetting("removeSetting", extension.id);
|
||||
}
|
||||
|
@ -193,8 +193,7 @@ var gMenuBuilder = {
|
||||
}
|
||||
|
||||
if (item.id && item.extension && item.extension.id) {
|
||||
element.setAttribute("id",
|
||||
`${makeWidgetId(item.extension.id)}_${item.id}`);
|
||||
element.setAttribute("id", `${makeWidgetId(item.extension.id)}_${item.id}`);
|
||||
}
|
||||
|
||||
if (item.icons) {
|
||||
|
@ -6,10 +6,9 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
OS: "resource://gre/modules/osfile.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"pkcs11db",
|
||||
"@mozilla.org/security/pkcs11moduledb;1",
|
||||
"nsIPKCS11ModuleDB");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "pkcs11db",
|
||||
"@mozilla.org/security/pkcs11moduledb;1",
|
||||
"nsIPKCS11ModuleDB");
|
||||
|
||||
var {DefaultMap} = ExtensionUtils;
|
||||
|
||||
|
@ -190,8 +190,8 @@ this.windows = class extends ExtensionAPI {
|
||||
if (allowScriptsToClose) {
|
||||
for (let {linkedBrowser} of window.gBrowser.tabs) {
|
||||
onXULFrameLoaderCreated({target: linkedBrowser});
|
||||
linkedBrowser.addEventListener( // eslint-disable-line mozilla/balanced-listeners
|
||||
"XULFrameLoaderCreated", onXULFrameLoaderCreated);
|
||||
// eslint-disable-next-line mozilla/balanced-listeners
|
||||
linkedBrowser.addEventListener("XULFrameLoaderCreated", onXULFrameLoaderCreated);
|
||||
}
|
||||
}
|
||||
if (createData.titlePreface !== null) {
|
||||
|
@ -32,13 +32,13 @@ add_task(async function testBrowserActionPopupResize() {
|
||||
Assert.lessOrEqual(Math.abs(dims.window.innerHeight - expected), 1,
|
||||
`Panel window should be ${expected}px tall (was ${dims.window.innerHeight})`);
|
||||
is(dims.body.clientHeight, dims.body.scrollHeight,
|
||||
"Panel body should be tall enough to fit its contents");
|
||||
"Panel body should be tall enough to fit its contents");
|
||||
|
||||
// Tolerate if it is 1px too wide, as that may happen with the current resizing method.
|
||||
Assert.lessOrEqual(Math.abs(dims.window.innerWidth - expected), 1,
|
||||
`Panel window should be ${expected}px wide`);
|
||||
is(dims.body.clientWidth, dims.body.scrollWidth,
|
||||
"Panel body should be wide enough to fit its contents");
|
||||
"Panel body should be wide enough to fit its contents");
|
||||
}
|
||||
|
||||
/* eslint-disable mozilla/no-cpows-in-tests */
|
||||
@ -162,7 +162,7 @@ async function testPopupSize(standardsMode, browserWin = window, arrowSide = "to
|
||||
// The 'ViewShown' event is the only way to correctly determine when the extensions'
|
||||
// panelview has finished transitioning and is fully in view.
|
||||
let shownPromise = BrowserTestUtils.waitForEvent(panelMultiView, "ViewShown",
|
||||
e => (e.originalTarget.id || "").includes(widgetId));
|
||||
e => (e.originalTarget.id || "").includes(widgetId));
|
||||
let browser = await openPanel(extension, browserWin);
|
||||
let origPanelRect = panel.getBoundingClientRect();
|
||||
|
||||
|
@ -56,13 +56,13 @@ add_task(async function testBrowserActionTelemetryTiming() {
|
||||
histogram.clear();
|
||||
|
||||
is(histogram.snapshot().sum, 0,
|
||||
`No data recorded for histogram: ${TIMING_HISTOGRAM}.`);
|
||||
`No data recorded for histogram: ${TIMING_HISTOGRAM}.`);
|
||||
|
||||
await extension1.startup();
|
||||
await extension2.startup();
|
||||
|
||||
is(histogram.snapshot().sum, 0,
|
||||
`No data recorded for histogram after startup: ${TIMING_HISTOGRAM}.`);
|
||||
`No data recorded for histogram after startup: ${TIMING_HISTOGRAM}.`);
|
||||
|
||||
clickBrowserAction(extension1);
|
||||
await awaitExtensionPanel(extension1);
|
||||
@ -117,7 +117,7 @@ add_task(async function testBrowserActionTelemetryResults() {
|
||||
histogram.clear();
|
||||
|
||||
is(histogram.snapshot().sum, 0,
|
||||
`No data recorded for histogram: ${TIMING_HISTOGRAM}.`);
|
||||
`No data recorded for histogram: ${TIMING_HISTOGRAM}.`);
|
||||
|
||||
await extension.startup();
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
add_task(async function setup() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.serviceWorkers.exemptFromPerDomainMax", true],
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", true]],
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", true]],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -486,7 +486,8 @@ add_task(async function test_bookmark_contextmenu() {
|
||||
});
|
||||
await extension.startup();
|
||||
await extension.awaitMessage("bookmark-created");
|
||||
let menu = await openChromeContextMenu("placesContext",
|
||||
let menu = await openChromeContextMenu(
|
||||
"placesContext",
|
||||
"#PersonalToolbar .bookmark-item:last-child");
|
||||
|
||||
let menuItem = menu.getElementsByAttribute("label", "Get bookmark")[0];
|
||||
@ -515,11 +516,12 @@ add_task(async function test_bookmark_context_requires_permission() {
|
||||
});
|
||||
await extension.startup();
|
||||
await extension.awaitMessage("bookmark-created");
|
||||
let menu = await openChromeContextMenu("placesContext",
|
||||
let menu = await openChromeContextMenu(
|
||||
"placesContext",
|
||||
"#PersonalToolbar .bookmark-item:last-child");
|
||||
|
||||
Assert.equal(menu.getElementsByAttribute("label", "Get bookmark").length, 0,
|
||||
"bookmark context menu not created with `bookmarks` permission.");
|
||||
"bookmark context menu not created with `bookmarks` permission.");
|
||||
|
||||
closeChromeContextMenu("placesContext");
|
||||
|
||||
|
@ -3,7 +3,8 @@
|
||||
"use strict";
|
||||
|
||||
add_task(async function() {
|
||||
let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser,
|
||||
let tab1 = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
"http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html");
|
||||
|
||||
gBrowser.selectedTab = tab1;
|
||||
|
@ -69,10 +69,10 @@ function testScript() {
|
||||
// Sanity check - the pages must be in the same process.
|
||||
let pages = browser.extension.getViews();
|
||||
browser.test.assertTrue(pages.includes(window),
|
||||
"Expected this tab to be an extension view");
|
||||
"Expected this tab to be an extension view");
|
||||
pages = pages.filter(w => w !== window);
|
||||
browser.test.assertEq(pages[0], browser.extension.getBackgroundPage(),
|
||||
"Expected the other page to be a background page");
|
||||
"Expected the other page to be a background page");
|
||||
browser.test.sendMessage("tab.html ready");
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,8 @@
|
||||
"use strict";
|
||||
|
||||
add_task(async function() {
|
||||
let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser,
|
||||
let tab1 = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
"http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html");
|
||||
|
||||
gBrowser.selectedTab = tab1;
|
||||
|
@ -3,7 +3,8 @@
|
||||
"use strict";
|
||||
|
||||
add_task(async function() {
|
||||
let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser,
|
||||
let tab1 = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
"http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html");
|
||||
|
||||
// Install an extension.
|
||||
|
@ -3,7 +3,8 @@
|
||||
"use strict";
|
||||
|
||||
add_task(async function() {
|
||||
let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser,
|
||||
let tab1 = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
"http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html");
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
|
@ -49,9 +49,9 @@ add_task(async function test_devtools_inspectedWindow_tabId() {
|
||||
}
|
||||
|
||||
function devtools_page() {
|
||||
browser.test.assertEq(undefined, browser.runtime.getBackgroundPage,
|
||||
"The `runtime.getBackgroundPage` API method should be missing in a devtools_page context"
|
||||
);
|
||||
browser.test.assertEq(
|
||||
undefined, browser.runtime.getBackgroundPage,
|
||||
"The `runtime.getBackgroundPage` API method should be missing in a devtools_page context");
|
||||
|
||||
try {
|
||||
let tabId = browser.devtools.inspectedWindow.tabId;
|
||||
|
@ -173,7 +173,7 @@ add_task(async function test_devtools_inspectedWindow_eval_bindings() {
|
||||
const objectPreviewProperties = options.objectActor.preview.ownProperties;
|
||||
is(objectType, "object", "The inspected object has the expected type");
|
||||
Assert.deepEqual(Object.keys(objectPreviewProperties), ["testkey"],
|
||||
"The inspected object has the expected preview properties");
|
||||
"The inspected object has the expected preview properties");
|
||||
}
|
||||
})();
|
||||
|
||||
|
@ -181,7 +181,7 @@ add_task(async function test_devtools_inspectedWindow_reload_custom_user_agent()
|
||||
try {
|
||||
const [text] = await browser.tabs.executeScript(activeTabId, {code});
|
||||
browser.test.assertEq(expectedContent, text,
|
||||
`Got the expected userAgent with userAgent=${enabled}`);
|
||||
`Got the expected userAgent with userAgent=${enabled}`);
|
||||
} catch (err) {
|
||||
browser.test.fail(`Error: ${err.message} - ${err.stack}`);
|
||||
}
|
||||
|
@ -31,11 +31,11 @@ async function testThemeSwitching(extension, locations = ["page"]) {
|
||||
await switchTheme(newTheme);
|
||||
for (let location of locations) {
|
||||
is(await extension.awaitMessage(`devtools_theme_changed_${location}`),
|
||||
newTheme,
|
||||
`The onThemeChanged event listener fired for the ${location}.`);
|
||||
newTheme,
|
||||
`The onThemeChanged event listener fired for the ${location}.`);
|
||||
is(await extension.awaitMessage(`current_theme_${location}`),
|
||||
newTheme,
|
||||
`The current theme is reported as expected for the ${location}.`);
|
||||
newTheme,
|
||||
`The current theme is reported as expected for the ${location}.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -80,8 +80,8 @@ add_task(async function test_theme_name_no_panel() {
|
||||
info("developer toolbox opened");
|
||||
|
||||
is(await extension.awaitMessage("initial_theme"),
|
||||
"light",
|
||||
"The initial theme is reported as expected.");
|
||||
"light",
|
||||
"The initial theme is reported as expected.");
|
||||
|
||||
await testThemeSwitching(extension);
|
||||
|
||||
@ -201,8 +201,8 @@ add_task(async function test_devtools_page_panels_create() {
|
||||
|
||||
await extension.awaitMessage("devtools_panel_created");
|
||||
is(await extension.awaitMessage("initial_theme_page"),
|
||||
"light",
|
||||
"The initial theme is reported as expected from a devtools page.");
|
||||
"light",
|
||||
"The initial theme is reported as expected from a devtools page.");
|
||||
|
||||
const toolboxAdditionalTools = toolbox.getAdditionalTools();
|
||||
|
||||
@ -220,8 +220,8 @@ add_task(async function test_devtools_page_panels_create() {
|
||||
is(devtoolsPanelTabId, devtoolsPageTabId,
|
||||
"Got the same devtools.inspectedWindow.tabId from devtools page and panel");
|
||||
is(await extension.awaitMessage("initial_theme_panel"),
|
||||
"light",
|
||||
"The initial theme is reported as expected from a devtools panel.");
|
||||
"light",
|
||||
"The initial theme is reported as expected from a devtools panel.");
|
||||
info("Addon Devtools Panel shown");
|
||||
|
||||
await testThemeSwitching(extension, ["page", "panel"]);
|
||||
@ -282,8 +282,8 @@ add_task(async function test_devtools_page_panels_create() {
|
||||
await gDevTools.showToolbox(target, panelId);
|
||||
await extension.awaitMessage("devtools_panel_shown");
|
||||
is(await extension.awaitMessage("initial_theme_panel"),
|
||||
"light",
|
||||
"The initial theme is reported as expected from a devtools panel.");
|
||||
"light",
|
||||
"The initial theme is reported as expected from a devtools panel.");
|
||||
info("Addon Devtools Panel shown - after visibilityswitch toggled");
|
||||
|
||||
info("Wait until the Addon Devtools Panel has been loaded - after visibilityswitch toggled");
|
||||
|
@ -49,7 +49,7 @@ add_task(async function test_legacy_extension_context_contentscript_connection()
|
||||
function contentScript() {
|
||||
browser.runtime.sendMessage("webextension -> legacy_extension message", (reply) => {
|
||||
browser.test.assertEq("legacy_extension -> webextension reply", reply,
|
||||
"Got the expected reply from the LegacyExtensionContext");
|
||||
"Got the expected reply from the LegacyExtensionContext");
|
||||
browser.test.sendMessage("got-reply-message");
|
||||
});
|
||||
|
||||
|
@ -76,11 +76,11 @@ add_task(async function() {
|
||||
let actual = await extension.awaitMessage(event);
|
||||
if (expected.text) {
|
||||
is(actual.text, expected.text,
|
||||
`Expected "${event}" to have fired with text: "${expected.text}".`);
|
||||
`Expected "${event}" to have fired with text: "${expected.text}".`);
|
||||
}
|
||||
if (expected.disposition) {
|
||||
is(actual.disposition, expected.disposition,
|
||||
`Expected "${event}" to have fired with disposition: "${expected.disposition}".`);
|
||||
`Expected "${event}" to have fired with disposition: "${expected.disposition}".`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,10 +205,10 @@ add_task(async function() {
|
||||
let item = gURLBar.popup.richlistbox.children[0];
|
||||
|
||||
is(item.getAttribute("title"), expectedText,
|
||||
`Expected heuristic result to have title: "${expectedText}".`);
|
||||
`Expected heuristic result to have title: "${expectedText}".`);
|
||||
|
||||
is(item.getAttribute("displayurl"), `${keyword} ${text}`,
|
||||
`Expected heuristic result to have displayurl: "${keyword} ${text}".`);
|
||||
`Expected heuristic result to have displayurl: "${keyword} ${text}".`);
|
||||
|
||||
let promiseEvent = expectEvent("on-input-entered-fired", {
|
||||
text,
|
||||
@ -250,10 +250,10 @@ add_task(async function() {
|
||||
|
||||
ok(!!item, "Expected item to exist");
|
||||
is(item.getAttribute("title"), description,
|
||||
`Expected suggestion to have title: "${description}".`);
|
||||
`Expected suggestion to have title: "${description}".`);
|
||||
|
||||
is(item.getAttribute("displayurl"), `${keyword} ${content}`,
|
||||
`Expected suggestion to have displayurl: "${keyword} ${content}".`);
|
||||
`Expected suggestion to have displayurl: "${keyword} ${content}".`);
|
||||
}
|
||||
|
||||
let text = await startInputSession(info.suggestions.length - 1);
|
||||
|
@ -41,9 +41,9 @@ add_task(async function testPageActionPopupResize() {
|
||||
|
||||
is(dims.window.innerHeight, expected, `Panel window should be ${expected}px tall`);
|
||||
is(body.clientHeight, body.scrollHeight,
|
||||
"Panel body should be tall enough to fit its contents");
|
||||
"Panel body should be tall enough to fit its contents");
|
||||
is(root.clientHeight, root.scrollHeight,
|
||||
"Panel root should be tall enough to fit its contents");
|
||||
"Panel root should be tall enough to fit its contents");
|
||||
|
||||
// Tolerate if it is 1px too wide, as that may happen with the current resizing method.
|
||||
ok(Math.abs(dims.window.innerWidth - expected) <= 1, `Panel window should be ${expected}px wide`);
|
||||
@ -141,9 +141,9 @@ add_task(async function testPageActionPopupReflow() {
|
||||
`Panel window height (${dims.window.innerHeight}px) should be taller than two lines of text.`);
|
||||
|
||||
is(dims.body.clientHeight, dims.body.scrollHeight,
|
||||
"Panel body should be tall enough to fit its contents");
|
||||
"Panel body should be tall enough to fit its contents");
|
||||
is(dims.root.clientHeight, dims.root.scrollHeight,
|
||||
"Panel root should be tall enough to fit its contents");
|
||||
"Panel root should be tall enough to fit its contents");
|
||||
|
||||
await extension.unload();
|
||||
});
|
||||
|
@ -16,7 +16,7 @@ add_task(async function test_sessions_forget_closed_tab() {
|
||||
},
|
||||
error => {
|
||||
browser.test.assertEq(error.message,
|
||||
`Could not find closed tab using sessionId ${sessionId}.`);
|
||||
`Could not find closed tab using sessionId ${sessionId}.`);
|
||||
browser.test.sendMessage("forget-reject");
|
||||
}
|
||||
);
|
||||
@ -45,8 +45,9 @@ add_task(async function test_sessions_forget_closed_tab() {
|
||||
let recentlyClosedTab = recentlyClosed[0].tab;
|
||||
|
||||
// Check that forgetting a tab works properly
|
||||
extension.sendMessage("forget-tab", recentlyClosedTab.windowId,
|
||||
recentlyClosedTab.sessionId);
|
||||
extension.sendMessage("forget-tab",
|
||||
recentlyClosedTab.windowId,
|
||||
recentlyClosedTab.sessionId);
|
||||
await extension.awaitMessage("forgot-tab");
|
||||
extension.sendMessage("check-sessions");
|
||||
let remainingClosed = await extension.awaitMessage("recentlyClosed");
|
||||
@ -56,8 +57,9 @@ add_task(async function test_sessions_forget_closed_tab() {
|
||||
"The correct tab was forgotten.");
|
||||
|
||||
// Check that re-forgetting the same tab fails properly
|
||||
extension.sendMessage("forget-tab", recentlyClosedTab.windowId,
|
||||
recentlyClosedTab.sessionId);
|
||||
extension.sendMessage("forget-tab",
|
||||
recentlyClosedTab.windowId,
|
||||
recentlyClosedTab.sessionId);
|
||||
await extension.awaitMessage("forget-reject");
|
||||
extension.sendMessage("check-sessions");
|
||||
remainingClosed = await extension.awaitMessage("recentlyClosed");
|
||||
|
@ -22,8 +22,9 @@ add_task(async function test_sessions_forget_closed_window() {
|
||||
browser.test.sendMessage("forgot-window");
|
||||
},
|
||||
error => {
|
||||
browser.test.assertEq(error.message,
|
||||
`Could not find closed window using sessionId ${sessionId}.`);
|
||||
browser.test.assertEq(
|
||||
error.message,
|
||||
`Could not find closed window using sessionId ${sessionId}.`);
|
||||
browser.test.sendMessage("forget-reject");
|
||||
}
|
||||
);
|
||||
|
@ -98,9 +98,11 @@ add_task(async function test_sessions_get_recently_closed_navigated() {
|
||||
function background() {
|
||||
browser.sessions.getRecentlyClosed({maxResults: 1}).then(recentlyClosed => {
|
||||
let tab = recentlyClosed[0].window.tabs[0];
|
||||
browser.test.assertEq("http://example.com/", tab.url,
|
||||
browser.test.assertEq(
|
||||
"http://example.com/", tab.url,
|
||||
"Tab in closed window has the expected url.");
|
||||
browser.test.assertTrue(tab.title.includes("mochitest index"),
|
||||
browser.test.assertTrue(
|
||||
tab.title.includes("mochitest index"),
|
||||
"Tab in closed window has the expected title.");
|
||||
browser.test.notifyPass("getRecentlyClosed with navigation");
|
||||
});
|
||||
|
@ -15,10 +15,10 @@ add_task(async function test_extension_adding_engine() {
|
||||
manifest: {
|
||||
"chrome_settings_overrides": {
|
||||
"search_provider": {
|
||||
"name": "MozSearch",
|
||||
"keyword": "MozSearch",
|
||||
"search_url": kSearchEngineURL,
|
||||
"suggest_url": kSearchSuggestURL,
|
||||
"name": "MozSearch",
|
||||
"keyword": "MozSearch",
|
||||
"search_url": kSearchEngineURL,
|
||||
"suggest_url": kSearchSuggestURL,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -49,9 +49,9 @@ add_task(async function test_extension_adding_engine_with_spaces() {
|
||||
manifest: {
|
||||
"chrome_settings_overrides": {
|
||||
"search_provider": {
|
||||
"name": "MozSearch ",
|
||||
"keyword": "MozSearch",
|
||||
"search_url": "https://example.com/?q={searchTerms}",
|
||||
"name": "MozSearch ",
|
||||
"keyword": "MozSearch",
|
||||
"search_url": "https://example.com/?q={searchTerms}",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -75,14 +75,14 @@ add_task(async function test_upgrade_default_position_engine() {
|
||||
manifest: {
|
||||
"chrome_settings_overrides": {
|
||||
"search_provider": {
|
||||
"name": "MozSearch",
|
||||
"keyword": "MozSearch",
|
||||
"search_url": "https://example.com/?q={searchTerms}",
|
||||
"name": "MozSearch",
|
||||
"keyword": "MozSearch",
|
||||
"search_url": "https://example.com/?q={searchTerms}",
|
||||
},
|
||||
},
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "testengine@mozilla.com",
|
||||
"id": "testengine@mozilla.com",
|
||||
},
|
||||
},
|
||||
"version": "0.1",
|
||||
@ -94,14 +94,14 @@ add_task(async function test_upgrade_default_position_engine() {
|
||||
manifest: {
|
||||
"chrome_settings_overrides": {
|
||||
"search_provider": {
|
||||
"name": "MozSearch",
|
||||
"keyword": "MozSearch",
|
||||
"search_url": "https://example.com/?q={searchTerms}",
|
||||
"name": "MozSearch",
|
||||
"keyword": "MozSearch",
|
||||
"search_url": "https://example.com/?q={searchTerms}",
|
||||
},
|
||||
},
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "testengine@mozilla.com",
|
||||
"id": "testengine@mozilla.com",
|
||||
},
|
||||
},
|
||||
"version": "0.2",
|
||||
|
@ -142,7 +142,7 @@ add_task(async function testCaptureVisibleTabPermissions() {
|
||||
|
||||
background() {
|
||||
browser.test.assertEq(undefined, browser.tabs.captureVisibleTab,
|
||||
'Extension without "<all_urls>" permission should not have access to captureVisibleTab');
|
||||
'Extension without "<all_urls>" permission should not have access to captureVisibleTab');
|
||||
browser.test.notifyPass("captureVisibleTabPermissions");
|
||||
},
|
||||
});
|
||||
|
@ -28,9 +28,8 @@ add_task(async function moveMultiple() {
|
||||
async function reset() {
|
||||
let tabs = await browser.tabs.query({url: "http://example.com/*"});
|
||||
await browser.tabs.move(
|
||||
tabs.sort((a, b) => (num(a.url) - num(b.url))).map(tab => tab.id),
|
||||
{index: 0}
|
||||
);
|
||||
tabs.sort((a, b) => (num(a.url) - num(b.url))).map(tab => tab.id),
|
||||
{index: 0});
|
||||
}
|
||||
|
||||
async function move(moveIndexes, moveTo) {
|
||||
|
@ -74,7 +74,7 @@ add_task(async function testTabEvents() {
|
||||
*/
|
||||
async function openTab(windowId) {
|
||||
browser.test.assertEq(0, Object.keys(events).length,
|
||||
"No events remaining before testing openTab.");
|
||||
"No events remaining before testing openTab.");
|
||||
|
||||
let tab = await browser.tabs.create({windowId});
|
||||
|
||||
@ -95,7 +95,7 @@ add_task(async function testTabEvents() {
|
||||
*/
|
||||
async function openWindow(urls) {
|
||||
browser.test.assertEq(0, Object.keys(events).length,
|
||||
"No events remaining before testing openWindow.");
|
||||
"No events remaining before testing openWindow.");
|
||||
|
||||
let window = await browser.windows.create({url: urls});
|
||||
browser.test.log(`Opened new window ${window.id}`);
|
||||
@ -105,9 +105,9 @@ add_task(async function testTabEvents() {
|
||||
tabIds.push(tab.id);
|
||||
|
||||
let expectedEvents = [
|
||||
"onCreated",
|
||||
"onActivated",
|
||||
"onHighlighted",
|
||||
"onCreated",
|
||||
"onActivated",
|
||||
"onHighlighted",
|
||||
];
|
||||
if (i !== 0) {
|
||||
expectedEvents.splice(1);
|
||||
@ -123,7 +123,7 @@ add_task(async function testTabEvents() {
|
||||
*/
|
||||
async function highlightTab(tabId) {
|
||||
browser.test.assertEq(0, Object.keys(events).length,
|
||||
"No events remaining before testing highlightTab.");
|
||||
"No events remaining before testing highlightTab.");
|
||||
|
||||
browser.test.log(`Highlighting tab ${tabId}`);
|
||||
let tab = await browser.tabs.update(tabId, {active: true});
|
||||
|
@ -154,7 +154,7 @@ add_task(async function test_update_reload() {
|
||||
is(history.entries.length, 1,
|
||||
"Tab history contains the expected number of entries.");
|
||||
is(history.entries[0].url, URL,
|
||||
`Tab history contains the expected entry: URL.`);
|
||||
`Tab history contains the expected entry: URL.`);
|
||||
|
||||
extension.sendMessage("update", tabId, {url: `${URL}1/`});
|
||||
await Promise.all([
|
||||
@ -166,7 +166,7 @@ add_task(async function test_update_reload() {
|
||||
is(history.entries.length, 2,
|
||||
"Tab history contains the expected number of entries.");
|
||||
is(history.entries[1].url, `${URL}1/`,
|
||||
`Tab history contains the expected entry: ${URL}1/.`);
|
||||
`Tab history contains the expected entry: ${URL}1/.`);
|
||||
|
||||
extension.sendMessage("update", tabId, {url: `${URL}2/`, loadReplace: true});
|
||||
await Promise.all([
|
||||
@ -178,7 +178,7 @@ add_task(async function test_update_reload() {
|
||||
is(history.entries.length, 2,
|
||||
"Tab history contains the expected number of entries.");
|
||||
is(history.entries[1].url, `${URL}2/`,
|
||||
`Tab history contains the expected entry: ${URL}2/.`);
|
||||
`Tab history contains the expected entry: ${URL}2/.`);
|
||||
|
||||
await extension.unload();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
|
@ -2,16 +2,16 @@
|
||||
|
||||
const ENCODED_IMAGE_DATA = "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgNjQgNjQiPjxwYXRoIGQ9Im01NS45IDMyLjFsLTIyLjctMTQuOWMwIDAgMTIuOS0xNy40IDE5LjQtMTQuOSAzLjEgMS4xIDUuNCAyNS4xIDMuMyAyOS44IiBmaWxsPSIjM2U0MzQ3Ii8+PHBhdGggZD0ibTU0LjkgMzMuOWwtOS00LjFjMCAwLTUuMy0xNCA2LjEtMjQuMSAyLjQgMiA1LjEgMjUgMi45IDI4LjIiIGZpbGw9IiNmZmYiLz48cGF0aCBkPSJtOC4xIDMyLjFsMjIuNi0xNC45YzAgMC0xMi45LTE3LjQtMTkuNC0xNC45LTMgMS4xLTUuMyAyNS4xLTMuMiAyOS44IiBmaWxsPSIjM2U0MzQ3Ii8+PHBhdGggZD0ibTkuMSAzMy45bDktNC4xYzAgMCA1LjMtMTQtNi4xLTI0LjEtMi40IDItNS4xIDI1LTIuOSAyOC4yIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTMyLDEzQzE4LjksMTMsMiwzMy42LDIsNDUuNEMyMC41LDQ1LjQsMTkuNyw2MiwzMiw2MnMxMS41LTE2LjYsMzAtMTYuNkM2MiwzMy42LDQ1LjEsMTMsMzIsMTN6IiBmaWxsPSIjZmY4NzM2Ii8+PGcgZmlsbD0iI2ZmZiI+PHBhdGggZD0iTTMyLDU2LjJjMCw1LjEsOS42LDQuMiw5LjUtMi45YzYuNy05LjQsMTkuOS04LjcsMTkuOS04LjdDMzkuNiwzMi40LDMyLDU2LjIsMzIsNTYuMnoiLz48cGF0aCBkPSJNMzIsNTYuMmMwLDUuMS05LjYsNC4yLTkuNS0yLjlDMTUuOCw0NCwyLjYsNDQuNywyLjYsNDQuN0MyNC40LDMyLjQsMzIsNTYuMiwzMiw1Ni4yeiIvPjwvZz48ZyBmaWxsPSIjZmY4NzM2Ij48cGF0aCBkPSJtNTMuNCAxOC41Yy00IC43LTQuOSA2LjMtNC45IDYuM2w2IDUuM2MtMi4zLTUuOS0xLjEtMTEuNi0xLjEtMTEuNiIvPjxwYXRoIGQ9Im01MS4xIDEzLjVjLTQuNCAzLjktNS4xIDguNy01LjEgOC43bDYgNS4zYy0yLjQtNS44LS45LTE0LS45LTE0Ii8+PHBhdGggZD0ibTEwLjYgMTguNWM0IC43IDQuOSA2LjMgNC45IDYuM2wtNiA1LjNjMi4zLTUuOSAxLjEtMTEuNiAxLjEtMTEuNiIvPjxwYXRoIGQ9Im0xMi45IDEzLjVjNC40IDMuOSA1LjEgOC43IDUuMSA4LjdsLTYgNS4zYzIuNC01LjguOS0xNCAuOS0xNCIvPjwvZz48cGF0aCBkPSJtNTIuOCAzMS4xYy01LjctMS44LTEwLjktMy40LTEzLjguOS0yLjQgMy43LjcgOS40LjcgOS40IDExLjIgMS4yIDEzLjEtMTAuMyAxMy4xLTEwLjMiIGZpbGw9IiMzZTQzNDciLz48ZWxsaXBzZSBjeD0iNDMiIGN5PSIzNi4zIiByeD0iNC4yIiByeT0iNC4xIiBmaWxsPSIjZDVmZjgzIi8+PGcgZmlsbD0iIzNlNDM0NyI+PGVsbGlwc2UgY3g9IjQzIiBjeT0iMzYuMyIgcng9IjIuNyIgcnk9IjIuNyIvPjxwYXRoIGQ9Im0xMS4yIDMxLjFjNS43LTEuOCAxMC45LTMuNCAxMy43LjkgMi40IDMuNy0uNyA5LjQtLjcgOS40LTExLjEgMS4yLTEzLTEwLjMtMTMtMTAuMyIvPjwvZz48ZWxsaXBzZSBjeD0iMjEiIGN5PSIzNi4zIiByeD0iNC4yIiByeT0iNC4xIiBmaWxsPSIjZDVmZjgzIi8+PGcgZmlsbD0iIzNlNDM0NyI+PGVsbGlwc2UgY3g9IjIxIiBjeT0iMzYuMyIgcng9IjIuNyIgcnk9IjIuNyIvPjxwYXRoIGQ9Im00MS4yIDQ3LjljLS43LTIuMy0xLjgtNC40LTMtNi41IDEuMSAyLjEgMiA0LjMgMi41IDYuNi41IDIuMy43IDQuNyAwIDYuOC0uNCAxLTEgMi0xLjggMi42LS44LjYtMS44IDEtMi43IDEtLjkgMC0xLjktLjMtMi41LTEtLjYtLjctLjktMS42LS44LTIuNmwtLjkuMmgtLjljMCAxLS4yIDEuOS0uOCAyLjYtLjYuNy0xLjUgMS0yLjUgMS0uOSAwLTEuOS0uNC0yLjctMS0uOC0uNi0xLjQtMS42LTEuOC0yLjYtLjgtMi4xLS42LTQuNiAwLTYuOC41LTIuMyAxLjUtNC41IDIuNS02LjYtMS4yIDItMi4zIDQuMS0zIDYuNS0uNyAyLjMtMS4xIDQuOC0uNCA3LjMuMyAxLjIgMSAyLjQgMS45IDMuMy45LjkgMi4xIDEuNCAzLjQgMS41IDEuMi4xIDIuNi0uMiAzLjctMS4yLjMtLjIuNS0uNS43LS44LjIuMy40LjYuNy44IDEgMSAyLjQgMS4zIDMuNyAxLjIgMS4zLS4xIDIuNC0uNyAzLjQtMS41LjktLjkgMS42LTIgMS45LTMuMy41LTIuNi4xLTUuMi0uNi03LjUiLz48cGF0aCBkPSJtMzcuNiA1MC4zYy0xLjEtMS4xLTQuNS0xLjItNS42LTEuMi0xIDAtNC41LjEtNS42IDEuMi0uOC44LS4yIDIuOCAxLjkgNC41IDEuMyAxLjEgMi42IDEuNCAzLjYgMS40IDEgMCAyLjMtLjMgMy42LTEuNCAyLjMtMS43IDIuOS0zLjcgMi4xLTQuNSIvPjwvZz48L3N2Zz4=";
|
||||
|
||||
/**
|
||||
* Verifies that the button uses the expected icon.
|
||||
*
|
||||
* @param {string} selector The CSS selector used to find the button
|
||||
* within the DOM.
|
||||
* @param {boolean} shouldHaveCustomStyling True if the button should
|
||||
* have custom styling, False otherwise.
|
||||
* @param {string} message The message that is printed to the console
|
||||
* by the verifyFn.
|
||||
*/
|
||||
/**
|
||||
* Verifies that the button uses the expected icon.
|
||||
*
|
||||
* @param {string} selector The CSS selector used to find the button
|
||||
* within the DOM.
|
||||
* @param {boolean} shouldHaveCustomStyling True if the button should
|
||||
* have custom styling, False otherwise.
|
||||
* @param {string} message The message that is printed to the console
|
||||
* by the verifyFn.
|
||||
*/
|
||||
function verifyButtonProperties(selector, shouldHaveCustomStyling, message) {
|
||||
try {
|
||||
let element = document.querySelector(selector);
|
||||
@ -23,48 +23,50 @@ function verifyButtonProperties(selector, shouldHaveCustomStyling, message) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the button uses default styling.
|
||||
*
|
||||
* @param {string} selector The CSS selector used to find the button
|
||||
* within the DOM.
|
||||
* @param {string} message The message that is printed to the console
|
||||
* by the verifyFn.
|
||||
*/
|
||||
/**
|
||||
* Verifies that the button uses default styling.
|
||||
*
|
||||
* @param {string} selector The CSS selector used to find the button
|
||||
* within the DOM.
|
||||
* @param {string} message The message that is printed to the console
|
||||
* by the verifyFn.
|
||||
*/
|
||||
function verifyButtonWithoutCustomStyling(selector, message) {
|
||||
verifyButtonProperties(selector, false, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the button uses non-default styling.
|
||||
*
|
||||
* @param {string} selector The CSS selector used to find the button
|
||||
* within the DOM.
|
||||
* @param {string} message The message that is printed to the console
|
||||
* by the verifyFn.
|
||||
*/
|
||||
/**
|
||||
* Verifies that the button uses non-default styling.
|
||||
*
|
||||
* @param {string} selector The CSS selector used to find the button
|
||||
* within the DOM.
|
||||
* @param {string} message The message that is printed to the console
|
||||
* by the verifyFn.
|
||||
*/
|
||||
function verifyButtonWithCustomStyling(selector, message) {
|
||||
verifyButtonProperties(selector, true, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops through all of the buttons to confirm that they are styled
|
||||
* as expected (either with or without custom styling).
|
||||
*
|
||||
* @param {object} icons Array of an array that specifies which buttons should
|
||||
* have custom icons.
|
||||
* @param {object} iconInfo An array of arrays that maps API names to
|
||||
* CSS selectors.
|
||||
* @param {string} area The name of the area that the button resides in.
|
||||
*/
|
||||
/**
|
||||
* Loops through all of the buttons to confirm that they are styled
|
||||
* as expected (either with or without custom styling).
|
||||
*
|
||||
* @param {object} icons Array of an array that specifies which buttons should
|
||||
* have custom icons.
|
||||
* @param {object} iconInfo An array of arrays that maps API names to
|
||||
* CSS selectors.
|
||||
* @param {string} area The name of the area that the button resides in.
|
||||
*/
|
||||
function checkButtons(icons, iconInfo, area) {
|
||||
for (let button of iconInfo) {
|
||||
let iconInfo = icons.find(arr => arr[0] == button[0]);
|
||||
if (iconInfo[1]) {
|
||||
verifyButtonWithCustomStyling(button[1],
|
||||
verifyButtonWithCustomStyling(
|
||||
button[1],
|
||||
`The ${button[1]} should have its icon customized in the ${area}`);
|
||||
} else {
|
||||
verifyButtonWithoutCustomStyling(button[1],
|
||||
verifyButtonWithoutCustomStyling(
|
||||
button[1],
|
||||
`The ${button[1]} should not have its icon customized in the ${area}`);
|
||||
}
|
||||
}
|
||||
@ -135,7 +137,8 @@ async function runTestWithIcons(icons) {
|
||||
CustomizableUI.addWidgetToArea(button[2], CustomizableUI.AREA_NAVBAR);
|
||||
}
|
||||
|
||||
verifyButtonWithoutCustomStyling(button[1],
|
||||
verifyButtonWithoutCustomStyling(
|
||||
button[1],
|
||||
`The ${button[1]} should not have its icon customized when the test starts`);
|
||||
|
||||
let iconInfo = icons.find(arr => arr[0] == button[0]);
|
||||
@ -151,7 +154,8 @@ async function runTestWithIcons(icons) {
|
||||
await extension.unload();
|
||||
|
||||
for (let button of ICON_INFO) {
|
||||
verifyButtonWithoutCustomStyling(button[1],
|
||||
verifyButtonWithoutCustomStyling(
|
||||
button[1],
|
||||
`The ${button[1]} should not have its icon customized when the theme is unloaded`);
|
||||
}
|
||||
}
|
||||
|
@ -70,14 +70,14 @@ add_task(async function testWindowTitle() {
|
||||
if (msg === "update") {
|
||||
let win = await browser.windows.get(windowId);
|
||||
browser.test.assertTrue(win.title.startsWith(expected.before.preface),
|
||||
"Window has the expected title preface before update.");
|
||||
"Window has the expected title preface before update.");
|
||||
browser.test.assertTrue(win.title.includes(expected.before.text),
|
||||
"Window has the expected title text before update.");
|
||||
"Window has the expected title text before update.");
|
||||
win = await browser.windows.update(windowId, options);
|
||||
browser.test.assertTrue(win.title.startsWith(expected.after.preface),
|
||||
"Window has the expected title preface after update.");
|
||||
"Window has the expected title preface after update.");
|
||||
browser.test.assertTrue(win.title.includes(expected.after.text),
|
||||
"Window has the expected title text after update.");
|
||||
"Window has the expected title text after update.");
|
||||
browser.test.sendMessage("updated", win);
|
||||
}
|
||||
});
|
||||
|
@ -144,12 +144,15 @@ function promisePossiblyInaccurateContentDimensions(browser) {
|
||||
}
|
||||
|
||||
return {
|
||||
window: copyProps(content,
|
||||
window: copyProps(
|
||||
content,
|
||||
["innerWidth", "innerHeight", "outerWidth", "outerHeight",
|
||||
"scrollX", "scrollY", "scrollMaxX", "scrollMaxY"]),
|
||||
body: copyProps(content.document.body,
|
||||
body: copyProps(
|
||||
content.document.body,
|
||||
["clientWidth", "clientHeight", "scrollWidth", "scrollHeight"]),
|
||||
root: copyProps(content.document.documentElement,
|
||||
root: copyProps(
|
||||
content.document.documentElement,
|
||||
["clientWidth", "clientHeight", "scrollWidth", "scrollHeight"]),
|
||||
isStandards: content.document.compatMode !== "BackCompat",
|
||||
};
|
||||
|
@ -194,10 +194,9 @@ add_task(async function test_bookmarks() {
|
||||
browser.test.assertEq(1, results.length, "getTree returns one result");
|
||||
let bookmark = results[0].children.find(bookmarkItem => bookmarkItem.id == unsortedId);
|
||||
browser.test.assertEq(
|
||||
"Other Bookmarks",
|
||||
bookmark.title,
|
||||
"Folder returned from getTree has the expected title"
|
||||
);
|
||||
"Other Bookmarks",
|
||||
bookmark.title,
|
||||
"Folder returned from getTree has the expected title");
|
||||
browser.test.assertEq("folder", bookmark.type,
|
||||
"Folder returned from getTree has the expected type");
|
||||
|
||||
@ -207,9 +206,8 @@ add_task(async function test_bookmarks() {
|
||||
"Expected error thrown when trying to create a bookmark with an invalid parentId"
|
||||
);
|
||||
browser.test.assertTrue(
|
||||
error.message.includes(`"parentGuid":"invalid"`),
|
||||
"Expected error thrown when trying to create a bookmark with an invalid parentId"
|
||||
);
|
||||
error.message.includes(`"parentGuid":"invalid"`),
|
||||
"Expected error thrown when trying to create a bookmark with an invalid parentId");
|
||||
});
|
||||
}).then(() => {
|
||||
return browser.bookmarks.remove(ourId);
|
||||
@ -695,19 +693,19 @@ add_task(async function test_tree_with_empty_folder() {
|
||||
await browser.bookmarks.create({title: "A bookmark", url: "http://example.com", parentId: nonEmptyFolder.id});
|
||||
|
||||
let tree = await browser.bookmarks.getSubTree(nonEmptyFolder.parentId);
|
||||
browser.test.assertEq(0,
|
||||
tree[0].children[0].children.length,
|
||||
browser.test.assertEq(
|
||||
0, tree[0].children[0].children.length,
|
||||
"The empty folder returns an empty array for children.");
|
||||
browser.test.assertEq(1,
|
||||
tree[0].children[1].children.length,
|
||||
browser.test.assertEq(
|
||||
1, tree[0].children[1].children.length,
|
||||
"The non-empty folder returns a single item array for children.");
|
||||
|
||||
let children = await browser.bookmarks.getChildren(nonEmptyFolder.parentId);
|
||||
// getChildren should only return immediate children. This is not tested in the
|
||||
// monster test above.
|
||||
for (let child of children) {
|
||||
browser.test.assertEq(undefined,
|
||||
child.children,
|
||||
browser.test.assertEq(
|
||||
undefined, child.children,
|
||||
"Child from getChildren does not contain any children.");
|
||||
}
|
||||
|
||||
|
@ -32,15 +32,18 @@ add_task(async function testSettingsProperties() {
|
||||
let settings = await extension.awaitMessage("settings");
|
||||
|
||||
// Verify that we get the keys back we expect.
|
||||
deepEqual(Object.keys(settings.dataToRemove).sort(), SETTINGS_LIST,
|
||||
"dataToRemove contains expected properties.");
|
||||
deepEqual(Object.keys(settings.dataRemovalPermitted).sort(), SETTINGS_LIST,
|
||||
"dataToRemove contains expected properties.");
|
||||
deepEqual(Object.keys(settings.dataToRemove).sort(),
|
||||
SETTINGS_LIST,
|
||||
"dataToRemove contains expected properties.");
|
||||
deepEqual(Object.keys(settings.dataRemovalPermitted).sort(),
|
||||
SETTINGS_LIST,
|
||||
"dataToRemove contains expected properties.");
|
||||
|
||||
let dataTypeSet = settings.dataToRemove;
|
||||
for (let key of Object.keys(dataTypeSet)) {
|
||||
equal(Preferences.get(`${PREF_DOMAIN}${key.toLowerCase()}`), dataTypeSet[key],
|
||||
`${key} property of dataToRemove matches the expected pref.`);
|
||||
equal(Preferences.get(`${PREF_DOMAIN}${key.toLowerCase()}`),
|
||||
dataTypeSet[key],
|
||||
`${key} property of dataToRemove matches the expected pref.`);
|
||||
}
|
||||
|
||||
dataTypeSet = settings.dataRemovalPermitted;
|
||||
|
@ -73,9 +73,10 @@ add_task(async function test_overrides_update_removal() {
|
||||
|
||||
equal(extension.version, "1.0", "The installed addon has the expected version.");
|
||||
ok(getHomePageURL().endsWith(HOMEPAGE_URI),
|
||||
"Home page url is overriden by the extension.");
|
||||
equal(Services.search.currentEngine.name, "DuckDuckGo",
|
||||
"Default engine is overriden by the extension");
|
||||
"Home page url is overriden by the extension.");
|
||||
equal(Services.search.currentEngine.name,
|
||||
"DuckDuckGo",
|
||||
"Default engine is overriden by the extension");
|
||||
|
||||
extensionInfo.manifest = {
|
||||
"version": "2.0",
|
||||
@ -91,10 +92,12 @@ add_task(async function test_overrides_update_removal() {
|
||||
await prefPromise;
|
||||
|
||||
equal(extension.version, "2.0", "The updated addon has the expected version.");
|
||||
equal(getHomePageURL(), defaultHomepageURL,
|
||||
"Home page url reverted to the default after update.");
|
||||
equal(Services.search.currentEngine.name, defaultEngineName,
|
||||
"Default engine reverted to the default after update.");
|
||||
equal(getHomePageURL(),
|
||||
defaultHomepageURL,
|
||||
"Home page url reverted to the default after update.");
|
||||
equal(Services.search.currentEngine.name,
|
||||
defaultEngineName,
|
||||
"Default engine reverted to the default after update.");
|
||||
|
||||
await extension.unload();
|
||||
|
||||
|
@ -6,7 +6,8 @@ add_task(async function() {
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
background: () => {
|
||||
browser.test.sendMessage("features",
|
||||
browser.test.sendMessage(
|
||||
"features",
|
||||
Object.values(browser.geckoProfiler.ProfilerFeature));
|
||||
},
|
||||
manifest: {
|
||||
@ -27,16 +28,16 @@ add_task(async function() {
|
||||
|
||||
const allFeaturesAcceptedByProfiler = Services.profiler.GetAllFeatures([]);
|
||||
ok(allFeaturesAcceptedByProfiler.length >= 2,
|
||||
"Either we've massively reduced the profiler's feature set, or something is wrong.");
|
||||
"Either we've massively reduced the profiler's feature set, or something is wrong.");
|
||||
|
||||
// Check that the list of available values in the ProfilerFeature enum
|
||||
// matches the list of features supported by the profiler.
|
||||
for (const feature of allFeaturesAcceptedByProfiler) {
|
||||
ok(acceptedFeatures.includes(feature),
|
||||
`The schema of the geckoProfiler.start() method should accept the "${feature}" feature.`);
|
||||
`The schema of the geckoProfiler.start() method should accept the "${feature}" feature.`);
|
||||
}
|
||||
for (const feature of acceptedFeatures) {
|
||||
ok(allFeaturesAcceptedByProfiler.includes(feature),
|
||||
`The schema of the geckoProfiler.start() method mentions a "${feature}" feature which is not supported by the profiler.`);
|
||||
`The schema of the geckoProfiler.start() method mentions a "${feature}" feature which is not supported by the profiler.`);
|
||||
}
|
||||
});
|
||||
|
@ -309,8 +309,8 @@ add_task(async function test_add_url() {
|
||||
equal(results.result.title, results.details.title, "URL was added with the correct title");
|
||||
if (results.details.visitTime) {
|
||||
equal(results.result.lastVisitTime,
|
||||
Number(ExtensionUtils.normalizeTime(results.details.visitTime)),
|
||||
"URL was added with the correct date");
|
||||
Number(ExtensionUtils.normalizeTime(results.details.visitTime)),
|
||||
"URL was added with the correct date");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,13 +99,13 @@ add_task(async function test_multiple_extensions_overriding_newtab_page() {
|
||||
let ext3 = ExtensionTestUtils.loadExtension(extObj);
|
||||
|
||||
equal(aboutNewTabService.newTabURL, DEFAULT_NEW_TAB_URL,
|
||||
"newTabURL is set to the default.");
|
||||
"newTabURL is set to the default.");
|
||||
|
||||
await promiseStartupManager();
|
||||
|
||||
await ext1.startup();
|
||||
equal(aboutNewTabService.newTabURL, DEFAULT_NEW_TAB_URL,
|
||||
"newTabURL is still set to the default.");
|
||||
"newTabURL is still set to the default.");
|
||||
|
||||
await checkNewTabPageOverride(ext1, aboutNewTabService.newTabURL, NOT_CONTROLLABLE);
|
||||
|
||||
@ -147,7 +147,7 @@ add_task(async function test_multiple_extensions_overriding_newtab_page() {
|
||||
|
||||
await ext3.startup();
|
||||
ok(aboutNewTabService.newTabURL.endsWith(NEWTAB_URI_3),
|
||||
"newTabURL is overriden by the third extension.");
|
||||
"newTabURL is overriden by the third extension.");
|
||||
await checkNewTabPageOverride(ext2, NEWTAB_URI_3, CONTROLLED_BY_OTHER);
|
||||
|
||||
// Disable the second extension.
|
||||
@ -155,7 +155,7 @@ add_task(async function test_multiple_extensions_overriding_newtab_page() {
|
||||
addon.userDisabled = true;
|
||||
await disabledPromise;
|
||||
ok(aboutNewTabService.newTabURL.endsWith(NEWTAB_URI_3),
|
||||
"newTabURL is still overriden by the third extension.");
|
||||
"newTabURL is still overriden by the third extension.");
|
||||
await checkNewTabPageOverride(ext3, NEWTAB_URI_3, CONTROLLED_BY_THIS);
|
||||
|
||||
// Re-enable the second extension.
|
||||
@ -163,7 +163,7 @@ add_task(async function test_multiple_extensions_overriding_newtab_page() {
|
||||
addon.userDisabled = false;
|
||||
await enabledPromise;
|
||||
ok(aboutNewTabService.newTabURL.endsWith(NEWTAB_URI_3),
|
||||
"newTabURL is still overriden by the third extension.");
|
||||
"newTabURL is still overriden by the third extension.");
|
||||
await checkNewTabPageOverride(ext3, NEWTAB_URI_3, CONTROLLED_BY_THIS);
|
||||
|
||||
await ext3.unload();
|
||||
@ -173,7 +173,7 @@ add_task(async function test_multiple_extensions_overriding_newtab_page() {
|
||||
|
||||
await ext2.unload();
|
||||
equal(aboutNewTabService.newTabURL, DEFAULT_NEW_TAB_URL,
|
||||
"newTabURL url is reset to the default.");
|
||||
"newTabURL url is reset to the default.");
|
||||
|
||||
await promiseShutdownManager();
|
||||
});
|
||||
|
@ -29,6 +29,7 @@ const NOTIFY_INITIATING_MANUAL_RESTORE = "sessionstore-initiating-manual-restore
|
||||
const NOTIFY_CLOSED_OBJECTS_CHANGED = "sessionstore-closed-objects-changed";
|
||||
|
||||
const NOTIFY_TAB_RESTORED = "sessionstore-debug-tab-restored"; // WARNING: debug-only
|
||||
const NOTIFY_DOMWINDOWCLOSED_HANDLED = "sessionstore-debug-domwindowclosed-handled"; // WARNING: debug-only
|
||||
|
||||
// Maximum number of tabs to restore simultaneously. Previously controlled by
|
||||
// the browser.sessionstore.max_concurrent_tabs pref.
|
||||
@ -772,6 +773,9 @@ var SessionStoreInternal = {
|
||||
this.onClose(aSubject).then(() => {
|
||||
this._notifyOfClosedObjectsChange();
|
||||
});
|
||||
if (gDebuggingEnabled) {
|
||||
Services.obs.notifyObservers(null, NOTIFY_DOMWINDOWCLOSED_HANDLED);
|
||||
}
|
||||
break;
|
||||
case "quit-application-granted":
|
||||
let syncShutdown = aData == "syncShutdown";
|
||||
|
@ -42,28 +42,30 @@ add_task(async function test_add_interesting_window() {
|
||||
// it's really not worth restoring.
|
||||
browser.userTypedValue = null;
|
||||
|
||||
// Once the domWindowClosed Promise resolves, the window should
|
||||
// have closed, and SessionStore's onClose handler should have just
|
||||
// run.
|
||||
let domWindowClosed = BrowserTestUtils.domWindowClosed(newWin);
|
||||
|
||||
// Once this windowClosed Promise resolves, we should have finished
|
||||
// the flush and revisited our decision to put this window into
|
||||
// the closed windows array.
|
||||
let windowClosed = BrowserTestUtils.windowClosed(newWin);
|
||||
|
||||
let handled = false;
|
||||
whenDomWindowClosedHandled(() => {
|
||||
// SessionStore's onClose handler should have just run.
|
||||
let currentClosedWindows = ss.getClosedWindowCount();
|
||||
is(currentClosedWindows, initialClosedWindows,
|
||||
"We should not have added the window to the closed windows array");
|
||||
|
||||
handled = true;
|
||||
});
|
||||
|
||||
// Ok, let's close the window.
|
||||
newWin.close();
|
||||
|
||||
await domWindowClosed;
|
||||
// OnClose has just finished running.
|
||||
let currentClosedWindows = ss.getClosedWindowCount();
|
||||
is(currentClosedWindows, initialClosedWindows,
|
||||
"We should not have added the window to the closed windows array");
|
||||
|
||||
await windowClosed;
|
||||
|
||||
ok(handled, "domwindowclosed should already be handled here");
|
||||
|
||||
// The window flush has finished
|
||||
currentClosedWindows = ss.getClosedWindowCount();
|
||||
let currentClosedWindows = ss.getClosedWindowCount();
|
||||
is(currentClosedWindows,
|
||||
initialClosedWindows + 1,
|
||||
"We should have added the window to the closed windows array");
|
||||
@ -110,28 +112,30 @@ add_task(async function test_remove_uninteresting_window() {
|
||||
sessionHistory.PurgeHistory(sessionHistory.count);
|
||||
});
|
||||
|
||||
// Once the domWindowClosed Promise resolves, the window should
|
||||
// have closed, and SessionStore's onClose handler should have just
|
||||
// run.
|
||||
let domWindowClosed = BrowserTestUtils.domWindowClosed(newWin);
|
||||
|
||||
// Once this windowClosed Promise resolves, we should have finished
|
||||
// the flush and revisited our decision to put this window into
|
||||
// the closed windows array.
|
||||
let windowClosed = BrowserTestUtils.windowClosed(newWin);
|
||||
|
||||
let handled = false;
|
||||
whenDomWindowClosedHandled(() => {
|
||||
// SessionStore's onClose handler should have just run.
|
||||
let currentClosedWindows = ss.getClosedWindowCount();
|
||||
is(currentClosedWindows, initialClosedWindows + 1,
|
||||
"We should have added the window to the closed windows array");
|
||||
|
||||
handled = true;
|
||||
});
|
||||
|
||||
// Ok, let's close the window.
|
||||
newWin.close();
|
||||
|
||||
await domWindowClosed;
|
||||
// OnClose has just finished running.
|
||||
let currentClosedWindows = ss.getClosedWindowCount();
|
||||
is(currentClosedWindows, initialClosedWindows + 1,
|
||||
"We should have added the window to the closed windows array");
|
||||
|
||||
await windowClosed;
|
||||
|
||||
ok(handled, "domwindowclosed should already be handled here");
|
||||
|
||||
// The window flush has finished
|
||||
currentClosedWindows = ss.getClosedWindowCount();
|
||||
let currentClosedWindows = ss.getClosedWindowCount();
|
||||
is(currentClosedWindows,
|
||||
initialClosedWindows,
|
||||
"We should have removed the window from the closed windows array");
|
||||
|
@ -84,21 +84,26 @@ let forgetWinHelper = async function(forgetFn) {
|
||||
|
||||
// Now close the window and immediately choose to forget it.
|
||||
let windowClosed = BrowserTestUtils.windowClosed(newWin);
|
||||
let domWindowClosed = BrowserTestUtils.domWindowClosed(newWin);
|
||||
|
||||
let handled = false;
|
||||
whenDomWindowClosedHandled(() => {
|
||||
// At this point, the window will have closed and the onClose handler
|
||||
// has run, but the final update to SessionStore hasn't come up yet.
|
||||
// Now do the oepration that should cause us to forget the window.
|
||||
forgetFn();
|
||||
|
||||
is(ss.getClosedWindowCount(), 0, "Should have forgotten the closed window");
|
||||
|
||||
handled = true;
|
||||
});
|
||||
|
||||
newWin.close();
|
||||
await domWindowClosed;
|
||||
|
||||
// At this point, the window will have closed and the onClose handler
|
||||
// has run, but the final update to SessionStore hasn't come up yet.
|
||||
// Now do the oepration that should cause us to forget the window.
|
||||
forgetFn();
|
||||
|
||||
is(ss.getClosedWindowCount(), 0, "Should have forgotten the closed window");
|
||||
|
||||
// Now wait for the final update to come up.
|
||||
await windowClosed;
|
||||
|
||||
ok(handled, "domwindowclosed should already be handled here");
|
||||
|
||||
is(ss.getClosedWindowCount(), 0, "Should not have stored the closed window");
|
||||
};
|
||||
|
||||
|
@ -564,3 +564,10 @@ async function checkScroll(tab, expected, msg) {
|
||||
let scroll = JSON.parse(ss.getTabState(tab)).scroll || null;
|
||||
is(JSON.stringify(scroll), JSON.stringify(expected), msg);
|
||||
}
|
||||
|
||||
function whenDomWindowClosedHandled(aCallback) {
|
||||
Services.obs.addObserver(function observer(aSubject, aTopic) {
|
||||
Services.obs.removeObserver(observer, aTopic);
|
||||
aCallback();
|
||||
}, "sessionstore-debug-domwindowclosed-handled");
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
This is the PDF.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 2.0.185
|
||||
Current extension version is: 2.0.197
|
||||
|
||||
Taken from upstream commit: f2994736
|
||||
Taken from upstream commit: 371ca514
|
||||
|
@ -79,6 +79,7 @@ function isDefaultHandler() {
|
||||
}
|
||||
|
||||
function initializeDefaultPreferences() {
|
||||
/* eslint-disable semi */
|
||||
var DEFAULT_PREFERENCES =
|
||||
{
|
||||
"showPreviousViewOnLoad": true,
|
||||
@ -101,8 +102,9 @@ function initializeDefaultPreferences() {
|
||||
"enablePrintAutoRotate": false,
|
||||
"disablePageMode": false,
|
||||
"disablePageLabels": false
|
||||
};
|
||||
}
|
||||
|
||||
/* eslint-enable semi */
|
||||
|
||||
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + ".");
|
||||
var defaultValue;
|
||||
|
@ -33,6 +33,7 @@ XPCOMUtils.defineLazyServiceGetter(Svc, "mime",
|
||||
"@mozilla.org/mime;1",
|
||||
"nsIMIMEService");
|
||||
|
||||
/* eslint-disable semi */
|
||||
var DEFAULT_PREFERENCES =
|
||||
{
|
||||
"showPreviousViewOnLoad": true,
|
||||
@ -55,8 +56,9 @@ var DEFAULT_PREFERENCES =
|
||||
"enablePrintAutoRotate": false,
|
||||
"disablePageMode": false,
|
||||
"disablePageLabels": false
|
||||
};
|
||||
}
|
||||
|
||||
/* eslint-enable semi */
|
||||
|
||||
var PdfjsChromeUtils = {
|
||||
// For security purposes when running remote, we restrict preferences
|
||||
|
@ -98,7 +98,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.unreachable = exports.warn = exports.utf8StringToString = exports.stringToUTF8String = exports.stringToPDFString = exports.stringToBytes = exports.string32 = exports.shadow = exports.setVerbosityLevel = exports.ReadableStream = exports.removeNullCharacters = exports.readUint32 = exports.readUint16 = exports.readInt8 = exports.log2 = exports.loadJpegStream = exports.isEvalSupported = exports.isLittleEndian = exports.createValidAbsoluteUrl = exports.isSameOrigin = exports.isNodeJS = exports.isSpace = exports.isString = exports.isNum = exports.isEmptyObj = exports.isBool = exports.isArrayBuffer = exports.info = exports.getVerbosityLevel = exports.getLookupTableFactory = exports.deprecated = exports.createObjectURL = exports.createPromiseCapability = exports.createBlob = exports.bytesToString = exports.assert = exports.arraysToBytes = exports.arrayByteLength = exports.FormatError = exports.XRefParseException = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.StatTimer = exports.PasswordResponses = exports.PasswordException = exports.PageViewport = exports.NotImplementedException = exports.NativeImageDecoding = exports.MissingPDFException = exports.MissingDataException = exports.MessageHandler = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VERBOSITY_LEVELS = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = undefined;
|
||||
exports.unreachable = exports.warn = exports.utf8StringToString = exports.stringToUTF8String = exports.stringToPDFString = exports.stringToBytes = exports.string32 = exports.shadow = exports.setVerbosityLevel = exports.ReadableStream = exports.removeNullCharacters = exports.readUint32 = exports.readUint16 = exports.readInt8 = exports.log2 = exports.loadJpegStream = exports.isEvalSupported = exports.isLittleEndian = exports.createValidAbsoluteUrl = exports.isSameOrigin = exports.isNodeJS = exports.isSpace = exports.isString = exports.isNum = exports.isEmptyObj = exports.isBool = exports.isArrayBuffer = exports.info = exports.getVerbosityLevel = exports.getLookupTableFactory = exports.deprecated = exports.createObjectURL = exports.createPromiseCapability = exports.createBlob = exports.bytesToString = exports.assert = exports.arraysToBytes = exports.arrayByteLength = exports.FormatError = exports.XRefParseException = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PasswordResponses = exports.PasswordException = exports.PageViewport = exports.NotImplementedException = exports.NativeImageDecoding = exports.MissingPDFException = exports.MissingDataException = exports.MessageHandler = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VERBOSITY_LEVELS = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = undefined;
|
||||
|
||||
__w_pdfjs_require__(9);
|
||||
|
||||
@ -904,63 +904,6 @@ function createPromiseCapability() {
|
||||
});
|
||||
return capability;
|
||||
}
|
||||
var StatTimer = function StatTimerClosure() {
|
||||
function rpad(str, pad, length) {
|
||||
while (str.length < length) {
|
||||
str += pad;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
function StatTimer() {
|
||||
this.started = Object.create(null);
|
||||
this.times = [];
|
||||
this.enabled = true;
|
||||
}
|
||||
StatTimer.prototype = {
|
||||
time: function StatTimer_time(name) {
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
if (name in this.started) {
|
||||
warn('Timer is already running for ' + name);
|
||||
}
|
||||
this.started[name] = Date.now();
|
||||
},
|
||||
timeEnd: function StatTimer_timeEnd(name) {
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
if (!(name in this.started)) {
|
||||
warn('Timer has not been started for ' + name);
|
||||
}
|
||||
this.times.push({
|
||||
'name': name,
|
||||
'start': this.started[name],
|
||||
'end': Date.now()
|
||||
});
|
||||
delete this.started[name];
|
||||
},
|
||||
toString: function StatTimer_toString() {
|
||||
var i, ii;
|
||||
var times = this.times;
|
||||
var out = '';
|
||||
var longest = 0;
|
||||
for (i = 0, ii = times.length; i < ii; ++i) {
|
||||
var name = times[i]['name'];
|
||||
if (name.length > longest) {
|
||||
longest = name.length;
|
||||
}
|
||||
}
|
||||
for (i = 0, ii = times.length; i < ii; ++i) {
|
||||
var span = times[i];
|
||||
var duration = span.end - span.start;
|
||||
out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
return StatTimer;
|
||||
}();
|
||||
var createBlob = function createBlob(data, contentType) {
|
||||
if (typeof Blob !== 'undefined') {
|
||||
return new Blob([data], { type: contentType });
|
||||
@ -1399,7 +1342,6 @@ exports.NotImplementedException = NotImplementedException;
|
||||
exports.PageViewport = PageViewport;
|
||||
exports.PasswordException = PasswordException;
|
||||
exports.PasswordResponses = PasswordResponses;
|
||||
exports.StatTimer = StatTimer;
|
||||
exports.StreamType = StreamType;
|
||||
exports.TextRenderingMode = TextRenderingMode;
|
||||
exports.UnexpectedResponseException = UnexpectedResponseException;
|
||||
@ -1456,7 +1398,7 @@ exports.unreachable = unreachable;
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.SimpleXMLParser = exports.DOMSVGFactory = exports.DOMCMapReaderFactory = exports.DOMCanvasFactory = exports.DEFAULT_LINK_REL = exports.getDefaultSetting = exports.LinkTarget = exports.getFilenameFromUrl = exports.isExternalLinkTargetSet = exports.addLinkAttributes = exports.RenderingCancelledException = exports.CustomStyle = undefined;
|
||||
exports.DummyStatTimer = exports.StatTimer = exports.SimpleXMLParser = exports.DOMSVGFactory = exports.DOMCMapReaderFactory = exports.DOMCanvasFactory = exports.DEFAULT_LINK_REL = exports.getDefaultSetting = exports.LinkTarget = exports.getFilenameFromUrl = exports.isExternalLinkTargetSet = exports.addLinkAttributes = exports.RenderingCancelledException = exports.CustomStyle = undefined;
|
||||
|
||||
var _util = __w_pdfjs_require__(0);
|
||||
|
||||
@ -1805,6 +1747,67 @@ function isExternalLinkTargetSet() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
class StatTimer {
|
||||
constructor(enable = true) {
|
||||
this.enabled = !!enable;
|
||||
this.reset();
|
||||
}
|
||||
reset() {
|
||||
this.started = Object.create(null);
|
||||
this.times = [];
|
||||
}
|
||||
time(name) {
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
if (name in this.started) {
|
||||
(0, _util.warn)('Timer is already running for ' + name);
|
||||
}
|
||||
this.started[name] = Date.now();
|
||||
}
|
||||
timeEnd(name) {
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
if (!(name in this.started)) {
|
||||
(0, _util.warn)('Timer has not been started for ' + name);
|
||||
}
|
||||
this.times.push({
|
||||
'name': name,
|
||||
'start': this.started[name],
|
||||
'end': Date.now()
|
||||
});
|
||||
delete this.started[name];
|
||||
}
|
||||
toString() {
|
||||
let times = this.times;
|
||||
let out = '',
|
||||
longest = 0;
|
||||
for (let i = 0, ii = times.length; i < ii; ++i) {
|
||||
let name = times[i]['name'];
|
||||
if (name.length > longest) {
|
||||
longest = name.length;
|
||||
}
|
||||
}
|
||||
for (let i = 0, ii = times.length; i < ii; ++i) {
|
||||
let span = times[i];
|
||||
let duration = span.end - span.start;
|
||||
out += `${span['name'].padEnd(longest)} ${duration}ms\n`;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
class DummyStatTimer {
|
||||
constructor() {
|
||||
throw new Error('Cannot initialize DummyStatTimer.');
|
||||
}
|
||||
static reset() {}
|
||||
static time(name) {}
|
||||
static timeEnd(name) {}
|
||||
static toString() {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
exports.CustomStyle = CustomStyle;
|
||||
exports.RenderingCancelledException = RenderingCancelledException;
|
||||
exports.addLinkAttributes = addLinkAttributes;
|
||||
@ -1817,6 +1820,8 @@ exports.DOMCanvasFactory = DOMCanvasFactory;
|
||||
exports.DOMCMapReaderFactory = DOMCMapReaderFactory;
|
||||
exports.DOMSVGFactory = DOMSVGFactory;
|
||||
exports.SimpleXMLParser = SimpleXMLParser;
|
||||
exports.StatTimer = StatTimer;
|
||||
exports.DummyStatTimer = DummyStatTimer;
|
||||
|
||||
/***/ }),
|
||||
/* 2 */
|
||||
@ -1960,7 +1965,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
|
||||
if (worker.destroyed) {
|
||||
return Promise.reject(new Error('Worker was destroyed'));
|
||||
}
|
||||
let apiVersion = '2.0.185';
|
||||
let apiVersion = '2.0.197';
|
||||
source.disableRange = (0, _dom_utils.getDefaultSetting)('disableRange');
|
||||
source.disableAutoFetch = (0, _dom_utils.getDefaultSetting)('disableAutoFetch');
|
||||
source.disableStream = (0, _dom_utils.getDefaultSetting)('disableStream');
|
||||
@ -2144,8 +2149,7 @@ var PDFPageProxy = function PDFPageProxyClosure() {
|
||||
this.pageIndex = pageIndex;
|
||||
this.pageInfo = pageInfo;
|
||||
this.transport = transport;
|
||||
this.stats = new _util.StatTimer();
|
||||
this.stats.enabled = (0, _dom_utils.getDefaultSetting)('enableStats');
|
||||
this._stats = (0, _dom_utils.getDefaultSetting)('enableStats') ? new _dom_utils.StatTimer() : _dom_utils.DummyStatTimer;
|
||||
this.commonObjs = transport.commonObjs;
|
||||
this.objs = new PDFObjects();
|
||||
this.cleanupAfterRender = false;
|
||||
@ -2184,7 +2188,7 @@ var PDFPageProxy = function PDFPageProxyClosure() {
|
||||
return this.annotationsPromise;
|
||||
},
|
||||
render: function PDFPageProxy_render(params) {
|
||||
var stats = this.stats;
|
||||
let stats = this._stats;
|
||||
stats.time('Overall');
|
||||
this.pendingCleanup = false;
|
||||
var renderingIntent = params.intent === 'print' ? 'print' : 'display';
|
||||
@ -2202,7 +2206,7 @@ var PDFPageProxy = function PDFPageProxyClosure() {
|
||||
argsArray: [],
|
||||
lastChunk: false
|
||||
};
|
||||
this.stats.time('Page Request');
|
||||
stats.time('Page Request');
|
||||
this.transport.messageHandler.send('RenderPageRequest', {
|
||||
pageIndex: this.pageNumber - 1,
|
||||
intent: renderingIntent,
|
||||
@ -2335,11 +2339,11 @@ var PDFPageProxy = function PDFPageProxyClosure() {
|
||||
this.pendingCleanup = false;
|
||||
return Promise.all(waitOn);
|
||||
},
|
||||
cleanup: function PDFPageProxy_cleanup() {
|
||||
cleanup(resetStats = false) {
|
||||
this.pendingCleanup = true;
|
||||
this._tryCleanup();
|
||||
this._tryCleanup(resetStats);
|
||||
},
|
||||
_tryCleanup: function PDFPageProxy_tryCleanup() {
|
||||
_tryCleanup(resetStats = false) {
|
||||
if (!this.pendingCleanup || Object.keys(this.intentStates).some(function (intent) {
|
||||
var intentState = this.intentStates[intent];
|
||||
return intentState.renderTasks.length !== 0 || intentState.receivingOperatorList;
|
||||
@ -2351,6 +2355,9 @@ var PDFPageProxy = function PDFPageProxyClosure() {
|
||||
}, this);
|
||||
this.objs.clear();
|
||||
this.annotationsPromise = null;
|
||||
if (resetStats) {
|
||||
this._stats.reset();
|
||||
}
|
||||
this.pendingCleanup = false;
|
||||
},
|
||||
_startRenderPage: function PDFPageProxy_startRenderPage(transparency, intent) {
|
||||
@ -2374,6 +2381,9 @@ var PDFPageProxy = function PDFPageProxyClosure() {
|
||||
intentState.receivingOperatorList = false;
|
||||
this._tryCleanup();
|
||||
}
|
||||
},
|
||||
get stats() {
|
||||
return this._stats instanceof _dom_utils.StatTimer ? this._stats : null;
|
||||
}
|
||||
};
|
||||
return PDFPageProxy;
|
||||
@ -2804,7 +2814,7 @@ var WorkerTransport = function WorkerTransportClosure() {
|
||||
return;
|
||||
}
|
||||
var page = this.pageCache[data.pageIndex];
|
||||
page.stats.timeEnd('Page Request');
|
||||
page._stats.timeEnd('Page Request');
|
||||
page._startRenderPage(data.transparency, data.intent);
|
||||
}, this);
|
||||
messageHandler.on('RenderPageChunk', function transportRender(data) {
|
||||
@ -3253,8 +3263,8 @@ var InternalRenderTask = function InternalRenderTaskClosure() {
|
||||
}();
|
||||
var version, build;
|
||||
{
|
||||
exports.version = version = '2.0.185';
|
||||
exports.build = build = 'f2994736';
|
||||
exports.version = version = '2.0.197';
|
||||
exports.build = build = '371ca514';
|
||||
}
|
||||
exports.getDocument = getDocument;
|
||||
exports.LoopbackPort = LoopbackPort;
|
||||
@ -4627,8 +4637,8 @@ exports.SVGGraphics = SVGGraphics;
|
||||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.0.185';
|
||||
var pdfjsBuild = 'f2994736';
|
||||
var pdfjsVersion = '2.0.197';
|
||||
var pdfjsBuild = '371ca514';
|
||||
var pdfjsSharedUtil = __w_pdfjs_require__(0);
|
||||
var pdfjsDisplayGlobal = __w_pdfjs_require__(12);
|
||||
var pdfjsDisplayAPI = __w_pdfjs_require__(3);
|
||||
@ -4664,7 +4674,6 @@ exports.createBlob = pdfjsSharedUtil.createBlob;
|
||||
exports.RenderingCancelledException = pdfjsDisplayDOMUtils.RenderingCancelledException;
|
||||
exports.getFilenameFromUrl = pdfjsDisplayDOMUtils.getFilenameFromUrl;
|
||||
exports.addLinkAttributes = pdfjsDisplayDOMUtils.addLinkAttributes;
|
||||
exports.StatTimer = pdfjsSharedUtil.StatTimer;
|
||||
|
||||
/***/ }),
|
||||
/* 9 */
|
||||
@ -7752,8 +7761,8 @@ if (!_global_scope2.default.PDFJS) {
|
||||
}
|
||||
var PDFJS = _global_scope2.default.PDFJS;
|
||||
{
|
||||
PDFJS.version = '2.0.185';
|
||||
PDFJS.build = 'f2994736';
|
||||
PDFJS.version = '2.0.197';
|
||||
PDFJS.build = '371ca514';
|
||||
}
|
||||
PDFJS.pdfBug = false;
|
||||
if (PDFJS.verbosity !== undefined) {
|
||||
|
166
browser/extensions/pdfjs/content/build/pdf.worker.js
vendored
166
browser/extensions/pdfjs/content/build/pdf.worker.js
vendored
@ -98,7 +98,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.unreachable = exports.warn = exports.utf8StringToString = exports.stringToUTF8String = exports.stringToPDFString = exports.stringToBytes = exports.string32 = exports.shadow = exports.setVerbosityLevel = exports.ReadableStream = exports.removeNullCharacters = exports.readUint32 = exports.readUint16 = exports.readInt8 = exports.log2 = exports.loadJpegStream = exports.isEvalSupported = exports.isLittleEndian = exports.createValidAbsoluteUrl = exports.isSameOrigin = exports.isNodeJS = exports.isSpace = exports.isString = exports.isNum = exports.isEmptyObj = exports.isBool = exports.isArrayBuffer = exports.info = exports.getVerbosityLevel = exports.getLookupTableFactory = exports.deprecated = exports.createObjectURL = exports.createPromiseCapability = exports.createBlob = exports.bytesToString = exports.assert = exports.arraysToBytes = exports.arrayByteLength = exports.FormatError = exports.XRefParseException = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.StatTimer = exports.PasswordResponses = exports.PasswordException = exports.PageViewport = exports.NotImplementedException = exports.NativeImageDecoding = exports.MissingPDFException = exports.MissingDataException = exports.MessageHandler = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VERBOSITY_LEVELS = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = undefined;
|
||||
exports.unreachable = exports.warn = exports.utf8StringToString = exports.stringToUTF8String = exports.stringToPDFString = exports.stringToBytes = exports.string32 = exports.shadow = exports.setVerbosityLevel = exports.ReadableStream = exports.removeNullCharacters = exports.readUint32 = exports.readUint16 = exports.readInt8 = exports.log2 = exports.loadJpegStream = exports.isEvalSupported = exports.isLittleEndian = exports.createValidAbsoluteUrl = exports.isSameOrigin = exports.isNodeJS = exports.isSpace = exports.isString = exports.isNum = exports.isEmptyObj = exports.isBool = exports.isArrayBuffer = exports.info = exports.getVerbosityLevel = exports.getLookupTableFactory = exports.deprecated = exports.createObjectURL = exports.createPromiseCapability = exports.createBlob = exports.bytesToString = exports.assert = exports.arraysToBytes = exports.arrayByteLength = exports.FormatError = exports.XRefParseException = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PasswordResponses = exports.PasswordException = exports.PageViewport = exports.NotImplementedException = exports.NativeImageDecoding = exports.MissingPDFException = exports.MissingDataException = exports.MessageHandler = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VERBOSITY_LEVELS = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = undefined;
|
||||
|
||||
__w_pdfjs_require__(20);
|
||||
|
||||
@ -904,63 +904,6 @@ function createPromiseCapability() {
|
||||
});
|
||||
return capability;
|
||||
}
|
||||
var StatTimer = function StatTimerClosure() {
|
||||
function rpad(str, pad, length) {
|
||||
while (str.length < length) {
|
||||
str += pad;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
function StatTimer() {
|
||||
this.started = Object.create(null);
|
||||
this.times = [];
|
||||
this.enabled = true;
|
||||
}
|
||||
StatTimer.prototype = {
|
||||
time: function StatTimer_time(name) {
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
if (name in this.started) {
|
||||
warn('Timer is already running for ' + name);
|
||||
}
|
||||
this.started[name] = Date.now();
|
||||
},
|
||||
timeEnd: function StatTimer_timeEnd(name) {
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
if (!(name in this.started)) {
|
||||
warn('Timer has not been started for ' + name);
|
||||
}
|
||||
this.times.push({
|
||||
'name': name,
|
||||
'start': this.started[name],
|
||||
'end': Date.now()
|
||||
});
|
||||
delete this.started[name];
|
||||
},
|
||||
toString: function StatTimer_toString() {
|
||||
var i, ii;
|
||||
var times = this.times;
|
||||
var out = '';
|
||||
var longest = 0;
|
||||
for (i = 0, ii = times.length; i < ii; ++i) {
|
||||
var name = times[i]['name'];
|
||||
if (name.length > longest) {
|
||||
longest = name.length;
|
||||
}
|
||||
}
|
||||
for (i = 0, ii = times.length; i < ii; ++i) {
|
||||
var span = times[i];
|
||||
var duration = span.end - span.start;
|
||||
out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
return StatTimer;
|
||||
}();
|
||||
var createBlob = function createBlob(data, contentType) {
|
||||
if (typeof Blob !== 'undefined') {
|
||||
return new Blob([data], { type: contentType });
|
||||
@ -1399,7 +1342,6 @@ exports.NotImplementedException = NotImplementedException;
|
||||
exports.PageViewport = PageViewport;
|
||||
exports.PasswordException = PasswordException;
|
||||
exports.PasswordResponses = PasswordResponses;
|
||||
exports.StatTimer = StatTimer;
|
||||
exports.StreamType = StreamType;
|
||||
exports.TextRenderingMode = TextRenderingMode;
|
||||
exports.UnexpectedResponseException = UnexpectedResponseException;
|
||||
@ -17047,7 +16989,7 @@ exports.CFFCompiler = CFFCompiler;
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getSupplementalGlyphMapForArialBlack = exports.getGlyphMapForStandardFonts = exports.getSymbolsFonts = exports.getSerifFonts = exports.getNonStdFontMap = exports.getStdFontMap = undefined;
|
||||
exports.getSupplementalGlyphMapForCalibri = exports.getSupplementalGlyphMapForArialBlack = exports.getGlyphMapForStandardFonts = exports.getSymbolsFonts = exports.getSerifFonts = exports.getNonStdFontMap = exports.getStdFontMap = undefined;
|
||||
|
||||
var _util = __w_pdfjs_require__(0);
|
||||
|
||||
@ -17110,6 +17052,10 @@ var getStdFontMap = (0, _util.getLookupTableFactory)(function (t) {
|
||||
t['TimesNewRomanPSMT-Italic'] = 'Times-Italic';
|
||||
});
|
||||
var getNonStdFontMap = (0, _util.getLookupTableFactory)(function (t) {
|
||||
t['Calibri'] = 'Helvetica';
|
||||
t['Calibri-Bold'] = 'Helvetica-Bold';
|
||||
t['Calibri-BoldItalic'] = 'Helvetica-BoldOblique';
|
||||
t['Calibri-Italic'] = 'Helvetica-Oblique';
|
||||
t['CenturyGothic'] = 'Helvetica';
|
||||
t['CenturyGothic-Bold'] = 'Helvetica-Bold';
|
||||
t['CenturyGothic-BoldItalic'] = 'Helvetica-BoldOblique';
|
||||
@ -17681,12 +17627,99 @@ var getSupplementalGlyphMapForArialBlack = (0, _util.getLookupTableFactory)(func
|
||||
t[264] = 261;
|
||||
t[291] = 346;
|
||||
});
|
||||
let getSupplementalGlyphMapForCalibri = (0, _util.getLookupTableFactory)(function (t) {
|
||||
t[1] = 32;
|
||||
t[4] = 65;
|
||||
t[17] = 66;
|
||||
t[18] = 67;
|
||||
t[24] = 68;
|
||||
t[28] = 69;
|
||||
t[38] = 70;
|
||||
t[39] = 71;
|
||||
t[44] = 72;
|
||||
t[47] = 73;
|
||||
t[58] = 74;
|
||||
t[60] = 75;
|
||||
t[62] = 76;
|
||||
t[68] = 77;
|
||||
t[69] = 78;
|
||||
t[75] = 79;
|
||||
t[87] = 80;
|
||||
t[89] = 81;
|
||||
t[90] = 82;
|
||||
t[94] = 83;
|
||||
t[100] = 84;
|
||||
t[104] = 85;
|
||||
t[115] = 86;
|
||||
t[116] = 87;
|
||||
t[121] = 88;
|
||||
t[122] = 89;
|
||||
t[127] = 90;
|
||||
t[258] = 97;
|
||||
t[268] = 261;
|
||||
t[271] = 98;
|
||||
t[272] = 99;
|
||||
t[273] = 263;
|
||||
t[282] = 100;
|
||||
t[286] = 101;
|
||||
t[295] = 281;
|
||||
t[296] = 102;
|
||||
t[336] = 103;
|
||||
t[346] = 104;
|
||||
t[349] = 105;
|
||||
t[361] = 106;
|
||||
t[364] = 107;
|
||||
t[367] = 108;
|
||||
t[371] = 322;
|
||||
t[373] = 109;
|
||||
t[374] = 110;
|
||||
t[381] = 111;
|
||||
t[383] = 243;
|
||||
t[393] = 112;
|
||||
t[395] = 113;
|
||||
t[396] = 114;
|
||||
t[400] = 115;
|
||||
t[401] = 347;
|
||||
t[410] = 116;
|
||||
t[437] = 117;
|
||||
t[448] = 118;
|
||||
t[449] = 119;
|
||||
t[454] = 120;
|
||||
t[455] = 121;
|
||||
t[460] = 122;
|
||||
t[463] = 380;
|
||||
t[853] = 44;
|
||||
t[855] = 58;
|
||||
t[856] = 46;
|
||||
t[876] = 47;
|
||||
t[878] = 45;
|
||||
t[882] = 45;
|
||||
t[894] = 40;
|
||||
t[895] = 41;
|
||||
t[896] = 91;
|
||||
t[897] = 93;
|
||||
t[923] = 64;
|
||||
t[1004] = 48;
|
||||
t[1005] = 49;
|
||||
t[1006] = 50;
|
||||
t[1007] = 51;
|
||||
t[1008] = 52;
|
||||
t[1009] = 53;
|
||||
t[1010] = 54;
|
||||
t[1011] = 55;
|
||||
t[1012] = 56;
|
||||
t[1013] = 57;
|
||||
t[1081] = 37;
|
||||
t[1085] = 43;
|
||||
t[1086] = 45;
|
||||
});
|
||||
exports.getStdFontMap = getStdFontMap;
|
||||
exports.getNonStdFontMap = getNonStdFontMap;
|
||||
exports.getSerifFonts = getSerifFonts;
|
||||
exports.getSymbolsFonts = getSymbolsFonts;
|
||||
exports.getGlyphMapForStandardFonts = getGlyphMapForStandardFonts;
|
||||
exports.getSupplementalGlyphMapForArialBlack = getSupplementalGlyphMapForArialBlack;
|
||||
exports.getSupplementalGlyphMapForCalibri = getSupplementalGlyphMapForCalibri;
|
||||
|
||||
/***/ }),
|
||||
/* 16 */
|
||||
@ -20728,8 +20761,8 @@ exports.PostScriptCompiler = PostScriptCompiler;
|
||||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.0.185';
|
||||
var pdfjsBuild = 'f2994736';
|
||||
var pdfjsVersion = '2.0.197';
|
||||
var pdfjsBuild = '371ca514';
|
||||
var pdfjsCoreWorker = __w_pdfjs_require__(19);
|
||||
exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
|
||||
|
||||
@ -20924,7 +20957,7 @@ var WorkerMessageHandler = {
|
||||
var cancelXHRs = null;
|
||||
var WorkerTasks = [];
|
||||
let apiVersion = docParams.apiVersion;
|
||||
let workerVersion = '2.0.185';
|
||||
let workerVersion = '2.0.197';
|
||||
if (apiVersion !== null && apiVersion !== workerVersion) {
|
||||
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
|
||||
}
|
||||
@ -32329,7 +32362,7 @@ var OpenTypeFileBuilder = function OpenTypeFileBuilderClosure() {
|
||||
};
|
||||
return OpenTypeFileBuilder;
|
||||
}();
|
||||
var ProblematicCharRanges = new Int32Array([0x0000, 0x0020, 0x007F, 0x00A1, 0x00AD, 0x00AE, 0x0600, 0x0780, 0x08A0, 0x10A0, 0x1780, 0x1800, 0x1C00, 0x1C50, 0x2000, 0x2010, 0x2011, 0x2012, 0x2028, 0x2030, 0x205F, 0x2070, 0x25CC, 0x25CD, 0x3000, 0x3001, 0x3164, 0x3165, 0xAA60, 0xAA80, 0xFFF0, 0x10000]);
|
||||
var ProblematicCharRanges = new Int32Array([0x0000, 0x0020, 0x007F, 0x00A1, 0x00AD, 0x00AE, 0x0600, 0x0780, 0x08A0, 0x10A0, 0x1780, 0x1800, 0x1C00, 0x1C50, 0x2000, 0x2010, 0x2011, 0x2012, 0x2028, 0x2030, 0x205F, 0x2070, 0x25CC, 0x25CD, 0x3000, 0x3001, 0x3164, 0x3165, 0xAA60, 0xAA80, 0xD800, 0xE000, 0xFFF0, 0x10000]);
|
||||
var Font = function FontClosure() {
|
||||
function Font(name, file, properties) {
|
||||
var charCode;
|
||||
@ -32848,6 +32881,11 @@ var Font = function FontClosure() {
|
||||
for (charCode in SupplementalGlyphMapForArialBlack) {
|
||||
map[+charCode] = SupplementalGlyphMapForArialBlack[charCode];
|
||||
}
|
||||
} else if (/Calibri/i.test(name)) {
|
||||
let SupplementalGlyphMapForCalibri = (0, _standard_fonts.getSupplementalGlyphMapForCalibri)();
|
||||
for (charCode in SupplementalGlyphMapForCalibri) {
|
||||
map[+charCode] = SupplementalGlyphMapForCalibri[charCode];
|
||||
}
|
||||
}
|
||||
var isIdentityUnicode = this.toUnicode instanceof IdentityToUnicodeMap;
|
||||
if (!isIdentityUnicode) {
|
||||
|
@ -1911,7 +1911,7 @@ function webViewerPageRendered(evt) {
|
||||
let thumbnailView = PDFViewerApplication.pdfThumbnailViewer.getThumbnail(pageIndex);
|
||||
thumbnailView.setImage(pageView);
|
||||
}
|
||||
if (_pdfjsLib.PDFJS.pdfBug && Stats.enabled && pageView.stats) {
|
||||
if (_pdfjsLib.PDFJS.pdfBug && typeof Stats !== 'undefined' && Stats.enabled && pageView.stats) {
|
||||
Stats.add(pageNumber, pageView.stats);
|
||||
}
|
||||
if (pageView.error) {
|
||||
@ -2111,9 +2111,9 @@ function webViewerPageChanging(evt) {
|
||||
if (PDFViewerApplication.pdfSidebar.isThumbnailViewVisible) {
|
||||
PDFViewerApplication.pdfThumbnailViewer.scrollThumbnailIntoView(page);
|
||||
}
|
||||
if (_pdfjsLib.PDFJS.pdfBug && Stats.enabled) {
|
||||
if (_pdfjsLib.PDFJS.pdfBug && typeof Stats !== 'undefined' && Stats.enabled) {
|
||||
let pageView = PDFViewerApplication.pdfViewer.getPageView(page - 1);
|
||||
if (pageView.stats) {
|
||||
if (pageView && pageView.stats) {
|
||||
Stats.add(page, pageView.stats);
|
||||
}
|
||||
}
|
||||
|
@ -192,6 +192,9 @@
|
||||
@RESPATH@/components/dom.xpt
|
||||
@RESPATH@/components/dom_base.xpt
|
||||
@RESPATH@/components/dom_bindings.xpt
|
||||
#ifdef MOZ_DEBUG
|
||||
@RESPATH@/components/dom_bindings_test.xpt
|
||||
#endif
|
||||
@RESPATH@/components/dom_file.xpt
|
||||
@RESPATH@/components/dom_system.xpt
|
||||
@RESPATH@/components/dom_canvas.xpt
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "nsIAnonymousContentCreator.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsCSSAnonBoxes.h"
|
||||
#include "nsDocument.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -66,7 +67,8 @@ ExplicitChildIterator::ExplicitChildIterator(const nsIContent* aParent,
|
||||
mIsFirst(aStartAtBeginning),
|
||||
mIndexInInserted(0)
|
||||
{
|
||||
mParentAsSlot = HTMLSlotElement::FromContent(mParent);
|
||||
mParentAsSlot = nsDocument::IsWebComponentsEnabled(mParent) ?
|
||||
HTMLSlotElement::FromContent(mParent) : nullptr;
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "nsString.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsAtom.h"
|
||||
#include "plhash.h"
|
||||
|
||||
class nsIDocument;
|
||||
class nsNodeInfoManager;
|
||||
|
6
dom/base/crashtests/1422931.html
Normal file
6
dom/base/crashtests/1422931.html
Normal file
@ -0,0 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<!-- Testing slot element with "dom.webcomponents.enabled" set to false -->
|
||||
<slot><div></div></slot>
|
||||
</html>
|
@ -236,4 +236,5 @@ load 1406109-1.html
|
||||
pref(dom.webcomponents.enabled,true) load 1324463.html
|
||||
pref(dom.webcomponents.customelements.enabled,true) load 1413815.html
|
||||
load 1411473.html
|
||||
pref(dom.webcomponents.enabled,false) load 1422931.html
|
||||
pref(dom.webcomponents.enabled,true) load 1419799.html
|
||||
|
@ -7534,7 +7534,7 @@ nsContentUtils::IsContentInsertionPoint(nsIContent* aContent)
|
||||
bool
|
||||
nsContentUtils::HasDistributedChildren(nsIContent* aContent)
|
||||
{
|
||||
if (!aContent) {
|
||||
if (!aContent || !nsDocument::IsWebComponentsEnabled(aContent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1208,7 +1208,8 @@ nsExternalResourceMap::PendingLoad::OnDataAvailable(nsIRequest* aRequest,
|
||||
uint64_t aOffset,
|
||||
uint32_t aCount)
|
||||
{
|
||||
NS_PRECONDITION(mTargetListener, "Shouldn't be getting called!");
|
||||
// mTargetListener might be null if SetupViewer or AddExternalResource failed.
|
||||
NS_ENSURE_TRUE(mTargetListener, NS_ERROR_FAILURE);
|
||||
if (mDisplayDocument->ExternalResourceMap().HaveShutDown()) {
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
@ -1581,6 +1582,10 @@ nsIDocument::nsIDocument()
|
||||
for (auto& cnt : mIncCounters) {
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
// Set this when document is created and value stays the same for the lifetime
|
||||
// of the document.
|
||||
mIsWebComponentsEnabled = nsContentUtils::IsWebComponentsEnabled();
|
||||
}
|
||||
|
||||
nsDocument::nsDocument(const char* aContentType)
|
||||
@ -2720,6 +2725,30 @@ nsDocument::IsSynthesized() {
|
||||
return synthesized;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
|
||||
{
|
||||
JS::Rooted<JSObject*> obj(aCx, aObject);
|
||||
|
||||
JSAutoCompartment ac(aCx, obj);
|
||||
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, obj));
|
||||
nsCOMPtr<nsPIDOMWindowInner> window =
|
||||
do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(global));
|
||||
|
||||
nsIDocument* doc = window ? window->GetExtantDoc() : nullptr;
|
||||
if (!doc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return doc->IsWebComponentsEnabled();
|
||||
}
|
||||
|
||||
bool
|
||||
nsDocument::IsWebComponentsEnabled(const nsINode* aNode)
|
||||
{
|
||||
return aNode->OwnerDoc()->IsWebComponentsEnabled();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
|
||||
nsILoadGroup* aLoadGroup,
|
||||
|
@ -665,6 +665,11 @@ public:
|
||||
virtual void ResolveScheduledSVGPresAttrs() override;
|
||||
bool IsSynthesized();
|
||||
|
||||
// Check whether web components are enabled for the global of aObject.
|
||||
static bool IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject);
|
||||
// Check whether web components are enabled for the document this node belongs
|
||||
// to.
|
||||
static bool IsWebComponentsEnabled(const nsINode* aNode);
|
||||
private:
|
||||
void AddOnDemandBuiltInUASheet(mozilla::StyleSheet* aSheet);
|
||||
void SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages);
|
||||
|
@ -259,6 +259,7 @@
|
||||
|
||||
#include "mozilla/dom/ClientManager.h"
|
||||
#include "mozilla/dom/ClientSource.h"
|
||||
#include "mozilla/dom/ClientState.h"
|
||||
|
||||
// Apple system headers seem to have a check() macro. <sigh>
|
||||
#ifdef check
|
||||
@ -2317,6 +2318,12 @@ nsPIDOMWindowInner::GetClientInfo() const
|
||||
return Move(nsGlobalWindowInner::Cast(this)->GetClientInfo());
|
||||
}
|
||||
|
||||
Maybe<ClientState>
|
||||
nsPIDOMWindowInner::GetClientState() const
|
||||
{
|
||||
return Move(nsGlobalWindowInner::Cast(this)->GetClientState());
|
||||
}
|
||||
|
||||
Maybe<ServiceWorkerDescriptor>
|
||||
nsPIDOMWindowInner::GetController() const
|
||||
{
|
||||
@ -6157,6 +6164,21 @@ nsGlobalWindowInner::GetClientInfo() const
|
||||
return Move(clientInfo);
|
||||
}
|
||||
|
||||
Maybe<ClientState>
|
||||
nsGlobalWindowInner::GetClientState() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
Maybe<ClientState> clientState;
|
||||
if (mClientSource) {
|
||||
ClientState state;
|
||||
nsresult rv = mClientSource->SnapshotState(&state);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
clientState.emplace(state);
|
||||
}
|
||||
}
|
||||
return Move(clientState);
|
||||
}
|
||||
|
||||
Maybe<ServiceWorkerDescriptor>
|
||||
nsGlobalWindowInner::GetController() const
|
||||
{
|
||||
|
@ -348,6 +348,7 @@ public:
|
||||
void SyncStateFromParentWindow();
|
||||
|
||||
mozilla::Maybe<mozilla::dom::ClientInfo> GetClientInfo() const;
|
||||
mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
|
||||
mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
|
||||
|
||||
virtual nsresult FireDelayedDOMEvents() override;
|
||||
|
@ -5966,24 +5966,26 @@ nsGlobalWindowOuter::CloseOuter(bool aTrustedCaller)
|
||||
|
||||
// Don't allow scripts from content to close non-neterror windows that
|
||||
// were not opened by script.
|
||||
nsAutoString url;
|
||||
nsresult rv = mDoc->GetURL(url);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
if (mDoc) {
|
||||
nsAutoString url;
|
||||
nsresult rv = mDoc->GetURL(url);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
if (!StringBeginsWith(url, NS_LITERAL_STRING("about:neterror")) &&
|
||||
!mHadOriginalOpener && !aTrustedCaller) {
|
||||
bool allowClose = mAllowScriptsToClose ||
|
||||
Preferences::GetBool("dom.allow_scripts_to_close_windows", true);
|
||||
if (!allowClose) {
|
||||
// We're blocking the close operation
|
||||
// report localized error msg in JS console
|
||||
nsContentUtils::ReportToConsole(
|
||||
nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("DOM Window"), mDoc, // Better name for the category?
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
"WindowCloseBlockedWarning");
|
||||
if (!StringBeginsWith(url, NS_LITERAL_STRING("about:neterror")) &&
|
||||
!mHadOriginalOpener && !aTrustedCaller) {
|
||||
bool allowClose = mAllowScriptsToClose ||
|
||||
Preferences::GetBool("dom.allow_scripts_to_close_windows", true);
|
||||
if (!allowClose) {
|
||||
// We're blocking the close operation
|
||||
// report localized error msg in JS console
|
||||
nsContentUtils::ReportToConsole(
|
||||
nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("DOM Window"), mDoc, // Better name for the category?
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
"WindowCloseBlockedWarning");
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3256,6 +3256,11 @@ public:
|
||||
virtual bool AllowPaymentRequest() const = 0;
|
||||
virtual void SetAllowPaymentRequest(bool aAllowPaymentRequest) = 0;
|
||||
|
||||
bool IsWebComponentsEnabled() const
|
||||
{
|
||||
return mIsWebComponentsEnabled;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool GetUseCounter(mozilla::UseCounter aUseCounter)
|
||||
{
|
||||
@ -3612,6 +3617,9 @@ protected:
|
||||
// True if the encoding menu should be disabled.
|
||||
bool mEncodingMenuDisabled : 1;
|
||||
|
||||
// True if dom.webcomponents.enabled pref is set when document is created.
|
||||
bool mIsWebComponentsEnabled : 1;
|
||||
|
||||
// Whether <style scoped> support is enabled in this document.
|
||||
enum { eScopedStyle_Unknown, eScopedStyle_Disabled, eScopedStyle_Enabled };
|
||||
unsigned int mIsScopedStyleEnabled : 2;
|
||||
|
@ -47,6 +47,7 @@ class ThrottledEventQueue;
|
||||
namespace dom {
|
||||
class AudioContext;
|
||||
class ClientInfo;
|
||||
class ClientState;
|
||||
class DocGroup;
|
||||
class TabGroup;
|
||||
class Element;
|
||||
@ -327,6 +328,7 @@ public:
|
||||
bool HasOpenWebSockets() const;
|
||||
|
||||
mozilla::Maybe<mozilla::dom::ClientInfo> GetClientInfo() const;
|
||||
mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
|
||||
mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
|
||||
|
||||
mozilla::dom::TabGroup* TabGroup();
|
||||
|
@ -21,6 +21,7 @@
|
||||
#ifdef DEBUG
|
||||
#include "nsRange.h"
|
||||
#endif
|
||||
#include "nsDocument.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -157,6 +158,12 @@ void nsTextNode::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
nsGenericDOMDataNode::UnbindFromTree(aDeep, aNullParent);
|
||||
}
|
||||
|
||||
bool
|
||||
nsTextNode::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
|
||||
{
|
||||
return nsDocument::IsWebComponentsEnabled(aCx, aObject);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
nsTextNode::List(FILE* out, int32_t aIndent) const
|
||||
|
@ -75,6 +75,10 @@ public:
|
||||
|
||||
virtual nsIDOMNode* AsDOMNode() override { return this; }
|
||||
|
||||
// Need to have a copy here because including nsDocument.h in this file will
|
||||
// fail to build on Windows.
|
||||
static bool IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject);
|
||||
|
||||
#ifdef DEBUG
|
||||
virtual void List(FILE* out, int32_t aIndent) const override;
|
||||
virtual void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const override;
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "mozilla/dom/TestFunctions.h"
|
||||
#include "mozilla/dom/TestFunctionsBinding.h"
|
||||
#include "nsStringBuffer.h"
|
||||
#include "mozITestInterfaceJS.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -83,6 +85,22 @@ TestFunctions::GetStringDataAsDOMString(const Optional<uint32_t>& aLength,
|
||||
// No need to do anything here; aString is already empty.
|
||||
}
|
||||
|
||||
void
|
||||
TestFunctions::TestThrowNsresult(ErrorResult& aError)
|
||||
{
|
||||
nsCOMPtr<mozITestInterfaceJS> impl =
|
||||
do_CreateInstance("@mozilla.org/dom/test-interface-js;1");
|
||||
aError = impl->TestThrowNsresult();
|
||||
}
|
||||
|
||||
void
|
||||
TestFunctions::TestThrowNsresultFromNative(ErrorResult& aError)
|
||||
{
|
||||
nsCOMPtr<mozITestInterfaceJS> impl =
|
||||
do_CreateInstance("@mozilla.org/dom/test-interface-js;1");
|
||||
aError = impl->TestThrowNsresultFromNative();
|
||||
}
|
||||
|
||||
bool
|
||||
TestFunctions::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
|
||||
JS::MutableHandle<JSObject*> aWrapper)
|
||||
|
@ -40,6 +40,9 @@ public:
|
||||
void GetStringDataAsDOMString(const Optional<uint32_t>& aLength,
|
||||
DOMString& aString);
|
||||
|
||||
void TestThrowNsresult(ErrorResult& aError);
|
||||
void TestThrowNsresultFromNative(ErrorResult& aError);
|
||||
|
||||
bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
|
||||
JS::MutableHandle<JSObject*> aWrapper);
|
||||
private:
|
||||
|
@ -16,7 +16,8 @@ TestInterfaceJS.prototype = {
|
||||
classID: Components.ID("{2ac4e026-cf25-47d5-b067-78d553c3cad8}"),
|
||||
contractID: "@mozilla.org/dom/test-interface-js;1",
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
|
||||
Ci.nsIDOMGlobalPropertyInitializer]),
|
||||
Ci.nsIDOMGlobalPropertyInitializer,
|
||||
Ci.mozITestInterfaceJS]),
|
||||
|
||||
init: function(win) { this._win = win; },
|
||||
|
||||
@ -77,6 +78,21 @@ TestInterfaceJS.prototype = {
|
||||
throw new this._win.TypeError("We are a TypeError");
|
||||
},
|
||||
|
||||
testThrowNsresult: function() {
|
||||
throw Components.results.NS_BINDING_ABORTED;
|
||||
},
|
||||
|
||||
testThrowNsresultFromNative: function(x) {
|
||||
// We want to throw an exception that we generate from an nsresult thrown
|
||||
// by a C++ component. Ideally we'd have one explicitly for testing, but
|
||||
// for now just piggyback on nsStandardURL.
|
||||
var url = Components.classes["@mozilla.org/network/standard-url;1"]
|
||||
.createInstance(Ci.nsIURI);
|
||||
url.QueryInterface(Ci.nsIMutable);
|
||||
url.mutable = false;
|
||||
url.spec = "http://example.com";
|
||||
},
|
||||
|
||||
testThrowCallbackError: function(callback) {
|
||||
callback();
|
||||
},
|
||||
|
@ -78,7 +78,7 @@ skip-if = debug == false
|
||||
[test_oom_reporting.html]
|
||||
[test_domProxyArrayLengthGetter.html]
|
||||
[test_exceptionSanitization.html]
|
||||
skip-if = os == "android"
|
||||
skip-if = debug == false
|
||||
[test_stringBindings.html]
|
||||
skip-if = debug == false
|
||||
[test_jsimplemented_subclassing.html]
|
||||
|
@ -56,3 +56,10 @@ LOCAL_INCLUDES += [
|
||||
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
||||
if CONFIG['MOZ_DEBUG']:
|
||||
XPIDL_SOURCES += [
|
||||
'mozITestInterfaceJS.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom_bindings_test'
|
||||
|
21
dom/bindings/test/mozITestInterfaceJS.idl
Normal file
21
dom/bindings/test/mozITestInterfaceJS.idl
Normal file
@ -0,0 +1,21 @@
|
||||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* An interface to allow testing of binding interactions with JS-implemented
|
||||
* XPCOM components. The actual implementation is TestInterfaceJS, just like
|
||||
* for TestInteraceJS.webidl.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(9eeb2c12-ddd9-4734-8cfb-c0cdfb136e07)]
|
||||
interface mozITestInterfaceJS : nsISupports {
|
||||
// Test throwing Components.results.NS_BINDING_ABORTED.
|
||||
void testThrowNsresult();
|
||||
// Test calling a C++ component which throws an nsresult exception.
|
||||
void testThrowNsresultFromNative();
|
||||
};
|
@ -19,27 +19,42 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1295322
|
||||
</pre>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1295322 **/
|
||||
iframe = document.createElement('iframe');
|
||||
iframe.name = "eWin";
|
||||
document.body.appendChild(iframe);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
async function runTests() {
|
||||
await SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]});
|
||||
|
||||
try{
|
||||
// NOTE: The idea here is to call something that will end up throwing an
|
||||
// exception in a JS component and then propagate back to C++ code before
|
||||
// returning to us. If opening a feed: URI stops doing that, we will need a
|
||||
// new guinea pig here.
|
||||
open('feed://java:script:codeshouldgohere','eWin');
|
||||
ok(false, "Should have thrown!");
|
||||
} catch(e){
|
||||
try {
|
||||
is(e.name, "SyntaxError", "Should have the right exception");
|
||||
is(e.filename, location.href,
|
||||
"Should not be seeing where the exception really came from");
|
||||
} catch (e2) {
|
||||
ok(false, "Should be able to work with the exception");
|
||||
var t = new TestFunctions();
|
||||
|
||||
try {
|
||||
t.testThrowNsresult();
|
||||
} catch (e) {
|
||||
try {
|
||||
is(e.name, "NS_BINDING_ABORTED",
|
||||
"Should have the right exception");
|
||||
is(e.filename, location.href,
|
||||
"Should not be seeing where the exception really came from");
|
||||
} catch (e2) {
|
||||
ok(false, "Should be able to work with the exception");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
t.testThrowNsresultFromNative();
|
||||
} catch (e) {
|
||||
try {
|
||||
is(e.name, "NS_ERROR_UNEXPECTED",
|
||||
"Should have the right exception");
|
||||
is(e.filename, location.href,
|
||||
"Should not be seeing where the exception really came from");
|
||||
} catch (e2) {
|
||||
ok(false, "Should be able to work with the exception");
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
runTests();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -9,12 +9,16 @@
|
||||
#include "ClientHandleChild.h"
|
||||
#include "ClientHandleOpChild.h"
|
||||
#include "ClientManager.h"
|
||||
#include "ClientState.h"
|
||||
#include "mozilla/dom/PClientManagerChild.h"
|
||||
#include "mozilla/dom/ServiceWorkerDescriptor.h"
|
||||
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
using mozilla::dom::ipc::StructuredCloneData;
|
||||
|
||||
ClientHandle::~ClientHandle()
|
||||
{
|
||||
Shutdown();
|
||||
@ -122,5 +126,59 @@ ClientHandle::Control(const ServiceWorkerDescriptor& aServiceWorker)
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
RefPtr<ClientStatePromise>
|
||||
ClientHandle::Focus()
|
||||
{
|
||||
RefPtr<ClientStatePromise::Private> outerPromise =
|
||||
new ClientStatePromise::Private(__func__);
|
||||
|
||||
RefPtr<ClientOpPromise> innerPromise = StartOp(ClientFocusArgs());
|
||||
|
||||
innerPromise->Then(mSerialEventTarget, __func__,
|
||||
[outerPromise](const ClientOpResult& aResult) {
|
||||
outerPromise->Resolve(ClientState::FromIPC(aResult.get_IPCClientState()), __func__);
|
||||
}, [outerPromise](const ClientOpResult& aResult) {
|
||||
outerPromise->Reject(aResult.get_nsresult(), __func__);
|
||||
});
|
||||
|
||||
RefPtr<ClientStatePromise> ref = outerPromise.get();
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
RefPtr<GenericPromise>
|
||||
ClientHandle::PostMessage(StructuredCloneData& aData,
|
||||
const ServiceWorkerDescriptor& aSource)
|
||||
{
|
||||
RefPtr<GenericPromise> ref;
|
||||
|
||||
if (IsShutdown()) {
|
||||
ref = GenericPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
ClientPostMessageArgs args;
|
||||
args.serviceWorker() = aSource.ToIPC();
|
||||
|
||||
if (!aData.BuildClonedMessageDataForBackgroundChild(GetActor()->Manager()->Manager(),
|
||||
args.clonedData())) {
|
||||
ref = GenericPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
RefPtr<GenericPromise::Private> outerPromise =
|
||||
new GenericPromise::Private(__func__);
|
||||
|
||||
RefPtr<ClientOpPromise> innerPromise = StartOp(args);
|
||||
innerPromise->Then(mSerialEventTarget, __func__,
|
||||
[outerPromise](const ClientOpResult& aResult) {
|
||||
outerPromise->Resolve(true, __func__);
|
||||
}, [outerPromise](const ClientOpResult& aResult) {
|
||||
outerPromise->Reject(aResult.get_nsresult(), __func__);
|
||||
});
|
||||
|
||||
ref = outerPromise.get();
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -25,6 +25,10 @@ class ClientOpConstructorArgs;
|
||||
class PClientManagerChild;
|
||||
class ServiceWorkerDescriptor;
|
||||
|
||||
namespace ipc {
|
||||
class StructuredCloneData;
|
||||
}
|
||||
|
||||
// The ClientHandle allows code to take a simple ClientInfo struct and
|
||||
// convert it into a live actor-backed object attached to a particular
|
||||
// ClientSource somewhere in the browser. If the ClientSource is
|
||||
@ -70,6 +74,22 @@ public:
|
||||
RefPtr<GenericPromise>
|
||||
Control(const ServiceWorkerDescriptor& aServiceWorker);
|
||||
|
||||
// Focus the Client if possible. If successful the promise will resolve with
|
||||
// a new ClientState snapshot after focus has completed. If focusing fails
|
||||
// for any reason then the promise will reject.
|
||||
RefPtr<ClientStatePromise>
|
||||
Focus();
|
||||
|
||||
// Send a postMessage() call to the target Client. Currently this only
|
||||
// supports sending from a ServiceWorker source and the MessageEvent is
|
||||
// dispatched to the Client's navigator.serviceWorker event target. The
|
||||
// returned promise will resolve if the MessageEvent is dispatched or if
|
||||
// it triggers an error handled in the Client's context. Other errors
|
||||
// will result in the promise rejecting.
|
||||
RefPtr<GenericPromise>
|
||||
PostMessage(ipc::StructuredCloneData& aData,
|
||||
const ServiceWorkerDescriptor& aSource);
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(ClientHandle);
|
||||
};
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "ClientHandleParent.h"
|
||||
#include "ClientSourceParent.h"
|
||||
#include "mozilla/dom/PClientManagerParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -34,7 +35,33 @@ ClientHandleOpParent::Init(const ClientOpConstructorArgs& aArgs)
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise> p = source->StartOp(aArgs);
|
||||
RefPtr<ClientOpPromise> p;
|
||||
|
||||
// ClientPostMessageArgs can contain PBlob actors. This means we
|
||||
// can't just forward the args from one PBackground manager to
|
||||
// another. Instead, unpack the structured clone data and repack
|
||||
// it into a new set of arguments.
|
||||
if (aArgs.type() == ClientOpConstructorArgs::TClientPostMessageArgs) {
|
||||
const ClientPostMessageArgs& orig = aArgs.get_ClientPostMessageArgs();
|
||||
|
||||
ClientPostMessageArgs rebuild;
|
||||
rebuild.serviceWorker() = orig.serviceWorker();
|
||||
|
||||
StructuredCloneData data;
|
||||
data.BorrowFromClonedMessageDataForBackgroundParent(orig.clonedData());
|
||||
if (!data.BuildClonedMessageDataForBackgroundParent(source->Manager()->Manager(),
|
||||
rebuild.clonedData())) {
|
||||
Unused << PClientHandleOpParent::Send__delete__(this, NS_ERROR_DOM_ABORT_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
p = source->StartOp(rebuild);
|
||||
}
|
||||
|
||||
// Other argument types can just be forwarded straight through.
|
||||
else {
|
||||
p = source->StartOp(aArgs);
|
||||
}
|
||||
|
||||
// Capturing 'this' is safe here because we disconnect the promise in
|
||||
// ActorDestroy() which ensures neither lambda is called if the actor
|
||||
|
@ -67,6 +67,35 @@ struct ClientControlledArgs
|
||||
IPCServiceWorkerDescriptor serviceWorker;
|
||||
};
|
||||
|
||||
struct ClientFocusArgs
|
||||
{
|
||||
};
|
||||
|
||||
struct ClientNavigateArgs
|
||||
{
|
||||
IPCClientInfo target;
|
||||
nsCString url;
|
||||
nsCString baseURL;
|
||||
};
|
||||
|
||||
struct ClientPostMessageArgs
|
||||
{
|
||||
ClonedMessageData clonedData;
|
||||
IPCServiceWorkerDescriptor serviceWorker;
|
||||
};
|
||||
|
||||
struct ClientMatchAllArgs
|
||||
{
|
||||
IPCServiceWorkerDescriptor serviceWorker;
|
||||
ClientType type;
|
||||
bool includeUncontrolled;
|
||||
};
|
||||
|
||||
struct ClientClaimArgs
|
||||
{
|
||||
IPCServiceWorkerDescriptor serviceWorker;
|
||||
};
|
||||
|
||||
struct ClientGetInfoAndStateArgs
|
||||
{
|
||||
nsID id;
|
||||
@ -75,22 +104,41 @@ struct ClientGetInfoAndStateArgs
|
||||
|
||||
struct ClientOpenWindowArgs
|
||||
{
|
||||
PrincipalInfo principalInfo;
|
||||
nsCString url;
|
||||
nsCString baseURL;
|
||||
};
|
||||
|
||||
union ClientOpConstructorArgs
|
||||
{
|
||||
ClientControlledArgs;
|
||||
ClientFocusArgs;
|
||||
ClientNavigateArgs;
|
||||
ClientPostMessageArgs;
|
||||
ClientMatchAllArgs;
|
||||
ClientClaimArgs;
|
||||
ClientGetInfoAndStateArgs;
|
||||
ClientOpenWindowArgs;
|
||||
};
|
||||
|
||||
struct ClientList
|
||||
{
|
||||
ClientInfoAndState[] values;
|
||||
};
|
||||
|
||||
struct ClientNavigateOpConstructorArgs
|
||||
{
|
||||
PClientSource target;
|
||||
nsCString url;
|
||||
nsCString baseURL;
|
||||
};
|
||||
|
||||
union ClientOpResult
|
||||
{
|
||||
nsresult;
|
||||
IPCClientState;
|
||||
ClientInfoAndState;
|
||||
ClientList;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -257,6 +257,24 @@ ClientManager::CreateHandle(const ClientInfo& aClientInfo,
|
||||
return mgr->CreateHandleInternal(aClientInfo, aSerialEventTarget);
|
||||
}
|
||||
|
||||
// static
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManager::MatchAll(const ClientMatchAllArgs& aArgs,
|
||||
nsISerialEventTarget* aSerialEventTarget)
|
||||
{
|
||||
RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
|
||||
return mgr->StartOp(aArgs, aSerialEventTarget);
|
||||
}
|
||||
|
||||
// static
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManager::Claim(const ClientClaimArgs& aArgs,
|
||||
nsISerialEventTarget* aSerialEventTarget)
|
||||
{
|
||||
RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
|
||||
return mgr->StartOp(aArgs, aSerialEventTarget);
|
||||
}
|
||||
|
||||
// static
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManager::GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs,
|
||||
@ -266,5 +284,23 @@ ClientManager::GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs,
|
||||
return mgr->StartOp(aArgs, aSerialEventTarget);
|
||||
}
|
||||
|
||||
// static
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManager::Navigate(const ClientNavigateArgs& aArgs,
|
||||
nsISerialEventTarget* aSerialEventTarget)
|
||||
{
|
||||
RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
|
||||
return mgr->StartOp(aArgs, aSerialEventTarget);
|
||||
}
|
||||
|
||||
// static
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManager::OpenWindow(const ClientOpenWindowArgs& aArgs,
|
||||
nsISerialEventTarget* aSerialEventTarget)
|
||||
{
|
||||
RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
|
||||
return mgr->StartOp(aArgs, aSerialEventTarget);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -18,11 +18,15 @@ class PrincipalInfo;
|
||||
} // namespace ipc
|
||||
namespace dom {
|
||||
|
||||
class ClientClaimArgs;
|
||||
class ClientGetInfoAndStateArgs;
|
||||
class ClientHandle;
|
||||
class ClientInfo;
|
||||
class ClientManagerChild;
|
||||
class ClientMatchAllArgs;
|
||||
class ClientNavigateArgs;
|
||||
class ClientOpConstructorArgs;
|
||||
class ClientOpenWindowArgs;
|
||||
class ClientSource;
|
||||
enum class ClientType : uint8_t;
|
||||
|
||||
@ -94,10 +98,24 @@ public:
|
||||
CreateHandle(const ClientInfo& aClientInfo,
|
||||
nsISerialEventTarget* aSerialEventTarget);
|
||||
|
||||
static RefPtr<ClientOpPromise>
|
||||
MatchAll(const ClientMatchAllArgs& aArgs, nsISerialEventTarget* aTarget);
|
||||
|
||||
static RefPtr<ClientOpPromise>
|
||||
Claim(const ClientClaimArgs& aArgs, nsISerialEventTarget* aSerialEventTarget);
|
||||
|
||||
static RefPtr<ClientOpPromise>
|
||||
GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs,
|
||||
nsISerialEventTarget* aSerialEventTarget);
|
||||
|
||||
static RefPtr<ClientOpPromise>
|
||||
Navigate(const ClientNavigateArgs& aArgs,
|
||||
nsISerialEventTarget* aSerialEventTarget);
|
||||
|
||||
static RefPtr<ClientOpPromise>
|
||||
OpenWindow(const ClientOpenWindowArgs& aArgs,
|
||||
nsISerialEventTarget* aSerialEventTarget);
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(mozilla::dom::ClientManager)
|
||||
};
|
||||
|
||||
|
@ -7,10 +7,13 @@
|
||||
#include "ClientManagerOpParent.h"
|
||||
|
||||
#include "ClientManagerService.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
using mozilla::ipc::BackgroundParent;
|
||||
|
||||
template <typename Method, typename... Args>
|
||||
void
|
||||
ClientManagerOpParent::DoServiceOp(Method aMethod, Args&&... aArgs)
|
||||
@ -48,12 +51,37 @@ void
|
||||
ClientManagerOpParent::Init(const ClientOpConstructorArgs& aArgs)
|
||||
{
|
||||
switch (aArgs.type()) {
|
||||
case ClientOpConstructorArgs::TClientNavigateArgs:
|
||||
{
|
||||
DoServiceOp(&ClientManagerService::Navigate,
|
||||
aArgs.get_ClientNavigateArgs());
|
||||
break;
|
||||
}
|
||||
case ClientOpConstructorArgs::TClientMatchAllArgs:
|
||||
{
|
||||
DoServiceOp(&ClientManagerService::MatchAll,
|
||||
aArgs.get_ClientMatchAllArgs());
|
||||
break;
|
||||
}
|
||||
case ClientOpConstructorArgs::TClientClaimArgs:
|
||||
{
|
||||
DoServiceOp(&ClientManagerService::Claim, aArgs.get_ClientClaimArgs());
|
||||
break;
|
||||
}
|
||||
case ClientOpConstructorArgs::TClientGetInfoAndStateArgs:
|
||||
{
|
||||
DoServiceOp(&ClientManagerService::GetInfoAndState,
|
||||
aArgs.get_ClientGetInfoAndStateArgs());
|
||||
break;
|
||||
}
|
||||
case ClientOpConstructorArgs::TClientOpenWindowArgs:
|
||||
{
|
||||
RefPtr<ContentParent> contentParent =
|
||||
BackgroundParent::GetContentParent(Manager()->Manager());
|
||||
DoServiceOp(&ClientManagerService::OpenWindow,
|
||||
aArgs.get_ClientOpenWindowArgs(), contentParent.forget());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown Client operation!");
|
||||
|
@ -7,12 +7,18 @@
|
||||
#include "ClientManagerService.h"
|
||||
|
||||
#include "ClientManagerParent.h"
|
||||
#include "ClientNavigateOpParent.h"
|
||||
#include "ClientOpenWindowOpParent.h"
|
||||
#include "ClientOpenWindowUtils.h"
|
||||
#include "ClientSourceParent.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/SystemGroup.h"
|
||||
#include "nsIAsyncShutdown.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -302,6 +308,229 @@ ClientManagerService::RemoveManager(ClientManagerParent* aManager)
|
||||
MOZ_ASSERT(removed);
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManagerService::Navigate(const ClientNavigateArgs& aArgs)
|
||||
{
|
||||
RefPtr<ClientOpPromise> ref;
|
||||
|
||||
ClientSourceParent* source = FindSource(aArgs.target().id(),
|
||||
aArgs.target().principalInfo());
|
||||
if (!source) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
PClientManagerParent* manager = source->Manager();
|
||||
MOZ_DIAGNOSTIC_ASSERT(manager);
|
||||
|
||||
ClientNavigateOpConstructorArgs args;
|
||||
args.url() = aArgs.url();
|
||||
args.baseURL() = aArgs.baseURL();
|
||||
|
||||
// This is safe to do because the ClientSourceChild cannot directly delete
|
||||
// itself. Instead it sends a Teardown message to the parent which then
|
||||
// calls delete. That means we can be sure that we are not racing with
|
||||
// source destruction here.
|
||||
args.targetParent() = source;
|
||||
|
||||
RefPtr<ClientOpPromise::Private> promise =
|
||||
new ClientOpPromise::Private(__func__);
|
||||
|
||||
ClientNavigateOpParent* op = new ClientNavigateOpParent(args, promise);
|
||||
PClientNavigateOpParent* result =
|
||||
manager->SendPClientNavigateOpConstructor(op, args);
|
||||
if (!result) {
|
||||
promise->Reject(NS_ERROR_FAILURE, __func__);
|
||||
ref = promise;
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
ref = promise;
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class PromiseListHolder final
|
||||
{
|
||||
RefPtr<ClientOpPromise::Private> mResultPromise;
|
||||
nsTArray<RefPtr<ClientOpPromise>> mPromiseList;
|
||||
nsTArray<ClientInfoAndState> mResultList;
|
||||
uint32_t mOutstandingPromiseCount;
|
||||
|
||||
void
|
||||
ProcessSuccess(const ClientInfoAndState& aResult)
|
||||
{
|
||||
mResultList.AppendElement(aResult);
|
||||
ProcessCompletion();
|
||||
}
|
||||
|
||||
void
|
||||
ProcessCompletion()
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mOutstandingPromiseCount > 0);
|
||||
mOutstandingPromiseCount -= 1;
|
||||
MaybeFinish();
|
||||
}
|
||||
|
||||
~PromiseListHolder() = default;
|
||||
public:
|
||||
PromiseListHolder()
|
||||
: mResultPromise(new ClientOpPromise::Private(__func__))
|
||||
, mOutstandingPromiseCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
already_AddRefed<ClientOpPromise>
|
||||
GetResultPromise()
|
||||
{
|
||||
RefPtr<PromiseListHolder> kungFuDeathGrip = this;
|
||||
mResultPromise->Then(
|
||||
GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[kungFuDeathGrip] (const ClientOpResult& aResult) { },
|
||||
[kungFuDeathGrip] (nsresult aResult) { });
|
||||
|
||||
RefPtr<ClientOpPromise> ref = mResultPromise;
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
void
|
||||
AddPromise(RefPtr<ClientOpPromise>&& aPromise)
|
||||
{
|
||||
mPromiseList.AppendElement(Move(aPromise));
|
||||
MOZ_DIAGNOSTIC_ASSERT(mPromiseList.LastElement());
|
||||
mOutstandingPromiseCount += 1;
|
||||
|
||||
RefPtr<PromiseListHolder> self(this);
|
||||
mPromiseList.LastElement()->Then(
|
||||
GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[self] (const ClientOpResult& aResult) {
|
||||
// TODO: This is pretty clunky. Try to figure out a better
|
||||
// wait for MatchAll() and Claim() to share this code
|
||||
// even though they expect different return values.
|
||||
if (aResult.type() == ClientOpResult::TClientInfoAndState) {
|
||||
self->ProcessSuccess(aResult.get_ClientInfoAndState());
|
||||
} else {
|
||||
self->ProcessCompletion();
|
||||
}
|
||||
}, [self] (nsresult aResult) {
|
||||
self->ProcessCompletion();
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
MaybeFinish()
|
||||
{
|
||||
if (!mOutstandingPromiseCount) {
|
||||
mResultPromise->Resolve(mResultList, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(PromiseListHolder)
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManagerService::MatchAll(const ClientMatchAllArgs& aArgs)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
ServiceWorkerDescriptor swd(aArgs.serviceWorker());
|
||||
const PrincipalInfo& principalInfo = swd.PrincipalInfo();
|
||||
|
||||
RefPtr<PromiseListHolder> promiseList = new PromiseListHolder();
|
||||
|
||||
for (auto iter = mSourceTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
ClientSourceParent* source = iter.UserData();
|
||||
MOZ_DIAGNOSTIC_ASSERT(source);
|
||||
|
||||
if (source->IsFrozen() || !source->ExecutionReady()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aArgs.type() != ClientType::All &&
|
||||
source->Info().Type() != aArgs.type()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!MatchPrincipalInfo(source->Info().PrincipalInfo(), principalInfo)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!aArgs.includeUncontrolled()) {
|
||||
const Maybe<ServiceWorkerDescriptor>& controller =
|
||||
source->GetController();
|
||||
if (controller.isNothing()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(controller.ref().Id() != swd.Id() ||
|
||||
controller.ref().Scope() != swd.Scope()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
promiseList->AddPromise(
|
||||
source->StartOp(Move(ClientGetInfoAndStateArgs(source->Info().Id(),
|
||||
source->Info().PrincipalInfo()))));
|
||||
}
|
||||
|
||||
// Maybe finish the promise now in case we didn't find any matching clients.
|
||||
promiseList->MaybeFinish();
|
||||
|
||||
return promiseList->GetResultPromise();
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManagerService::Claim(const ClientClaimArgs& aArgs)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
const IPCServiceWorkerDescriptor& serviceWorker = aArgs.serviceWorker();
|
||||
const PrincipalInfo& principalInfo = serviceWorker.principalInfo();
|
||||
|
||||
RefPtr<PromiseListHolder> promiseList = new PromiseListHolder();
|
||||
|
||||
for (auto iter = mSourceTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
ClientSourceParent* source = iter.UserData();
|
||||
MOZ_DIAGNOSTIC_ASSERT(source);
|
||||
|
||||
if (source->IsFrozen()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!MatchPrincipalInfo(source->Info().PrincipalInfo(), principalInfo)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Maybe<ServiceWorkerDescriptor>& controller = source->GetController();
|
||||
if (controller.isSome() &&
|
||||
controller.ref().Scope() == serviceWorker.scope() &&
|
||||
controller.ref().Id() == serviceWorker.id()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: This logic to determine if a service worker should control
|
||||
// a particular client should be moved to the ServiceWorkerManager.
|
||||
// This can't happen until the SWM is moved to the parent process,
|
||||
// though.
|
||||
if (!source->ExecutionReady() ||
|
||||
source->Info().Type() == ClientType::Serviceworker ||
|
||||
source->Info().URL().Find(serviceWorker.scope()) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
promiseList->AddPromise(source->StartOp(aArgs));
|
||||
}
|
||||
|
||||
// Maybe finish the promise now in case we didn't find any matching clients.
|
||||
promiseList->MaybeFinish();
|
||||
|
||||
return promiseList->GetResultPromise();
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManagerService::GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs)
|
||||
{
|
||||
@ -316,5 +545,90 @@ ClientManagerService::GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs)
|
||||
return source->StartOp(aArgs);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class OpenWindowRunnable final : public Runnable
|
||||
{
|
||||
RefPtr<ClientOpPromise::Private> mPromise;
|
||||
const ClientOpenWindowArgs mArgs;
|
||||
RefPtr<ContentParent> mSourceProcess;
|
||||
|
||||
~OpenWindowRunnable()
|
||||
{
|
||||
NS_ReleaseOnMainThreadSystemGroup(mSourceProcess.forget());
|
||||
}
|
||||
|
||||
public:
|
||||
OpenWindowRunnable(ClientOpPromise::Private* aPromise,
|
||||
const ClientOpenWindowArgs& aArgs,
|
||||
already_AddRefed<ContentParent> aSourceProcess)
|
||||
: Runnable("ClientManagerService::OpenWindowRunnable")
|
||||
, mPromise(aPromise)
|
||||
, mArgs(aArgs)
|
||||
, mSourceProcess(aSourceProcess)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mPromise);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!BrowserTabsRemoteAutostart()) {
|
||||
RefPtr<ClientOpPromise> p = ClientOpenWindowInCurrentProcess(mArgs);
|
||||
p->ChainTo(mPromise.forget(), __func__);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<ContentParent> targetProcess;
|
||||
|
||||
// Possibly try to open the window in the same process that called
|
||||
// openWindow(). This is a temporary compat setting until the
|
||||
// multi-e10s service worker refactor is complete.
|
||||
if (Preferences::GetBool("dom.clients.openwindow_favors_same_process",
|
||||
false)) {
|
||||
targetProcess = mSourceProcess;
|
||||
}
|
||||
|
||||
// Otherwise, use our normal remote process selection mechanism for
|
||||
// opening the window. This will start a process if one is not
|
||||
// present.
|
||||
if (!targetProcess) {
|
||||
targetProcess =
|
||||
ContentParent::GetNewOrUsedBrowserProcess(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE),
|
||||
ContentParent::GetInitialProcessPriority(nullptr),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
ClientOpenWindowOpParent* actor =
|
||||
new ClientOpenWindowOpParent(mArgs, mPromise);
|
||||
|
||||
// If this fails the actor will be automatically destroyed which will
|
||||
// reject the promise.
|
||||
Unused << targetProcess->SendPClientOpenWindowOpConstructor(actor, mArgs);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManagerService::OpenWindow(const ClientOpenWindowArgs& aArgs,
|
||||
already_AddRefed<ContentParent> aSourceProcess)
|
||||
{
|
||||
RefPtr<ClientOpPromise::Private> promise =
|
||||
new ClientOpPromise::Private(__func__);
|
||||
|
||||
nsCOMPtr<nsIRunnable> r = new OpenWindowRunnable(promise, aArgs,
|
||||
Move(aSourceProcess));
|
||||
MOZ_ALWAYS_SUCCEEDS(SystemGroup::Dispatch(TaskCategory::Other,
|
||||
r.forget()));
|
||||
|
||||
RefPtr<ClientOpPromise> ref = promise;
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -59,9 +59,22 @@ public:
|
||||
void
|
||||
RemoveManager(ClientManagerParent* aManager);
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
Navigate(const ClientNavigateArgs& aArgs);
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
MatchAll(const ClientMatchAllArgs& aArgs);
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
Claim(const ClientClaimArgs& aArgs);
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs);
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
OpenWindow(const ClientOpenWindowArgs& aArgs,
|
||||
already_AddRefed<ContentParent> aSourceProcess);
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(mozilla::dom::ClientManagerService)
|
||||
};
|
||||
|
||||
|
@ -6,17 +6,284 @@
|
||||
|
||||
#include "ClientNavigateOpChild.h"
|
||||
|
||||
#include "ClientState.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocShellLoadInfo.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIWebProgress.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
namespace {
|
||||
|
||||
class NavigateLoadListener final : public nsIWebProgressListener
|
||||
, public nsSupportsWeakReference
|
||||
{
|
||||
RefPtr<ClientOpPromise::Private> mPromise;
|
||||
RefPtr<nsPIDOMWindowOuter> mOuterWindow;
|
||||
nsCOMPtr<nsIURI> mBaseURL;
|
||||
|
||||
~NavigateLoadListener() = default;
|
||||
|
||||
public:
|
||||
NavigateLoadListener(ClientOpPromise::Private* aPromise,
|
||||
nsPIDOMWindowOuter* aOuterWindow,
|
||||
nsIURI* aBaseURL)
|
||||
: mPromise(aPromise)
|
||||
, mOuterWindow(aOuterWindow)
|
||||
, mBaseURL(aBaseURL)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mPromise);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mOuterWindow);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mBaseURL);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStateChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
||||
uint32_t aStateFlags, nsresult aResult) override
|
||||
{
|
||||
if (!(aStateFlags & STATE_IS_DOCUMENT) ||
|
||||
!(aStateFlags & (STATE_STOP | STATE_TRANSFERRING))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
aWebProgress->RemoveProgressListener(this);
|
||||
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
||||
if (!channel) {
|
||||
mPromise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> channelURL;
|
||||
nsresult rv = NS_GetFinalChannelURI(channel, getter_AddRefs(channelURL));
|
||||
if (NS_FAILED(rv)) {
|
||||
mPromise->Reject(rv, __func__);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
MOZ_DIAGNOSTIC_ASSERT(ssm);
|
||||
|
||||
// If the resulting window is not same origin, then resolve immediately
|
||||
// without returning any information about the new Client. This is
|
||||
// step 6.10 in the Client.navigate(url) spec.
|
||||
rv = ssm->CheckSameOriginURI(mBaseURL, channelURL, false);
|
||||
if (NS_FAILED(rv)) {
|
||||
mPromise->Resolve(NS_OK, __func__);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsPIDOMWindowInner* innerWindow = mOuterWindow->GetCurrentInnerWindow();
|
||||
MOZ_DIAGNOSTIC_ASSERT(innerWindow);
|
||||
|
||||
Maybe<ClientInfo> clientInfo = innerWindow->GetClientInfo();
|
||||
MOZ_DIAGNOSTIC_ASSERT(clientInfo.isSome());
|
||||
|
||||
Maybe<ClientState> clientState = innerWindow->GetClientState();
|
||||
MOZ_DIAGNOSTIC_ASSERT(clientState.isSome());
|
||||
|
||||
// Otherwise, if the new window is same-origin we want to return a
|
||||
// ClientInfoAndState object so we can provide a Client snapshot
|
||||
// to the caller. This is step 6.11 and 6.12 in the Client.navigate(url)
|
||||
// spec.
|
||||
mPromise->Resolve(ClientInfoAndState(clientInfo.ref().ToIPC(),
|
||||
clientState.ref().ToIPC()), __func__);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnProgressChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
||||
int32_t aCurSelfProgress, int32_t aMaxSelfProgress,
|
||||
int32_t aCurTotalProgress, int32_t aMaxTotalProgress) override
|
||||
{
|
||||
MOZ_CRASH("Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
||||
nsIURI* aLocation, uint32_t aFlags) override
|
||||
{
|
||||
MOZ_CRASH("Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
||||
nsresult aStatus, const char16_t* aMessage) override
|
||||
{
|
||||
MOZ_CRASH("Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
|
||||
uint32_t aState) override
|
||||
{
|
||||
MOZ_CRASH("Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(NavigateLoadListener, nsIWebProgressListener,
|
||||
nsISupportsWeakReference);
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
already_AddRefed<ClientOpPromise>
|
||||
ClientNavigateOpChild::DoNavigate(const ClientNavigateOpConstructorArgs& aArgs)
|
||||
{
|
||||
RefPtr<ClientOpPromise> ref;
|
||||
nsCOMPtr<nsPIDOMWindowInner> window;
|
||||
|
||||
// Navigating the target client window will result in the original
|
||||
// ClientSource being destroyed. To avoid potential UAF mistakes
|
||||
// we use a small scope to access the ClientSource object. Once
|
||||
// we have a strong reference to the window object we should not
|
||||
// access the ClientSource again.
|
||||
{
|
||||
ClientSourceChild* targetActor =
|
||||
static_cast<ClientSourceChild*>(aArgs.targetChild());
|
||||
MOZ_DIAGNOSTIC_ASSERT(targetActor);
|
||||
|
||||
ClientSource* target = targetActor->GetSource();
|
||||
if (!target) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
__func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
window = target->GetInnerWindow();
|
||||
if (!window) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
__func__);
|
||||
return ref.forget();
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mSerialEventTarget = window->EventTargetFor(TaskCategory::Other);
|
||||
|
||||
// In theory we could do the URL work before paying the IPC overhead
|
||||
// cost, but in practice its easier to do it here. The ClientHandle
|
||||
// may be off-main-thread while this method is guaranteed to always
|
||||
// be main thread.
|
||||
nsCOMPtr<nsIURI> baseURL;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(baseURL), aArgs.baseURL());
|
||||
if (NS_FAILED(rv)) {
|
||||
ref = ClientOpPromise::CreateAndReject(rv, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> url;
|
||||
rv = NS_NewURI(getter_AddRefs(url), aArgs.url(), nullptr, baseURL);
|
||||
if (NS_FAILED(rv)) {
|
||||
ref = ClientOpPromise::CreateAndReject(rv, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
if (url->GetSpecOrDefault().EqualsLiteral("about:blank")) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
|
||||
if (!doc || !doc->IsActive()) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
|
||||
if (!principal) {
|
||||
ref = ClientOpPromise::CreateAndReject(rv, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
|
||||
nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
|
||||
if (!docShell || !webProgress) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
|
||||
rv = docShell->CreateLoadInfo(getter_AddRefs(loadInfo));
|
||||
if (NS_FAILED(rv)) {
|
||||
ref = ClientOpPromise::CreateAndReject(rv, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
loadInfo->SetTriggeringPrincipal(principal);
|
||||
loadInfo->SetReferrerPolicy(doc->GetReferrerPolicy());
|
||||
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadStopContent);
|
||||
loadInfo->SetSourceDocShell(docShell);
|
||||
rv = docShell->LoadURI(url, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, true);
|
||||
if (NS_FAILED(rv)) {
|
||||
ref = ClientOpPromise::CreateAndReject(rv, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise::Private> promise =
|
||||
new ClientOpPromise::Private(__func__);
|
||||
|
||||
nsCOMPtr<nsIWebProgressListener> listener =
|
||||
new NavigateLoadListener(promise, window->GetOuterWindow(), baseURL);
|
||||
|
||||
rv = webProgress->AddProgressListener(listener,
|
||||
nsIWebProgress::NOTIFY_STATE_DOCUMENT);
|
||||
if (NS_FAILED(rv)) {
|
||||
promise->Reject(rv, __func__);
|
||||
ref = promise;
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
ref = promise.get();
|
||||
|
||||
ref->Then(mSerialEventTarget, __func__,
|
||||
[listener] (const ClientOpResult& aResult) { },
|
||||
[listener] (nsresult aResult) { });
|
||||
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ClientNavigateOpChild::ActorDestroy(ActorDestroyReason aReason)
|
||||
{
|
||||
mPromiseRequestHolder.DisconnectIfExists();
|
||||
}
|
||||
|
||||
void
|
||||
ClientNavigateOpChild::Init(const ClientNavigateOpConstructorArgs& aArgs)
|
||||
{
|
||||
RefPtr<ClientOpPromise> promise = DoNavigate(aArgs);
|
||||
|
||||
// Normally we get the event target from the window in DoNavigate(). If a
|
||||
// failure occurred, though, we may need to fall back to the current thread
|
||||
// target.
|
||||
if (!mSerialEventTarget) {
|
||||
mSerialEventTarget = GetCurrentThreadSerialEventTarget();
|
||||
}
|
||||
|
||||
// Capturing `this` is safe here since we clear the mPromiseRequestHolder in
|
||||
// ActorDestroy.
|
||||
promise->Then(mSerialEventTarget, __func__,
|
||||
[this] (const ClientOpResult& aResult) {
|
||||
mPromiseRequestHolder.Complete();
|
||||
PClientNavigateOpChild::Send__delete__(this, aResult);
|
||||
}, [this] (nsresult aResult) {
|
||||
mPromiseRequestHolder.Complete();
|
||||
PClientNavigateOpChild::Send__delete__(this, aResult);
|
||||
})->Track(mPromiseRequestHolder);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
@ -7,12 +7,19 @@
|
||||
#define _mozilla_dom_ClientNavigateOpChild_h
|
||||
|
||||
#include "mozilla/dom/PClientNavigateOpChild.h"
|
||||
#include "ClientOpPromise.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ClientNavigateOpChild final : public PClientNavigateOpChild
|
||||
{
|
||||
MozPromiseRequestHolder<ClientOpPromise> mPromiseRequestHolder;
|
||||
nsCOMPtr<nsISerialEventTarget> mSerialEventTarget;
|
||||
|
||||
already_AddRefed<ClientOpPromise>
|
||||
DoNavigate(const ClientNavigateOpConstructorArgs& aArgs);
|
||||
|
||||
// PClientNavigateOpChild interface
|
||||
void
|
||||
ActorDestroy(ActorDestroyReason aReason) override;
|
||||
|
@ -14,6 +14,10 @@ using mozilla::ipc::IPCResult;
|
||||
void
|
||||
ClientNavigateOpParent::ActorDestroy(ActorDestroyReason aReason)
|
||||
{
|
||||
if (mPromise) {
|
||||
mPromise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__);
|
||||
mPromise = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
IPCResult
|
||||
|
@ -5,18 +5,38 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ClientOpenWindowOpChild.h"
|
||||
#include "ClientOpenWindowUtils.h"
|
||||
#include "mozilla/SystemGroup.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
already_AddRefed<ClientOpPromise>
|
||||
ClientOpenWindowOpChild::DoOpenWindow(const ClientOpenWindowArgs& aArgs)
|
||||
{
|
||||
RefPtr<ClientOpPromise> ref =
|
||||
ClientOpenWindowInCurrentProcess(aArgs);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ClientOpenWindowOpChild::ActorDestroy(ActorDestroyReason aReason)
|
||||
{
|
||||
mPromiseRequestHolder.DisconnectIfExists();
|
||||
}
|
||||
|
||||
void
|
||||
ClientOpenWindowOpChild::Init(const ClientOpenWindowArgs& aArgs)
|
||||
{
|
||||
RefPtr<ClientOpPromise> promise = DoOpenWindow(aArgs);
|
||||
promise->Then(SystemGroup::EventTargetFor(TaskCategory::Other), __func__,
|
||||
[this] (const ClientOpResult& aResult) {
|
||||
mPromiseRequestHolder.Complete();
|
||||
PClientOpenWindowOpChild::Send__delete__(this, aResult);
|
||||
}, [this] (nsresult aResult) {
|
||||
mPromiseRequestHolder.Complete();
|
||||
PClientOpenWindowOpChild::Send__delete__(this, aResult);
|
||||
})->Track(mPromiseRequestHolder);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
@ -7,12 +7,18 @@
|
||||
#define _mozilla_dom_ClientOpenWindowOpChild_h
|
||||
|
||||
#include "mozilla/dom/PClientOpenWindowOpChild.h"
|
||||
#include "ClientOpPromise.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ClientOpenWindowOpChild final : public PClientOpenWindowOpChild
|
||||
{
|
||||
MozPromiseRequestHolder<ClientOpPromise> mPromiseRequestHolder;
|
||||
|
||||
already_AddRefed<ClientOpPromise>
|
||||
DoOpenWindow(const ClientOpenWindowArgs& aArgs);
|
||||
|
||||
// PClientOpenWindowOpChild interface
|
||||
void
|
||||
ActorDestroy(ActorDestroyReason aReason) override;
|
||||
|
463
dom/clients/manager/ClientOpenWindowUtils.cpp
Normal file
463
dom/clients/manager/ClientOpenWindowUtils.cpp
Normal file
@ -0,0 +1,463 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "ClientOpenWindowUtils.h"
|
||||
|
||||
#include "ClientInfo.h"
|
||||
#include "ClientState.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIBrowserDOMWindow.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDOMChromeWindow.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIWebProgress.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsPIWindowWatcher.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#include "FennecJNIWrappers.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
namespace {
|
||||
|
||||
class WebProgressListener final : public nsIWebProgressListener
|
||||
, public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
WebProgressListener(nsPIDOMWindowOuter* aWindow,
|
||||
nsIURI* aBaseURI,
|
||||
already_AddRefed<ClientOpPromise::Private> aPromise)
|
||||
: mPromise(aPromise)
|
||||
, mWindow(aWindow)
|
||||
, mBaseURI(aBaseURI)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aBaseURI);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStateChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
uint32_t aStateFlags, nsresult aStatus) override
|
||||
{
|
||||
if (!(aStateFlags & STATE_IS_DOCUMENT) ||
|
||||
!(aStateFlags & (STATE_STOP | STATE_TRANSFERRING))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Our caller keeps a strong reference, so it is safe to remove the listener
|
||||
// from ServiceWorkerPrivate.
|
||||
aWebProgress->RemoveProgressListener(this);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
|
||||
if (NS_WARN_IF(!doc)) {
|
||||
mPromise->Reject(NS_ERROR_FAILURE, __func__);
|
||||
mPromise = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check same origin.
|
||||
nsCOMPtr<nsIScriptSecurityManager> securityManager =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
nsresult rv = securityManager->CheckSameOriginURI(doc->GetOriginalURI(),
|
||||
mBaseURI, false);
|
||||
if (NS_FAILED(rv)) {
|
||||
mPromise->Resolve(NS_OK, __func__);
|
||||
mPromise = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsPIDOMWindowInner* innerWindow = doc->GetInnerWindow();
|
||||
if (NS_WARN_IF(!innerWindow)) {
|
||||
mPromise->Reject(NS_ERROR_FAILURE, __func__);
|
||||
mPromise = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Maybe<ClientInfo> info = innerWindow->GetClientInfo();
|
||||
Maybe<ClientState> state = innerWindow->GetClientState();
|
||||
|
||||
if (NS_WARN_IF(info.isNothing() || state.isNothing())) {
|
||||
mPromise->Reject(NS_ERROR_FAILURE, __func__);
|
||||
mPromise = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mPromise->Resolve(ClientInfoAndState(info.ref().ToIPC(), state.ref().ToIPC()),
|
||||
__func__);
|
||||
mPromise = nullptr;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnProgressChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
int32_t aCurSelfProgress,
|
||||
int32_t aMaxSelfProgress,
|
||||
int32_t aCurTotalProgress,
|
||||
int32_t aMaxTotalProgress) override
|
||||
{
|
||||
MOZ_ASSERT(false, "Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnLocationChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
nsIURI* aLocation,
|
||||
uint32_t aFlags) override
|
||||
{
|
||||
MOZ_ASSERT(false, "Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStatusChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
nsresult aStatus, const char16_t* aMessage) override
|
||||
{
|
||||
MOZ_ASSERT(false, "Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnSecurityChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
uint32_t aState) override
|
||||
{
|
||||
MOZ_ASSERT(false, "Unexpected notification.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~WebProgressListener()
|
||||
{
|
||||
if (mPromise) {
|
||||
mPromise->Reject(NS_ERROR_ABORT, __func__);
|
||||
mPromise = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise::Private> mPromise;
|
||||
// TODO: make window a weak ref and stop cycle collecting
|
||||
nsCOMPtr<nsPIDOMWindowOuter> mWindow;
|
||||
nsCOMPtr<nsIURI> mBaseURI;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(WebProgressListener, nsIWebProgressListener,
|
||||
nsISupportsWeakReference);
|
||||
|
||||
nsresult
|
||||
OpenWindow(const ClientOpenWindowArgs& aArgs,
|
||||
nsPIDOMWindowOuter** aWindow)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aWindow);
|
||||
|
||||
// [[1. Let url be the result of parsing url with entry settings object's API
|
||||
// base URL.]]
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(baseURI), aArgs.baseURL());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_TYPE_ERR;
|
||||
}
|
||||
|
||||
rv = NS_NewURI(getter_AddRefs(uri), aArgs.url(), nullptr, baseURI);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_TYPE_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
PrincipalInfoToPrincipal(aArgs.principalInfo());
|
||||
MOZ_DIAGNOSTIC_ASSERT(principal);
|
||||
|
||||
// [[6.1 Open Window]]
|
||||
if (XRE_IsContentProcess()) {
|
||||
|
||||
// Let's create a sandbox in order to have a valid JSContext and correctly
|
||||
// propagate the SubjectPrincipal.
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
MOZ_DIAGNOSTIC_ASSERT(xpc);
|
||||
|
||||
JS::Rooted<JSObject*> sandbox(cx);
|
||||
rv = xpc->CreateSandbox(cx, principal, sandbox.address());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_TYPE_ERR;
|
||||
}
|
||||
|
||||
JSAutoCompartment ac(cx, sandbox);
|
||||
|
||||
// ContentProcess
|
||||
nsCOMPtr<nsIWindowWatcher> wwatch =
|
||||
do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
nsCOMPtr<nsPIWindowWatcher> pwwatch(do_QueryInterface(wwatch));
|
||||
NS_ENSURE_STATE(pwwatch);
|
||||
|
||||
nsCString spec;
|
||||
rv = uri->GetSpec(spec);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIDOMWindowProxy> newWindow;
|
||||
rv = pwwatch->OpenWindow2(nullptr,
|
||||
spec.get(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
false, false, true, nullptr,
|
||||
// Not a spammy popup; we got permission, we swear!
|
||||
/* aIsPopupSpam = */ false,
|
||||
// Don't force noopener. We're not passing in an
|
||||
// opener anyway, and we _do_ want the returned
|
||||
// window.
|
||||
/* aForceNoOpener = */ false,
|
||||
/* aLoadInfp = */ nullptr,
|
||||
getter_AddRefs(newWindow));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
nsCOMPtr<nsPIDOMWindowOuter> pwindow = nsPIDOMWindowOuter::From(newWindow);
|
||||
pwindow.forget(aWindow);
|
||||
MOZ_DIAGNOSTIC_ASSERT(*aWindow);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Find the most recent browser window and open a new tab in it.
|
||||
nsCOMPtr<nsPIDOMWindowOuter> browserWindow =
|
||||
nsContentUtils::GetMostRecentNonPBWindow();
|
||||
if (!browserWindow) {
|
||||
// It is possible to be running without a browser window on Mac OS, so
|
||||
// we need to open a new chrome window.
|
||||
// TODO(catalinb): open new chrome window. Bug 1218080
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMChromeWindow> chromeWin = do_QueryInterface(browserWindow);
|
||||
if (NS_WARN_IF(!chromeWin)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIBrowserDOMWindow> bwin;
|
||||
chromeWin->GetBrowserDOMWindow(getter_AddRefs(bwin));
|
||||
|
||||
if (NS_WARN_IF(!bwin)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIDOMWindowProxy> win;
|
||||
rv = bwin->OpenURI(uri, nullptr,
|
||||
nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW,
|
||||
nsIBrowserDOMWindow::OPEN_NEW,
|
||||
principal,
|
||||
getter_AddRefs(win));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
NS_ENSURE_STATE(win);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> pWin = nsPIDOMWindowOuter::From(win);
|
||||
pWin.forget(aWindow);
|
||||
MOZ_DIAGNOSTIC_ASSERT(*aWindow);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
WaitForLoad(const ClientOpenWindowArgs& aArgs,
|
||||
nsPIDOMWindowOuter* aOuterWindow,
|
||||
ClientOpPromise::Private* aPromise)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aOuterWindow);
|
||||
|
||||
RefPtr<ClientOpPromise::Private> promise = aPromise;
|
||||
|
||||
nsresult rv = nsContentUtils::DispatchFocusChromeEvent(aOuterWindow);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
promise->Reject(rv, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
rv = NS_NewURI(getter_AddRefs(baseURI), aArgs.baseURL());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
promise->Reject(rv, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = aOuterWindow->GetDocShell();
|
||||
nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
|
||||
|
||||
if (NS_WARN_IF(!webProgress)) {
|
||||
promise->Reject(NS_ERROR_FAILURE, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise> ref = promise;
|
||||
|
||||
RefPtr<WebProgressListener> listener =
|
||||
new WebProgressListener(aOuterWindow, baseURI, promise.forget());
|
||||
|
||||
|
||||
rv = webProgress->AddProgressListener(listener,
|
||||
nsIWebProgress::NOTIFY_STATE_DOCUMENT);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
promise->Reject(rv, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
// Hold the listener alive until the promise settles
|
||||
ref->Then(aOuterWindow->EventTargetFor(TaskCategory::Other), __func__,
|
||||
[listener] (const ClientOpResult& aResult) { },
|
||||
[listener] (nsresult aResult) { });
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
||||
class LaunchObserver final : public nsIObserver
|
||||
{
|
||||
RefPtr<GenericPromise::Private> mPromise;
|
||||
|
||||
LaunchObserver()
|
||||
: mPromise(new GenericPromise::Private(__func__))
|
||||
{
|
||||
}
|
||||
|
||||
~LaunchObserver() = default;
|
||||
|
||||
NS_IMETHOD
|
||||
Observe(nsISupports* aSubject, const char* aTopic, const char16_t * aData) override
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (os) {
|
||||
os->RemoveObserver(this, "BrowserChrome:Ready");
|
||||
}
|
||||
mPromise->Resolve(true, __func__);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
public:
|
||||
static already_AddRefed<LaunchObserver>
|
||||
Create()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (NS_WARN_IF(!os)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<LaunchObserver> ref = new LaunchObserver();
|
||||
|
||||
nsresult rv = os->AddObserver(ref, "BrowserChrome:Ready", /* weakRef */ false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
void
|
||||
Cancel()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (os) {
|
||||
os->RemoveObserver(this, "BrowserChrome:Ready");
|
||||
}
|
||||
mPromise->Reject(NS_ERROR_ABORT, __func__);
|
||||
}
|
||||
|
||||
GenericPromise*
|
||||
Promise()
|
||||
{
|
||||
return mPromise;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(LaunchObserver, nsIObserver);
|
||||
|
||||
#endif // MOZ_WIDGET_ANDROID
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
already_AddRefed<ClientOpPromise>
|
||||
ClientOpenWindowInCurrentProcess(const ClientOpenWindowArgs& aArgs)
|
||||
{
|
||||
RefPtr<ClientOpPromise::Private> promise =
|
||||
new ClientOpPromise::Private(__func__);
|
||||
RefPtr<ClientOpPromise> ref = promise;
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
// This fires an intent that will start launching Fennec and foreground it,
|
||||
// if necessary. We create an observer so that we can determine when
|
||||
// the launch has completed.
|
||||
RefPtr<LaunchObserver> launchObserver = LaunchObserver::Create();
|
||||
java::GeckoApp::LaunchOrBringToFront();
|
||||
#endif // MOZ_WIDGET_ANDROID
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> outerWindow;
|
||||
nsresult rv = OpenWindow(aArgs, getter_AddRefs(outerWindow));
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
// If we get the NOT_AVAILABLE error that means the browser is still
|
||||
// launching on android. Use the observer we created above to wait
|
||||
// until the launch completes and then try to open the window again.
|
||||
if (rv == NS_ERROR_NOT_AVAILABLE && launchObserver) {
|
||||
RefPtr<GenericPromise> p = launchObserver->Promise();
|
||||
p->Then(outerWindow->EventTargetFor(TaskCategory::Other), __func__,
|
||||
[aArgs, promise] (bool aResult) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> outerWindow;
|
||||
nsresult rv = OpenWindow(aArgs, getter_AddRefs(outerWindow));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
promise->Reject(rv, __func__);
|
||||
}
|
||||
|
||||
WaitForLoad(aArgs, outerWindow, promise);
|
||||
}, [promise] (nsresult aResult) {
|
||||
promise->Reject(aResult, __func__);
|
||||
});
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
// If we didn't get the NOT_AVAILABLE error then there is no need
|
||||
// wait for the browser to launch. Cancel the observer so that it
|
||||
// will release.
|
||||
if (launchObserver) {
|
||||
launchObserver->Cancel();
|
||||
}
|
||||
#endif // MOZ_WIDGET_ANDROID
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
promise->Reject(rv, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(outerWindow);
|
||||
WaitForLoad(aArgs, outerWindow, promise);
|
||||
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
21
dom/clients/manager/ClientOpenWindowUtils.h
Normal file
21
dom/clients/manager/ClientOpenWindowUtils.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
#ifndef _mozilla_dom_ClientOpenWindowUtils_h
|
||||
#define _mozilla_dom_ClientOpenWindowUtils_h
|
||||
|
||||
#include "ClientOpPromise.h"
|
||||
#include "mozilla/dom/ClientIPCTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
already_AddRefed<ClientOpPromise>
|
||||
ClientOpenWindowInCurrentProcess(const ClientOpenWindowArgs &aArgs);
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // _mozilla_dom_ClientOpenWindowUtils_h
|
@ -12,15 +12,29 @@
|
||||
#include "ClientState.h"
|
||||
#include "ClientValidation.h"
|
||||
#include "mozilla/dom/ClientIPCTypes.h"
|
||||
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
||||
#include "mozilla/dom/MessageEvent.h"
|
||||
#include "mozilla/dom/MessageEventBinding.h"
|
||||
#include "mozilla/dom/Navigator.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
#include "mozilla/dom/WorkerScope.h"
|
||||
#include "mozilla/dom/ServiceWorkerContainer.h"
|
||||
#include "mozilla/dom/workers/ServiceWorkerManager.h"
|
||||
#include "mozilla/dom/workers/bindings/ServiceWorker.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
using mozilla::dom::ipc::StructuredCloneData;
|
||||
using mozilla::dom::workers::ServiceWorkerInfo;
|
||||
using mozilla::dom::workers::ServiceWorkerManager;
|
||||
using mozilla::dom::workers::ServiceWorkerRegistrationInfo;
|
||||
using mozilla::dom::workers::WorkerPrivate;
|
||||
using mozilla::ipc::PrincipalInfo;
|
||||
using mozilla::ipc::PrincipalInfoToPrincipal;
|
||||
|
||||
void
|
||||
ClientSource::Shutdown()
|
||||
@ -361,6 +375,188 @@ ClientSource::GetController() const
|
||||
return mController;
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientSource::Focus(const ClientFocusArgs& aArgs)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(ClientSource);
|
||||
|
||||
RefPtr<ClientOpPromise> ref;
|
||||
|
||||
if (mClientInfo.Type() != ClientType::Window) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
|
||||
__func__);
|
||||
return ref.forget();
|
||||
}
|
||||
nsPIDOMWindowOuter* outer = nullptr;
|
||||
|
||||
nsPIDOMWindowInner* inner = GetInnerWindow();
|
||||
if (inner) {
|
||||
outer = inner->GetOuterWindow();
|
||||
} else {
|
||||
nsIDocShell* docshell = GetDocShell();
|
||||
if (docshell) {
|
||||
outer = docshell->GetWindow();
|
||||
}
|
||||
}
|
||||
|
||||
if (!outer) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
__func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsresult rv = nsContentUtils::DispatchFocusChromeEvent(outer);
|
||||
if (NS_FAILED(rv)) {
|
||||
ref = ClientOpPromise::CreateAndReject(rv, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
ClientState state;
|
||||
rv = SnapshotState(&state);
|
||||
if (NS_FAILED(rv)) {
|
||||
ref = ClientOpPromise::CreateAndReject(rv, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
ref = ClientOpPromise::CreateAndResolve(state.ToIPC(), __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientSource::PostMessage(const ClientPostMessageArgs& aArgs)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(ClientSource);
|
||||
RefPtr<ClientOpPromise> ref;
|
||||
|
||||
ServiceWorkerDescriptor source(aArgs.serviceWorker());
|
||||
const PrincipalInfo& principalInfo = source.PrincipalInfo();
|
||||
|
||||
StructuredCloneData clonedData;
|
||||
clonedData.BorrowFromClonedMessageDataForBackgroundChild(aArgs.clonedData());
|
||||
|
||||
// Currently we only support firing these messages on window Clients.
|
||||
// Once we expose ServiceWorkerContainer and the ServiceWorker on Worker
|
||||
// threads then this will need to change. See bug 1113522.
|
||||
if (mClientInfo.Type() != ClientType::Window) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_NOT_IMPLEMENTED, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<ServiceWorkerContainer> target;
|
||||
nsCOMPtr<nsIGlobalObject> globalObject;
|
||||
|
||||
// We don't need to force the creation of the about:blank document
|
||||
// here because there is no postMessage listener. If a listener
|
||||
// was registered then the document will already be created.
|
||||
nsPIDOMWindowInner* window = GetInnerWindow();
|
||||
if (window) {
|
||||
globalObject = do_QueryInterface(window);
|
||||
RefPtr<Navigator> navigator =
|
||||
static_cast<Navigator*>(window->GetNavigator());
|
||||
if (navigator) {
|
||||
target = navigator->ServiceWorker();
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!target)) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
__func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
// If AutoJSAPI::Init() fails then either global is nullptr or not
|
||||
// in a usable state.
|
||||
AutoJSAPI jsapi;
|
||||
if (!jsapi.Init(globalObject)) {
|
||||
ref = ClientOpPromise::CreateAndResolve(NS_OK, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
ErrorResult result;
|
||||
JS::Rooted<JS::Value> messageData(cx);
|
||||
clonedData.Read(cx, &messageData, result);
|
||||
if (result.MaybeSetPendingException(cx)) {
|
||||
// We reported the error in the current window context. Resolve
|
||||
// promise instead of rejecting.
|
||||
ref = ClientOpPromise::CreateAndResolve(NS_OK, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
RootedDictionary<MessageEventInit> init(cx);
|
||||
|
||||
init.mData = messageData;
|
||||
if (!clonedData.TakeTransferredPortsAsSequence(init.mPorts)) {
|
||||
// Report the error in the current window context and resolve the
|
||||
// promise instead of rejecting.
|
||||
xpc::Throw(cx, NS_ERROR_OUT_OF_MEMORY);
|
||||
ref = ClientOpPromise::CreateAndResolve(NS_OK, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
PrincipalInfoToPrincipal(principalInfo, &rv);
|
||||
if (NS_FAILED(rv) || !principal) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
nsAutoCString origin;
|
||||
rv = principal->GetOriginNoSuffix(origin);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
CopyUTF8toUTF16(origin, init.mOrigin);
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (!swm) {
|
||||
// Shutting down. Just don't deliver this message.
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> reg =
|
||||
swm->GetRegistration(principal, source.Scope());
|
||||
if (reg) {
|
||||
RefPtr<ServiceWorkerInfo> serviceWorker = reg->GetByID(source.Id());
|
||||
if (serviceWorker) {
|
||||
init.mSource.SetValue().SetAsServiceWorker() =
|
||||
serviceWorker->GetOrCreateInstance(GetInnerWindow());
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<MessageEvent> event =
|
||||
MessageEvent::Constructor(target, NS_LITERAL_STRING("message"), init);
|
||||
event->SetTrusted(true);
|
||||
|
||||
bool preventDefaultCalled = false;
|
||||
rv = target->DispatchEvent(static_cast<dom::Event*>(event.get()),
|
||||
&preventDefaultCalled);
|
||||
if (NS_FAILED(rv)) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
ref = ClientOpPromise::CreateAndResolve(NS_OK, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientSource::Claim(const ClientClaimArgs& aArgs)
|
||||
{
|
||||
SetController(ServiceWorkerDescriptor(aArgs.serviceWorker()));
|
||||
|
||||
RefPtr<ClientOpPromise> ref =
|
||||
ClientOpPromise::CreateAndResolve(NS_OK, __func__);
|
||||
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientSource::GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs)
|
||||
{
|
||||
|
@ -12,6 +12,10 @@
|
||||
#include "mozilla/dom/ServiceWorkerDescriptor.h"
|
||||
#include "mozilla/Variant.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#undef PostMessage
|
||||
#endif
|
||||
|
||||
class nsIDocShell;
|
||||
class nsISerialEventTarget;
|
||||
class nsPIDOMWindowInner;
|
||||
@ -19,11 +23,17 @@ class nsPIDOMWindowInner;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ClientClaimArgs;
|
||||
class ClientControlledArgs;
|
||||
class ClientFocusArgs;
|
||||
class ClientGetInfoAndStateArgs;
|
||||
class ClientManager;
|
||||
class ClientPostMessageArgs;
|
||||
class ClientSourceChild;
|
||||
class ClientSourceConstructorArgs;
|
||||
class ClientSourceExecutionReadyArgs;
|
||||
class ClientState;
|
||||
class ClientWindowState;
|
||||
class PClientManagerChild;
|
||||
|
||||
namespace workers {
|
||||
@ -131,6 +141,15 @@ public:
|
||||
const Maybe<ServiceWorkerDescriptor>&
|
||||
GetController() const;
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
Focus(const ClientFocusArgs& aArgs);
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
PostMessage(const ClientPostMessageArgs& aArgs);
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
Claim(const ClientClaimArgs& aArgs);
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs);
|
||||
|
||||
|
@ -79,6 +79,21 @@ ClientSourceOpChild::Init(const ClientOpConstructorArgs& aArgs)
|
||||
DoSourceOp(&ClientSource::Control, aArgs.get_ClientControlledArgs());
|
||||
break;
|
||||
}
|
||||
case ClientOpConstructorArgs::TClientFocusArgs:
|
||||
{
|
||||
DoSourceOp(&ClientSource::Focus, aArgs.get_ClientFocusArgs());
|
||||
break;
|
||||
}
|
||||
case ClientOpConstructorArgs::TClientPostMessageArgs:
|
||||
{
|
||||
DoSourceOp(&ClientSource::PostMessage, aArgs.get_ClientPostMessageArgs());
|
||||
break;
|
||||
}
|
||||
case ClientOpConstructorArgs::TClientClaimArgs:
|
||||
{
|
||||
DoSourceOp(&ClientSource::Claim, aArgs.get_ClientClaimArgs());
|
||||
break;
|
||||
}
|
||||
case ClientOpConstructorArgs::TClientGetInfoAndStateArgs:
|
||||
{
|
||||
DoSourceOp(&ClientSource::GetInfoAndState,
|
||||
|
@ -225,6 +225,12 @@ ClientSourceParent::ExecutionReady() const
|
||||
return mExecutionReady;
|
||||
}
|
||||
|
||||
const Maybe<ServiceWorkerDescriptor>&
|
||||
ClientSourceParent::GetController() const
|
||||
{
|
||||
return mController;
|
||||
}
|
||||
|
||||
void
|
||||
ClientSourceParent::AttachHandle(ClientHandleParent* aClientHandle)
|
||||
{
|
||||
|
@ -70,6 +70,9 @@ public:
|
||||
bool
|
||||
ExecutionReady() const;
|
||||
|
||||
const Maybe<ServiceWorkerDescriptor>&
|
||||
GetController() const;
|
||||
|
||||
void
|
||||
AttachHandle(ClientHandleParent* aClientSource);
|
||||
|
||||
|
@ -38,6 +38,7 @@ UNIFIED_SOURCES += [
|
||||
'ClientOpenWindowOpActors.cpp',
|
||||
'ClientOpenWindowOpChild.cpp',
|
||||
'ClientOpenWindowOpParent.cpp',
|
||||
'ClientOpenWindowUtils.cpp',
|
||||
'ClientPrefs.cpp',
|
||||
'ClientSource.cpp',
|
||||
'ClientSourceChild.cpp',
|
||||
|
@ -16,7 +16,7 @@ NS_NewHTMLSlotElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
mozilla::dom::FromParser aFromParser)
|
||||
{
|
||||
RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo);
|
||||
if (nsContentUtils::IsWebComponentsEnabled()) {
|
||||
if (nsDocument::IsWebComponentsEnabled(nodeInfo->GetDocument())) {
|
||||
already_AddRefed<mozilla::dom::NodeInfo> nodeInfoArg(nodeInfo.forget());
|
||||
return new mozilla::dom::HTMLSlotElement(nodeInfoArg);
|
||||
}
|
||||
|
@ -647,6 +647,8 @@ public:
|
||||
virtual bool
|
||||
DeallocPClientOpenWindowOpParent(PClientOpenWindowOpParent* aActor) override;
|
||||
|
||||
static hal::ProcessPriority GetInitialProcessPriority(Element* aFrameElement);
|
||||
|
||||
// Control the priority of the IPC messages for input events.
|
||||
void SetInputPriorityEventEnabled(bool aEnabled);
|
||||
bool IsInputPriorityEventEnabled()
|
||||
@ -680,8 +682,6 @@ private:
|
||||
static nsDataHashtable<nsUint32HashKey, ContentParent*> *sJSPluginContentParents;
|
||||
static StaticAutoPtr<LinkedList<ContentParent> > sContentParents;
|
||||
|
||||
static hal::ProcessPriority GetInitialProcessPriority(Element* aFrameElement);
|
||||
|
||||
static ContentBridgeParent* CreateContentBridgeParent(const TabContext& aContext,
|
||||
const hal::ProcessPriority& aPriority,
|
||||
const TabId& aOpenerTabId,
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mozilla/dom/DOMStringList.h"
|
||||
#include "nsIPrefetchService.h"
|
||||
#include "nsCPrefetchService.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
@ -254,19 +254,19 @@ dictionary ShadowRootInit {
|
||||
// https://dom.spec.whatwg.org/#element
|
||||
partial interface Element {
|
||||
// Shadow DOM v1
|
||||
[Throws, Pref="dom.webcomponents.enabled"]
|
||||
[Throws, Func="nsDocument::IsWebComponentsEnabled"]
|
||||
ShadowRoot attachShadow(ShadowRootInit shadowRootInitDict);
|
||||
[BinaryName="shadowRootByMode", Pref="dom.webcomponents.enabled"]
|
||||
[BinaryName="shadowRootByMode", Func="nsDocument::IsWebComponentsEnabled"]
|
||||
readonly attribute ShadowRoot? shadowRoot;
|
||||
[BinaryName="assignedSlotByMode", Pref="dom.webcomponents.enabled"]
|
||||
[BinaryName="assignedSlotByMode", Func="nsDocument::IsWebComponentsEnabled"]
|
||||
readonly attribute HTMLSlotElement? assignedSlot;
|
||||
[CEReactions, Unscopable, SetterThrows, Pref="dom.webcomponents.enabled"]
|
||||
[CEReactions, Unscopable, SetterThrows, Func="nsDocument::IsWebComponentsEnabled"]
|
||||
attribute DOMString slot;
|
||||
|
||||
// [deprecated] Shadow DOM v0
|
||||
[Throws, Pref="dom.webcomponents.enabled"]
|
||||
[Throws, Func="nsDocument::IsWebComponentsEnabled"]
|
||||
ShadowRoot createShadowRoot();
|
||||
[Pref="dom.webcomponents.enabled"]
|
||||
[Func="nsDocument::IsWebComponentsEnabled"]
|
||||
NodeList getDestinationInsertionPoints();
|
||||
};
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
* and create derivative works of this document.
|
||||
*/
|
||||
|
||||
[Pref="dom.webcomponents.enabled", Exposed=Window, HTMLConstructor]
|
||||
[Func="nsDocument::IsWebComponentsEnabled", Exposed=Window, HTMLConstructor]
|
||||
interface HTMLSlotElement : HTMLElement {
|
||||
[CEReactions, SetterThrows] attribute DOMString name;
|
||||
sequence<Node> assignedNodes(optional AssignedNodesOptions options);
|
||||
|
@ -17,7 +17,7 @@ enum ShadowRootMode {
|
||||
};
|
||||
|
||||
// https://dom.spec.whatwg.org/#shadowroot
|
||||
[Pref="dom.webcomponents.enabled"]
|
||||
[Func="nsDocument::IsWebComponentsEnabled"]
|
||||
interface ShadowRoot : DocumentFragment
|
||||
{
|
||||
// Shadow DOM v1
|
||||
|
@ -38,4 +38,10 @@ interface TestFunctions {
|
||||
// DOMString argument on the C++ side and trying to hand it
|
||||
// stringbuffers. If length not passed, use our full length.
|
||||
DOMString getStringDataAsDOMString(optional unsigned long length);
|
||||
|
||||
// Functions that just punch through to mozITestInterfaceJS.idl
|
||||
[Throws]
|
||||
void testThrowNsresult();
|
||||
[Throws]
|
||||
void testThrowNsresultFromNative();
|
||||
};
|
||||
|
@ -19,7 +19,7 @@ interface Text : CharacterData {
|
||||
};
|
||||
|
||||
partial interface Text {
|
||||
[BinaryName="assignedSlotByMode", Pref="dom.webcomponents.enabled"]
|
||||
[BinaryName="assignedSlotByMode", Func="nsTextNode::IsWebComponentsEnabled"]
|
||||
readonly attribute HTMLSlotElement? assignedSlot;
|
||||
};
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user