зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to graphics
This commit is contained in:
Коммит
5e2990dc18
10
.cron.yml
10
.cron.yml
|
@ -25,3 +25,13 @@ jobs:
|
||||||
- date
|
- date
|
||||||
when: [] # never (temporary)
|
when: [] # never (temporary)
|
||||||
|
|
||||||
|
- name: nightly-mochitest-valgrind
|
||||||
|
job:
|
||||||
|
type: decision-task
|
||||||
|
treeherder-symbol: Vg
|
||||||
|
target-tasks-method: mochitest_valgrind
|
||||||
|
run-on-projects:
|
||||||
|
- mozilla-central
|
||||||
|
when:
|
||||||
|
- {hour: 16, minute: 0}
|
||||||
|
- {hour: 4, minute: 0}
|
||||||
|
|
|
@ -115,7 +115,6 @@ devtools/server/tests/browser/**
|
||||||
devtools/server/tests/mochitest/**
|
devtools/server/tests/mochitest/**
|
||||||
devtools/server/tests/unit/**
|
devtools/server/tests/unit/**
|
||||||
devtools/shared/heapsnapshot/**
|
devtools/shared/heapsnapshot/**
|
||||||
devtools/shared/transport/tests/unit/**
|
|
||||||
devtools/shared/webconsole/test/**
|
devtools/shared/webconsole/test/**
|
||||||
|
|
||||||
# Ignore devtools pre-processed files
|
# Ignore devtools pre-processed files
|
||||||
|
|
|
@ -461,11 +461,15 @@ DocAccessibleParent::Destroy()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_ASSERTION(mChildDocs.IsEmpty(),
|
|
||||||
"why weren't the child docs destroyed already?");
|
|
||||||
mShutdown = true;
|
mShutdown = true;
|
||||||
|
|
||||||
uint32_t childDocCount = mChildDocs.Length();
|
uint32_t childDocCount = mChildDocs.Length();
|
||||||
|
for (uint32_t i = 0; i < childDocCount; i++) {
|
||||||
|
for (uint32_t j = i + 1; j < childDocCount; j++) {
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(mChildDocs[i] != mChildDocs[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (uint32_t i = childDocCount - 1; i < childDocCount; i--)
|
for (uint32_t i = childDocCount - 1; i < childDocCount; i--)
|
||||||
mChildDocs[i]->Destroy();
|
mChildDocs[i]->Destroy();
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,6 @@ module.exports = {
|
||||||
|
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-shadow": "error",
|
"no-shadow": "error",
|
||||||
"no-undef": "off"
|
"no-undef": "error"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
rules: {
|
||||||
|
"no-undef": "off"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -4121,6 +4121,13 @@ function OpenBrowserWindow(options) {
|
||||||
extraFeatures += ",non-remote";
|
extraFeatures += ",non-remote";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the window is maximized, we want to skip the animation, since we're
|
||||||
|
// going to be taking up most of the screen anyways, and we want to optimize
|
||||||
|
// for showing the user a useful window as soon as possible.
|
||||||
|
if (window.windowState == window.STATE_MAXIMIZED) {
|
||||||
|
extraFeatures += ",suppressanimation";
|
||||||
|
}
|
||||||
|
|
||||||
// if and only if the current window is a browser window and it has a document with a character
|
// if and only if the current window is a browser window and it has a document with a character
|
||||||
// set, then extract the current charset menu setting from the current document and use it to
|
// set, then extract the current charset menu setting from the current document and use it to
|
||||||
// initialize the new browser window...
|
// initialize the new browser window...
|
||||||
|
|
|
@ -703,6 +703,7 @@
|
||||||
consumeanchor="identity-box"
|
consumeanchor="identity-box"
|
||||||
onclick="PageProxyClickHandler(event);"/>
|
onclick="PageProxyClickHandler(event);"/>
|
||||||
<image id="sharing-icon" mousethrough="always"/>
|
<image id="sharing-icon" mousethrough="always"/>
|
||||||
|
<image id="tracking-protection-icon"/>
|
||||||
<box id="blocked-permissions-container" align="center">
|
<box id="blocked-permissions-container" align="center">
|
||||||
<image data-permission-id="geo" class="blocked-permission-icon geo-icon" role="button"
|
<image data-permission-id="geo" class="blocked-permission-icon geo-icon" role="button"
|
||||||
tooltiptext="&urlbar.geolocationBlocked.tooltip;"/>
|
tooltiptext="&urlbar.geolocationBlocked.tooltip;"/>
|
||||||
|
@ -751,7 +752,6 @@
|
||||||
<image id="eme-notification-icon" class="notification-anchor-icon drm-icon" role="button"
|
<image id="eme-notification-icon" class="notification-anchor-icon drm-icon" role="button"
|
||||||
tooltiptext="&urlbar.emeNotificationAnchor.tooltip;"/>
|
tooltiptext="&urlbar.emeNotificationAnchor.tooltip;"/>
|
||||||
</box>
|
</box>
|
||||||
<image id="tracking-protection-icon"/>
|
|
||||||
<image id="connection-icon"/>
|
<image id="connection-icon"/>
|
||||||
<hbox id="identity-icon-labels">
|
<hbox id="identity-icon-labels">
|
||||||
<label id="identity-icon-label" class="plain" flex="1"/>
|
<label id="identity-icon-label" class="plain" flex="1"/>
|
||||||
|
|
|
@ -79,6 +79,8 @@ support-files =
|
||||||
browser_webext_nopermissions.xpi
|
browser_webext_nopermissions.xpi
|
||||||
browser_webext_update1.xpi
|
browser_webext_update1.xpi
|
||||||
browser_webext_update2.xpi
|
browser_webext_update2.xpi
|
||||||
|
browser_webext_update_icon1.xpi
|
||||||
|
browser_webext_update_icon2.xpi
|
||||||
browser_webext_update.json
|
browser_webext_update.json
|
||||||
!/image/test/mochitest/blue.png
|
!/image/test/mochitest/blue.png
|
||||||
!/toolkit/content/tests/browser/common/mockTransfer.js
|
!/toolkit/content/tests/browser/common/mockTransfer.js
|
||||||
|
|
|
@ -2,6 +2,7 @@ const {AddonManagerPrivate} = Cu.import("resource://gre/modules/AddonManager.jsm
|
||||||
|
|
||||||
const URL_BASE = "https://example.com/browser/browser/base/content/test/general";
|
const URL_BASE = "https://example.com/browser/browser/base/content/test/general";
|
||||||
const ID = "update@tests.mozilla.org";
|
const ID = "update@tests.mozilla.org";
|
||||||
|
const ID_ICON = "update_icon@tests.mozilla.org";
|
||||||
|
|
||||||
function promiseInstallAddon(url) {
|
function promiseInstallAddon(url) {
|
||||||
return AddonManager.getInstallForURL(url, null, "application/x-xpinstall")
|
return AddonManager.getInstallForURL(url, null, "application/x-xpinstall")
|
||||||
|
@ -84,7 +85,8 @@ add_task(function setup() {
|
||||||
]});
|
]});
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_background_update() {
|
// Helper function to test background updates.
|
||||||
|
function* backgroundUpdateTest(url, id, checkIconFn) {
|
||||||
yield SpecialPowers.pushPrefEnv({set: [
|
yield SpecialPowers.pushPrefEnv({set: [
|
||||||
// Turn on background updates
|
// Turn on background updates
|
||||||
["extensions.update.enabled", true],
|
["extensions.update.enabled", true],
|
||||||
|
@ -94,7 +96,7 @@ add_task(function* test_background_update() {
|
||||||
]});
|
]});
|
||||||
|
|
||||||
// Install version 1.0 of the test extension
|
// Install version 1.0 of the test extension
|
||||||
let addon = yield promiseInstallAddon(`${URL_BASE}/browser_webext_update1.xpi`);
|
let addon = yield promiseInstallAddon(url);
|
||||||
|
|
||||||
ok(addon, "Addon was installed");
|
ok(addon, "Addon was installed");
|
||||||
is(getBadgeStatus(), "", "Should not start out with an addon alert badge");
|
is(getBadgeStatus(), "", "Should not start out with an addon alert badge");
|
||||||
|
@ -129,11 +131,12 @@ add_task(function* test_background_update() {
|
||||||
ok(!win.gViewController.isLoading, "about:addons view is fully loaded");
|
ok(!win.gViewController.isLoading, "about:addons view is fully loaded");
|
||||||
is(win.gViewController.currentViewId, VIEW, "about:addons is at extensions list");
|
is(win.gViewController.currentViewId, VIEW, "about:addons is at extensions list");
|
||||||
|
|
||||||
// Wait for the permission prompt and cancel it
|
// Wait for the permission prompt, check the contents, then cancel the update
|
||||||
let panel = yield popupPromise;
|
let panel = yield popupPromise;
|
||||||
|
checkIconFn(panel.getAttribute("icon"));
|
||||||
panel.secondaryButton.click();
|
panel.secondaryButton.click();
|
||||||
|
|
||||||
addon = yield AddonManager.getAddonByID(ID);
|
addon = yield AddonManager.getAddonByID(id);
|
||||||
is(addon.version, "1.0", "Should still be running the old version");
|
is(addon.version, "1.0", "Should still be running the old version");
|
||||||
|
|
||||||
yield BrowserTestUtils.removeTab(tab);
|
yield BrowserTestUtils.removeTab(tab);
|
||||||
|
@ -187,7 +190,26 @@ add_task(function* test_background_update() {
|
||||||
|
|
||||||
addon.uninstall();
|
addon.uninstall();
|
||||||
yield SpecialPowers.popPrefEnv();
|
yield SpecialPowers.popPrefEnv();
|
||||||
});
|
}
|
||||||
|
|
||||||
|
function checkDefaultIcon(icon) {
|
||||||
|
is(icon, "chrome://mozapps/skin/extensions/extensionGeneric.svg",
|
||||||
|
"Popup has the default extension icon");
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(() => backgroundUpdateTest(`${URL_BASE}/browser_webext_update1.xpi`,
|
||||||
|
ID, checkDefaultIcon));
|
||||||
|
|
||||||
|
function checkNonDefaultIcon(icon) {
|
||||||
|
// The icon should come from the extension, don't bother with the precise
|
||||||
|
// path, just make sure we've got a jar url pointing to the right path
|
||||||
|
// inside the jar.
|
||||||
|
ok(icon.startsWith("jar:file://"), "Icon is a jar url");
|
||||||
|
ok(icon.endsWith("/icon.png"), "Icon is icon.png inside a jar");
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(() => backgroundUpdateTest(`${URL_BASE}/browser_webext_update_icon1.xpi`,
|
||||||
|
ID_ICON, checkNonDefaultIcon));
|
||||||
|
|
||||||
// Helper function to test a specific scenario for interactive updates.
|
// Helper function to test a specific scenario for interactive updates.
|
||||||
// `checkFn` is a callable that triggers a check for updates.
|
// `checkFn` is a callable that triggers a check for updates.
|
||||||
|
|
|
@ -13,6 +13,20 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"update_icon@tests.mozilla.org": {
|
||||||
|
"updates": [
|
||||||
|
{
|
||||||
|
"version": "2.0",
|
||||||
|
"update_link": "https://example.com/browser/browser/base/content/test/general/browser_webext_update_icon2.xpi",
|
||||||
|
"applications": {
|
||||||
|
"gecko": {
|
||||||
|
"strict_min_version": "1",
|
||||||
|
"advisory_max_version": "55.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -321,7 +321,7 @@ var gTests = [
|
||||||
|
|
||||||
{
|
{
|
||||||
desc: "getUserMedia screen: clicking through without selecting a screen denies",
|
desc: "getUserMedia screen: clicking through without selecting a screen denies",
|
||||||
run: function* checkReloading() {
|
run: function* checkClickThroughDenies() {
|
||||||
let promise = promisePopupNotificationShown("webRTC-shareDevices");
|
let promise = promisePopupNotificationShown("webRTC-shareDevices");
|
||||||
yield promiseRequestDevice(false, true, null, "screen");
|
yield promiseRequestDevice(false, true, null, "screen");
|
||||||
yield promise;
|
yield promise;
|
||||||
|
|
|
@ -407,12 +407,14 @@ function* closeStream(aAlreadyClosed, aFrameId, aStreamCount = 1) {
|
||||||
|
|
||||||
function* reloadAndAssertClosedStreams() {
|
function* reloadAndAssertClosedStreams() {
|
||||||
info("reloading the web page");
|
info("reloading the web page");
|
||||||
let promise = promiseObserverCalled("recording-device-events");
|
let promises = [
|
||||||
|
promiseObserverCalled("recording-device-events"),
|
||||||
|
promiseObserverCalled("recording-window-ended")
|
||||||
|
];
|
||||||
yield ContentTask.spawn(gBrowser.selectedBrowser, null,
|
yield ContentTask.spawn(gBrowser.selectedBrowser, null,
|
||||||
"() => content.location.reload()");
|
"() => content.location.reload()");
|
||||||
yield promise;
|
yield Promise.all(promises);
|
||||||
|
|
||||||
yield expectObserverCalled("recording-window-ended");
|
|
||||||
yield expectNoObserverCalled();
|
yield expectNoObserverCalled();
|
||||||
yield checkNotSharing();
|
yield checkNotSharing();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
rules: {
|
||||||
|
"no-undef": "off"
|
||||||
|
}
|
||||||
|
};
|
|
@ -221,7 +221,7 @@ BrowserAction.prototype = {
|
||||||
// If we have a pending pre-loaded popup, cancel it after we've waited
|
// If we have a pending pre-loaded popup, cancel it after we've waited
|
||||||
// long enough that we can be relatively certain it won't be opening.
|
// long enough that we can be relatively certain it won't be opening.
|
||||||
if (this.pendingPopup) {
|
if (this.pendingPopup) {
|
||||||
let {node} = this.widget.forWindow(window);
|
let node = window.gBrowser && this.widget.forWindow(window).node;
|
||||||
if (isAncestorOrSelf(node, event.originalTarget)) {
|
if (isAncestorOrSelf(node, event.originalTarget)) {
|
||||||
this.pendingPopupTimeout = setTimeout(() => this.clearPopup(),
|
this.pendingPopupTimeout = setTimeout(() => this.clearPopup(),
|
||||||
POPUP_PRELOAD_TIMEOUT_MS);
|
POPUP_PRELOAD_TIMEOUT_MS);
|
||||||
|
|
|
@ -58,9 +58,9 @@ extensions.on("page-shutdown", (type, context) => {
|
||||||
}
|
}
|
||||||
let {gBrowser} = context.xulBrowser.ownerGlobal;
|
let {gBrowser} = context.xulBrowser.ownerGlobal;
|
||||||
if (gBrowser) {
|
if (gBrowser) {
|
||||||
let tab = gBrowser.getTabForBrowser(context.xulBrowser);
|
let nativeTab = gBrowser.getTabForBrowser(context.xulBrowser);
|
||||||
if (tab) {
|
if (nativeTab) {
|
||||||
gBrowser.removeTab(tab);
|
gBrowser.removeTab(nativeTab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,16 +83,16 @@ let tabListener = {
|
||||||
onLocationChange(browser, webProgress, request, locationURI, flags) {
|
onLocationChange(browser, webProgress, request, locationURI, flags) {
|
||||||
if (webProgress.isTopLevel) {
|
if (webProgress.isTopLevel) {
|
||||||
let {gBrowser} = browser.ownerGlobal;
|
let {gBrowser} = browser.ownerGlobal;
|
||||||
let tab = gBrowser.getTabForBrowser(browser);
|
let nativeTab = gBrowser.getTabForBrowser(browser);
|
||||||
|
|
||||||
// Now we are certain that the first page in the tab was loaded.
|
// Now we are certain that the first page in the tab was loaded.
|
||||||
this.initializingTabs.delete(tab);
|
this.initializingTabs.delete(nativeTab);
|
||||||
|
|
||||||
// browser.innerWindowID is now set, resolve the promises if any.
|
// browser.innerWindowID is now set, resolve the promises if any.
|
||||||
let deferred = this.tabReadyPromises.get(tab);
|
let deferred = this.tabReadyPromises.get(nativeTab);
|
||||||
if (deferred) {
|
if (deferred) {
|
||||||
deferred.resolve(tab);
|
deferred.resolve(nativeTab);
|
||||||
this.tabReadyPromises.delete(tab);
|
this.tabReadyPromises.delete(nativeTab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -103,19 +103,20 @@ let tabListener = {
|
||||||
* changes to the requested URL. Other tabs are assumed to be ready once their
|
* changes to the requested URL. Other tabs are assumed to be ready once their
|
||||||
* inner window ID is known.
|
* inner window ID is known.
|
||||||
*
|
*
|
||||||
* @param {XULElement} tab The <tab> element.
|
* @param {XULElement} nativeTab The <tab> element.
|
||||||
* @returns {Promise} Resolves with the given tab once ready.
|
* @returns {Promise} Resolves with the given tab once ready.
|
||||||
*/
|
*/
|
||||||
awaitTabReady(tab) {
|
awaitTabReady(nativeTab) {
|
||||||
let deferred = this.tabReadyPromises.get(tab);
|
let deferred = this.tabReadyPromises.get(nativeTab);
|
||||||
if (!deferred) {
|
if (!deferred) {
|
||||||
deferred = PromiseUtils.defer();
|
deferred = PromiseUtils.defer();
|
||||||
if (!this.initializingTabs.has(tab) && (tab.linkedBrowser.innerWindowID ||
|
if (!this.initializingTabs.has(nativeTab) &&
|
||||||
tab.linkedBrowser.currentURI.spec === "about:blank")) {
|
(nativeTab.linkedBrowser.innerWindowID ||
|
||||||
deferred.resolve(tab);
|
nativeTab.linkedBrowser.currentURI.spec === "about:blank")) {
|
||||||
|
deferred.resolve(nativeTab);
|
||||||
} else {
|
} else {
|
||||||
this.initTabReady();
|
this.initTabReady();
|
||||||
this.tabReadyPromises.set(tab, deferred);
|
this.tabReadyPromises.set(nativeTab, deferred);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
|
@ -142,7 +143,7 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
tab = tabManager.getWrapper(tabTracker.activeTab);
|
tab = tabManager.getWrapper(tabTracker.activeTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
await tabListener.awaitTabReady(tab.tab);
|
await tabListener.awaitTabReady(tab.nativeTab);
|
||||||
|
|
||||||
return tab;
|
return tab;
|
||||||
}
|
}
|
||||||
|
@ -150,15 +151,15 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
let self = {
|
let self = {
|
||||||
tabs: {
|
tabs: {
|
||||||
onActivated: new WindowEventManager(context, "tabs.onActivated", "TabSelect", (fire, event) => {
|
onActivated: new WindowEventManager(context, "tabs.onActivated", "TabSelect", (fire, event) => {
|
||||||
let tab = event.originalTarget;
|
let nativeTab = event.originalTarget;
|
||||||
let tabId = tabTracker.getId(tab);
|
let tabId = tabTracker.getId(nativeTab);
|
||||||
let windowId = windowTracker.getId(tab.ownerGlobal);
|
let windowId = windowTracker.getId(nativeTab.ownerGlobal);
|
||||||
fire.async({tabId, windowId});
|
fire.async({tabId, windowId});
|
||||||
}).api(),
|
}).api(),
|
||||||
|
|
||||||
onCreated: new SingletonEventManager(context, "tabs.onCreated", fire => {
|
onCreated: new SingletonEventManager(context, "tabs.onCreated", fire => {
|
||||||
let listener = (eventName, event) => {
|
let listener = (eventName, event) => {
|
||||||
fire.async(tabManager.convert(event.tab));
|
fire.async(tabManager.convert(event.nativeTab));
|
||||||
};
|
};
|
||||||
|
|
||||||
tabTracker.on("tab-created", listener);
|
tabTracker.on("tab-created", listener);
|
||||||
|
@ -174,9 +175,9 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
* @see https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/Tabs/onHighlighted
|
* @see https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/Tabs/onHighlighted
|
||||||
*/
|
*/
|
||||||
onHighlighted: new WindowEventManager(context, "tabs.onHighlighted", "TabSelect", (fire, event) => {
|
onHighlighted: new WindowEventManager(context, "tabs.onHighlighted", "TabSelect", (fire, event) => {
|
||||||
let tab = event.originalTarget;
|
let nativeTab = event.originalTarget;
|
||||||
let tabIds = [tabTracker.getId(tab)];
|
let tabIds = [tabTracker.getId(nativeTab)];
|
||||||
let windowId = windowTracker.getId(tab.ownerGlobal);
|
let windowId = windowTracker.getId(nativeTab.ownerGlobal);
|
||||||
fire.async({tabIds, windowId});
|
fire.async({tabIds, windowId});
|
||||||
}).api(),
|
}).api(),
|
||||||
|
|
||||||
|
@ -236,17 +237,17 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
};
|
};
|
||||||
|
|
||||||
let moveListener = event => {
|
let moveListener = event => {
|
||||||
let tab = event.originalTarget;
|
let nativeTab = event.originalTarget;
|
||||||
|
|
||||||
if (ignoreNextMove.has(tab)) {
|
if (ignoreNextMove.has(nativeTab)) {
|
||||||
ignoreNextMove.delete(tab);
|
ignoreNextMove.delete(nativeTab);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fire.async(tabTracker.getId(tab), {
|
fire.async(tabTracker.getId(nativeTab), {
|
||||||
windowId: windowTracker.getId(tab.ownerGlobal),
|
windowId: windowTracker.getId(nativeTab.ownerGlobal),
|
||||||
fromIndex: event.detail,
|
fromIndex: event.detail,
|
||||||
toIndex: tab._tPos,
|
toIndex: nativeTab._tPos,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -400,22 +401,26 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
options.disallowInheritPrincipal = true;
|
options.disallowInheritPrincipal = true;
|
||||||
|
|
||||||
tabListener.initTabReady();
|
tabListener.initTabReady();
|
||||||
let tab = window.gBrowser.addTab(url || window.BROWSER_NEW_TAB_URL, options);
|
let nativeTab = window.gBrowser.addTab(url || window.BROWSER_NEW_TAB_URL, options);
|
||||||
|
|
||||||
let active = true;
|
let active = true;
|
||||||
if (createProperties.active !== null) {
|
if (createProperties.active !== null) {
|
||||||
active = createProperties.active;
|
active = createProperties.active;
|
||||||
}
|
}
|
||||||
if (active) {
|
if (active) {
|
||||||
window.gBrowser.selectedTab = tab;
|
window.gBrowser.selectedTab = nativeTab;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createProperties.index !== null) {
|
if (createProperties.index !== null) {
|
||||||
window.gBrowser.moveTabTo(tab, createProperties.index);
|
window.gBrowser.moveTabTo(nativeTab, createProperties.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createProperties.pinned) {
|
if (createProperties.pinned) {
|
||||||
window.gBrowser.pinTab(tab);
|
window.gBrowser.pinTab(nativeTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (active && !url) {
|
||||||
|
window.focusAndSelectUrlBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createProperties.url && createProperties.url !== window.BROWSER_NEW_TAB_URL) {
|
if (createProperties.url && createProperties.url !== window.BROWSER_NEW_TAB_URL) {
|
||||||
|
@ -427,10 +432,10 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
// `executeScript` wait until the requested URL is loaded in
|
// `executeScript` wait until the requested URL is loaded in
|
||||||
// the tab before dispatching messages to the inner window
|
// the tab before dispatching messages to the inner window
|
||||||
// that contains the URL we're attempting to load.
|
// that contains the URL we're attempting to load.
|
||||||
tabListener.initializingTabs.add(tab);
|
tabListener.initializingTabs.add(nativeTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tabManager.convert(tab);
|
return tabManager.convert(nativeTab);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -440,15 +445,15 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let tabId of tabs) {
|
for (let tabId of tabs) {
|
||||||
let tab = tabTracker.getTab(tabId);
|
let nativeTab = tabTracker.getTab(tabId);
|
||||||
tab.ownerGlobal.gBrowser.removeTab(tab);
|
nativeTab.ownerGlobal.gBrowser.removeTab(nativeTab);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async update(tabId, updateProperties) {
|
async update(tabId, updateProperties) {
|
||||||
let tab = getTabOrActive(tabId);
|
let nativeTab = getTabOrActive(tabId);
|
||||||
|
|
||||||
let tabbrowser = tab.ownerGlobal.gBrowser;
|
let tabbrowser = nativeTab.ownerGlobal.gBrowser;
|
||||||
|
|
||||||
if (updateProperties.url !== null) {
|
if (updateProperties.url !== null) {
|
||||||
let url = context.uri.resolve(updateProperties.url);
|
let url = context.uri.resolve(updateProperties.url);
|
||||||
|
@ -457,55 +462,53 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
return Promise.reject({message: `Illegal URL: ${url}`});
|
return Promise.reject({message: `Illegal URL: ${url}`});
|
||||||
}
|
}
|
||||||
|
|
||||||
tab.linkedBrowser.loadURI(url);
|
nativeTab.linkedBrowser.loadURI(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateProperties.active !== null) {
|
if (updateProperties.active !== null) {
|
||||||
if (updateProperties.active) {
|
if (updateProperties.active) {
|
||||||
tabbrowser.selectedTab = tab;
|
tabbrowser.selectedTab = nativeTab;
|
||||||
} else {
|
} else {
|
||||||
// Not sure what to do here? Which tab should we select?
|
// Not sure what to do here? Which tab should we select?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (updateProperties.muted !== null) {
|
if (updateProperties.muted !== null) {
|
||||||
if (tab.muted != updateProperties.muted) {
|
if (nativeTab.muted != updateProperties.muted) {
|
||||||
tab.toggleMuteAudio(extension.uuid);
|
nativeTab.toggleMuteAudio(extension.uuid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (updateProperties.pinned !== null) {
|
if (updateProperties.pinned !== null) {
|
||||||
if (updateProperties.pinned) {
|
if (updateProperties.pinned) {
|
||||||
tabbrowser.pinTab(tab);
|
tabbrowser.pinTab(nativeTab);
|
||||||
} else {
|
} else {
|
||||||
tabbrowser.unpinTab(tab);
|
tabbrowser.unpinTab(nativeTab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FIXME: highlighted/selected, openerTabId
|
// FIXME: highlighted/selected, openerTabId
|
||||||
|
|
||||||
return tabManager.convert(tab);
|
return tabManager.convert(nativeTab);
|
||||||
},
|
},
|
||||||
|
|
||||||
async reload(tabId, reloadProperties) {
|
async reload(tabId, reloadProperties) {
|
||||||
let tab = getTabOrActive(tabId);
|
let nativeTab = getTabOrActive(tabId);
|
||||||
|
|
||||||
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
|
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
|
||||||
if (reloadProperties && reloadProperties.bypassCache) {
|
if (reloadProperties && reloadProperties.bypassCache) {
|
||||||
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
|
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
|
||||||
}
|
}
|
||||||
tab.linkedBrowser.reloadWithFlags(flags);
|
nativeTab.linkedBrowser.reloadWithFlags(flags);
|
||||||
},
|
},
|
||||||
|
|
||||||
async get(tabId) {
|
async get(tabId) {
|
||||||
let tab = tabTracker.getTab(tabId);
|
return tabManager.get(tabId).convert();
|
||||||
|
|
||||||
return tabManager.convert(tab);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getCurrent() {
|
getCurrent() {
|
||||||
let tab;
|
let tabData;
|
||||||
if (context.tabId) {
|
if (context.tabId) {
|
||||||
tab = tabManager.get(context.tabId).convert();
|
tabData = tabManager.get(context.tabId).convert();
|
||||||
}
|
}
|
||||||
return Promise.resolve(tab);
|
return Promise.resolve(tabData);
|
||||||
},
|
},
|
||||||
|
|
||||||
async query(queryInfo) {
|
async query(queryInfo) {
|
||||||
|
@ -522,53 +525,21 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
tab => tab.convert());
|
tab => tab.convert());
|
||||||
},
|
},
|
||||||
|
|
||||||
captureVisibleTab(windowId, options) {
|
async captureVisibleTab(windowId, options) {
|
||||||
if (!extension.hasPermission("<all_urls>")) {
|
|
||||||
return Promise.reject({message: "The <all_urls> permission is required to use the captureVisibleTab API"});
|
|
||||||
}
|
|
||||||
|
|
||||||
let window = windowId == null ?
|
let window = windowId == null ?
|
||||||
windowTracker.topWindow :
|
windowTracker.topWindow :
|
||||||
windowTracker.getWindow(windowId, context);
|
windowTracker.getWindow(windowId, context);
|
||||||
|
|
||||||
let tab = window.gBrowser.selectedTab;
|
let tab = tabManager.wrapTab(window.gBrowser.selectedTab);
|
||||||
return tabListener.awaitTabReady(tab).then(() => {
|
await tabListener.awaitTabReady(tab.nativeTab);
|
||||||
let browser = tab.linkedBrowser;
|
|
||||||
let recipient = {
|
|
||||||
innerWindowID: browser.innerWindowID,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options) {
|
return tab.capture(context, options);
|
||||||
options = {};
|
|
||||||
}
|
|
||||||
if (options.format == null) {
|
|
||||||
options.format = "png";
|
|
||||||
}
|
|
||||||
if (options.quality == null) {
|
|
||||||
options.quality = 92;
|
|
||||||
}
|
|
||||||
|
|
||||||
let message = {
|
|
||||||
options,
|
|
||||||
width: browser.clientWidth,
|
|
||||||
height: browser.clientHeight,
|
|
||||||
};
|
|
||||||
|
|
||||||
return context.sendMessage(browser.messageManager, "Extension:Capture",
|
|
||||||
message, {recipient});
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async detectLanguage(tabId) {
|
async detectLanguage(tabId) {
|
||||||
let tab = getTabOrActive(tabId);
|
let tab = await promiseTabWhenReady(tabId);
|
||||||
|
|
||||||
return tabListener.awaitTabReady(tab).then(() => {
|
return tab.sendMessage(context, "Extension:DetectLanguage");
|
||||||
let browser = tab.linkedBrowser;
|
|
||||||
let recipient = {innerWindowID: browser.innerWindowID};
|
|
||||||
|
|
||||||
return context.sendMessage(browser.messageManager, "Extension:DetectLanguage",
|
|
||||||
{}, {recipient});
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async executeScript(tabId, details) {
|
async executeScript(tabId, details) {
|
||||||
|
@ -615,9 +586,9 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
let indexMap = new Map();
|
let indexMap = new Map();
|
||||||
|
|
||||||
let tabs = tabIds.map(tabId => tabTracker.getTab(tabId));
|
let tabs = tabIds.map(tabId => tabTracker.getTab(tabId));
|
||||||
for (let tab of tabs) {
|
for (let nativeTab of tabs) {
|
||||||
// If the window is not specified, use the window from the tab.
|
// If the window is not specified, use the window from the tab.
|
||||||
let window = destinationWindow || tab.ownerGlobal;
|
let window = destinationWindow || nativeTab.ownerGlobal;
|
||||||
let gBrowser = window.gBrowser;
|
let gBrowser = window.gBrowser;
|
||||||
|
|
||||||
let insertionPoint = indexMap.get(window) || index;
|
let insertionPoint = indexMap.get(window) || index;
|
||||||
|
@ -631,32 +602,32 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
// be moved to a position after the current set of pinned tabs.
|
// be moved to a position after the current set of pinned tabs.
|
||||||
// Attempts to move a tab to an illegal position are ignored.
|
// Attempts to move a tab to an illegal position are ignored.
|
||||||
let numPinned = gBrowser._numPinnedTabs;
|
let numPinned = gBrowser._numPinnedTabs;
|
||||||
let ok = tab.pinned ? insertionPoint <= numPinned : insertionPoint >= numPinned;
|
let ok = nativeTab.pinned ? insertionPoint <= numPinned : insertionPoint >= numPinned;
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
indexMap.set(window, insertionPoint + 1);
|
indexMap.set(window, insertionPoint + 1);
|
||||||
|
|
||||||
if (tab.ownerGlobal != window) {
|
if (nativeTab.ownerGlobal != window) {
|
||||||
// If the window we are moving the tab in is different, then move the tab
|
// If the window we are moving the tab in is different, then move the tab
|
||||||
// to the new window.
|
// to the new window.
|
||||||
tab = gBrowser.adoptTab(tab, insertionPoint, false);
|
nativeTab = gBrowser.adoptTab(nativeTab, insertionPoint, false);
|
||||||
} else {
|
} else {
|
||||||
// If the window we are moving is the same, just move the tab.
|
// If the window we are moving is the same, just move the tab.
|
||||||
gBrowser.moveTabTo(tab, insertionPoint);
|
gBrowser.moveTabTo(nativeTab, insertionPoint);
|
||||||
}
|
}
|
||||||
tabsMoved.push(tab);
|
tabsMoved.push(nativeTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tabsMoved.map(tab => tabManager.convert(tab));
|
return tabsMoved.map(nativeTab => tabManager.convert(nativeTab));
|
||||||
},
|
},
|
||||||
|
|
||||||
duplicate(tabId) {
|
duplicate(tabId) {
|
||||||
let tab = tabTracker.getTab(tabId);
|
let nativeTab = tabTracker.getTab(tabId);
|
||||||
|
|
||||||
let gBrowser = tab.ownerGlobal.gBrowser;
|
let gBrowser = nativeTab.ownerGlobal.gBrowser;
|
||||||
let newTab = gBrowser.duplicateTab(tab);
|
let newTab = gBrowser.duplicateTab(nativeTab);
|
||||||
|
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
// We need to use SSTabRestoring because any attributes set before
|
// We need to use SSTabRestoring because any attributes set before
|
||||||
|
@ -667,10 +638,10 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
|
|
||||||
// Pinned tabs that are duplicated are inserted
|
// Pinned tabs that are duplicated are inserted
|
||||||
// after the existing pinned tab and pinned.
|
// after the existing pinned tab and pinned.
|
||||||
if (tab.pinned) {
|
if (nativeTab.pinned) {
|
||||||
gBrowser.pinTab(newTab);
|
gBrowser.pinTab(newTab);
|
||||||
}
|
}
|
||||||
gBrowser.moveTabTo(newTab, tab._tPos + 1);
|
gBrowser.moveTabTo(newTab, nativeTab._tPos + 1);
|
||||||
}, {once: true});
|
}, {once: true});
|
||||||
|
|
||||||
newTab.addEventListener("SSTabRestored", function() {
|
newTab.addEventListener("SSTabRestored", function() {
|
||||||
|
@ -683,24 +654,24 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
},
|
},
|
||||||
|
|
||||||
getZoom(tabId) {
|
getZoom(tabId) {
|
||||||
let tab = getTabOrActive(tabId);
|
let nativeTab = getTabOrActive(tabId);
|
||||||
|
|
||||||
let {ZoomManager} = tab.ownerGlobal;
|
let {ZoomManager} = nativeTab.ownerGlobal;
|
||||||
let zoom = ZoomManager.getZoomForBrowser(tab.linkedBrowser);
|
let zoom = ZoomManager.getZoomForBrowser(nativeTab.linkedBrowser);
|
||||||
|
|
||||||
return Promise.resolve(zoom);
|
return Promise.resolve(zoom);
|
||||||
},
|
},
|
||||||
|
|
||||||
setZoom(tabId, zoom) {
|
setZoom(tabId, zoom) {
|
||||||
let tab = getTabOrActive(tabId);
|
let nativeTab = getTabOrActive(tabId);
|
||||||
|
|
||||||
let {FullZoom, ZoomManager} = tab.ownerGlobal;
|
let {FullZoom, ZoomManager} = nativeTab.ownerGlobal;
|
||||||
|
|
||||||
if (zoom === 0) {
|
if (zoom === 0) {
|
||||||
// A value of zero means use the default zoom factor.
|
// A value of zero means use the default zoom factor.
|
||||||
return FullZoom.reset(tab.linkedBrowser);
|
return FullZoom.reset(nativeTab.linkedBrowser);
|
||||||
} else if (zoom >= ZoomManager.MIN && zoom <= ZoomManager.MAX) {
|
} else if (zoom >= ZoomManager.MIN && zoom <= ZoomManager.MAX) {
|
||||||
FullZoom.setZoom(zoom, tab.linkedBrowser);
|
FullZoom.setZoom(zoom, nativeTab.linkedBrowser);
|
||||||
} else {
|
} else {
|
||||||
return Promise.reject({
|
return Promise.reject({
|
||||||
message: `Zoom value ${zoom} out of range (must be between ${ZoomManager.MIN} and ${ZoomManager.MAX})`,
|
message: `Zoom value ${zoom} out of range (must be between ${ZoomManager.MIN} and ${ZoomManager.MAX})`,
|
||||||
|
@ -711,9 +682,9 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
},
|
},
|
||||||
|
|
||||||
_getZoomSettings(tabId) {
|
_getZoomSettings(tabId) {
|
||||||
let tab = getTabOrActive(tabId);
|
let nativeTab = getTabOrActive(tabId);
|
||||||
|
|
||||||
let {FullZoom} = tab.ownerGlobal;
|
let {FullZoom} = nativeTab.ownerGlobal;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
mode: "automatic",
|
mode: "automatic",
|
||||||
|
@ -727,9 +698,9 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
},
|
},
|
||||||
|
|
||||||
setZoomSettings(tabId, settings) {
|
setZoomSettings(tabId, settings) {
|
||||||
let tab = getTabOrActive(tabId);
|
let nativeTab = getTabOrActive(tabId);
|
||||||
|
|
||||||
let currentSettings = this._getZoomSettings(tab.id);
|
let currentSettings = this._getZoomSettings(tabTracker.getId(nativeTab));
|
||||||
|
|
||||||
if (!Object.keys(settings).every(key => settings[key] === currentSettings[key])) {
|
if (!Object.keys(settings).every(key => settings[key] === currentSettings[key])) {
|
||||||
return Promise.reject(`Unsupported zoom settings: ${JSON.stringify(settings)}`);
|
return Promise.reject(`Unsupported zoom settings: ${JSON.stringify(settings)}`);
|
||||||
|
@ -750,14 +721,14 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
|
|
||||||
// Store the zoom level for all existing tabs.
|
// Store the zoom level for all existing tabs.
|
||||||
for (let window of windowTracker.browserWindows()) {
|
for (let window of windowTracker.browserWindows()) {
|
||||||
for (let tab of window.gBrowser.tabs) {
|
for (let nativeTab of window.gBrowser.tabs) {
|
||||||
let browser = tab.linkedBrowser;
|
let browser = nativeTab.linkedBrowser;
|
||||||
zoomLevels.set(browser, getZoomLevel(browser));
|
zoomLevels.set(browser, getZoomLevel(browser));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let tabCreated = (eventName, event) => {
|
let tabCreated = (eventName, event) => {
|
||||||
let browser = event.tab.linkedBrowser;
|
let browser = event.nativeTab.linkedBrowser;
|
||||||
zoomLevels.set(browser, getZoomLevel(browser));
|
zoomLevels.set(browser, getZoomLevel(browser));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -774,8 +745,8 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
}
|
}
|
||||||
|
|
||||||
let {gBrowser} = browser.ownerGlobal;
|
let {gBrowser} = browser.ownerGlobal;
|
||||||
let tab = gBrowser.getTabForBrowser(browser);
|
let nativeTab = gBrowser.getTabForBrowser(browser);
|
||||||
if (!tab) {
|
if (!nativeTab) {
|
||||||
// We only care about zoom events in the top-level browser of a tab.
|
// We only care about zoom events in the top-level browser of a tab.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -786,7 +757,7 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
|
||||||
if (oldZoomFactor != newZoomFactor) {
|
if (oldZoomFactor != newZoomFactor) {
|
||||||
zoomLevels.set(browser, newZoomFactor);
|
zoomLevels.set(browser, newZoomFactor);
|
||||||
|
|
||||||
let tabId = tabTracker.getId(tab);
|
let tabId = tabTracker.getId(nativeTab);
|
||||||
fire.async({
|
fire.async({
|
||||||
tabId,
|
tabId,
|
||||||
oldZoomFactor,
|
oldZoomFactor,
|
||||||
|
|
|
@ -49,23 +49,23 @@ global.TabContext = function TabContext(getDefaults, extension) {
|
||||||
};
|
};
|
||||||
|
|
||||||
TabContext.prototype = {
|
TabContext.prototype = {
|
||||||
get(tab) {
|
get(nativeTab) {
|
||||||
if (!this.tabData.has(tab)) {
|
if (!this.tabData.has(nativeTab)) {
|
||||||
this.tabData.set(tab, this.getDefaults(tab));
|
this.tabData.set(nativeTab, this.getDefaults(nativeTab));
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.tabData.get(tab);
|
return this.tabData.get(nativeTab);
|
||||||
},
|
},
|
||||||
|
|
||||||
clear(tab) {
|
clear(nativeTab) {
|
||||||
this.tabData.delete(tab);
|
this.tabData.delete(nativeTab);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleEvent(event) {
|
handleEvent(event) {
|
||||||
if (event.type == "TabSelect") {
|
if (event.type == "TabSelect") {
|
||||||
let tab = event.target;
|
let nativeTab = event.target;
|
||||||
this.emit("tab-select", tab);
|
this.emit("tab-select", nativeTab);
|
||||||
this.emit("location-change", tab);
|
this.emit("location-change", nativeTab);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -83,8 +83,8 @@ TabContext.prototype = {
|
||||||
let lastLocation = this.lastLocation.get(browser);
|
let lastLocation = this.lastLocation.get(browser);
|
||||||
if (browser === gBrowser.selectedBrowser &&
|
if (browser === gBrowser.selectedBrowser &&
|
||||||
!(lastLocation && lastLocation.equalsExceptRef(browser.currentURI))) {
|
!(lastLocation && lastLocation.equalsExceptRef(browser.currentURI))) {
|
||||||
let tab = gBrowser.getTabForBrowser(browser);
|
let nativeTab = gBrowser.getTabForBrowser(browser);
|
||||||
this.emit("location-change", tab, true);
|
this.emit("location-change", nativeTab, true);
|
||||||
}
|
}
|
||||||
this.lastLocation.set(browser, browser.currentURI);
|
this.lastLocation.set(browser, browser.currentURI);
|
||||||
},
|
},
|
||||||
|
@ -106,6 +106,21 @@ class WindowTracker extends WindowTrackerBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event manager API provider which listens for a DOM event in any browser
|
||||||
|
* window, and calls the given listener function whenever an event is received.
|
||||||
|
* That listener function receives a `fire` object, which it can use to dispatch
|
||||||
|
* events to the extension, and a DOM event object.
|
||||||
|
*
|
||||||
|
* @param {BaseContext} context
|
||||||
|
* The extension context which the event manager belongs to.
|
||||||
|
* @param {string} name
|
||||||
|
* The API name of the event manager, e.g.,"runtime.onMessage".
|
||||||
|
* @param {string} event
|
||||||
|
* The name of the DOM event to listen for.
|
||||||
|
* @param {function} listener
|
||||||
|
* The listener function to call when a DOM event is received.
|
||||||
|
*/
|
||||||
global.WindowEventManager = class extends SingletonEventManager {
|
global.WindowEventManager = class extends SingletonEventManager {
|
||||||
constructor(context, name, event, listener) {
|
constructor(context, name, event, listener) {
|
||||||
super(context, name, fire => {
|
super(context, name, fire => {
|
||||||
|
@ -152,28 +167,28 @@ class TabTracker extends TabTrackerBase {
|
||||||
/* eslint-enable mozilla/balanced-listeners */
|
/* eslint-enable mozilla/balanced-listeners */
|
||||||
}
|
}
|
||||||
|
|
||||||
getId(tab) {
|
getId(nativeTab) {
|
||||||
if (this._tabs.has(tab)) {
|
if (this._tabs.has(nativeTab)) {
|
||||||
return this._tabs.get(tab);
|
return this._tabs.get(nativeTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
|
|
||||||
let id = this._nextId++;
|
let id = this._nextId++;
|
||||||
this.setId(tab, id);
|
this.setId(nativeTab, id);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
setId(tab, id) {
|
setId(nativeTab, id) {
|
||||||
this._tabs.set(tab, id);
|
this._tabs.set(nativeTab, id);
|
||||||
this._tabIds.set(id, tab);
|
this._tabIds.set(id, nativeTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleTabDestroyed(event, {tab}) {
|
_handleTabDestroyed(event, {nativeTab}) {
|
||||||
let id = this._tabs.get(tab);
|
let id = this._tabs.get(nativeTab);
|
||||||
if (id) {
|
if (id) {
|
||||||
this._tabs.delete(tab);
|
this._tabs.delete(nativeTab);
|
||||||
if (this._tabIds.get(id) === tab) {
|
if (this._tabIds.get(id) === nativeTab) {
|
||||||
this._tabIds.delete(id);
|
this._tabIds.delete(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,9 +207,9 @@ class TabTracker extends TabTrackerBase {
|
||||||
* A XUL <tab> element.
|
* A XUL <tab> element.
|
||||||
*/
|
*/
|
||||||
getTab(tabId, default_ = undefined) {
|
getTab(tabId, default_ = undefined) {
|
||||||
let tab = this._tabIds.get(tabId);
|
let nativeTab = this._tabIds.get(tabId);
|
||||||
if (tab) {
|
if (nativeTab) {
|
||||||
return tab;
|
return nativeTab;
|
||||||
}
|
}
|
||||||
if (default_ !== undefined) {
|
if (default_ !== undefined) {
|
||||||
return default_;
|
return default_;
|
||||||
|
@ -202,8 +217,13 @@ class TabTracker extends TabTrackerBase {
|
||||||
throw new ExtensionError(`Invalid tab ID: ${tabId}`);
|
throw new ExtensionError(`Invalid tab ID: ${tabId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Event} event
|
||||||
|
* The DOM Event to handle.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
handleEvent(event) {
|
handleEvent(event) {
|
||||||
let tab = event.target;
|
let nativeTab = event.target;
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case "TabOpen":
|
case "TabOpen":
|
||||||
|
@ -213,10 +233,10 @@ class TabTracker extends TabTrackerBase {
|
||||||
|
|
||||||
// This tab is being created to adopt a tab from a different window.
|
// This tab is being created to adopt a tab from a different window.
|
||||||
// Copy the ID from the old tab to the new.
|
// Copy the ID from the old tab to the new.
|
||||||
this.setId(tab, this.getId(adoptedTab));
|
this.setId(nativeTab, this.getId(adoptedTab));
|
||||||
|
|
||||||
adoptedTab.linkedBrowser.messageManager.sendAsyncMessage("Extension:SetTabAndWindowId", {
|
adoptedTab.linkedBrowser.messageManager.sendAsyncMessage("Extension:SetTabAndWindowId", {
|
||||||
windowId: windowTracker.getId(tab.ownerGlobal),
|
windowId: windowTracker.getId(nativeTab.ownerGlobal),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,16 +258,24 @@ class TabTracker extends TabTrackerBase {
|
||||||
// Copy its ID to the new tab, in case it was created as the first tab
|
// Copy its ID to the new tab, in case it was created as the first tab
|
||||||
// of a new window, and did not have an `adoptedTab` detail when it was
|
// of a new window, and did not have an `adoptedTab` detail when it was
|
||||||
// opened.
|
// opened.
|
||||||
this.setId(adoptedBy, this.getId(tab));
|
this.setId(adoptedBy, this.getId(nativeTab));
|
||||||
|
|
||||||
this.emitDetached(tab, adoptedBy);
|
this.emitDetached(nativeTab, adoptedBy);
|
||||||
} else {
|
} else {
|
||||||
this.emitRemoved(tab, false);
|
this.emitRemoved(nativeTab, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A private method which is called whenever a new browser window is opened,
|
||||||
|
* and dispatches the necessary events for it.
|
||||||
|
*
|
||||||
|
* @param {DOMWindow} window
|
||||||
|
* The window being opened.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
_handleWindowOpen(window) {
|
_handleWindowOpen(window) {
|
||||||
if (window.arguments && window.arguments[0] instanceof window.XULElement) {
|
if (window.arguments && window.arguments[0] instanceof window.XULElement) {
|
||||||
// If the first window argument is a XUL element, it means the
|
// If the first window argument is a XUL element, it means the
|
||||||
|
@ -259,16 +287,16 @@ class TabTracker extends TabTrackerBase {
|
||||||
// by the first MozAfterPaint event. That code handles finally
|
// by the first MozAfterPaint event. That code handles finally
|
||||||
// adopting the tab, and clears it from the arguments list in the
|
// adopting the tab, and clears it from the arguments list in the
|
||||||
// process, so if we run later than it, we're too late.
|
// process, so if we run later than it, we're too late.
|
||||||
let tab = window.arguments[0];
|
let nativeTab = window.arguments[0];
|
||||||
let adoptedBy = window.gBrowser.tabs[0];
|
let adoptedBy = window.gBrowser.tabs[0];
|
||||||
|
|
||||||
this.adoptedTabs.set(tab, adoptedBy);
|
this.adoptedTabs.set(nativeTab, adoptedBy);
|
||||||
this.setId(adoptedBy, this.getId(tab));
|
this.setId(adoptedBy, this.getId(nativeTab));
|
||||||
|
|
||||||
// We need to be sure to fire this event after the onDetached event
|
// We need to be sure to fire this event after the onDetached event
|
||||||
// for the original tab.
|
// for the original tab.
|
||||||
let listener = (event, details) => {
|
let listener = (event, details) => {
|
||||||
if (details.tab === tab) {
|
if (details.nativeTab === nativeTab) {
|
||||||
this.off("tab-detached", listener);
|
this.off("tab-detached", listener);
|
||||||
|
|
||||||
Promise.resolve().then(() => {
|
Promise.resolve().then(() => {
|
||||||
|
@ -279,43 +307,85 @@ class TabTracker extends TabTrackerBase {
|
||||||
|
|
||||||
this.on("tab-detached", listener);
|
this.on("tab-detached", listener);
|
||||||
} else {
|
} else {
|
||||||
for (let tab of window.gBrowser.tabs) {
|
for (let nativeTab of window.gBrowser.tabs) {
|
||||||
this.emitCreated(tab);
|
this.emitCreated(nativeTab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A private method which is called whenever a browser window is closed,
|
||||||
|
* and dispatches the necessary events for it.
|
||||||
|
*
|
||||||
|
* @param {DOMWindow} window
|
||||||
|
* The window being closed.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
_handleWindowClose(window) {
|
_handleWindowClose(window) {
|
||||||
for (let tab of window.gBrowser.tabs) {
|
for (let nativeTab of window.gBrowser.tabs) {
|
||||||
if (this.adoptedTabs.has(tab)) {
|
if (this.adoptedTabs.has(nativeTab)) {
|
||||||
this.emitDetached(tab, this.adoptedTabs.get(tab));
|
this.emitDetached(nativeTab, this.adoptedTabs.get(nativeTab));
|
||||||
} else {
|
} else {
|
||||||
this.emitRemoved(tab, true);
|
this.emitRemoved(nativeTab, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emitAttached(tab) {
|
/**
|
||||||
let newWindowId = windowTracker.getId(tab.ownerGlobal);
|
* Emits a "tab-attached" event for the given tab element.
|
||||||
let tabId = this.getId(tab);
|
*
|
||||||
|
* @param {NativeTab} nativeTab
|
||||||
|
* The tab element in the window to which the tab is being attached.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
emitAttached(nativeTab) {
|
||||||
|
let newWindowId = windowTracker.getId(nativeTab.ownerGlobal);
|
||||||
|
let tabId = this.getId(nativeTab);
|
||||||
|
|
||||||
this.emit("tab-attached", {tab, tabId, newWindowId, newPosition: tab._tPos});
|
this.emit("tab-attached", {nativeTab, tabId, newWindowId, newPosition: nativeTab._tPos});
|
||||||
}
|
}
|
||||||
|
|
||||||
emitDetached(tab, adoptedBy) {
|
/**
|
||||||
let oldWindowId = windowTracker.getId(tab.ownerGlobal);
|
* Emits a "tab-detached" event for the given tab element.
|
||||||
let tabId = this.getId(tab);
|
*
|
||||||
|
* @param {NativeTab} nativeTab
|
||||||
|
* The tab element in the window from which the tab is being detached.
|
||||||
|
* @param {NativeTab} adoptedBy
|
||||||
|
* The tab element in the window to which detached tab is being moved,
|
||||||
|
* and will adopt this tab's contents.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
emitDetached(nativeTab, adoptedBy) {
|
||||||
|
let oldWindowId = windowTracker.getId(nativeTab.ownerGlobal);
|
||||||
|
let tabId = this.getId(nativeTab);
|
||||||
|
|
||||||
this.emit("tab-detached", {tab, adoptedBy, tabId, oldWindowId, oldPosition: tab._tPos});
|
this.emit("tab-detached", {nativeTab, adoptedBy, tabId, oldWindowId, oldPosition: nativeTab._tPos});
|
||||||
}
|
}
|
||||||
|
|
||||||
emitCreated(tab) {
|
/**
|
||||||
this.emit("tab-created", {tab});
|
* Emits a "tab-created" event for the given tab element.
|
||||||
|
*
|
||||||
|
* @param {NativeTab} nativeTab
|
||||||
|
* The tab element which is being created.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
emitCreated(nativeTab) {
|
||||||
|
this.emit("tab-created", {nativeTab});
|
||||||
}
|
}
|
||||||
|
|
||||||
emitRemoved(tab, isWindowClosing) {
|
/**
|
||||||
let windowId = windowTracker.getId(tab.ownerGlobal);
|
* Emits a "tab-removed" event for the given tab element.
|
||||||
let tabId = this.getId(tab);
|
*
|
||||||
|
* @param {NativeTab} nativeTab
|
||||||
|
* The tab element which is being removed.
|
||||||
|
* @param {boolean} isWindowClosing
|
||||||
|
* True if the tab is being removed because the browser window is
|
||||||
|
* closing.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
emitRemoved(nativeTab, isWindowClosing) {
|
||||||
|
let windowId = windowTracker.getId(nativeTab.ownerGlobal);
|
||||||
|
let tabId = this.getId(nativeTab);
|
||||||
|
|
||||||
// When addons run in-process, `window.close()` is synchronous. Most other
|
// When addons run in-process, `window.close()` is synchronous. Most other
|
||||||
// addon-invoked calls are asynchronous since they go through a proxy
|
// addon-invoked calls are asynchronous since they go through a proxy
|
||||||
|
@ -327,7 +397,7 @@ class TabTracker extends TabTrackerBase {
|
||||||
// event listener is registered. To make sure that the event listener is
|
// event listener is registered. To make sure that the event listener is
|
||||||
// notified, we dispatch `tabs.onRemoved` asynchronously.
|
// notified, we dispatch `tabs.onRemoved` asynchronously.
|
||||||
Services.tm.mainThread.dispatch(() => {
|
Services.tm.mainThread.dispatch(() => {
|
||||||
this.emit("tab-removed", {tab, tabId, windowId, isWindowClosing});
|
this.emit("tab-removed", {nativeTab, tabId, windowId, isWindowClosing});
|
||||||
}, Ci.nsIThread.DISPATCH_NORMAL);
|
}, Ci.nsIThread.DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,9 +421,9 @@ class TabTracker extends TabTrackerBase {
|
||||||
if (gBrowser && gBrowser.getTabForBrowser) {
|
if (gBrowser && gBrowser.getTabForBrowser) {
|
||||||
result.windowId = windowTracker.getId(browser.ownerGlobal);
|
result.windowId = windowTracker.getId(browser.ownerGlobal);
|
||||||
|
|
||||||
let tab = gBrowser.getTabForBrowser(browser);
|
let nativeTab = gBrowser.getTabForBrowser(browser);
|
||||||
if (tab) {
|
if (nativeTab) {
|
||||||
result.tabId = this.getId(tab);
|
result.tabId = this.getId(nativeTab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,19 +446,19 @@ Object.assign(global, {tabTracker, windowTracker});
|
||||||
|
|
||||||
class Tab extends TabBase {
|
class Tab extends TabBase {
|
||||||
get _favIconUrl() {
|
get _favIconUrl() {
|
||||||
return this.window.gBrowser.getIcon(this.tab);
|
return this.window.gBrowser.getIcon(this.nativeTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
get audible() {
|
get audible() {
|
||||||
return this.tab.soundPlaying;
|
return this.nativeTab.soundPlaying;
|
||||||
}
|
}
|
||||||
|
|
||||||
get browser() {
|
get browser() {
|
||||||
return this.tab.linkedBrowser;
|
return this.nativeTab.linkedBrowser;
|
||||||
}
|
}
|
||||||
|
|
||||||
get cookieStoreId() {
|
get cookieStoreId() {
|
||||||
return getCookieStoreIdForTab(this, this.tab);
|
return getCookieStoreIdForTab(this, this.nativeTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
get height() {
|
get height() {
|
||||||
|
@ -396,41 +466,37 @@ class Tab extends TabBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
get index() {
|
get index() {
|
||||||
return this.tab._tPos;
|
return this.nativeTab._tPos;
|
||||||
}
|
|
||||||
|
|
||||||
get innerWindowID() {
|
|
||||||
return this.browser.innerWindowID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get mutedInfo() {
|
get mutedInfo() {
|
||||||
let tab = this.tab;
|
let {nativeTab} = this;
|
||||||
|
|
||||||
let mutedInfo = {muted: tab.muted};
|
let mutedInfo = {muted: nativeTab.muted};
|
||||||
if (tab.muteReason === null) {
|
if (nativeTab.muteReason === null) {
|
||||||
mutedInfo.reason = "user";
|
mutedInfo.reason = "user";
|
||||||
} else if (tab.muteReason) {
|
} else if (nativeTab.muteReason) {
|
||||||
mutedInfo.reason = "extension";
|
mutedInfo.reason = "extension";
|
||||||
mutedInfo.extensionId = tab.muteReason;
|
mutedInfo.extensionId = nativeTab.muteReason;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mutedInfo;
|
return mutedInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
get pinned() {
|
get pinned() {
|
||||||
return this.tab.pinned;
|
return this.nativeTab.pinned;
|
||||||
}
|
}
|
||||||
|
|
||||||
get active() {
|
get active() {
|
||||||
return this.tab.selected;
|
return this.nativeTab.selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
get selected() {
|
get selected() {
|
||||||
return this.tab.selected;
|
return this.nativeTab.selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
get status() {
|
get status() {
|
||||||
if (this.tab.getAttribute("busy") === "true") {
|
if (this.nativeTab.getAttribute("busy") === "true") {
|
||||||
return "loading";
|
return "loading";
|
||||||
}
|
}
|
||||||
return "complete";
|
return "complete";
|
||||||
|
@ -441,31 +507,47 @@ class Tab extends TabBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
get window() {
|
get window() {
|
||||||
return this.tab.ownerGlobal;
|
return this.nativeTab.ownerGlobal;
|
||||||
}
|
}
|
||||||
|
|
||||||
get windowId() {
|
get windowId() {
|
||||||
return windowTracker.getId(this.window);
|
return windowTracker.getId(this.window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static convertFromSessionStoreClosedData(extension, tab, window = null) {
|
/**
|
||||||
|
* Converts session store data to an object compatible with the return value
|
||||||
|
* of the convert() method, representing that data.
|
||||||
|
*
|
||||||
|
* @param {Extension} extension
|
||||||
|
* The extension for which to convert the data.
|
||||||
|
* @param {Object} tabData
|
||||||
|
* Session store data for a closed tab, as returned by
|
||||||
|
* `SessionStore.getClosedTabData()`.
|
||||||
|
* @param {DOMWindow} [window = null]
|
||||||
|
* The browser window which the tab belonged to before it was closed.
|
||||||
|
* May be null if the window the tab belonged to no longer exists.
|
||||||
|
*
|
||||||
|
* @returns {Object}
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
static convertFromSessionStoreClosedData(extension, tabData, window = null) {
|
||||||
let result = {
|
let result = {
|
||||||
sessionId: String(tab.closedId),
|
sessionId: String(tabData.closedId),
|
||||||
index: tab.pos ? tab.pos : 0,
|
index: tabData.pos ? tabData.pos : 0,
|
||||||
windowId: window && windowTracker.getId(window),
|
windowId: window && windowTracker.getId(window),
|
||||||
selected: false,
|
selected: false,
|
||||||
highlighted: false,
|
highlighted: false,
|
||||||
active: false,
|
active: false,
|
||||||
pinned: false,
|
pinned: false,
|
||||||
incognito: Boolean(tab.state && tab.state.isPrivate),
|
incognito: Boolean(tabData.state && tabData.state.isPrivate),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (extension.tabManager.hasTabPermission(tab)) {
|
if (extension.tabManager.hasTabPermission(tabData)) {
|
||||||
let entries = tab.state ? tab.state.entries : tab.entries;
|
let entries = tabData.state ? tabData.state.entries : tabData.entries;
|
||||||
result.url = entries[0].url;
|
result.url = entries[0].url;
|
||||||
result.title = entries[0].title;
|
result.title = entries[0].title;
|
||||||
if (tab.image) {
|
if (tabData.image) {
|
||||||
result.favIconUrl = tab.image;
|
result.favIconUrl = tabData.image;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,6 +556,22 @@ class Tab extends TabBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Window extends WindowBase {
|
class Window extends WindowBase {
|
||||||
|
/**
|
||||||
|
* Update the geometry of the browser window.
|
||||||
|
*
|
||||||
|
* @param {Object} options
|
||||||
|
* An object containing new values for the window's geometry.
|
||||||
|
* @param {integer} [options.left]
|
||||||
|
* The new pixel distance of the left side of the browser window from
|
||||||
|
* the left of the screen.
|
||||||
|
* @param {integer} [options.top]
|
||||||
|
* The new pixel distance of the top side of the browser window from
|
||||||
|
* the top of the screen.
|
||||||
|
* @param {integer} [options.width]
|
||||||
|
* The new pixel width of the window.
|
||||||
|
* @param {integer} [options.height]
|
||||||
|
* The new pixel height of the window.
|
||||||
|
*/
|
||||||
updateGeometry(options) {
|
updateGeometry(options) {
|
||||||
let {window} = this;
|
let {window} = this;
|
||||||
|
|
||||||
|
@ -582,25 +680,38 @@ class Window extends WindowBase {
|
||||||
* getTabs() {
|
* getTabs() {
|
||||||
let {tabManager} = this.extension;
|
let {tabManager} = this.extension;
|
||||||
|
|
||||||
for (let tab of this.window.gBrowser.tabs) {
|
for (let nativeTab of this.window.gBrowser.tabs) {
|
||||||
yield tabManager.getWrapper(tab);
|
yield tabManager.getWrapper(nativeTab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static convertFromSessionStoreClosedData(extension, window) {
|
/**
|
||||||
|
* Converts session store data to an object compatible with the return value
|
||||||
|
* of the convert() method, representing that data.
|
||||||
|
*
|
||||||
|
* @param {Extension} extension
|
||||||
|
* The extension for which to convert the data.
|
||||||
|
* @param {Object} windowData
|
||||||
|
* Session store data for a closed window, as returned by
|
||||||
|
* `SessionStore.getClosedWindowData()`.
|
||||||
|
*
|
||||||
|
* @returns {Object}
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
static convertFromSessionStoreClosedData(extension, windowData) {
|
||||||
let result = {
|
let result = {
|
||||||
sessionId: String(window.closedId),
|
sessionId: String(windowData.closedId),
|
||||||
focused: false,
|
focused: false,
|
||||||
incognito: false,
|
incognito: false,
|
||||||
type: "normal", // this is always "normal" for a closed window
|
type: "normal", // this is always "normal" for a closed window
|
||||||
// Surely this does not actually work?
|
// Surely this does not actually work?
|
||||||
state: this.getState(window),
|
state: this.getState(windowData),
|
||||||
alwaysOnTop: false,
|
alwaysOnTop: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (window.tabs.length) {
|
if (windowData.tabs.length) {
|
||||||
result.tabs = window.tabs.map(tab => {
|
result.tabs = windowData.tabs.map(tabData => {
|
||||||
return Tab.convertFromSessionStoreClosedData(extension, tab);
|
return Tab.convertFromSessionStoreClosedData(extension, tabData);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,24 +723,24 @@ Object.assign(global, {Tab, Window});
|
||||||
|
|
||||||
class TabManager extends TabManagerBase {
|
class TabManager extends TabManagerBase {
|
||||||
get(tabId, default_ = undefined) {
|
get(tabId, default_ = undefined) {
|
||||||
let tab = tabTracker.getTab(tabId, default_);
|
let nativeTab = tabTracker.getTab(tabId, default_);
|
||||||
|
|
||||||
if (tab) {
|
if (nativeTab) {
|
||||||
return this.getWrapper(tab);
|
return this.getWrapper(nativeTab);
|
||||||
}
|
}
|
||||||
return default_;
|
return default_;
|
||||||
}
|
}
|
||||||
|
|
||||||
addActiveTabPermission(tab = tabTracker.activeTab) {
|
addActiveTabPermission(nativeTab = tabTracker.activeTab) {
|
||||||
return super.addActiveTabPermission(tab);
|
return super.addActiveTabPermission(nativeTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
revokeActiveTabPermission(tab = tabTracker.activeTab) {
|
revokeActiveTabPermission(nativeTab = tabTracker.activeTab) {
|
||||||
return super.revokeActiveTabPermission(tab);
|
return super.revokeActiveTabPermission(nativeTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
wrapTab(tab) {
|
wrapTab(nativeTab) {
|
||||||
return new Tab(this.extension, tab, tabTracker.getId(tab));
|
return new Tab(this.extension, nativeTab, tabTracker.getId(nativeTab));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head><body>${url}</body></html>`;
|
let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head><body>${url}</body></html>`;
|
||||||
|
|
||||||
add_task(function* testBrowserActionClickCanceled() {
|
add_task(function* testBrowserActionClickCanceled() {
|
||||||
|
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com/");
|
||||||
|
|
||||||
let extension = ExtensionTestUtils.loadExtension({
|
let extension = ExtensionTestUtils.loadExtension({
|
||||||
manifest: {
|
manifest: {
|
||||||
"browser_action": {
|
"browser_action": {
|
||||||
|
@ -27,7 +29,6 @@ add_task(function* testBrowserActionClickCanceled() {
|
||||||
let browserAction = browserActionFor(ext);
|
let browserAction = browserActionFor(ext);
|
||||||
|
|
||||||
let widget = getBrowserActionWidget(extension).forWindow(window);
|
let widget = getBrowserActionWidget(extension).forWindow(window);
|
||||||
let tab = window.gBrowser.selectedTab;
|
|
||||||
|
|
||||||
// Test canceled click.
|
// Test canceled click.
|
||||||
EventUtils.synthesizeMouseAtCenter(widget.node, {type: "mousedown", button: 0}, window);
|
EventUtils.synthesizeMouseAtCenter(widget.node, {type: "mousedown", button: 0}, window);
|
||||||
|
@ -76,6 +77,8 @@ add_task(function* testBrowserActionClickCanceled() {
|
||||||
yield closeBrowserAction(extension);
|
yield closeBrowserAction(extension);
|
||||||
|
|
||||||
yield extension.unload();
|
yield extension.unload();
|
||||||
|
|
||||||
|
yield BrowserTestUtils.removeTab(tab);
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* testBrowserActionDisabled() {
|
add_task(function* testBrowserActionDisabled() {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
/* vim: set sts=2 sw=2 et tw=80: */
|
/* vim: set sts=2 sw=2 et tw=80: */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
add_task(function* () {
|
add_task(function* test_create_options() {
|
||||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:robots");
|
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:robots");
|
||||||
gBrowser.selectedTab = tab;
|
gBrowser.selectedTab = tab;
|
||||||
|
|
||||||
|
@ -164,3 +164,44 @@ add_task(function* () {
|
||||||
yield BrowserTestUtils.removeTab(tab);
|
yield BrowserTestUtils.removeTab(tab);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
add_task(function* test_urlbar_focus() {
|
||||||
|
const extension = ExtensionTestUtils.loadExtension({
|
||||||
|
background() {
|
||||||
|
browser.test.onMessage.addListener(async (cmd, ...args) => {
|
||||||
|
const result = await browser.tabs[cmd](...args);
|
||||||
|
browser.test.sendMessage("result", result);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
yield extension.startup();
|
||||||
|
|
||||||
|
// Test content is focused after opening a regular url
|
||||||
|
extension.sendMessage("create", {url: "https://example.com"});
|
||||||
|
const tab1 = yield extension.awaitMessage("result");
|
||||||
|
|
||||||
|
is(document.activeElement.tagName, "browser", "Content focused after opening a web page");
|
||||||
|
|
||||||
|
extension.sendMessage("remove", tab1.id);
|
||||||
|
yield extension.awaitMessage("result");
|
||||||
|
|
||||||
|
// Test urlbar is focused after opening an empty tab
|
||||||
|
extension.sendMessage("create", {});
|
||||||
|
const tab2 = yield extension.awaitMessage("result");
|
||||||
|
|
||||||
|
const active = document.activeElement;
|
||||||
|
info(`Active element: ${active.tagName}, id: ${active.id}, class: ${active.className}`);
|
||||||
|
|
||||||
|
const parent = active.parentNode;
|
||||||
|
info(`Parent element: ${parent.tagName}, id: ${parent.id}, class: ${parent.className}`);
|
||||||
|
|
||||||
|
info(`After opening an empty tab, gURLBar.focused: ${gURLBar.focused}`);
|
||||||
|
|
||||||
|
is(active.tagName, "html:input", "Input element focused");
|
||||||
|
ok(active.classList.contains("urlbar-input"), "Urlbar focused");
|
||||||
|
|
||||||
|
extension.sendMessage("remove", tab2.id);
|
||||||
|
yield extension.awaitMessage("result");
|
||||||
|
|
||||||
|
yield extension.unload();
|
||||||
|
});
|
||||||
|
|
|
@ -2318,7 +2318,9 @@ BrowserGlue.prototype = {
|
||||||
"chrome://browser/locale/accounts.properties"
|
"chrome://browser/locale/accounts.properties"
|
||||||
);
|
);
|
||||||
let title = accountsBundle.GetStringFromName("deviceConnectedTitle");
|
let title = accountsBundle.GetStringFromName("deviceConnectedTitle");
|
||||||
let body = accountsBundle.formatStringFromName("deviceConnectedBody", [deviceName], 1);
|
let body = accountsBundle.formatStringFromName("deviceConnectedBody" +
|
||||||
|
(deviceName ? "" : ".noDeviceName"),
|
||||||
|
[deviceName], 1);
|
||||||
let url = Services.urlFormatter.formatURLPref("identity.fxaccounts.settings.devices.uri");
|
let url = Services.urlFormatter.formatURLPref("identity.fxaccounts.settings.devices.uri");
|
||||||
|
|
||||||
function clickCallback(subject, topic, data) {
|
function clickCallback(subject, topic, data) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ support-files =
|
||||||
testEngine.xml
|
testEngine.xml
|
||||||
testEngine_diacritics.xml
|
testEngine_diacritics.xml
|
||||||
testEngine_dupe.xml
|
testEngine_dupe.xml
|
||||||
|
testEngine_missing_namespace.xml
|
||||||
testEngine_mozsearch.xml
|
testEngine_mozsearch.xml
|
||||||
tooManyEnginesOffered.html
|
tooManyEnginesOffered.html
|
||||||
webapi.html
|
webapi.html
|
||||||
|
|
|
@ -67,11 +67,12 @@ add_task(function* test_relative() {
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_invalid() {
|
add_task(function* test_invalid() {
|
||||||
gBrowser.selectedTab = AddSearchProvider("z://foobar");
|
let url = "z://foobar";
|
||||||
|
gBrowser.selectedTab = AddSearchProvider(url);
|
||||||
|
|
||||||
let dialog = yield promiseDialogOpened();
|
let dialog = yield promiseDialogOpened();
|
||||||
is(dialog.args.promptType, "alert", "Should see the alert dialog.");
|
is(dialog.args.promptType, "alert", "Should see the alert dialog.");
|
||||||
is(dialog.args.text, getString("error_invalid_engine_msg", brandName),
|
is(dialog.args.text, getString("error_invalid_engine_msg2", brandName, url),
|
||||||
"Should have seen the right error message")
|
"Should have seen the right error message")
|
||||||
dialog.document.documentElement.acceptDialog();
|
dialog.document.documentElement.acceptDialog();
|
||||||
|
|
||||||
|
@ -90,3 +91,16 @@ add_task(function* test_missing() {
|
||||||
|
|
||||||
gBrowser.removeCurrentTab();
|
gBrowser.removeCurrentTab();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
add_task(function* test_missing_namespace() {
|
||||||
|
let url = ROOT + "testEngine_missing_namespace.xml";
|
||||||
|
gBrowser.selectedTab = AddSearchProvider(url);
|
||||||
|
|
||||||
|
let dialog = yield promiseDialogOpened();
|
||||||
|
is(dialog.args.promptType, "alert", "Should see the alert dialog.");
|
||||||
|
is(dialog.args.text, getString("error_invalid_engine_msg2", brandName, url),
|
||||||
|
"Should have seen the right error message")
|
||||||
|
dialog.document.documentElement.acceptDialog();
|
||||||
|
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
});
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<OpenSearchDescription>
|
||||||
|
<ShortName>Foo</ShortName>
|
||||||
|
<Description>Foo Search</Description>
|
||||||
|
<InputEncoding>utf-8</InputEncoding>
|
||||||
|
<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC</Image>
|
||||||
|
<Url type="text/html" method="GET" template="http://mochi.test:8888/browser/browser/components/search/test/?search">
|
||||||
|
<Param name="test" value="{searchTerms}"/>
|
||||||
|
</Url>
|
||||||
|
<moz:SearchForm>http://mochi.test:8888/browser/browser/components/search/test/</moz:SearchForm>
|
||||||
|
<moz:Alias>fooalias</moz:Alias>
|
||||||
|
</OpenSearchDescription>
|
|
@ -4032,7 +4032,7 @@ var SessionStoreInternal = {
|
||||||
argString.data = "";
|
argString.data = "";
|
||||||
|
|
||||||
// Build feature string
|
// Build feature string
|
||||||
let features = "chrome,dialog=no,macsuppressanimation,all";
|
let features = "chrome,dialog=no,suppressanimation,all";
|
||||||
let winState = aState.windows[0];
|
let winState = aState.windows[0];
|
||||||
WINDOW_ATTRIBUTES.forEach(function(aFeature) {
|
WINDOW_ATTRIBUTES.forEach(function(aFeature) {
|
||||||
// Use !isNaN as an easy way to ignore sizemode and check for numbers
|
// Use !isNaN as an easy way to ignore sizemode and check for numbers
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/* global ADDON_ENABLE:false, ADDON_DISABLE:false, APP_SHUTDOWN: false */
|
||||||
|
|
||||||
const {classes: Cc, interfaces: Ci, utils: Cu, manager: Cm} = Components;
|
const {classes: Cc, interfaces: Ci, utils: Cu, manager: Cm} = Components;
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
// TODO : [nice to have] - Immediately save, buffer the actions in a local queue and send (so it works offline, works like our native extensions)
|
// TODO : [nice to have] - Immediately save, buffer the actions in a local queue and send (so it works offline, works like our native extensions)
|
||||||
|
|
||||||
/* eslint-disable no-shadow */
|
/* eslint-disable no-shadow */
|
||||||
|
/* eslint "mozilla/import-browserjs-globals": "error" */
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/* global $:false, Handlebars:false */
|
||||||
|
/* import-globals-from messages.js */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PKT_SAVED_OVERLAY is the view itself and contains all of the methods to manipute the overlay and messaging.
|
PKT_SAVED_OVERLAY is the view itself and contains all of the methods to manipute the overlay and messaging.
|
||||||
It does not contain any logic for saving or communication with the extension or server.
|
It does not contain any logic for saving or communication with the extension or server.
|
||||||
|
@ -171,7 +174,7 @@ var PKT_SAVED_OVERLAY = function(options) {
|
||||||
if ($.trim(text).length > 25 || !$.trim(text).length) {
|
if ($.trim(text).length > 25 || !$.trim(text).length) {
|
||||||
if (text.length > 25) {
|
if (text.length > 25) {
|
||||||
myself.showTagsError(myself.dictJSON.maxtaglength);
|
myself.showTagsError(myself.dictJSON.maxtaglength);
|
||||||
changestamp = Date.now();
|
this.changestamp = Date.now();
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
$(".token-input-input-token input").val(text).focus();
|
$(".token-input-input-token input").val(text).focus();
|
||||||
}, 10);
|
}, 10);
|
||||||
|
@ -203,7 +206,7 @@ var PKT_SAVED_OVERLAY = function(options) {
|
||||||
}
|
}
|
||||||
}).on("keypress", "input", function(e) {
|
}).on("keypress", "input", function(e) {
|
||||||
if (e.which == 13) {
|
if (e.which == 13) {
|
||||||
if (typeof changestamp == "undefined" || (Date.now() - changestamp > 250)) {
|
if (typeof this.changestamp == "undefined" || (Date.now() - this.changestamp > 250)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
myself.wrapper.find(".pkt_ext_btn").trigger("click");
|
myself.wrapper.find(".pkt_ext_btn").trigger("click");
|
||||||
}
|
}
|
||||||
|
@ -215,13 +218,13 @@ var PKT_SAVED_OVERLAY = function(options) {
|
||||||
},
|
},
|
||||||
onAdd() {
|
onAdd() {
|
||||||
myself.checkValidTagSubmit();
|
myself.checkValidTagSubmit();
|
||||||
changestamp = Date.now();
|
this.changestamp = Date.now();
|
||||||
myself.hideInactiveTags();
|
myself.hideInactiveTags();
|
||||||
myself.checkPlaceholderStatus();
|
myself.checkPlaceholderStatus();
|
||||||
},
|
},
|
||||||
onDelete() {
|
onDelete() {
|
||||||
myself.checkValidTagSubmit();
|
myself.checkValidTagSubmit();
|
||||||
changestamp = Date.now();
|
this.changestamp = Date.now();
|
||||||
myself.showActiveTags();
|
myself.showActiveTags();
|
||||||
myself.checkPlaceholderStatus();
|
myself.checkPlaceholderStatus();
|
||||||
},
|
},
|
||||||
|
@ -533,6 +536,7 @@ PKT_SAVED.prototype = {
|
||||||
$(function() {
|
$(function() {
|
||||||
if (!window.thePKT_SAVED) {
|
if (!window.thePKT_SAVED) {
|
||||||
var thePKT_SAVED = new PKT_SAVED();
|
var thePKT_SAVED = new PKT_SAVED();
|
||||||
|
/* global thePKT_SAVED */
|
||||||
window.thePKT_SAVED = thePKT_SAVED;
|
window.thePKT_SAVED = thePKT_SAVED;
|
||||||
thePKT_SAVED.init();
|
thePKT_SAVED.init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/* global $:false, Handlebars:false */
|
||||||
|
/* import-globals-from messages.js */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PKT_SIGNUP_OVERLAY is the view itself and contains all of the methods to manipute the overlay and messaging.
|
PKT_SIGNUP_OVERLAY is the view itself and contains all of the methods to manipute the overlay and messaging.
|
||||||
It does not contain any logic for saving or communication with the extension or server.
|
It does not contain any logic for saving or communication with the extension or server.
|
||||||
|
@ -157,6 +160,7 @@ PKT_SIGNUP.prototype = {
|
||||||
$(function() {
|
$(function() {
|
||||||
if (!window.thePKT_SIGNUP) {
|
if (!window.thePKT_SIGNUP) {
|
||||||
var thePKT_SIGNUP = new PKT_SIGNUP();
|
var thePKT_SIGNUP = new PKT_SIGNUP();
|
||||||
|
/* global thePKT_SIGNUP */
|
||||||
window.thePKT_SIGNUP = thePKT_SIGNUP;
|
window.thePKT_SIGNUP = thePKT_SIGNUP;
|
||||||
thePKT_SIGNUP.init();
|
thePKT_SIGNUP.init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,8 @@ var Presentation = {
|
||||||
init() {
|
init() {
|
||||||
log("init");
|
log("init");
|
||||||
// Register PresentationDevicePrompt into a XPCOM component.
|
// Register PresentationDevicePrompt into a XPCOM component.
|
||||||
Cu.import(PRESENTATION_DEVICE_PROMPT_PATH);
|
let {PresentationDevicePrompt} = Cu.import(PRESENTATION_DEVICE_PROMPT_PATH, {});
|
||||||
|
this.PresentationDevicePrompt = PresentationDevicePrompt;
|
||||||
this._register();
|
this._register();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -66,6 +67,7 @@ var Presentation = {
|
||||||
log("uninit");
|
log("uninit");
|
||||||
// Unregister PresentationDevicePrompt XPCOM component.
|
// Unregister PresentationDevicePrompt XPCOM component.
|
||||||
this._unregister();
|
this._unregister();
|
||||||
|
delete this.PresentationDevicePrompt;
|
||||||
Cu.unload(PRESENTATION_DEVICE_PROMPT_PATH);
|
Cu.unload(PRESENTATION_DEVICE_PROMPT_PATH);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -73,7 +75,7 @@ var Presentation = {
|
||||||
_register() {
|
_register() {
|
||||||
log("_register");
|
log("_register");
|
||||||
this._devicePromptFactory = new Factory();
|
this._devicePromptFactory = new Factory();
|
||||||
this._devicePromptFactory.register(PresentationDevicePrompt);
|
this._devicePromptFactory.register(this.PresentationDevicePrompt);
|
||||||
},
|
},
|
||||||
|
|
||||||
_unregister() {
|
_unregister() {
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const {utils: Cu} = Components;
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = ["CleanupManager"];
|
this.EXPORTED_SYMBOLS = ["CleanupManager"];
|
||||||
|
|
||||||
const cleanupHandlers = new Set();
|
const cleanupHandlers = new Set();
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/* global APP_SHUTDOWN:false */
|
||||||
|
|
||||||
let { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
let { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
|
@ -31,6 +31,7 @@ let WebCompatReporter = {
|
||||||
},
|
},
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
/* global TabListener */
|
||||||
Cu.import(TABLISTENER_JSM);
|
Cu.import(TABLISTENER_JSM);
|
||||||
|
|
||||||
let styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"]
|
let styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"]
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/* global content:false, sendAsyncMessage:false */
|
||||||
|
|
||||||
let { utils: Cu } = Components;
|
let { utils: Cu } = Components;
|
||||||
|
|
||||||
const TABDATA_MESSAGE = "WebCompat:SendTabData";
|
const TABDATA_MESSAGE = "WebCompat:SendTabData";
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/* global content:false, addMessageListener:false, removeMessageListener: false */
|
||||||
|
|
||||||
let { utils: Cu } = Components;
|
let { utils: Cu } = Components;
|
||||||
|
|
||||||
const SCREENSHOT_MESSAGE = "WebCompat:SendScreenshot";
|
const SCREENSHOT_MESSAGE = "WebCompat:SendScreenshot";
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
"extends": [
|
||||||
|
"../../../../testing/mochitest/browser.eslintrc.js"
|
||||||
|
]
|
||||||
|
};
|
|
@ -16,10 +16,13 @@ verificationSentBody = A verification link has been sent to %S.
|
||||||
verificationNotSentTitle = Unable to Send Verification
|
verificationNotSentTitle = Unable to Send Verification
|
||||||
verificationNotSentBody = We are unable to send a verification mail at this time, please try again later.
|
verificationNotSentBody = We are unable to send a verification mail at this time, please try again later.
|
||||||
|
|
||||||
# LOCALIZATION NOTE (deviceConnectedTitle, deviceConnectedBody)
|
# LOCALIZATION NOTE (deviceConnectedTitle, deviceConnectedBody, deviceConnectedBody.noDeviceName)
|
||||||
# These strings are used in a notification shown when a new device joins the Sync account.
|
# These strings are used in a notification shown when a new device joins the Sync account.
|
||||||
|
# deviceConnectedBody.noDeviceName is shown instead of deviceConnectedBody when we
|
||||||
|
# could not get the device name that joined
|
||||||
deviceConnectedTitle = Firefox Sync
|
deviceConnectedTitle = Firefox Sync
|
||||||
deviceConnectedBody = This computer is now syncing with %S.
|
deviceConnectedBody = This computer is now syncing with %S.
|
||||||
|
deviceConnectedBody.noDeviceName = This computer is now syncing with a new device.
|
||||||
|
|
||||||
# LOCALIZATION NOTE (syncStartNotification.title, syncStartNotification.body)
|
# LOCALIZATION NOTE (syncStartNotification.title, syncStartNotification.body)
|
||||||
# These strings are used in a notification shown after Sync is connected.
|
# These strings are used in a notification shown after Sync is connected.
|
||||||
|
|
|
@ -83,6 +83,7 @@ webextPerms.updateAccept.accessKey=U
|
||||||
|
|
||||||
webextPerms.description.bookmarks=Read and modify bookmarks
|
webextPerms.description.bookmarks=Read and modify bookmarks
|
||||||
webextPerms.description.downloads=Download files and read and modify the browser’s download history
|
webextPerms.description.downloads=Download files and read and modify the browser’s download history
|
||||||
|
webextPerms.description.geolocation=Access your location
|
||||||
webextPerms.description.history=Access browsing history
|
webextPerms.description.history=Access browsing history
|
||||||
# LOCALIZATION NOTE (webextPerms.description.nativeMessaging)
|
# LOCALIZATION NOTE (webextPerms.description.nativeMessaging)
|
||||||
# %S will be replaced with the name of the application
|
# %S will be replaced with the name of the application
|
||||||
|
|
|
@ -13,8 +13,12 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyPreferenceGetter(this, "useRemoteWebExtensions",
|
XPCOMUtils.defineLazyPreferenceGetter(this, "useRemoteWebExtensions",
|
||||||
"extensions.webextensions.remote", false);
|
"extensions.webextensions.remote", false);
|
||||||
|
XPCOMUtils.defineLazyPreferenceGetter(this, "useSeparateFileUriProcess",
|
||||||
|
"browser.tabs.remote.separateFileUriProcess", false);
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "Utils",
|
XPCOMUtils.defineLazyModuleGetter(this, "Utils",
|
||||||
"resource://gre/modules/sessionstore/Utils.jsm");
|
"resource://gre/modules/sessionstore/Utils.jsm");
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "console",
|
||||||
|
"resource://gre/modules/Console.jsm");
|
||||||
|
|
||||||
function getAboutModule(aURL) {
|
function getAboutModule(aURL) {
|
||||||
// Needs to match NS_GetAboutModuleName
|
// Needs to match NS_GetAboutModuleName
|
||||||
|
@ -56,7 +60,7 @@ this.E10SUtils = {
|
||||||
},
|
},
|
||||||
|
|
||||||
getRemoteTypeForURI(aURL, aMultiProcess,
|
getRemoteTypeForURI(aURL, aMultiProcess,
|
||||||
aPreferredRemoteType = DEFAULT_REMOTE_TYPE) {
|
aPreferredRemoteType = DEFAULT_REMOTE_TYPE) {
|
||||||
if (!aMultiProcess) {
|
if (!aMultiProcess) {
|
||||||
return NOT_REMOTE;
|
return NOT_REMOTE;
|
||||||
}
|
}
|
||||||
|
@ -66,92 +70,105 @@ this.E10SUtils = {
|
||||||
aURL = "about:blank";
|
aURL = "about:blank";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Javascript urls can load in any process, they apply to the current document
|
let uri;
|
||||||
if (aURL.startsWith("javascript:")) {
|
try {
|
||||||
return aPreferredRemoteType;
|
uri = Services.io.newURI(aURL);
|
||||||
|
} catch (e) {
|
||||||
|
// If we have an invalid URI, it's still possible that it might get
|
||||||
|
// fixed-up into a valid URI later on. However, we don't want to return
|
||||||
|
// aPreferredRemoteType here, in case the URI gets fixed-up into
|
||||||
|
// something that wouldn't normally run in that process.
|
||||||
|
return DEFAULT_REMOTE_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need data: URI's to load in a remote process, because some of our
|
return this.getRemoteTypeForURIObject(uri, aMultiProcess,
|
||||||
// tests rely on this. For blob: URI's, load them in their originating
|
aPreferredRemoteType);
|
||||||
// process unless it is non-remote. In that case, favor a remote (sandboxed)
|
},
|
||||||
// process with fewer privileges to limit exposure.
|
|
||||||
if (aURL.startsWith("data:") || aURL.startsWith("blob:")) {
|
|
||||||
return aPreferredRemoteType == NOT_REMOTE ? DEFAULT_REMOTE_TYPE
|
|
||||||
: aPreferredRemoteType;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aURL.startsWith("file:")) {
|
|
||||||
return Services.prefs.getBoolPref("browser.tabs.remote.separateFileUriProcess")
|
|
||||||
? FILE_REMOTE_TYPE : DEFAULT_REMOTE_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aURL.startsWith("about:")) {
|
|
||||||
// We need to special case about:blank because it needs to load in any.
|
|
||||||
if (aURL == "about:blank") {
|
|
||||||
return aPreferredRemoteType;
|
|
||||||
}
|
|
||||||
|
|
||||||
let url = Services.io.newURI(aURL);
|
|
||||||
let module = getAboutModule(url);
|
|
||||||
// If the module doesn't exist then an error page will be loading, that
|
|
||||||
// should be ok to load in any process
|
|
||||||
if (!module) {
|
|
||||||
return aPreferredRemoteType;
|
|
||||||
}
|
|
||||||
|
|
||||||
let flags = module.getURIFlags(url);
|
|
||||||
if (flags & Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD) {
|
|
||||||
return DEFAULT_REMOTE_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the about page can load in parent or child, it should be safe to
|
|
||||||
// load in any remote type.
|
|
||||||
if (flags & Ci.nsIAboutModule.URI_CAN_LOAD_IN_CHILD) {
|
|
||||||
return aPreferredRemoteType;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
getRemoteTypeForURIObject(aURI, aMultiProcess,
|
||||||
|
aPreferredRemoteType = DEFAULT_REMOTE_TYPE) {
|
||||||
|
if (!aMultiProcess) {
|
||||||
return NOT_REMOTE;
|
return NOT_REMOTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aURL.startsWith("chrome:")) {
|
switch (aURI.scheme) {
|
||||||
let url;
|
case "javascript":
|
||||||
try {
|
// javascript URIs can load in any, they apply to the current document.
|
||||||
// This can fail for invalid Chrome URIs, in which case we will end up
|
|
||||||
// not loading anything anyway.
|
|
||||||
url = Services.io.newURI(aURL);
|
|
||||||
} catch (ex) {
|
|
||||||
return aPreferredRemoteType;
|
return aPreferredRemoteType;
|
||||||
}
|
|
||||||
|
|
||||||
let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].
|
case "data":
|
||||||
getService(Ci.nsIXULChromeRegistry);
|
case "blob":
|
||||||
if (chromeReg.mustLoadURLRemotely(url)) {
|
// We need data: and blob: URIs to load in any remote process, because
|
||||||
return DEFAULT_REMOTE_TYPE;
|
// they need to be able to load in whatever is the current process
|
||||||
}
|
// unless it is non-remote. In that case we don't want to load them in
|
||||||
|
// the parent process, so we load them in the default remote process,
|
||||||
|
// which is sandboxed and limits any risk.
|
||||||
|
return aPreferredRemoteType == NOT_REMOTE ? DEFAULT_REMOTE_TYPE
|
||||||
|
: aPreferredRemoteType;
|
||||||
|
|
||||||
if (chromeReg.canLoadURLRemotely(url) &&
|
case "file":
|
||||||
aPreferredRemoteType != NOT_REMOTE) {
|
return useSeparateFileUriProcess ? FILE_REMOTE_TYPE
|
||||||
return DEFAULT_REMOTE_TYPE;
|
: DEFAULT_REMOTE_TYPE;
|
||||||
}
|
|
||||||
|
|
||||||
return NOT_REMOTE;
|
case "about":
|
||||||
|
let module = getAboutModule(aURI);
|
||||||
|
// If the module doesn't exist then an error page will be loading, that
|
||||||
|
// should be ok to load in any process
|
||||||
|
if (!module) {
|
||||||
|
return aPreferredRemoteType;
|
||||||
|
}
|
||||||
|
|
||||||
|
let flags = module.getURIFlags(aURI);
|
||||||
|
if (flags & Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD) {
|
||||||
|
return DEFAULT_REMOTE_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the about page can load in parent or child, it should be safe to
|
||||||
|
// load in any remote type.
|
||||||
|
if (flags & Ci.nsIAboutModule.URI_CAN_LOAD_IN_CHILD) {
|
||||||
|
return aPreferredRemoteType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NOT_REMOTE;
|
||||||
|
|
||||||
|
case "chrome":
|
||||||
|
let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].
|
||||||
|
getService(Ci.nsIXULChromeRegistry);
|
||||||
|
if (chromeReg.mustLoadURLRemotely(aURI)) {
|
||||||
|
return DEFAULT_REMOTE_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chromeReg.canLoadURLRemotely(aURI) &&
|
||||||
|
aPreferredRemoteType != NOT_REMOTE) {
|
||||||
|
return DEFAULT_REMOTE_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NOT_REMOTE;
|
||||||
|
|
||||||
|
case "moz-extension":
|
||||||
|
return useRemoteWebExtensions ? EXTENSION_REMOTE_TYPE : NOT_REMOTE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// For any other nested URIs, we use the innerURI to determine the
|
||||||
|
// remote type. In theory we should use the innermost URI, but some URIs
|
||||||
|
// have fake inner URIs (e.g. about URIs with inner moz-safe-about) and
|
||||||
|
// if such URIs are wrapped in other nested schemes like view-source:,
|
||||||
|
// we don't want to "skip" past "about:" by going straight to the
|
||||||
|
// innermost URI. Any URIs like this will need to be handled in the
|
||||||
|
// cases above, so we don't still end up using the fake inner URI here.
|
||||||
|
if (aURI instanceof Ci.nsINestedURI) {
|
||||||
|
let innerURI = aURI.QueryInterface(Ci.nsINestedURI).innerURI;
|
||||||
|
return this.getRemoteTypeForURIObject(innerURI, aMultiProcess,
|
||||||
|
aPreferredRemoteType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return validatedWebRemoteType(aPreferredRemoteType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aURL.startsWith("moz-extension:")) {
|
|
||||||
return useRemoteWebExtensions ? EXTENSION_REMOTE_TYPE : NOT_REMOTE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aURL.startsWith("view-source:")) {
|
|
||||||
return this.getRemoteTypeForURI(aURL.substr("view-source:".length),
|
|
||||||
aMultiProcess, aPreferredRemoteType);
|
|
||||||
}
|
|
||||||
|
|
||||||
return validatedWebRemoteType(aPreferredRemoteType);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
shouldLoadURIInThisProcess(aURI) {
|
shouldLoadURIInThisProcess(aURI) {
|
||||||
let remoteType = Services.appinfo.remoteType;
|
let remoteType = Services.appinfo.remoteType;
|
||||||
return remoteType == this.getRemoteTypeForURI(aURI.spec, true, remoteType);
|
return remoteType == this.getRemoteTypeForURIObject(aURI, true, remoteType);
|
||||||
},
|
},
|
||||||
|
|
||||||
shouldLoadURI(aDocShell, aURI, aReferrer) {
|
shouldLoadURI(aDocShell, aURI, aReferrer) {
|
||||||
|
|
|
@ -92,7 +92,7 @@ this.ExtensionsUI = {
|
||||||
let info = {
|
let info = {
|
||||||
addon,
|
addon,
|
||||||
permissions: addon.userPermissions,
|
permissions: addon.userPermissions,
|
||||||
icon: addon.iconURL || DEFAULT_EXTENSION_ICON,
|
icon: addon.iconURL,
|
||||||
type: "sideload",
|
type: "sideload",
|
||||||
};
|
};
|
||||||
this.showAddonsManager(browser, info).then(answer => {
|
this.showAddonsManager(browser, info).then(answer => {
|
||||||
|
@ -101,6 +101,7 @@ this.ExtensionsUI = {
|
||||||
},
|
},
|
||||||
|
|
||||||
showUpdate(browser, info) {
|
showUpdate(browser, info) {
|
||||||
|
info.icon = info.addon.iconURL;
|
||||||
info.type = "update";
|
info.type = "update";
|
||||||
this.showAddonsManager(browser, info).then(answer => {
|
this.showAddonsManager(browser, info).then(answer => {
|
||||||
if (answer) {
|
if (answer) {
|
||||||
|
@ -268,7 +269,7 @@ this.ExtensionsUI = {
|
||||||
|
|
||||||
let popupOptions = {
|
let popupOptions = {
|
||||||
hideClose: true,
|
hideClose: true,
|
||||||
popupIconURL: info.icon,
|
popupIconURL: info.icon || DEFAULT_EXTENSION_ICON,
|
||||||
persistent: true,
|
persistent: true,
|
||||||
|
|
||||||
eventCallback(topic) {
|
eventCallback(topic) {
|
||||||
|
|
|
@ -246,16 +246,11 @@ this.PermissionPromptPrototype = {
|
||||||
* allow or cancel itself based on the user's current
|
* allow or cancel itself based on the user's current
|
||||||
* permission settings without displaying the prompt.
|
* permission settings without displaying the prompt.
|
||||||
*
|
*
|
||||||
* If the <xul:browser> that the request is associated with
|
* If the permission is not already set and the <xul:browser> that the request
|
||||||
* does not belong to a browser window with the PopupNotifications
|
* is associated with does not belong to a browser window with the
|
||||||
* global set, the prompt request is ignored.
|
* PopupNotifications global set, the prompt request is ignored.
|
||||||
*/
|
*/
|
||||||
prompt() {
|
prompt() {
|
||||||
let chromeWin = this.browser.ownerGlobal;
|
|
||||||
if (!chromeWin.PopupNotifications) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We ignore requests from non-nsIStandardURLs
|
// We ignore requests from non-nsIStandardURLs
|
||||||
let requestingURI = this.principal.URI;
|
let requestingURI = this.principal.URI;
|
||||||
if (!(requestingURI instanceof Ci.nsIStandardURL)) {
|
if (!(requestingURI instanceof Ci.nsIStandardURL)) {
|
||||||
|
@ -286,6 +281,12 @@ this.PermissionPromptPrototype = {
|
||||||
.CustomEvent("PermissionStateChange"));
|
.CustomEvent("PermissionStateChange"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let chromeWin = this.browser.ownerGlobal;
|
||||||
|
if (!chromeWin.PopupNotifications) {
|
||||||
|
this.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Transform the PermissionPrompt actions into PopupNotification actions.
|
// Transform the PermissionPrompt actions into PopupNotification actions.
|
||||||
let popupNotificationActions = [];
|
let popupNotificationActions = [];
|
||||||
for (let promptAction of this.promptActions) {
|
for (let promptAction of this.promptActions) {
|
||||||
|
|
|
@ -252,7 +252,7 @@ this.SitePermissions = {
|
||||||
* @return {boolean} if the URI is supported.
|
* @return {boolean} if the URI is supported.
|
||||||
*/
|
*/
|
||||||
isSupportedURI(uri) {
|
isSupportedURI(uri) {
|
||||||
return uri && (uri.schemeIs("http") || uri.schemeIs("https"));
|
return uri && ["http", "https", "moz-extension"].includes(uri.scheme);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -19,11 +19,12 @@ function* getPriority(aBrowser) {
|
||||||
aBrowser = aBrowser.linkedBrowser;
|
aBrowser = aBrowser.linkedBrowser;
|
||||||
|
|
||||||
return yield ContentTask.spawn(aBrowser, null, function* () {
|
return yield ContentTask.spawn(aBrowser, null, function* () {
|
||||||
return docShell.QueryInterface(Components.interfaces.nsIWebNavigation)
|
return content.document.docShell
|
||||||
.QueryInterface(Components.interfaces.nsIDocumentLoader)
|
.QueryInterface(Components.interfaces.nsIWebNavigation)
|
||||||
.loadGroup
|
.QueryInterface(Components.interfaces.nsIDocumentLoader)
|
||||||
.QueryInterface(Components.interfaces.nsISupportsPriority)
|
.loadGroup
|
||||||
.priority;
|
.QueryInterface(Components.interfaces.nsISupportsPriority)
|
||||||
|
.priority;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,11 +33,12 @@ function* setPriority(aBrowser, aPriority) {
|
||||||
aBrowser = aBrowser.linkedBrowser;
|
aBrowser = aBrowser.linkedBrowser;
|
||||||
|
|
||||||
yield ContentTask.spawn(aBrowser, aPriority, function* (contentPriority) {
|
yield ContentTask.spawn(aBrowser, aPriority, function* (contentPriority) {
|
||||||
docShell.QueryInterface(Components.interfaces.nsIWebNavigation)
|
content.document.docShell
|
||||||
.QueryInterface(Components.interfaces.nsIDocumentLoader)
|
.QueryInterface(Components.interfaces.nsIWebNavigation)
|
||||||
.loadGroup
|
.QueryInterface(Components.interfaces.nsIDocumentLoader)
|
||||||
.QueryInterface(Ci.nsISupportsPriority)
|
.loadGroup
|
||||||
.priority = contentPriority;
|
.QueryInterface(Ci.nsISupportsPriority)
|
||||||
|
.priority = contentPriority;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/* global addMessageListener:false, sendAsyncMessage:false, XPCOMUtils */
|
||||||
|
|
||||||
const TEST_MSG = "ContentSearchTest";
|
const TEST_MSG = "ContentSearchTest";
|
||||||
const SERVICE_EVENT_TYPE = "ContentSearchService";
|
const SERVICE_EVENT_TYPE = "ContentSearchService";
|
||||||
const CLIENT_EVENT_TYPE = "ContentSearchClient";
|
const CLIENT_EVENT_TYPE = "ContentSearchClient";
|
||||||
|
@ -38,8 +40,8 @@ addMessageListener(TEST_MSG, msg => {
|
||||||
|
|
||||||
function waitForLoadAndStopIt(expectedURL, callback) {
|
function waitForLoadAndStopIt(expectedURL, callback) {
|
||||||
let Ci = Components.interfaces;
|
let Ci = Components.interfaces;
|
||||||
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
let webProgress = content.document.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
.getInterface(Ci.nsIWebProgress);
|
.getInterface(Ci.nsIWebProgress);
|
||||||
let listener = {
|
let listener = {
|
||||||
onStateChange(webProg, req, flags, status) {
|
onStateChange(webProg, req, flags, status) {
|
||||||
if (req instanceof Ci.nsIChannel) {
|
if (req instanceof Ci.nsIChannel) {
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||||
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||||
|
|
||||||
|
const {utils: Cu, interfaces: Ci} = Components;
|
||||||
|
|
||||||
|
Cu.import("resource:///modules/E10SUtils.jsm");
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
var TEST_PREFERRED_REMOTE_TYPES = [
|
||||||
|
E10SUtils.WEB_REMOTE_TYPE,
|
||||||
|
E10SUtils.NOT_REMOTE,
|
||||||
|
"fakeRemoteType",
|
||||||
|
]
|
||||||
|
|
||||||
|
// These test cases give a nestedURL and a plainURL that should always load in
|
||||||
|
// the same remote type. By making these tests comparisons, they should work
|
||||||
|
// with any pref combination.
|
||||||
|
var TEST_CASES = [
|
||||||
|
{
|
||||||
|
nestedURL: "jar:file:///some.file!/",
|
||||||
|
plainURL: "file:///some.file",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nestedURL: "jar:jar:file:///some.file!/!/",
|
||||||
|
plainURL: "file:///some.file",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nestedURL: "jar:http://some.site/file!/",
|
||||||
|
plainURL: "http://some.site/file",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nestedURL: "feed:http://some.site",
|
||||||
|
plainURL: "http://some.site",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nestedURL: "pcast:http://some.site",
|
||||||
|
plainURL: "http://some.site",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nestedURL: "view-source:http://some.site",
|
||||||
|
plainURL: "http://some.site",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nestedURL: "view-source:file:///some.file",
|
||||||
|
plainURL: "file:///some.file",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nestedURL: "view-source:about:home",
|
||||||
|
plainURL: "about:home",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nestedURL: "view-source:about:robots",
|
||||||
|
plainURL: "about:robots",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nestedURL: "view-source:feed:http://some.site",
|
||||||
|
plainURL: "http://some.site",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nestedURL: "view-source:pcast:http://some.site",
|
||||||
|
plainURL: "http://some.site",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
for (let testCase of TEST_CASES) {
|
||||||
|
for (let preferredRemoteType of TEST_PREFERRED_REMOTE_TYPES) {
|
||||||
|
let plainUri = Services.io.newURI(testCase.plainURL);
|
||||||
|
let plainRemoteType =
|
||||||
|
E10SUtils.getRemoteTypeForURIObject(plainUri, true, preferredRemoteType);
|
||||||
|
|
||||||
|
let nestedUri = Services.io.newURI(testCase.nestedURL);
|
||||||
|
let nestedRemoteType =
|
||||||
|
E10SUtils.getRemoteTypeForURIObject(nestedUri, true, preferredRemoteType);
|
||||||
|
|
||||||
|
let nestedStr = nestedUri.scheme + ":";
|
||||||
|
do {
|
||||||
|
nestedUri = nestedUri.QueryInterface(Ci.nsINestedURI).innerURI;
|
||||||
|
if (nestedUri.scheme == "about") {
|
||||||
|
nestedStr += nestedUri.spec;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nestedStr += nestedUri.scheme + ":";
|
||||||
|
} while (nestedUri instanceof Ci.nsINestedURI);
|
||||||
|
|
||||||
|
let plainStr = plainUri.scheme == "about" ? plainUri.spec
|
||||||
|
: plainUri.scheme + ":";
|
||||||
|
equal(nestedRemoteType, plainRemoteType,
|
||||||
|
`Check that ${nestedStr} loads in same remote type as ${plainStr}`
|
||||||
|
+ ` with preferred remote type: ${preferredRemoteType}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,5 +6,6 @@ skip-if = toolkit == 'android'
|
||||||
[test_AttributionCode.js]
|
[test_AttributionCode.js]
|
||||||
skip-if = os != 'win'
|
skip-if = os != 'win'
|
||||||
[test_DirectoryLinksProvider.js]
|
[test_DirectoryLinksProvider.js]
|
||||||
|
[test_E10SUtils_nested_URIs.js]
|
||||||
[test_SitePermissions.js]
|
[test_SitePermissions.js]
|
||||||
[test_LaterRun.js]
|
[test_LaterRun.js]
|
||||||
|
|
|
@ -109,6 +109,7 @@ def rust_triple_alias(host_or_target):
|
||||||
# NetBSD
|
# NetBSD
|
||||||
('x86_64', 'NetBSD'): 'x86_64-unknown-netbsd',
|
('x86_64', 'NetBSD'): 'x86_64-unknown-netbsd',
|
||||||
# OpenBSD
|
# OpenBSD
|
||||||
|
('x86', 'OpenBSD'): 'i686-unknown-openbsd',
|
||||||
('x86_64', 'OpenBSD'): 'x86_64-unknown-openbsd',
|
('x86_64', 'OpenBSD'): 'x86_64-unknown-openbsd',
|
||||||
# Linux
|
# Linux
|
||||||
('x86', 'Linux'): 'i686-unknown-linux-gnu',
|
('x86', 'Linux'): 'i686-unknown-linux-gnu',
|
||||||
|
|
|
@ -139,7 +139,7 @@ CopyURIs(const InfallibleTArray<URIParams>& aDomains, nsIDomainSet* aSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DomainPolicy::ApplyClone(DomainPolicyClone* aClone)
|
DomainPolicy::ApplyClone(const DomainPolicyClone* aClone)
|
||||||
{
|
{
|
||||||
CopyURIs(aClone->blacklist(), mBlacklist);
|
CopyURIs(aClone->blacklist(), mBlacklist);
|
||||||
CopyURIs(aClone->whitelist(), mWhitelist);
|
CopyURIs(aClone->whitelist(), mWhitelist);
|
||||||
|
|
|
@ -17,6 +17,7 @@ class DomainPolicyClone;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
[ptr] native DomainPolicyClonePtr(mozilla::dom::DomainPolicyClone);
|
[ptr] native DomainPolicyClonePtr(mozilla::dom::DomainPolicyClone);
|
||||||
|
[ptr] native DomainPolicyCloneConstPtr(const mozilla::dom::DomainPolicyClone);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When a domain policy is instantiated by invoking activateDomainPolicy() on
|
* When a domain policy is instantiated by invoking activateDomainPolicy() on
|
||||||
|
@ -41,7 +42,7 @@ interface nsIDomainPolicy : nsISupports
|
||||||
void deactivate();
|
void deactivate();
|
||||||
|
|
||||||
[noscript, notxpcom] void cloneDomainPolicy(in DomainPolicyClonePtr aClone);
|
[noscript, notxpcom] void cloneDomainPolicy(in DomainPolicyClonePtr aClone);
|
||||||
[noscript, notxpcom] void applyClone(in DomainPolicyClonePtr aClone);
|
[noscript, notxpcom] void applyClone(in DomainPolicyCloneConstPtr aClone);
|
||||||
};
|
};
|
||||||
|
|
||||||
[scriptable, builtinclass, uuid(665c981b-0a0f-4229-ac06-a826e02d4f69)]
|
[scriptable, builtinclass, uuid(665c981b-0a0f-4229-ac06-a826e02d4f69)]
|
||||||
|
|
|
@ -489,6 +489,7 @@ gdk/gdkkeysyms.h
|
||||||
gdk/gdkprivate.h
|
gdk/gdkprivate.h
|
||||||
gdk/gdkx.h
|
gdk/gdkx.h
|
||||||
gdk/gdkdirectfb.h
|
gdk/gdkdirectfb.h
|
||||||
|
gdk/gdkwayland.h
|
||||||
gdk-pixbuf/gdk-pixbuf.h
|
gdk-pixbuf/gdk-pixbuf.h
|
||||||
Gestalt.h
|
Gestalt.h
|
||||||
getopt.h
|
getopt.h
|
||||||
|
|
|
@ -111,6 +111,7 @@ registerCleanupFunction(function* cleanup() {
|
||||||
* @param {Object} options Object with various optional fields:
|
* @param {Object} options Object with various optional fields:
|
||||||
* - {Boolean} background If true, open the tab in background
|
* - {Boolean} background If true, open the tab in background
|
||||||
* - {ChromeWindow} window Firefox top level window we should use to open the tab
|
* - {ChromeWindow} window Firefox top level window we should use to open the tab
|
||||||
|
* - {Number} userContextId The userContextId of the tab.
|
||||||
* @return a promise that resolves to the tab object when the url is loaded
|
* @return a promise that resolves to the tab object when the url is loaded
|
||||||
*/
|
*/
|
||||||
var addTab = Task.async(function* (url, options = { background: false, window: window }) {
|
var addTab = Task.async(function* (url, options = { background: false, window: window }) {
|
||||||
|
@ -118,8 +119,9 @@ var addTab = Task.async(function* (url, options = { background: false, window: w
|
||||||
|
|
||||||
let { background } = options;
|
let { background } = options;
|
||||||
let { gBrowser } = options.window ? options.window : window;
|
let { gBrowser } = options.window ? options.window : window;
|
||||||
|
let { userContextId } = options;
|
||||||
|
|
||||||
let tab = gBrowser.addTab(url);
|
let tab = gBrowser.addTab(url, {userContextId});
|
||||||
if (!background) {
|
if (!background) {
|
||||||
gBrowser.selectedTab = tab;
|
gBrowser.selectedTab = tab;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,9 +59,9 @@ exports.viewSourceInDebugger = Task.async(function* (toolbox, sourceURL, sourceL
|
||||||
|
|
||||||
// New debugger frontend
|
// New debugger frontend
|
||||||
if (Services.prefs.getBoolPref("devtools.debugger.new-debugger-frontend")) {
|
if (Services.prefs.getBoolPref("devtools.debugger.new-debugger-frontend")) {
|
||||||
yield toolbox.selectTool("jsdebugger");
|
|
||||||
const source = dbg._selectors().getSourceByURL(dbg._getState(), sourceURL);
|
const source = dbg._selectors().getSourceByURL(dbg._getState(), sourceURL);
|
||||||
if (source) {
|
if (source) {
|
||||||
|
yield toolbox.selectTool("jsdebugger");
|
||||||
dbg._actions().selectSourceURL(sourceURL, { line: sourceLine });
|
dbg._actions().selectSourceURL(sourceURL, { line: sourceLine });
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,18 +9,23 @@ support-files =
|
||||||
storage-idb-delete-blocked.html
|
storage-idb-delete-blocked.html
|
||||||
storage-indexeddb-duplicate-names.html
|
storage-indexeddb-duplicate-names.html
|
||||||
storage-listings.html
|
storage-listings.html
|
||||||
|
storage-listings-usercontextid.html
|
||||||
storage-listings-with-fragment.html
|
storage-listings-with-fragment.html
|
||||||
storage-localstorage.html
|
storage-localstorage.html
|
||||||
storage-overflow.html
|
storage-overflow.html
|
||||||
storage-search.html
|
storage-search.html
|
||||||
storage-secured-iframe.html
|
storage-secured-iframe.html
|
||||||
|
storage-secured-iframe-usercontextid.html
|
||||||
storage-sessionstorage.html
|
storage-sessionstorage.html
|
||||||
storage-unsecured-iframe.html
|
storage-unsecured-iframe.html
|
||||||
|
storage-unsecured-iframe-usercontextid.html
|
||||||
storage-updates.html
|
storage-updates.html
|
||||||
head.js
|
head.js
|
||||||
!/devtools/client/framework/test/shared-head.js
|
!/devtools/client/framework/test/shared-head.js
|
||||||
|
|
||||||
[browser_storage_basic.js]
|
[browser_storage_basic.js]
|
||||||
|
[browser_storage_basic_usercontextid.js]
|
||||||
|
tags = usercontextid
|
||||||
[browser_storage_basic_with_fragment.js]
|
[browser_storage_basic_with_fragment.js]
|
||||||
[browser_storage_cache_delete.js]
|
[browser_storage_cache_delete.js]
|
||||||
[browser_storage_cache_error.js]
|
[browser_storage_cache_error.js]
|
||||||
|
@ -32,6 +37,8 @@ support-files =
|
||||||
[browser_storage_delete.js]
|
[browser_storage_delete.js]
|
||||||
[browser_storage_delete_all.js]
|
[browser_storage_delete_all.js]
|
||||||
[browser_storage_delete_tree.js]
|
[browser_storage_delete_tree.js]
|
||||||
|
[browser_storage_delete_usercontextid.js]
|
||||||
|
tags = usercontextid
|
||||||
[browser_storage_dom_cache_disabled.js]
|
[browser_storage_dom_cache_disabled.js]
|
||||||
[browser_storage_dynamic_updates_cookies.js]
|
[browser_storage_dynamic_updates_cookies.js]
|
||||||
[browser_storage_dynamic_updates_localStorage.js]
|
[browser_storage_dynamic_updates_localStorage.js]
|
||||||
|
|
|
@ -0,0 +1,184 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
// A test to check that the storage inspector is working correctly with
|
||||||
|
// userContextId.
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const testCases = [
|
||||||
|
[
|
||||||
|
["cookies", "http://test1.example.org"],
|
||||||
|
[
|
||||||
|
getCookieId("c1", "test1.example.org", "/browser"),
|
||||||
|
getCookieId("cs2", ".example.org", "/"),
|
||||||
|
getCookieId("c3", "test1.example.org", "/"),
|
||||||
|
getCookieId("uc1", ".example.org", "/")
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
["cookies", "https://sectest1.example.org"],
|
||||||
|
[
|
||||||
|
getCookieId("uc1", ".example.org", "/"),
|
||||||
|
getCookieId("cs2", ".example.org", "/"),
|
||||||
|
getCookieId("sc1", "sectest1.example.org", "/browser/devtools/client/storage/test/")
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[["localStorage", "http://test1.example.org"],
|
||||||
|
["ls1", "ls2"]],
|
||||||
|
[["localStorage", "http://sectest1.example.org"],
|
||||||
|
["iframe-u-ls1"]],
|
||||||
|
[["localStorage", "https://sectest1.example.org"],
|
||||||
|
["iframe-s-ls1"]],
|
||||||
|
[["sessionStorage", "http://test1.example.org"],
|
||||||
|
["ss1"]],
|
||||||
|
[["sessionStorage", "http://sectest1.example.org"],
|
||||||
|
["iframe-u-ss1", "iframe-u-ss2"]],
|
||||||
|
[["sessionStorage", "https://sectest1.example.org"],
|
||||||
|
["iframe-s-ss1"]],
|
||||||
|
[["indexedDB", "http://test1.example.org"],
|
||||||
|
["idb1 (default)", "idb2 (default)"]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb1 (default)"],
|
||||||
|
["obj1", "obj2"]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb2 (default)"],
|
||||||
|
["obj3"]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"],
|
||||||
|
[1, 2, 3]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb1 (default)", "obj2"],
|
||||||
|
[1]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb2 (default)", "obj3"],
|
||||||
|
[]],
|
||||||
|
[["indexedDB", "http://sectest1.example.org"],
|
||||||
|
[]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org"],
|
||||||
|
["idb-s1 (default)", "idb-s2 (default)"]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org", "idb-s1 (default)"],
|
||||||
|
["obj-s1"]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org", "idb-s2 (default)"],
|
||||||
|
["obj-s2"]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org", "idb-s1 (default)", "obj-s1"],
|
||||||
|
[6, 7]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org", "idb-s2 (default)", "obj-s2"],
|
||||||
|
[16]],
|
||||||
|
[["Cache", "http://test1.example.org", "plop"],
|
||||||
|
[MAIN_DOMAIN + "404_cached_file.js",
|
||||||
|
MAIN_DOMAIN + "browser_storage_basic.js"]],
|
||||||
|
];
|
||||||
|
|
||||||
|
const testCasesUserContextId = [
|
||||||
|
[
|
||||||
|
["cookies", "http://test1.example.org"],
|
||||||
|
[
|
||||||
|
getCookieId("c1uc1", "test1.example.org", "/browser"),
|
||||||
|
getCookieId("cs2uc1", ".example.org", "/"),
|
||||||
|
getCookieId("c3uc1", "test1.example.org", "/"),
|
||||||
|
getCookieId("uc1uc1", ".example.org", "/")
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
["cookies", "https://sectest1.example.org"],
|
||||||
|
[
|
||||||
|
getCookieId("uc1uc1", ".example.org", "/"),
|
||||||
|
getCookieId("cs2uc1", ".example.org", "/"),
|
||||||
|
getCookieId("sc1uc1", "sectest1.example.org",
|
||||||
|
"/browser/devtools/client/storage/test/")
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[["localStorage", "http://test1.example.org"],
|
||||||
|
["ls1uc1", "ls2uc1"]],
|
||||||
|
[["localStorage", "http://sectest1.example.org"],
|
||||||
|
["iframe-u-ls1uc1"]],
|
||||||
|
[["localStorage", "https://sectest1.example.org"],
|
||||||
|
["iframe-s-ls1uc1"]],
|
||||||
|
[["sessionStorage", "http://test1.example.org"],
|
||||||
|
["ss1uc1"]],
|
||||||
|
[["sessionStorage", "http://sectest1.example.org"],
|
||||||
|
["iframe-u-ss1uc1", "iframe-u-ss2uc1"]],
|
||||||
|
[["sessionStorage", "https://sectest1.example.org"],
|
||||||
|
["iframe-s-ss1uc1"]],
|
||||||
|
[["indexedDB", "http://test1.example.org"],
|
||||||
|
["idb1uc1 (default)", "idb2uc1 (default)"]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb1uc1 (default)"],
|
||||||
|
["obj1uc1", "obj2uc1"]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb2uc1 (default)"],
|
||||||
|
["obj3uc1"]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb1uc1 (default)", "obj1uc1"],
|
||||||
|
[1, 2, 3]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb1uc1 (default)", "obj2uc1"],
|
||||||
|
[1]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb2uc1 (default)", "obj3uc1"],
|
||||||
|
[]],
|
||||||
|
[["indexedDB", "http://sectest1.example.org"],
|
||||||
|
[]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org"],
|
||||||
|
["idb-s1uc1 (default)", "idb-s2uc1 (default)"]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org", "idb-s1uc1 (default)"],
|
||||||
|
["obj-s1uc1"]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org", "idb-s2uc1 (default)"],
|
||||||
|
["obj-s2uc1"]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org", "idb-s1uc1 (default)", "obj-s1uc1"],
|
||||||
|
[6, 7]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org", "idb-s2uc1 (default)", "obj-s2uc1"],
|
||||||
|
[16]],
|
||||||
|
[["Cache", "http://test1.example.org", "plopuc1"],
|
||||||
|
[MAIN_DOMAIN + "404_cached_file.js",
|
||||||
|
MAIN_DOMAIN + "browser_storage_basic.js"]],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that the desired number of tree items are present
|
||||||
|
*/
|
||||||
|
function testTree(tests) {
|
||||||
|
let doc = gPanelWindow.document;
|
||||||
|
for (let [item] of tests) {
|
||||||
|
ok(doc.querySelector("[data-id='" + JSON.stringify(item) + "']"),
|
||||||
|
"Tree item " + item[0] + " should be present in the storage tree");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that correct table entries are shown for each of the tree item
|
||||||
|
*/
|
||||||
|
function* testTables(tests) {
|
||||||
|
let doc = gPanelWindow.document;
|
||||||
|
// Expand all nodes so that the synthesized click event actually works
|
||||||
|
gUI.tree.expandAll();
|
||||||
|
|
||||||
|
// First tree item is already selected so no clicking and waiting for update
|
||||||
|
for (let id of tests[0][1]) {
|
||||||
|
ok(doc.querySelector(".table-widget-cell[data-id='" + id + "']"),
|
||||||
|
"Table item " + id + " should be present");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Click rest of the tree items and wait for the table to be updated
|
||||||
|
for (let [treeItem, items] of tests.slice(1)) {
|
||||||
|
yield selectTreeItem(treeItem);
|
||||||
|
|
||||||
|
// Check whether correct number of items are present in the table
|
||||||
|
is(doc.querySelectorAll(
|
||||||
|
".table-widget-wrapper:first-of-type .table-widget-cell"
|
||||||
|
).length, items.length, "Number of items in table is correct");
|
||||||
|
|
||||||
|
// Check if all the desired items are present in the table
|
||||||
|
for (let id of items) {
|
||||||
|
ok(doc.querySelector(".table-widget-cell[data-id='" + id + "']"),
|
||||||
|
"Table item " + id + " should be present");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(function* () {
|
||||||
|
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html");
|
||||||
|
|
||||||
|
testTree(testCases);
|
||||||
|
yield testTables(testCases);
|
||||||
|
|
||||||
|
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings-usercontextid.html",
|
||||||
|
{userContextId: 1});
|
||||||
|
|
||||||
|
testTree(testCasesUserContextId);
|
||||||
|
yield testTables(testCasesUserContextId);
|
||||||
|
|
||||||
|
yield finishTests();
|
||||||
|
});
|
|
@ -0,0 +1,174 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/* import-globals-from ../../framework/test/shared-head.js */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Test deleting storage items with userContextId.
|
||||||
|
|
||||||
|
// The items that will be deleted.
|
||||||
|
const TEST_CASES = [
|
||||||
|
[["localStorage", "http://test1.example.org"],
|
||||||
|
"ls1", "name"],
|
||||||
|
[["sessionStorage", "http://test1.example.org"],
|
||||||
|
"ss1", "name"],
|
||||||
|
[
|
||||||
|
["cookies", "http://test1.example.org"],
|
||||||
|
getCookieId("c1", "test1.example.org", "/browser"), "name"
|
||||||
|
],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"],
|
||||||
|
1, "name"],
|
||||||
|
[["Cache", "http://test1.example.org", "plop"],
|
||||||
|
MAIN_DOMAIN + "404_cached_file.js", "url"],
|
||||||
|
];
|
||||||
|
|
||||||
|
// The storage items that should exist for default userContextId
|
||||||
|
const storageItemsForDefault = [
|
||||||
|
[
|
||||||
|
["cookies", "http://test1.example.org"],
|
||||||
|
[
|
||||||
|
getCookieId("c1", "test1.example.org", "/browser"),
|
||||||
|
getCookieId("cs2", ".example.org", "/"),
|
||||||
|
getCookieId("c3", "test1.example.org", "/"),
|
||||||
|
getCookieId("uc1", ".example.org", "/")
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
["cookies", "https://sectest1.example.org"],
|
||||||
|
[
|
||||||
|
getCookieId("uc1", ".example.org", "/"),
|
||||||
|
getCookieId("cs2", ".example.org", "/"),
|
||||||
|
getCookieId("sc1", "sectest1.example.org", "/browser/devtools/client/storage/test/")
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[["localStorage", "http://test1.example.org"],
|
||||||
|
["ls1", "ls2"]],
|
||||||
|
[["localStorage", "http://sectest1.example.org"],
|
||||||
|
["iframe-u-ls1"]],
|
||||||
|
[["localStorage", "https://sectest1.example.org"],
|
||||||
|
["iframe-s-ls1"]],
|
||||||
|
[["sessionStorage", "http://test1.example.org"],
|
||||||
|
["ss1"]],
|
||||||
|
[["sessionStorage", "http://sectest1.example.org"],
|
||||||
|
["iframe-u-ss1", "iframe-u-ss2"]],
|
||||||
|
[["sessionStorage", "https://sectest1.example.org"],
|
||||||
|
["iframe-s-ss1"]],
|
||||||
|
[["indexedDB", "http://test1.example.org"],
|
||||||
|
["idb1 (default)", "idb2 (default)"]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb1 (default)"],
|
||||||
|
["obj1", "obj2"]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb2 (default)"],
|
||||||
|
["obj3"]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb1 (default)", "obj1"],
|
||||||
|
[1, 2, 3]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb1 (default)", "obj2"],
|
||||||
|
[1]],
|
||||||
|
[["indexedDB", "http://test1.example.org", "idb2 (default)", "obj3"],
|
||||||
|
[]],
|
||||||
|
[["indexedDB", "http://sectest1.example.org"],
|
||||||
|
[]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org"],
|
||||||
|
["idb-s1 (default)", "idb-s2 (default)"]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org", "idb-s1 (default)"],
|
||||||
|
["obj-s1"]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org", "idb-s2 (default)"],
|
||||||
|
["obj-s2"]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org", "idb-s1 (default)", "obj-s1"],
|
||||||
|
[6, 7]],
|
||||||
|
[["indexedDB", "https://sectest1.example.org", "idb-s2 (default)", "obj-s2"],
|
||||||
|
[16]],
|
||||||
|
[["Cache", "http://test1.example.org", "plop"],
|
||||||
|
[MAIN_DOMAIN + "404_cached_file.js",
|
||||||
|
MAIN_DOMAIN + "browser_storage_basic.js"]],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that the desired number of tree items are present
|
||||||
|
*/
|
||||||
|
function testTree(tests) {
|
||||||
|
let doc = gPanelWindow.document;
|
||||||
|
for (let [item] of tests) {
|
||||||
|
ok(doc.querySelector("[data-id='" + JSON.stringify(item) + "']"),
|
||||||
|
"Tree item " + item[0] + " should be present in the storage tree");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that correct table entries are shown for each of the tree item
|
||||||
|
*/
|
||||||
|
function* testTables(tests) {
|
||||||
|
let doc = gPanelWindow.document;
|
||||||
|
// Expand all nodes so that the synthesized click event actually works
|
||||||
|
gUI.tree.expandAll();
|
||||||
|
|
||||||
|
// First tree item is already selected so no clicking and waiting for update
|
||||||
|
for (let id of tests[0][1]) {
|
||||||
|
ok(doc.querySelector(".table-widget-cell[data-id='" + id + "']"),
|
||||||
|
"Table item " + id + " should be present");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Click rest of the tree items and wait for the table to be updated
|
||||||
|
for (let [treeItem, items] of tests.slice(1)) {
|
||||||
|
yield selectTreeItem(treeItem);
|
||||||
|
|
||||||
|
// Check whether correct number of items are present in the table
|
||||||
|
is(doc.querySelectorAll(
|
||||||
|
".table-widget-wrapper:first-of-type .table-widget-cell"
|
||||||
|
).length, items.length, "Number of items in table is correct");
|
||||||
|
|
||||||
|
// Check if all the desired items are present in the table
|
||||||
|
for (let id of items) {
|
||||||
|
ok(doc.querySelector(".table-widget-cell[data-id='" + id + "']"),
|
||||||
|
"Table item " + id + " should be present");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(function* () {
|
||||||
|
// First, open a tab with the default userContextId and setup its storages.
|
||||||
|
let tabDefault = yield openTab(MAIN_DOMAIN + "storage-listings.html");
|
||||||
|
|
||||||
|
// Second, start testing for userContextId 1.
|
||||||
|
// We use the same item name as the default page has to see deleting items
|
||||||
|
// from userContextId 1 will affect default one or not.
|
||||||
|
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html", {userContextId: 1});
|
||||||
|
|
||||||
|
let contextMenu = gPanelWindow.document.getElementById("storage-table-popup");
|
||||||
|
let menuDeleteItem = contextMenu.querySelector("#storage-table-popup-delete");
|
||||||
|
|
||||||
|
for (let [ treeItem, rowName, cellToClick] of TEST_CASES) {
|
||||||
|
let treeItemName = treeItem.join(" > ");
|
||||||
|
|
||||||
|
info(`Selecting tree item ${treeItemName}`);
|
||||||
|
yield selectTreeItem(treeItem);
|
||||||
|
|
||||||
|
let row = getRowCells(rowName);
|
||||||
|
ok(gUI.table.items.has(rowName), `There is a row '${rowName}' in ${treeItemName}`);
|
||||||
|
|
||||||
|
let eventWait = gUI.once("store-objects-updated");
|
||||||
|
|
||||||
|
yield waitForContextMenu(contextMenu, row[cellToClick], () => {
|
||||||
|
info(`Opened context menu in ${treeItemName}, row '${rowName}'`);
|
||||||
|
menuDeleteItem.click();
|
||||||
|
let truncatedRowName = String(rowName).replace(SEPARATOR_GUID, "-").substr(0, 16);
|
||||||
|
ok(menuDeleteItem.getAttribute("label").includes(truncatedRowName),
|
||||||
|
`Context menu item label contains '${rowName}' (maybe truncated)`);
|
||||||
|
});
|
||||||
|
|
||||||
|
yield eventWait;
|
||||||
|
|
||||||
|
ok(!gUI.table.items.has(rowName),
|
||||||
|
`There is no row '${rowName}' in ${treeItemName} after deletion`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final, we see that the default tab is intact or not.
|
||||||
|
yield BrowserTestUtils.switchTab(gBrowser, tabDefault);
|
||||||
|
yield openStoragePanel();
|
||||||
|
|
||||||
|
testTree(storageItemsForDefault);
|
||||||
|
yield testTables(storageItemsForDefault);
|
||||||
|
|
||||||
|
yield finishTests();
|
||||||
|
});
|
|
@ -49,16 +49,15 @@ registerCleanupFunction(() => {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This generator function opens the given url in a new tab, then sets up the
|
* This generator function opens the given url in a new tab, then sets up the
|
||||||
* page by waiting for all cookies, indexedDB items etc. to be created; Then
|
* page by waiting for all cookies, indexedDB items etc.
|
||||||
* opens the storage inspector and waits for the storage tree and table to be
|
|
||||||
* populated.
|
|
||||||
*
|
*
|
||||||
* @param url {String} The url to be opened in the new tab
|
* @param url {String} The url to be opened in the new tab
|
||||||
|
* @param options {Object} The tab options for the new tab
|
||||||
*
|
*
|
||||||
* @return {Promise} A promise that resolves after storage inspector is ready
|
* @return {Promise} A promise that resolves after the tab is ready
|
||||||
*/
|
*/
|
||||||
function* openTabAndSetupStorage(url) {
|
function* openTab(url, options = {}) {
|
||||||
let tab = yield addTab(url);
|
let tab = yield addTab(url, options);
|
||||||
let content = tab.linkedBrowser.contentWindow;
|
let content = tab.linkedBrowser.contentWindow;
|
||||||
|
|
||||||
gWindow = content.wrappedJSObject;
|
gWindow = content.wrappedJSObject;
|
||||||
|
@ -108,6 +107,24 @@ function* openTabAndSetupStorage(url) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This generator function opens the given url in a new tab, then sets up the
|
||||||
|
* page by waiting for all cookies, indexedDB items etc. to be created; Then
|
||||||
|
* opens the storage inspector and waits for the storage tree and table to be
|
||||||
|
* populated.
|
||||||
|
*
|
||||||
|
* @param url {String} The url to be opened in the new tab
|
||||||
|
* @param options {Object} The tab options for the new tab
|
||||||
|
*
|
||||||
|
* @return {Promise} A promise that resolves after storage inspector is ready
|
||||||
|
*/
|
||||||
|
function* openTabAndSetupStorage(url, options = {}) {
|
||||||
|
// open tab
|
||||||
|
yield openTab(url, options);
|
||||||
|
|
||||||
// open storage inspector
|
// open storage inspector
|
||||||
return yield openStoragePanel();
|
return yield openStoragePanel();
|
||||||
}
|
}
|
||||||
|
@ -204,46 +221,50 @@ function forceCollections() {
|
||||||
function* finishTests() {
|
function* finishTests() {
|
||||||
// Bug 1233497 makes it so that we can no longer yield CPOWs from Tasks.
|
// Bug 1233497 makes it so that we can no longer yield CPOWs from Tasks.
|
||||||
// We work around this by calling clear() via a ContentTask instead.
|
// We work around this by calling clear() via a ContentTask instead.
|
||||||
yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
|
while (gBrowser.tabs.length > 1) {
|
||||||
/**
|
yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
|
||||||
* Get all windows including frames recursively.
|
/**
|
||||||
*
|
* Get all windows including frames recursively.
|
||||||
* @param {Window} [baseWindow]
|
*
|
||||||
* The base window at which to start looking for child windows
|
* @param {Window} [baseWindow]
|
||||||
* (optional).
|
* The base window at which to start looking for child windows
|
||||||
* @return {Set}
|
* (optional).
|
||||||
* A set of windows.
|
* @return {Set}
|
||||||
*/
|
* A set of windows.
|
||||||
function getAllWindows(baseWindow) {
|
*/
|
||||||
let windows = new Set();
|
function getAllWindows(baseWindow) {
|
||||||
|
let windows = new Set();
|
||||||
|
|
||||||
let _getAllWindows = function (win) {
|
let _getAllWindows = function (win) {
|
||||||
windows.add(win.wrappedJSObject);
|
windows.add(win.wrappedJSObject);
|
||||||
|
|
||||||
for (let i = 0; i < win.length; i++) {
|
for (let i = 0; i < win.length; i++) {
|
||||||
_getAllWindows(win[i]);
|
_getAllWindows(win[i]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_getAllWindows(baseWindow);
|
||||||
|
|
||||||
|
return windows;
|
||||||
|
}
|
||||||
|
|
||||||
|
let windows = getAllWindows(content);
|
||||||
|
for (let win of windows) {
|
||||||
|
// Some windows (e.g., about: URLs) don't have storage available
|
||||||
|
try {
|
||||||
|
win.localStorage.clear();
|
||||||
|
win.sessionStorage.clear();
|
||||||
|
} catch (ex) {
|
||||||
|
// ignore
|
||||||
}
|
}
|
||||||
};
|
|
||||||
_getAllWindows(baseWindow);
|
|
||||||
|
|
||||||
return windows;
|
if (win.clear) {
|
||||||
}
|
yield win.clear();
|
||||||
|
}
|
||||||
let windows = getAllWindows(content);
|
|
||||||
for (let win of windows) {
|
|
||||||
// Some windows (e.g., about: URLs) don't have storage available
|
|
||||||
try {
|
|
||||||
win.localStorage.clear();
|
|
||||||
win.sessionStorage.clear();
|
|
||||||
} catch (ex) {
|
|
||||||
// ignore
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (win.clear) {
|
yield closeTabAndToolbox(gBrowser.selectedTab);
|
||||||
yield win.clear();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Services.cookies.removeAll();
|
Services.cookies.removeAll();
|
||||||
forceCollections();
|
forceCollections();
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
Storage inspector front end for userContextId - tests
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Storage inspector test for listing hosts and storages</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe src="http://sectest1.example.org/browser/devtools/client/storage/test/storage-unsecured-iframe-usercontextid.html"></iframe>
|
||||||
|
<iframe src="https://sectest1.example.org:443/browser/devtools/client/storage/test/storage-secured-iframe-usercontextid.html"></iframe>
|
||||||
|
<script type="application/javascript;version=1.7">
|
||||||
|
"use strict";
|
||||||
|
let partialHostname = location.hostname.match(/^[^.]+(\..*)$/)[1];
|
||||||
|
let cookieExpiresTime1 = 2000000000000;
|
||||||
|
let cookieExpiresTime2 = 2000000001000;
|
||||||
|
// Setting up some cookies to eat.
|
||||||
|
document.cookie = "c1uc1=foobar; expires=" +
|
||||||
|
new Date(cookieExpiresTime1).toGMTString() + "; path=/browser";
|
||||||
|
document.cookie = "cs2uc1=sessionCookie; path=/; domain=" + partialHostname;
|
||||||
|
document.cookie = "c3uc1=foobar-2; expires=" +
|
||||||
|
new Date(cookieExpiresTime2).toGMTString() + "; path=/";
|
||||||
|
// ... and some local storage items ..
|
||||||
|
localStorage.setItem("ls1uc1", "foobar");
|
||||||
|
localStorage.setItem("ls2uc1", "foobar-2");
|
||||||
|
// ... and finally some session storage items too
|
||||||
|
sessionStorage.setItem("ss1uc1", "foobar-3");
|
||||||
|
dump("added cookies and storage from main page\n");
|
||||||
|
|
||||||
|
let idbGenerator = async function() {
|
||||||
|
let request = indexedDB.open("idb1uc1", 1);
|
||||||
|
request.onerror = function() {
|
||||||
|
throw new Error("error opening db connection");
|
||||||
|
};
|
||||||
|
let db = await new Promise(done => {
|
||||||
|
request.onupgradeneeded = event => {
|
||||||
|
let db = event.target.result;
|
||||||
|
let store1 = db.createObjectStore("obj1uc1", { keyPath: "id" });
|
||||||
|
store1.createIndex("name", "name", { unique: false });
|
||||||
|
store1.createIndex("email", "email", { unique: true });
|
||||||
|
let store2 = db.createObjectStore("obj2uc1", { keyPath: "id2" });
|
||||||
|
store1.transaction.oncomplete = () => {
|
||||||
|
done(db);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Prevents AbortError
|
||||||
|
await new Promise(done => {
|
||||||
|
request.onsuccess = done;
|
||||||
|
});
|
||||||
|
|
||||||
|
let transaction = db.transaction(["obj1uc1", "obj2uc1"], "readwrite");
|
||||||
|
let store1 = transaction.objectStore("obj1uc1");
|
||||||
|
let store2 = transaction.objectStore("obj2uc1");
|
||||||
|
store1.add({id: 1, name: "foo", email: "foo@bar.com"});
|
||||||
|
store1.add({id: 2, name: "foo2", email: "foo2@bar.com"});
|
||||||
|
store1.add({id: 3, name: "foo2", email: "foo3@bar.com"});
|
||||||
|
store2.add({
|
||||||
|
id2: 1,
|
||||||
|
name: "foo",
|
||||||
|
email: "foo@bar.com",
|
||||||
|
extra: "baz"
|
||||||
|
});
|
||||||
|
// Prevents AbortError during close()
|
||||||
|
await new Promise(success => {
|
||||||
|
transaction.oncomplete = success;
|
||||||
|
});
|
||||||
|
|
||||||
|
db.close();
|
||||||
|
|
||||||
|
request = indexedDB.open("idb2uc1", 1);
|
||||||
|
let db2 = await new Promise(done => {
|
||||||
|
request.onupgradeneeded = event => {
|
||||||
|
let db2 = event.target.result;
|
||||||
|
let store3 = db2.createObjectStore("obj3uc1", { keyPath: "id3" });
|
||||||
|
store3.createIndex("name2", "name2", { unique: true });
|
||||||
|
store3.transaction.oncomplete = () => {
|
||||||
|
done(db2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
// Prevents AbortError during close()
|
||||||
|
await new Promise(done => {
|
||||||
|
request.onsuccess = done;
|
||||||
|
});
|
||||||
|
db2.close();
|
||||||
|
|
||||||
|
dump("added indexedDB from main page\n");
|
||||||
|
};
|
||||||
|
|
||||||
|
function deleteDB(dbName) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
dump("removing database " + dbName + " from " + document.location + "\n");
|
||||||
|
indexedDB.deleteDatabase(dbName).onsuccess = resolve;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchPut(cache, url) {
|
||||||
|
let response = await fetch(url);
|
||||||
|
await cache.put(url, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
let cacheGenerator = async function() {
|
||||||
|
let cache = await caches.open("plopuc1");
|
||||||
|
await fetchPut(cache, "404_cached_file.js");
|
||||||
|
await fetchPut(cache, "browser_storage_basic.js");
|
||||||
|
};
|
||||||
|
|
||||||
|
window.setup = function*() {
|
||||||
|
yield idbGenerator();
|
||||||
|
|
||||||
|
if (window.caches) {
|
||||||
|
yield cacheGenerator();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.clear = function*() {
|
||||||
|
yield deleteDB("idb1uc1");
|
||||||
|
yield deleteDB("idb2uc1");
|
||||||
|
|
||||||
|
if (window.caches) {
|
||||||
|
yield caches.delete("plopuc1");
|
||||||
|
}
|
||||||
|
|
||||||
|
dump("removed indexedDB and cache data from " + document.location + "\n");
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,91 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
Iframe for testing multiple host detetion in storage actor
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="application/javascript;version=1.7">
|
||||||
|
"use strict";
|
||||||
|
document.cookie = "sc1uc1=foobar;";
|
||||||
|
localStorage.setItem("iframe-s-ls1uc1", "foobar");
|
||||||
|
sessionStorage.setItem("iframe-s-ss1uc1", "foobar-2");
|
||||||
|
dump("added cookies and storage from secured iframe\n");
|
||||||
|
|
||||||
|
let idbGenerator = function*() {
|
||||||
|
let request = indexedDB.open("idb-s1uc1", 1);
|
||||||
|
request.onerror = function() {
|
||||||
|
throw new Error("error opening db connection");
|
||||||
|
};
|
||||||
|
let db = yield new Promise(done => {
|
||||||
|
request.onupgradeneeded = event => {
|
||||||
|
let db = event.target.result;
|
||||||
|
let store1 = db.createObjectStore("obj-s1uc1", { keyPath: "id" });
|
||||||
|
store1.transaction.oncomplete = () => {
|
||||||
|
done(db);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
yield new Promise(done => {
|
||||||
|
request.onsuccess = done;
|
||||||
|
});
|
||||||
|
|
||||||
|
let transaction = db.transaction(["obj-s1uc1"], "readwrite");
|
||||||
|
let store1 = transaction.objectStore("obj-s1uc1");
|
||||||
|
store1.add({id: 6, name: "foo", email: "foo@bar.com"});
|
||||||
|
store1.add({id: 7, name: "foo2", email: "foo2@bar.com"});
|
||||||
|
yield new Promise(success => {
|
||||||
|
transaction.oncomplete = success;
|
||||||
|
});
|
||||||
|
|
||||||
|
db.close();
|
||||||
|
|
||||||
|
request = indexedDB.open("idb-s2uc1", 1);
|
||||||
|
let db2 = yield new Promise(done => {
|
||||||
|
request.onupgradeneeded = event => {
|
||||||
|
let db2 = event.target.result;
|
||||||
|
let store3 =
|
||||||
|
db2.createObjectStore("obj-s2uc1", { keyPath: "id3", autoIncrement: true });
|
||||||
|
store3.createIndex("name2", "name2", { unique: true });
|
||||||
|
store3.transaction.oncomplete = () => {
|
||||||
|
done(db2);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
yield new Promise(done => {
|
||||||
|
request.onsuccess = done;
|
||||||
|
});
|
||||||
|
|
||||||
|
transaction = db2.transaction(["obj-s2uc1"], "readwrite");
|
||||||
|
let store3 = transaction.objectStore("obj-s2uc1");
|
||||||
|
store3.add({id3: 16, name2: "foo", email: "foo@bar.com"});
|
||||||
|
yield new Promise(success => {
|
||||||
|
transaction.oncomplete = success;
|
||||||
|
});
|
||||||
|
|
||||||
|
db2.close();
|
||||||
|
dump("added indexedDB from secured iframe\n");
|
||||||
|
};
|
||||||
|
|
||||||
|
function deleteDB(dbName) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
dump("removing database " + dbName + " from " + document.location + "\n");
|
||||||
|
indexedDB.deleteDatabase(dbName).onsuccess = resolve;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.setup = function*() {
|
||||||
|
yield idbGenerator();
|
||||||
|
};
|
||||||
|
|
||||||
|
window.clear = function*() {
|
||||||
|
yield deleteDB("idb-s1uc1");
|
||||||
|
yield deleteDB("idb-s2uc1");
|
||||||
|
|
||||||
|
dump("removed indexedDB data from " + document.location + "\n");
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
Iframe for testing multiple host detetion in storage actor
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
document.cookie = "uc1uc1=foobar; domain=.example.org; path=/";
|
||||||
|
localStorage.setItem("iframe-u-ls1uc1", "foobar");
|
||||||
|
sessionStorage.setItem("iframe-u-ss1uc1", "foobar1");
|
||||||
|
sessionStorage.setItem("iframe-u-ss2uc1", "foobar2");
|
||||||
|
dump("added cookies and storage from unsecured iframe\n");
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -37,6 +37,7 @@ const FilterButton = createClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
return dom.button({
|
return dom.button({
|
||||||
|
"aria-pressed": active === true,
|
||||||
className: classList.join(" "),
|
className: classList.join(" "),
|
||||||
onClick: this.onClick
|
onClick: this.onClick
|
||||||
}, label);
|
}, label);
|
||||||
|
|
|
@ -20,7 +20,8 @@ describe("FilterButton component:", () => {
|
||||||
it("displays as active when turned on", () => {
|
it("displays as active when turned on", () => {
|
||||||
const wrapper = render(FilterButton(props));
|
const wrapper = render(FilterButton(props));
|
||||||
expect(wrapper.html()).toBe(
|
expect(wrapper.html()).toBe(
|
||||||
"<button class=\"menu-filter-button error checked\">Error</button>"
|
"<button aria-pressed=\"true\" class=\"menu-filter-button error checked\">" +
|
||||||
|
"Error</button>"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -28,7 +29,7 @@ describe("FilterButton component:", () => {
|
||||||
const inactiveProps = Object.assign({}, props, { active: false });
|
const inactiveProps = Object.assign({}, props, { active: false });
|
||||||
const wrapper = render(FilterButton(inactiveProps));
|
const wrapper = render(FilterButton(inactiveProps));
|
||||||
expect(wrapper.html()).toBe(
|
expect(wrapper.html()).toBe(
|
||||||
"<button class=\"menu-filter-button error\">Error</button>"
|
"<button aria-pressed=\"false\" class=\"menu-filter-button error\">Error</button>"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1219,8 +1219,12 @@ StorageActors.createActor({
|
||||||
}, {
|
}, {
|
||||||
getCachesForHost: Task.async(function* (host) {
|
getCachesForHost: Task.async(function* (host) {
|
||||||
let uri = Services.io.newURI(host);
|
let uri = Services.io.newURI(host);
|
||||||
|
let attrs = this.storageActor
|
||||||
|
.document
|
||||||
|
.nodePrincipal
|
||||||
|
.originAttributes;
|
||||||
let principal =
|
let principal =
|
||||||
Services.scriptSecurityManager.getNoAppCodebasePrincipal(uri);
|
Services.scriptSecurityManager.createCodebasePrincipal(uri, attrs);
|
||||||
|
|
||||||
// The first argument tells if you want to get |content| cache or |chrome|
|
// The first argument tells if you want to get |content| cache or |chrome|
|
||||||
// cache.
|
// cache.
|
||||||
|
@ -1664,11 +1668,11 @@ StorageActors.createActor({
|
||||||
|
|
||||||
populateStoresForHost: Task.async(function* (host) {
|
populateStoresForHost: Task.async(function* (host) {
|
||||||
let storeMap = new Map();
|
let storeMap = new Map();
|
||||||
let {names} = yield this.getDBNamesForHost(host);
|
|
||||||
|
|
||||||
let win = this.storageActor.getWindowFromHost(host);
|
let win = this.storageActor.getWindowFromHost(host);
|
||||||
if (win) {
|
if (win) {
|
||||||
let principal = win.document.nodePrincipal;
|
let principal = win.document.nodePrincipal;
|
||||||
|
let {names} = yield this.getDBNamesForHost(host, principal);
|
||||||
|
|
||||||
for (let {name, storage} of names) {
|
for (let {name, storage} of names) {
|
||||||
let metadata = yield this.getDBMetaData(host, principal, name, storage);
|
let metadata = yield this.getDBMetaData(host, principal, name, storage);
|
||||||
|
@ -2025,8 +2029,8 @@ var indexedDBHelpers = {
|
||||||
/**
|
/**
|
||||||
* Fetches all the databases and their metadata for the given `host`.
|
* Fetches all the databases and their metadata for the given `host`.
|
||||||
*/
|
*/
|
||||||
getDBNamesForHost: Task.async(function* (host) {
|
getDBNamesForHost: Task.async(function* (host, principal) {
|
||||||
let sanitizedHost = this.getSanitizedHost(host);
|
let sanitizedHost = this.getSanitizedHost(host) + principal.originSuffix;
|
||||||
let profileDir = OS.Constants.Path.profileDir;
|
let profileDir = OS.Constants.Path.profileDir;
|
||||||
let files = [];
|
let files = [];
|
||||||
let names = [];
|
let names = [];
|
||||||
|
@ -2363,8 +2367,8 @@ var indexedDBHelpers = {
|
||||||
return indexedDBHelpers.splitNameAndStorage(name);
|
return indexedDBHelpers.splitNameAndStorage(name);
|
||||||
}
|
}
|
||||||
case "getDBNamesForHost": {
|
case "getDBNamesForHost": {
|
||||||
let [host] = args;
|
let [host, principal] = args;
|
||||||
return indexedDBHelpers.getDBNamesForHost(host);
|
return indexedDBHelpers.getDBNamesForHost(host, principal);
|
||||||
}
|
}
|
||||||
case "getValuesForHost": {
|
case "getValuesForHost": {
|
||||||
let [host, name, options, hostVsStores, principal] = args;
|
let [host, name, options, hostVsStores, principal] = args;
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/* exported Cr, CC, NetUtil, defer, errorCount, initTestDebuggerServer,
|
||||||
|
writeTestTempFile, socket_transport, local_transport, really_long
|
||||||
|
*/
|
||||||
|
|
||||||
var Cc = Components.classes;
|
var Cc = Components.classes;
|
||||||
var Ci = Components.interfaces;
|
var Ci = Components.interfaces;
|
||||||
var Cu = Components.utils;
|
var Cu = Components.utils;
|
||||||
|
@ -17,7 +21,6 @@ const defer = require("devtools/shared/defer");
|
||||||
const { Task } = require("devtools/shared/task");
|
const { Task } = require("devtools/shared/task");
|
||||||
|
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
|
||||||
|
|
||||||
// We do not want to log packets by default, because in some tests,
|
// We do not want to log packets by default, because in some tests,
|
||||||
// we can be sending large amounts of data. The test harness has
|
// we can be sending large amounts of data. The test harness has
|
||||||
|
@ -31,27 +34,21 @@ Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
|
||||||
const { DebuggerServer } = require("devtools/server/main");
|
const { DebuggerServer } = require("devtools/server/main");
|
||||||
const { DebuggerClient } = require("devtools/shared/client/main");
|
const { DebuggerClient } = require("devtools/shared/client/main");
|
||||||
|
|
||||||
function testExceptionHook(ex) {
|
// Convert an nsIScriptError 'flags' value into an appropriate string.
|
||||||
try {
|
function scriptErrorFlagsToKind(flags) {
|
||||||
do_report_unexpected_exception(ex);
|
let kind;
|
||||||
} catch (ex) {
|
if (flags & Ci.nsIScriptError.warningFlag) {
|
||||||
return {throw: ex};
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert an nsIScriptError 'aFlags' value into an appropriate string.
|
|
||||||
function scriptErrorFlagsToKind(aFlags) {
|
|
||||||
var kind;
|
|
||||||
if (aFlags & Ci.nsIScriptError.warningFlag)
|
|
||||||
kind = "warning";
|
kind = "warning";
|
||||||
if (aFlags & Ci.nsIScriptError.exceptionFlag)
|
}
|
||||||
|
if (flags & Ci.nsIScriptError.exceptionFlag) {
|
||||||
kind = "exception";
|
kind = "exception";
|
||||||
else
|
} else {
|
||||||
kind = "error";
|
kind = "error";
|
||||||
|
}
|
||||||
|
|
||||||
if (aFlags & Ci.nsIScriptError.strictFlag)
|
if (flags & Ci.nsIScriptError.strictFlag) {
|
||||||
kind = "strict " + kind;
|
kind = "strict " + kind;
|
||||||
|
}
|
||||||
|
|
||||||
return kind;
|
return kind;
|
||||||
}
|
}
|
||||||
|
@ -60,23 +57,24 @@ function scriptErrorFlagsToKind(aFlags) {
|
||||||
// into the ether.
|
// into the ether.
|
||||||
var errorCount = 0;
|
var errorCount = 0;
|
||||||
var listener = {
|
var listener = {
|
||||||
observe: function (aMessage) {
|
observe: function (message) {
|
||||||
errorCount++;
|
errorCount++;
|
||||||
|
let string = "";
|
||||||
try {
|
try {
|
||||||
// If we've been given an nsIScriptError, then we can print out
|
// If we've been given an nsIScriptError, then we can print out
|
||||||
// something nicely formatted, for tools like Emacs to pick up.
|
// something nicely formatted, for tools like Emacs to pick up.
|
||||||
var scriptError = aMessage.QueryInterface(Ci.nsIScriptError);
|
message.QueryInterface(Ci.nsIScriptError);
|
||||||
dump(aMessage.sourceName + ":" + aMessage.lineNumber + ": " +
|
dump(message.sourceName + ":" + message.lineNumber + ": " +
|
||||||
scriptErrorFlagsToKind(aMessage.flags) + ": " +
|
scriptErrorFlagsToKind(message.flags) + ": " +
|
||||||
aMessage.errorMessage + "\n");
|
message.errorMessage + "\n");
|
||||||
var string = aMessage.errorMessage;
|
string = message.errorMessage;
|
||||||
} catch (x) {
|
} catch (x) {
|
||||||
// Be a little paranoid with message, as the whole goal here is to lose
|
// Be a little paranoid with message, as the whole goal here is to lose
|
||||||
// no information.
|
// no information.
|
||||||
try {
|
try {
|
||||||
var string = "" + aMessage.message;
|
string = message.message;
|
||||||
} catch (x) {
|
} catch (e) {
|
||||||
var string = "<error converting error message to string>";
|
string = "<error converting error message to string>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +84,7 @@ var listener = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Throw in most cases, but ignore the "strict" messages
|
// Throw in most cases, but ignore the "strict" messages
|
||||||
if (!(aMessage.flags & Ci.nsIScriptError.strictFlag)) {
|
if (!(message.flags & Ci.nsIScriptError.strictFlag)) {
|
||||||
do_throw("head_dbg.js got console message: " + string + "\n");
|
do_throw("head_dbg.js got console message: " + string + "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,80 +94,6 @@ var consoleService = Cc["@mozilla.org/consoleservice;1"]
|
||||||
.getService(Ci.nsIConsoleService);
|
.getService(Ci.nsIConsoleService);
|
||||||
consoleService.registerListener(listener);
|
consoleService.registerListener(listener);
|
||||||
|
|
||||||
function check_except(func) {
|
|
||||||
try {
|
|
||||||
func();
|
|
||||||
} catch (e) {
|
|
||||||
do_check_true(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dump("Should have thrown an exception: " + func.toString());
|
|
||||||
do_check_true(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testGlobal(aName) {
|
|
||||||
let systemPrincipal = Cc["@mozilla.org/systemprincipal;1"]
|
|
||||||
.createInstance(Ci.nsIPrincipal);
|
|
||||||
|
|
||||||
let sandbox = Cu.Sandbox(systemPrincipal);
|
|
||||||
sandbox.__name = aName;
|
|
||||||
return sandbox;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addTestGlobal(aName)
|
|
||||||
{
|
|
||||||
let global = testGlobal(aName);
|
|
||||||
DebuggerServer.addTestGlobal(global);
|
|
||||||
return global;
|
|
||||||
}
|
|
||||||
|
|
||||||
// List the DebuggerClient |aClient|'s tabs, look for one whose title is
|
|
||||||
// |aTitle|, and apply |aCallback| to the packet's entry for that tab.
|
|
||||||
function getTestTab(aClient, aTitle, aCallback) {
|
|
||||||
aClient.listTabs(function (aResponse) {
|
|
||||||
for (let tab of aResponse.tabs) {
|
|
||||||
if (tab.title === aTitle) {
|
|
||||||
aCallback(tab);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
aCallback(null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach to |aClient|'s tab whose title is |aTitle|; pass |aCallback| the
|
|
||||||
// response packet and a TabClient instance referring to that tab.
|
|
||||||
function attachTestTab(aClient, aTitle, aCallback) {
|
|
||||||
getTestTab(aClient, aTitle, function (aTab) {
|
|
||||||
aClient.attachTab(aTab.actor, aCallback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach to |aClient|'s tab whose title is |aTitle|, and then attach to
|
|
||||||
// that tab's thread. Pass |aCallback| the thread attach response packet, a
|
|
||||||
// TabClient referring to the tab, and a ThreadClient referring to the
|
|
||||||
// thread.
|
|
||||||
function attachTestThread(aClient, aTitle, aCallback) {
|
|
||||||
attachTestTab(aClient, aTitle, function (aResponse, aTabClient) {
|
|
||||||
function onAttach(aResponse, aThreadClient) {
|
|
||||||
aCallback(aResponse, aTabClient, aThreadClient);
|
|
||||||
}
|
|
||||||
aTabClient.attachThread({ useSourceMaps: true }, onAttach);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach to |aClient|'s tab whose title is |aTitle|, attach to the tab's
|
|
||||||
// thread, and then resume it. Pass |aCallback| the thread's response to
|
|
||||||
// the 'resume' packet, a TabClient for the tab, and a ThreadClient for the
|
|
||||||
// thread.
|
|
||||||
function attachTestTabAndResume(aClient, aTitle, aCallback) {
|
|
||||||
attachTestThread(aClient, aTitle, function (aResponse, aTabClient, aThreadClient) {
|
|
||||||
aThreadClient.resume(function (aResponse) {
|
|
||||||
aCallback(aResponse, aTabClient, aThreadClient);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the testing debugger server.
|
* Initialize the testing debugger server.
|
||||||
*/
|
*/
|
||||||
|
@ -184,35 +108,6 @@ function initTestDebuggerServer() {
|
||||||
DebuggerServer.init();
|
DebuggerServer.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
function finishClient(aClient) {
|
|
||||||
aClient.close().then(function () {
|
|
||||||
do_test_finished();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes a relative file path and returns the absolute file url for it.
|
|
||||||
*/
|
|
||||||
function getFileUrl(aName, aAllowMissing = false) {
|
|
||||||
let file = do_get_file(aName, aAllowMissing);
|
|
||||||
return Services.io.newFileURI(file).spec;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the full path of the file with the specified name in a
|
|
||||||
* platform-independent and URL-like form.
|
|
||||||
*/
|
|
||||||
function getFilePath(aName, aAllowMissing = false) {
|
|
||||||
let file = do_get_file(aName, aAllowMissing);
|
|
||||||
let path = Services.io.newFileURI(file).spec;
|
|
||||||
let filePrePath = "file://";
|
|
||||||
if ("nsILocalFileWin" in Ci &&
|
|
||||||
file instanceof Ci.nsILocalFileWin) {
|
|
||||||
filePrePath += "/";
|
|
||||||
}
|
|
||||||
return path.slice(filePrePath.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper around do_get_file to prefix files with the name of current test to
|
* Wrapper around do_get_file to prefix files with the name of current test to
|
||||||
* avoid collisions when running in parallel.
|
* avoid collisions when running in parallel.
|
||||||
|
@ -224,16 +119,16 @@ function getTestTempFile(fileName, allowMissing) {
|
||||||
return do_get_file(fileName + "-" + thisTest, allowMissing);
|
return do_get_file(fileName + "-" + thisTest, allowMissing);
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeTestTempFile(aFileName, aContent) {
|
function writeTestTempFile(fileName, content) {
|
||||||
let file = getTestTempFile(aFileName, true);
|
let file = getTestTempFile(fileName, true);
|
||||||
let stream = Cc["@mozilla.org/network/file-output-stream;1"]
|
let stream = Cc["@mozilla.org/network/file-output-stream;1"]
|
||||||
.createInstance(Ci.nsIFileOutputStream);
|
.createInstance(Ci.nsIFileOutputStream);
|
||||||
stream.init(file, -1, -1, 0);
|
stream.init(file, -1, -1, 0);
|
||||||
try {
|
try {
|
||||||
do {
|
do {
|
||||||
let numWritten = stream.write(aContent, aContent.length);
|
let numWritten = stream.write(content, content.length);
|
||||||
aContent = aContent.slice(numWritten);
|
content = content.slice(numWritten);
|
||||||
} while (aContent.length > 0);
|
} while (content.length > 0);
|
||||||
} finally {
|
} finally {
|
||||||
stream.close();
|
stream.close();
|
||||||
}
|
}
|
||||||
|
@ -248,10 +143,10 @@ var socket_transport = Task.async(function* () {
|
||||||
authenticator.allowConnection = () => {
|
authenticator.allowConnection = () => {
|
||||||
return DebuggerServer.AuthenticationResult.ALLOW;
|
return DebuggerServer.AuthenticationResult.ALLOW;
|
||||||
};
|
};
|
||||||
let listener = DebuggerServer.createListener();
|
let debuggerListener = DebuggerServer.createListener();
|
||||||
listener.portOrPath = -1;
|
debuggerListener.portOrPath = -1;
|
||||||
listener.authenticator = authenticator;
|
debuggerListener.authenticator = authenticator;
|
||||||
yield listener.open();
|
yield debuggerListener.open();
|
||||||
}
|
}
|
||||||
let port = DebuggerServer._listeners[0].port;
|
let port = DebuggerServer._listeners[0].port;
|
||||||
do_print("Debugger server port is " + port);
|
do_print("Debugger server port is " + port);
|
||||||
|
|
|
@ -73,8 +73,8 @@ function json_reply(client, response) {
|
||||||
// Send bulk data to server
|
// Send bulk data to server
|
||||||
let copyDeferred = defer();
|
let copyDeferred = defer();
|
||||||
request.on("bulk-send-ready", ({writer, done}) => {
|
request.on("bulk-send-ready", ({writer, done}) => {
|
||||||
let input = Cc["@mozilla.org/io/string-input-stream;1"].
|
let input = Cc["@mozilla.org/io/string-input-stream;1"]
|
||||||
createInstance(Ci.nsIStringInputStream);
|
.createInstance(Ci.nsIStringInputStream);
|
||||||
input.setData(reallyLong, reallyLong.length);
|
input.setData(reallyLong, reallyLong.length);
|
||||||
try {
|
try {
|
||||||
writer.copyFrom(input, () => {
|
writer.copyFrom(input, () => {
|
||||||
|
|
|
@ -150,6 +150,18 @@ var test_bulk_request_cs = Task.async(function* (transportFactory, actorType, re
|
||||||
client.listTabs(clientDeferred.resolve);
|
client.listTabs(clientDeferred.resolve);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function bulkSendReadyCallback({copyFrom}) {
|
||||||
|
NetUtil.asyncFetch({
|
||||||
|
uri: NetUtil.newURI(getTestTempFile("bulk-input")),
|
||||||
|
loadUsingSystemPrincipal: true
|
||||||
|
}, input => {
|
||||||
|
copyFrom(input).then(() => {
|
||||||
|
input.close();
|
||||||
|
bulkCopyDeferred.resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
clientDeferred.promise.then(response => {
|
clientDeferred.promise.then(response => {
|
||||||
let request = client.startBulkRequest({
|
let request = client.startBulkRequest({
|
||||||
actor: response.testBulk,
|
actor: response.testBulk,
|
||||||
|
@ -158,17 +170,7 @@ var test_bulk_request_cs = Task.async(function* (transportFactory, actorType, re
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send bulk data to server
|
// Send bulk data to server
|
||||||
request.on("bulk-send-ready", ({copyFrom}) => {
|
request.on("bulk-send-ready", bulkSendReadyCallback);
|
||||||
NetUtil.asyncFetch({
|
|
||||||
uri: NetUtil.newURI(getTestTempFile("bulk-input")),
|
|
||||||
loadUsingSystemPrincipal: true
|
|
||||||
}, input => {
|
|
||||||
copyFrom(input).then(() => {
|
|
||||||
input.close();
|
|
||||||
bulkCopyDeferred.resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set up reply handling for this type
|
// Set up reply handling for this type
|
||||||
replyHandlers[replyType](request).then(() => {
|
replyHandlers[replyType](request).then(() => {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
var gPort;
|
var gPort;
|
||||||
var gExtraListener;
|
var gExtraListener;
|
||||||
|
|
||||||
function run_test()
|
function run_test() {
|
||||||
{
|
|
||||||
do_print("Starting test at " + new Date().toTimeString());
|
do_print("Starting test at " + new Date().toTimeString());
|
||||||
initTestDebuggerServer();
|
initTestDebuggerServer();
|
||||||
|
|
||||||
|
@ -16,8 +16,7 @@ function run_test()
|
||||||
run_next_test();
|
run_next_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
function* test_socket_conn()
|
function* test_socket_conn() {
|
||||||
{
|
|
||||||
do_check_eq(DebuggerServer.listeningSockets, 0);
|
do_check_eq(DebuggerServer.listeningSockets, 0);
|
||||||
let AuthenticatorType = DebuggerServer.Authenticators.get("PROMPT");
|
let AuthenticatorType = DebuggerServer.Authenticators.get("PROMPT");
|
||||||
let authenticator = new AuthenticatorType.Server();
|
let authenticator = new AuthenticatorType.Server();
|
||||||
|
@ -53,9 +52,9 @@ function* test_socket_conn()
|
||||||
|
|
||||||
let closedDeferred = defer();
|
let closedDeferred = defer();
|
||||||
transport.hooks = {
|
transport.hooks = {
|
||||||
onPacket: function (aPacket) {
|
onPacket: function (packet) {
|
||||||
this.onPacket = function (aPacket) {
|
this.onPacket = function ({unicode}) {
|
||||||
do_check_eq(aPacket.unicode, unicodeString);
|
do_check_eq(unicode, unicodeString);
|
||||||
transport.close();
|
transport.close();
|
||||||
};
|
};
|
||||||
// Verify that things work correctly when bigger than the output
|
// Verify that things work correctly when bigger than the output
|
||||||
|
@ -64,9 +63,9 @@ function* test_socket_conn()
|
||||||
type: "echo",
|
type: "echo",
|
||||||
reallylong: really_long(),
|
reallylong: really_long(),
|
||||||
unicode: unicodeString});
|
unicode: unicodeString});
|
||||||
do_check_eq(aPacket.from, "root");
|
do_check_eq(packet.from, "root");
|
||||||
},
|
},
|
||||||
onClosed: function (aStatus) {
|
onClosed: function (status) {
|
||||||
closedDeferred.resolve();
|
closedDeferred.resolve();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -74,8 +73,7 @@ function* test_socket_conn()
|
||||||
return closedDeferred.promise;
|
return closedDeferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function* test_socket_shutdown()
|
function* test_socket_shutdown() {
|
||||||
{
|
|
||||||
do_check_eq(DebuggerServer.listeningSockets, 2);
|
do_check_eq(DebuggerServer.listeningSockets, 2);
|
||||||
gExtraListener.close();
|
gExtraListener.close();
|
||||||
do_check_eq(DebuggerServer.listeningSockets, 1);
|
do_check_eq(DebuggerServer.listeningSockets, 1);
|
||||||
|
@ -87,7 +85,7 @@ function* test_socket_shutdown()
|
||||||
|
|
||||||
do_print("Connecting to a server socket at " + new Date().toTimeString());
|
do_print("Connecting to a server socket at " + new Date().toTimeString());
|
||||||
try {
|
try {
|
||||||
let transport = yield DebuggerClient.socketConnect({
|
yield DebuggerClient.socketConnect({
|
||||||
host: "127.0.0.1",
|
host: "127.0.0.1",
|
||||||
port: gPort
|
port: gPort
|
||||||
});
|
});
|
||||||
|
@ -98,24 +96,22 @@ function* test_socket_shutdown()
|
||||||
// machines it may just time out.
|
// machines it may just time out.
|
||||||
do_check_true(true);
|
do_check_true(true);
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shouldn't reach this, should never connect.
|
// Shouldn't reach this, should never connect.
|
||||||
do_check_true(false);
|
do_check_true(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_pipe_conn()
|
function test_pipe_conn() {
|
||||||
{
|
|
||||||
let transport = DebuggerServer.connectPipe();
|
let transport = DebuggerServer.connectPipe();
|
||||||
transport.hooks = {
|
transport.hooks = {
|
||||||
onPacket: function (aPacket) {
|
onPacket: function (packet) {
|
||||||
do_check_eq(aPacket.from, "root");
|
do_check_eq(packet.from, "root");
|
||||||
transport.close();
|
transport.close();
|
||||||
},
|
},
|
||||||
onClosed: function (aStatus) {
|
onClosed: function (status) {
|
||||||
run_next_test();
|
run_next_test();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Bug 755412 - checks if the server drops the connection on an improperly
|
* Bug 755412 - checks if the server drops the connection on an improperly
|
||||||
* framed packet, i.e. when the length header is invalid.
|
* framed packet, i.e. when the length header is invalid.
|
||||||
*/
|
*/
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const { RawPacket } = require("devtools/shared/transport/packets");
|
const { RawPacket } = require("devtools/shared/transport/packets");
|
||||||
|
|
||||||
|
@ -61,8 +62,8 @@ var test_helper = Task.async(function* (payload) {
|
||||||
});
|
});
|
||||||
let closedDeferred = defer();
|
let closedDeferred = defer();
|
||||||
transport.hooks = {
|
transport.hooks = {
|
||||||
onPacket: function (aPacket) {
|
onPacket: function (packet) {
|
||||||
this.onPacket = function (aPacket) {
|
this.onPacket = function () {
|
||||||
do_throw(new Error("This connection should be dropped."));
|
do_throw(new Error("This connection should be dropped."));
|
||||||
transport.close();
|
transport.close();
|
||||||
};
|
};
|
||||||
|
@ -71,7 +72,7 @@ var test_helper = Task.async(function* (payload) {
|
||||||
transport._outgoing.push(new RawPacket(transport, payload));
|
transport._outgoing.push(new RawPacket(transport, payload));
|
||||||
transport._flushOutgoing();
|
transport._flushOutgoing();
|
||||||
},
|
},
|
||||||
onClosed: function (aStatus) {
|
onClosed: function (status) {
|
||||||
do_check_true(true);
|
do_check_true(true);
|
||||||
closedDeferred.resolve();
|
closedDeferred.resolve();
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const StreamUtils = require("devtools/shared/transport/stream-utils");
|
const StreamUtils = require("devtools/shared/transport/stream-utils");
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ function run_test() {
|
||||||
/** * Tests ***/
|
/** * Tests ***/
|
||||||
|
|
||||||
var test_bulk_send_error = Task.async(function* (transportFactory) {
|
var test_bulk_send_error = Task.async(function* (transportFactory) {
|
||||||
let deferred = defer();
|
|
||||||
let transport = yield transportFactory();
|
let transport = yield transportFactory();
|
||||||
|
|
||||||
let client = new DebuggerClient(transport);
|
let client = new DebuggerClient(transport);
|
||||||
|
@ -33,6 +32,5 @@ var test_bulk_send_error = Task.async(function* (transportFactory) {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
do_check_true(true);
|
do_check_true(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const { JSONPacket, BulkPacket } =
|
const { JSONPacket, BulkPacket } =
|
||||||
require("devtools/shared/transport/packets");
|
require("devtools/shared/transport/packets");
|
||||||
|
|
|
@ -74,9 +74,9 @@ var test_bulk_transfer_transport = Task.async(function* (transportFactory) {
|
||||||
|
|
||||||
// Client
|
// Client
|
||||||
transport.hooks = {
|
transport.hooks = {
|
||||||
onPacket: function (aPacket) {
|
onPacket: function (packet) {
|
||||||
// We've received the initial start up packet
|
// We've received the initial start up packet
|
||||||
do_check_eq(aPacket.from, "root");
|
do_check_eq(packet.from, "root");
|
||||||
|
|
||||||
// Server
|
// Server
|
||||||
do_check_eq(Object.keys(DebuggerServer._connections).length, 1);
|
do_check_eq(Object.keys(DebuggerServer._connections).length, 1);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const { RootActor } = require("devtools/server/actors/root");
|
const { RootActor } = require("devtools/server/actors/root");
|
||||||
const { DebuggerServer } = require("devtools/server/main");
|
const { DebuggerServer } = require("devtools/server/main");
|
||||||
|
@ -7,8 +8,8 @@ const { DebuggerServer } = require("devtools/server/main");
|
||||||
/**
|
/**
|
||||||
* Root actor that doesn't have the bulk trait.
|
* Root actor that doesn't have the bulk trait.
|
||||||
*/
|
*/
|
||||||
function createRootActor(aConnection) {
|
function createRootActor(connection) {
|
||||||
let root = new RootActor(aConnection, {
|
let root = new RootActor(connection, {
|
||||||
globalActorFactories: DebuggerServer.globalActorFactories
|
globalActorFactories: DebuggerServer.globalActorFactories
|
||||||
});
|
});
|
||||||
root.applicationType = "xpcshell-tests";
|
root.applicationType = "xpcshell-tests";
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const { ActorPool, appendExtraActors, createExtraActors } =
|
const { ActorPool, appendExtraActors, createExtraActors } =
|
||||||
require("devtools/server/actors/common");
|
require("devtools/server/actors/common");
|
||||||
|
@ -9,8 +10,8 @@ const { DebuggerServer } = require("devtools/server/main");
|
||||||
const promise = require("promise");
|
const promise = require("promise");
|
||||||
|
|
||||||
var gTestGlobals = [];
|
var gTestGlobals = [];
|
||||||
DebuggerServer.addTestGlobal = function (aGlobal) {
|
DebuggerServer.addTestGlobal = function (global) {
|
||||||
gTestGlobals.push(aGlobal);
|
gTestGlobals.push(global);
|
||||||
};
|
};
|
||||||
|
|
||||||
// A mock tab list, for use by tests. This simply presents each global in
|
// A mock tab list, for use by tests. This simply presents each global in
|
||||||
|
@ -20,18 +21,18 @@ DebuggerServer.addTestGlobal = function (aGlobal) {
|
||||||
// As implemented now, we consult gTestGlobals when we're constructed, not
|
// As implemented now, we consult gTestGlobals when we're constructed, not
|
||||||
// when we're iterated over, so tests have to add their globals before the
|
// when we're iterated over, so tests have to add their globals before the
|
||||||
// root actor is created.
|
// root actor is created.
|
||||||
function TestTabList(aConnection) {
|
function TestTabList(connection) {
|
||||||
this.conn = aConnection;
|
this.conn = connection;
|
||||||
|
|
||||||
// An array of actors for each global added with
|
// An array of actors for each global added with
|
||||||
// DebuggerServer.addTestGlobal.
|
// DebuggerServer.addTestGlobal.
|
||||||
this._tabActors = [];
|
this._tabActors = [];
|
||||||
|
|
||||||
// A pool mapping those actors' names to the actors.
|
// A pool mapping those actors' names to the actors.
|
||||||
this._tabActorPool = new ActorPool(aConnection);
|
this._tabActorPool = new ActorPool(connection);
|
||||||
|
|
||||||
for (let global of gTestGlobals) {
|
for (let global of gTestGlobals) {
|
||||||
let actor = new TestTabActor(aConnection, global);
|
let actor = new TestTabActor(connection, global);
|
||||||
actor.selected = false;
|
actor.selected = false;
|
||||||
this._tabActors.push(actor);
|
this._tabActors.push(actor);
|
||||||
this._tabActorPool.addActor(actor);
|
this._tabActorPool.addActor(actor);
|
||||||
|
@ -40,7 +41,7 @@ function TestTabList(aConnection) {
|
||||||
this._tabActors[0].selected = true;
|
this._tabActors[0].selected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
aConnection.addActorPool(this._tabActorPool);
|
connection.addActorPool(this._tabActorPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestTabList.prototype = {
|
TestTabList.prototype = {
|
||||||
|
@ -50,18 +51,18 @@ TestTabList.prototype = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function createRootActor(aConnection) {
|
function createRootActor(connection) {
|
||||||
let root = new RootActor(aConnection, {
|
let root = new RootActor(connection, {
|
||||||
tabList: new TestTabList(aConnection),
|
tabList: new TestTabList(connection),
|
||||||
globalActorFactories: DebuggerServer.globalActorFactories
|
globalActorFactories: DebuggerServer.globalActorFactories
|
||||||
});
|
});
|
||||||
root.applicationType = "xpcshell-tests";
|
root.applicationType = "xpcshell-tests";
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
function TestTabActor(aConnection, aGlobal) {
|
function TestTabActor(connection, global) {
|
||||||
this.conn = aConnection;
|
this.conn = connection;
|
||||||
this._global = aGlobal;
|
this._global = global;
|
||||||
this._threadActor = new ThreadActor(this, this._global);
|
this._threadActor = new ThreadActor(this, this._global);
|
||||||
this.conn.addActor(this._threadActor);
|
this.conn.addActor(this._threadActor);
|
||||||
this._attached = false;
|
this._attached = false;
|
||||||
|
@ -96,7 +97,7 @@ TestTabActor.prototype = {
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
|
|
||||||
onAttach: function (aRequest) {
|
onAttach: function (request) {
|
||||||
this._attached = true;
|
this._attached = true;
|
||||||
|
|
||||||
let response = { type: "tabAttached", threadActor: this._threadActor.actorID };
|
let response = { type: "tabAttached", threadActor: this._threadActor.actorID };
|
||||||
|
@ -105,9 +106,9 @@ TestTabActor.prototype = {
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
|
|
||||||
onDetach: function (aRequest) {
|
onDetach: function (request) {
|
||||||
if (!this._attached) {
|
if (!this._attached) {
|
||||||
return { "error":"wrongState" };
|
return { "error": "wrongState" };
|
||||||
}
|
}
|
||||||
return { type: "detached" };
|
return { type: "detached" };
|
||||||
},
|
},
|
||||||
|
|
|
@ -7572,7 +7572,13 @@ nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
|
||||||
|
|
||||||
nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel);
|
nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel);
|
||||||
if (reporter) {
|
if (reporter) {
|
||||||
reporter->FlushConsoleReports(GetDocument());
|
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||||
|
aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
|
||||||
|
if (loadGroup) {
|
||||||
|
reporter->FlushConsoleReports(loadGroup);
|
||||||
|
} else {
|
||||||
|
reporter->FlushConsoleReports(GetDocument());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> url;
|
nsCOMPtr<nsIURI> url;
|
||||||
|
|
|
@ -464,7 +464,9 @@ promise_test(function(t) {
|
||||||
return watcher.wait_for('transitionend');
|
return watcher.wait_for('transitionend');
|
||||||
}).then(function(evt) {
|
}).then(function(evt) {
|
||||||
transition.cancel();
|
transition.cancel();
|
||||||
return watcher.wait_for('transitioncancel');
|
|
||||||
|
// Then wait a couple of frames and check that no event was dispatched
|
||||||
|
return waitForAnimationFrames(2);
|
||||||
});
|
});
|
||||||
}, 'Cancel the transition after clearing the target effect');
|
}, 'Cancel the transition after clearing the target effect');
|
||||||
|
|
||||||
|
|
|
@ -933,18 +933,28 @@ TimeoutManager::Timeouts::ResetTimersForThrottleReduction(int32_t aPreviousThrot
|
||||||
// current timeout in the list.
|
// current timeout in the list.
|
||||||
Timeout* nextTimeout = timeout->getNext();
|
Timeout* nextTimeout = timeout->getNext();
|
||||||
|
|
||||||
// It is safe to remove and re-insert because When() is now
|
// Since we are only reducing intervals in this method we can
|
||||||
// strictly smaller than it used to be, so we know we'll insert
|
// make an optimization here. If the reduction does not cause us
|
||||||
// |timeout| before nextTimeout.
|
// to fall before our previous timeout then we do not have to
|
||||||
NS_ASSERTION(!nextTimeout ||
|
// remove and re-insert the current timeout. This is important
|
||||||
timeout->When() < nextTimeout->When(), "How did that happen?");
|
// because re-insertion makes this algorithm O(n^2). Since we
|
||||||
timeout->remove();
|
// will typically be shifting a lot of timers at once this
|
||||||
// Insert() will addref |timeout| and reset mFiringDepth. Make sure to
|
// optimization saves us a lot of work.
|
||||||
// undo that after calling it.
|
Timeout* prevTimeout = timeout->getPrevious();
|
||||||
uint32_t firingDepth = timeout->mFiringDepth;
|
if (prevTimeout && prevTimeout->When() > timeout->When()) {
|
||||||
Insert(timeout, aSortBy);
|
// It is safe to remove and re-insert because When() is now
|
||||||
timeout->mFiringDepth = firingDepth;
|
// strictly smaller than it used to be, so we know we'll insert
|
||||||
timeout->Release();
|
// |timeout| before nextTimeout.
|
||||||
|
NS_ASSERTION(!nextTimeout ||
|
||||||
|
timeout->When() < nextTimeout->When(), "How did that happen?");
|
||||||
|
timeout->remove();
|
||||||
|
// Insert() will addref |timeout| and reset mFiringDepth. Make sure to
|
||||||
|
// undo that after calling it.
|
||||||
|
uint32_t firingDepth = timeout->mFiringDepth;
|
||||||
|
Insert(timeout, aSortBy);
|
||||||
|
timeout->mFiringDepth = firingDepth;
|
||||||
|
timeout->Release();
|
||||||
|
}
|
||||||
|
|
||||||
nsresult rv = timeout->InitTimer(aQueue, delay.ToMilliseconds());
|
nsresult rv = timeout->InitTimer(aQueue, delay.ToMilliseconds());
|
||||||
|
|
||||||
|
|
|
@ -1797,8 +1797,7 @@ nsContentUtils::ParseLegacyFontSize(const nsAString& aValue)
|
||||||
bool
|
bool
|
||||||
nsContentUtils::IsControlledByServiceWorker(nsIDocument* aDocument)
|
nsContentUtils::IsControlledByServiceWorker(nsIDocument* aDocument)
|
||||||
{
|
{
|
||||||
if (aDocument &&
|
if (nsContentUtils::IsInPrivateBrowsing(aDocument)) {
|
||||||
aDocument->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2084,11 +2083,8 @@ nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAString& aPerm)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSCompartment* c = js::GetContextCompartment(aCx);
|
|
||||||
nsIPrincipal* p = nsJSPrincipals::get(JS_GetCompartmentPrincipals(c));
|
|
||||||
|
|
||||||
// Otherwise, only allow if caller is an addon with the permission.
|
// Otherwise, only allow if caller is an addon with the permission.
|
||||||
return BasePrincipal::Cast(p)->AddonHasPermission(aPerm);
|
return BasePrincipal::Cast(SubjectPrincipal(aCx))->AddonHasPermission(aPerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
|
@ -2174,16 +2170,8 @@ nsContentUtils::IsCallerContentXBL()
|
||||||
bool
|
bool
|
||||||
nsContentUtils::IsSystemCaller(JSContext* aCx)
|
nsContentUtils::IsSystemCaller(JSContext* aCx)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
// Note that SubjectPrincipal() assumes we are in a compartment here.
|
||||||
|
return SubjectPrincipal(aCx) == sSystemPrincipal;
|
||||||
// This is similar to what SubjectPrincipal() does, except we do in fact
|
|
||||||
// assume that we're in a compartment here; anyone who calls this function in
|
|
||||||
// situations where that's not the case is doing it wrong.
|
|
||||||
JSCompartment *compartment = js::GetContextCompartment(aCx);
|
|
||||||
MOZ_ASSERT(compartment);
|
|
||||||
|
|
||||||
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
|
|
||||||
return nsJSPrincipals::get(principals) == sSystemPrincipal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -2777,6 +2765,22 @@ nsContentUtils::GenerateStateKey(nsIContent* aContent,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
nsIPrincipal*
|
||||||
|
nsContentUtils::SubjectPrincipal(JSContext* aCx)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
// As opposed to SubjectPrincipal(), we do in fact assume that
|
||||||
|
// we're in a compartment here; anyone who calls this function
|
||||||
|
// in situations where that's not the case is doing it wrong.
|
||||||
|
JSCompartment* compartment = js::GetContextCompartment(aCx);
|
||||||
|
MOZ_ASSERT(compartment);
|
||||||
|
|
||||||
|
JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
|
||||||
|
return nsJSPrincipals::get(principals);
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
nsIPrincipal*
|
nsIPrincipal*
|
||||||
nsContentUtils::SubjectPrincipal()
|
nsContentUtils::SubjectPrincipal()
|
||||||
|
@ -2803,7 +2807,7 @@ nsContentUtils::SubjectPrincipal()
|
||||||
// The natural thing to return is a null principal. Ideally, we'd return a
|
// The natural thing to return is a null principal. Ideally, we'd return a
|
||||||
// different null principal each time, to avoid any unexpected interactions
|
// different null principal each time, to avoid any unexpected interactions
|
||||||
// when the principal accidentally gets inherited somewhere. But
|
// when the principal accidentally gets inherited somewhere. But
|
||||||
// GetSubjectPrincipal doesn't return strong references, so there's no way to
|
// SubjectPrincipal doesn't return strong references, so there's no way to
|
||||||
// sanely manage the lifetime of multiple null principals.
|
// sanely manage the lifetime of multiple null principals.
|
||||||
//
|
//
|
||||||
// So we use a singleton null principal. To avoid it being accidentally
|
// So we use a singleton null principal. To avoid it being accidentally
|
||||||
|
@ -2814,8 +2818,7 @@ nsContentUtils::SubjectPrincipal()
|
||||||
return sNullSubjectPrincipal;
|
return sNullSubjectPrincipal;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
|
return SubjectPrincipal(cx);
|
||||||
return nsJSPrincipals::get(principals);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -3202,6 +3205,40 @@ nsContentUtils::GetOriginAttributes(nsILoadGroup* aLoadGroup)
|
||||||
return attrs;
|
return attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
bool
|
||||||
|
nsContentUtils::IsInPrivateBrowsing(nsIDocument* aDoc)
|
||||||
|
{
|
||||||
|
if (!aDoc) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsILoadGroup> loadGroup = aDoc->GetDocumentLoadGroup();
|
||||||
|
if (loadGroup) {
|
||||||
|
return IsInPrivateBrowsing(loadGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIChannel> channel = aDoc->GetChannel();
|
||||||
|
return channel && NS_UsePrivateBrowsing(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
bool
|
||||||
|
nsContentUtils::IsInPrivateBrowsing(nsILoadGroup* aLoadGroup)
|
||||||
|
{
|
||||||
|
if (!aLoadGroup) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool isPrivate = false;
|
||||||
|
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
||||||
|
aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
||||||
|
if (callbacks) {
|
||||||
|
nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
|
||||||
|
isPrivate = loadContext && loadContext->UsePrivateBrowsing();
|
||||||
|
}
|
||||||
|
return isPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsContentUtils::DocumentInactiveForImageLoads(nsIDocument* aDocument)
|
nsContentUtils::DocumentInactiveForImageLoads(nsIDocument* aDocument)
|
||||||
{
|
{
|
||||||
|
@ -3221,26 +3258,9 @@ nsContentUtils::GetImgLoaderForDocument(nsIDocument* aDoc)
|
||||||
if (!aDoc) {
|
if (!aDoc) {
|
||||||
return imgLoader::NormalLoader();
|
return imgLoader::NormalLoader();
|
||||||
}
|
}
|
||||||
|
bool isPrivate = IsInPrivateBrowsing(aDoc);
|
||||||
nsCOMPtr<nsILoadGroup> loadGroup = aDoc->GetDocumentLoadGroup();
|
return isPrivate ? imgLoader::PrivateBrowsingLoader()
|
||||||
if (loadGroup) {
|
: imgLoader::NormalLoader();
|
||||||
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
|
||||||
loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
|
||||||
if (callbacks) {
|
|
||||||
nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
|
|
||||||
if (loadContext && loadContext->UsePrivateBrowsing()) {
|
|
||||||
return imgLoader::PrivateBrowsingLoader();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return imgLoader::NormalLoader();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIChannel> channel = aDoc->GetChannel();
|
|
||||||
if (channel && NS_UsePrivateBrowsing(channel)) {
|
|
||||||
return imgLoader::PrivateBrowsingLoader();
|
|
||||||
}
|
|
||||||
|
|
||||||
return imgLoader::NormalLoader();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -3672,6 +3692,22 @@ nsContentUtils::ReportToConsoleNonLocalized(const nsAString& aErrorText,
|
||||||
innerWindowID = aDocument->InnerWindowID();
|
innerWindowID = aDocument->InnerWindowID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory,
|
||||||
|
innerWindowID, aURI, aSourceLine,
|
||||||
|
aLineNumber, aColumnNumber, aLocationMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ nsresult
|
||||||
|
nsContentUtils::ReportToConsoleByWindowID(const nsAString& aErrorText,
|
||||||
|
uint32_t aErrorFlags,
|
||||||
|
const nsACString& aCategory,
|
||||||
|
uint64_t aInnerWindowID,
|
||||||
|
nsIURI* aURI,
|
||||||
|
const nsAFlatString& aSourceLine,
|
||||||
|
uint32_t aLineNumber,
|
||||||
|
uint32_t aColumnNumber,
|
||||||
|
MissingErrorLocationMode aLocationMode)
|
||||||
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
if (!sConsoleService) { // only need to bother null-checking here
|
if (!sConsoleService) { // only need to bother null-checking here
|
||||||
rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID, &sConsoleService);
|
rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID, &sConsoleService);
|
||||||
|
@ -3698,7 +3734,7 @@ nsContentUtils::ReportToConsoleNonLocalized(const nsAString& aErrorText,
|
||||||
aSourceLine,
|
aSourceLine,
|
||||||
aLineNumber, aColumnNumber,
|
aLineNumber, aColumnNumber,
|
||||||
aErrorFlags, aCategory,
|
aErrorFlags, aCategory,
|
||||||
innerWindowID);
|
aInnerWindowID);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
return sConsoleService->LogMessage(errorObject);
|
return sConsoleService->LogMessage(errorObject);
|
||||||
|
@ -7337,8 +7373,18 @@ nsContentUtils::GetInnerWindowID(nsIRequest* aRequest)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return GetInnerWindowID(loadGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
nsContentUtils::GetInnerWindowID(nsILoadGroup* aLoadGroup)
|
||||||
|
{
|
||||||
|
if (!aLoadGroup) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
||||||
rv = loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
nsresult rv = aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
||||||
if (NS_FAILED(rv) || !callbacks) {
|
if (NS_FAILED(rv) || !callbacks) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -8621,7 +8667,7 @@ nsContentUtils::InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we are in private browsing, and record that fact
|
// Check if we are in private browsing, and record that fact
|
||||||
if (document->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId) {
|
if (IsInPrivateBrowsing(document)) {
|
||||||
access = StorageAccess::ePrivateBrowsing;
|
access = StorageAccess::ePrivateBrowsing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -545,6 +545,10 @@ public:
|
||||||
return sSecurityManager;
|
return sSecurityManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the subject principal from the JSContext. May only be called
|
||||||
|
// from the main thread and assumes an existing compartment.
|
||||||
|
static nsIPrincipal* SubjectPrincipal(JSContext* aCx);
|
||||||
|
|
||||||
// Returns the subject principal. Guaranteed to return non-null. May only
|
// Returns the subject principal. Guaranteed to return non-null. May only
|
||||||
// be called when nsContentUtils is initialized.
|
// be called when nsContentUtils is initialized.
|
||||||
static nsIPrincipal* SubjectPrincipal();
|
static nsIPrincipal* SubjectPrincipal();
|
||||||
|
@ -817,6 +821,16 @@ public:
|
||||||
static mozilla::OriginAttributes
|
static mozilla::OriginAttributes
|
||||||
GetOriginAttributes(nsILoadGroup* aLoadGroup);
|
GetOriginAttributes(nsILoadGroup* aLoadGroup);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this document is in a Private Browsing window.
|
||||||
|
*/
|
||||||
|
static bool IsInPrivateBrowsing(nsIDocument* aDoc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this loadGroup uses Private Browsing.
|
||||||
|
*/
|
||||||
|
static bool IsInPrivateBrowsing(nsILoadGroup* aLoadGroup);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If aNode is not an element, return true exactly when aContent's binding
|
* If aNode is not an element, return true exactly when aContent's binding
|
||||||
* parent is null.
|
* parent is null.
|
||||||
|
@ -884,6 +898,37 @@ public:
|
||||||
MissingErrorLocationMode aLocationMode
|
MissingErrorLocationMode aLocationMode
|
||||||
= eUSE_CALLING_LOCATION);
|
= eUSE_CALLING_LOCATION);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report a non-localized error message to the error console base on the
|
||||||
|
* innerWindowID.
|
||||||
|
* @param aErrorText the error message
|
||||||
|
* @param aErrorFlags See nsIScriptError.
|
||||||
|
* @param aCategory Name of module reporting error.
|
||||||
|
* @param [aInnerWindowID] Inner window ID for document which triggered the
|
||||||
|
* message.
|
||||||
|
* @param [aURI=nullptr] (Optional) URI of resource containing error.
|
||||||
|
* @param [aSourceLine=EmptyString()] (Optional) The text of the line that
|
||||||
|
contains the error (may be empty).
|
||||||
|
* @param [aLineNumber=0] (Optional) Line number within resource
|
||||||
|
containing error.
|
||||||
|
* @param [aColumnNumber=0] (Optional) Column number within resource
|
||||||
|
containing error.
|
||||||
|
If aURI is null, then aDocument->GetDocumentURI() is used.
|
||||||
|
* @param [aLocationMode] (Optional) Specifies the behavior if
|
||||||
|
error location information is omitted.
|
||||||
|
*/
|
||||||
|
static nsresult ReportToConsoleByWindowID(const nsAString& aErrorText,
|
||||||
|
uint32_t aErrorFlags,
|
||||||
|
const nsACString& aCategory,
|
||||||
|
uint64_t aInnerWindowID,
|
||||||
|
nsIURI* aURI = nullptr,
|
||||||
|
const nsAFlatString& aSourceLine
|
||||||
|
= EmptyString(),
|
||||||
|
uint32_t aLineNumber = 0,
|
||||||
|
uint32_t aColumnNumber = 0,
|
||||||
|
MissingErrorLocationMode aLocationMode
|
||||||
|
= eUSE_CALLING_LOCATION);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report a localized error message to the error console.
|
* Report a localized error message to the error console.
|
||||||
* @param aErrorFlags See nsIScriptError.
|
* @param aErrorFlags See nsIScriptError.
|
||||||
|
@ -2447,10 +2492,15 @@ public:
|
||||||
static bool IsForbiddenResponseHeader(const nsACString& aHeader);
|
static bool IsForbiddenResponseHeader(const nsACString& aHeader);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the inner window ID for the window associated with a request,
|
* Returns the inner window ID for the window associated with a request.
|
||||||
*/
|
*/
|
||||||
static uint64_t GetInnerWindowID(nsIRequest* aRequest);
|
static uint64_t GetInnerWindowID(nsIRequest* aRequest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the inner window ID for the window associated with a load group.
|
||||||
|
*/
|
||||||
|
static uint64_t GetInnerWindowID(nsILoadGroup* aLoadGroup);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the hostname for aURI is an IPv6 it encloses it in brackets,
|
* If the hostname for aURI is an IPv6 it encloses it in brackets,
|
||||||
* otherwise it just outputs the hostname in aHost.
|
* otherwise it just outputs the hostname in aHost.
|
||||||
|
|
|
@ -8579,14 +8579,18 @@ nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_WEBSPEECH
|
|
||||||
if (win) {
|
if (win) {
|
||||||
auto* globalWindow = nsGlobalWindow::Cast(win);
|
auto* globalWindow = nsGlobalWindow::Cast(win);
|
||||||
|
#ifdef MOZ_WEBSPEECH
|
||||||
if (globalWindow->HasActiveSpeechSynthesis()) {
|
if (globalWindow->HasActiveSpeechSynthesis()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
if (globalWindow->HasUsedVR()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13239,6 +13239,14 @@ nsGlobalWindow::NotifyVREventListenerAdded()
|
||||||
EnableVRUpdates();
|
EnableVRUpdates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsGlobalWindow::HasUsedVR() const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsInnerWindow());
|
||||||
|
|
||||||
|
return mHasVREvents;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsGlobalWindow::EnableTimeChangeNotifications()
|
nsGlobalWindow::EnableTimeChangeNotifications()
|
||||||
{
|
{
|
||||||
|
|
|
@ -448,6 +448,7 @@ public:
|
||||||
// Inner windows only.
|
// Inner windows only.
|
||||||
virtual void SetHasGamepadEventListener(bool aHasGamepad = true) override;
|
virtual void SetHasGamepadEventListener(bool aHasGamepad = true) override;
|
||||||
void NotifyVREventListenerAdded();
|
void NotifyVREventListenerAdded();
|
||||||
|
bool HasUsedVR() const;
|
||||||
virtual void EventListenerAdded(nsIAtom* aType) override;
|
virtual void EventListenerAdded(nsIAtom* aType) override;
|
||||||
|
|
||||||
// nsIInterfaceRequestor
|
// nsIInterfaceRequestor
|
||||||
|
|
|
@ -2488,7 +2488,12 @@ nsScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
|
||||||
}
|
}
|
||||||
rv = aSRIDataVerifier->Verify(aRequest->mIntegrity, channel, sourceUri,
|
rv = aSRIDataVerifier->Verify(aRequest->mIntegrity, channel, sourceUri,
|
||||||
mReporter);
|
mReporter);
|
||||||
mReporter->FlushConsoleReports(mDocument);
|
if (channelRequest) {
|
||||||
|
mReporter->FlushReportsToConsole(
|
||||||
|
nsContentUtils::GetInnerWindowID(channelRequest));
|
||||||
|
} else {
|
||||||
|
mReporter->FlushConsoleReports(mDocument);
|
||||||
|
}
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
rv = NS_ERROR_SRI_CORRUPT;
|
rv = NS_ERROR_SRI_CORRUPT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
with Files("**"):
|
||||||
|
BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
|
||||||
|
|
||||||
EXPORTS.mozilla.dom.battery += [
|
EXPORTS.mozilla.dom.battery += [
|
||||||
'Constants.h',
|
'Constants.h',
|
||||||
'Types.h',
|
'Types.h',
|
||||||
|
|
|
@ -15446,6 +15446,7 @@ class CGCallback(CGClass):
|
||||||
|
|
||||||
setupCall = fill(
|
setupCall = fill(
|
||||||
"""
|
"""
|
||||||
|
MOZ_ASSERT(!aRv.Failed(), "Don't pass an already-failed ErrorResult to a callback!");
|
||||||
if (!aExecutionReason) {
|
if (!aExecutionReason) {
|
||||||
aExecutionReason = "${executionReason}";
|
aExecutionReason = "${executionReason}";
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
with Files("**"):
|
||||||
|
BUG_COMPONENT = ("Core", "DOM")
|
||||||
|
|
||||||
TEST_DIRS += ['test']
|
TEST_DIRS += ['test']
|
||||||
|
|
||||||
XPIDL_SOURCES += [
|
XPIDL_SOURCES += [
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
with Files("**"):
|
||||||
|
BUG_COMPONENT = ("Core", "DOM")
|
||||||
|
|
||||||
EXPORTS.mozilla.dom += [
|
EXPORTS.mozilla.dom += [
|
||||||
'BroadcastChannel.h',
|
'BroadcastChannel.h',
|
||||||
]
|
]
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
with Files("**"):
|
||||||
|
BUG_COMPONENT = ("Core", "DOM")
|
||||||
|
|
||||||
EXPORTS.mozilla += [
|
EXPORTS.mozilla += [
|
||||||
'BrowserElementParent.h',
|
'BrowserElementParent.h',
|
||||||
]
|
]
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
|
||||||
|
with Files("**"):
|
||||||
|
BUG_COMPONENT = ("Core", "DOM")
|
||||||
|
|
||||||
EXPORTS.mozilla.dom.cache += [
|
EXPORTS.mozilla.dom.cache += [
|
||||||
'Action.h',
|
'Action.h',
|
||||||
'ActorChild.h',
|
'ActorChild.h',
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
with Files("**"):
|
||||||
|
BUG_COMPONENT = ("Core", "Embedding: APIs")
|
||||||
|
|
||||||
XPIDL_SOURCES += [
|
XPIDL_SOURCES += [
|
||||||
'nsICommandManager.idl',
|
'nsICommandManager.idl',
|
||||||
'nsICommandParams.idl',
|
'nsICommandParams.idl',
|
||||||
|
|
|
@ -39,11 +39,9 @@ ConsoleReportCollector::AddConsoleReport(uint32_t aErrorFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ConsoleReportCollector::FlushConsoleReports(nsIDocument* aDocument,
|
ConsoleReportCollector::FlushReportsToConsole(uint64_t aInnerWindowID,
|
||||||
ReportAction aAction)
|
ReportAction aAction)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
nsTArray<PendingReport> reports;
|
nsTArray<PendingReport> reports;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -58,6 +56,22 @@ ConsoleReportCollector::FlushConsoleReports(nsIDocument* aDocument,
|
||||||
for (uint32_t i = 0; i < reports.Length(); ++i) {
|
for (uint32_t i = 0; i < reports.Length(); ++i) {
|
||||||
PendingReport& report = reports[i];
|
PendingReport& report = reports[i];
|
||||||
|
|
||||||
|
nsXPIDLString errorText;
|
||||||
|
nsresult rv;
|
||||||
|
if (!report.mStringParams.IsEmpty()) {
|
||||||
|
rv = nsContentUtils::FormatLocalizedString(report.mPropertiesFile,
|
||||||
|
report.mMessageName.get(),
|
||||||
|
report.mStringParams,
|
||||||
|
errorText);
|
||||||
|
} else {
|
||||||
|
rv = nsContentUtils::GetLocalizedString(report.mPropertiesFile,
|
||||||
|
report.mMessageName.get(),
|
||||||
|
errorText);
|
||||||
|
}
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// It would be nice if we did not have to do this since ReportToConsole()
|
// It would be nice if we did not have to do this since ReportToConsole()
|
||||||
// just turns around and converts it back to a spec.
|
// just turns around and converts it back to a spec.
|
||||||
nsCOMPtr<nsIURI> uri;
|
nsCOMPtr<nsIURI> uri;
|
||||||
|
@ -69,26 +83,33 @@ ConsoleReportCollector::FlushConsoleReports(nsIDocument* aDocument,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert back from nsTArray<nsString> to the char16_t** format required
|
nsContentUtils::ReportToConsoleByWindowID(errorText,
|
||||||
// by our l10n libraries and ReportToConsole. (bug 1219762)
|
report.mErrorFlags,
|
||||||
UniquePtr<const char16_t*[]> params;
|
report.mCategory,
|
||||||
uint32_t paramsLength = report.mStringParams.Length();
|
aInnerWindowID,
|
||||||
if (paramsLength > 0) {
|
uri,
|
||||||
params = MakeUnique<const char16_t*[]>(paramsLength);
|
EmptyString(),
|
||||||
for (uint32_t j = 0; j < paramsLength; ++j) {
|
report.mLineNumber,
|
||||||
params[j] = report.mStringParams[j].get();
|
report.mColumnNumber);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsContentUtils::ReportToConsole(report.mErrorFlags, report.mCategory,
|
|
||||||
aDocument, report.mPropertiesFile,
|
|
||||||
report.mMessageName.get(),
|
|
||||||
params.get(),
|
|
||||||
paramsLength, uri, EmptyString(),
|
|
||||||
report.mLineNumber, report.mColumnNumber);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConsoleReportCollector::FlushConsoleReports(nsIDocument* aDocument,
|
||||||
|
ReportAction aAction)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
FlushReportsToConsole(aDocument ? aDocument->InnerWindowID() : 0, aAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConsoleReportCollector::FlushConsoleReports(nsILoadGroup* aLoadGroup,
|
||||||
|
ReportAction aAction)
|
||||||
|
{
|
||||||
|
FlushReportsToConsole(nsContentUtils::GetInnerWindowID(aLoadGroup), aAction);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ConsoleReportCollector::FlushConsoleReports(nsIConsoleReportCollector* aCollector)
|
ConsoleReportCollector::FlushConsoleReports(nsIConsoleReportCollector* aCollector)
|
||||||
{
|
{
|
||||||
|
@ -110,71 +131,6 @@ ConsoleReportCollector::FlushConsoleReports(nsIConsoleReportCollector* aCollecto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
ConsoleReportCollector::FlushReportsByWindowId(uint64_t aWindowId,
|
|
||||||
ReportAction aAction)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
nsTArray<PendingReport> reports;
|
|
||||||
|
|
||||||
{
|
|
||||||
MutexAutoLock lock(mMutex);
|
|
||||||
if (aAction == ReportAction::Forget) {
|
|
||||||
mPendingReports.SwapElements(reports);
|
|
||||||
} else {
|
|
||||||
reports = mPendingReports;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIConsoleService> consoleService =
|
|
||||||
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
|
||||||
if (!consoleService) {
|
|
||||||
NS_WARNING("GetConsoleService failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
for (uint32_t i = 0; i < reports.Length(); ++i) {
|
|
||||||
PendingReport& report = reports[i];
|
|
||||||
|
|
||||||
nsXPIDLString errorText;
|
|
||||||
if (!report.mStringParams.IsEmpty()) {
|
|
||||||
rv = nsContentUtils::FormatLocalizedString(report.mPropertiesFile,
|
|
||||||
report.mMessageName.get(),
|
|
||||||
report.mStringParams,
|
|
||||||
errorText);
|
|
||||||
} else {
|
|
||||||
rv = nsContentUtils::GetLocalizedString(report.mPropertiesFile,
|
|
||||||
report.mMessageName.get(),
|
|
||||||
errorText);
|
|
||||||
}
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIScriptError> errorObject =
|
|
||||||
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = errorObject->InitWithWindowID(errorText,
|
|
||||||
NS_ConvertUTF8toUTF16(report.mSourceFileURI),
|
|
||||||
EmptyString(),
|
|
||||||
report.mLineNumber,
|
|
||||||
report.mColumnNumber,
|
|
||||||
report.mErrorFlags,
|
|
||||||
report.mCategory,
|
|
||||||
aWindowId);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
consoleService->LogMessage(errorObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ConsoleReportCollector::ClearConsoleReports()
|
ConsoleReportCollector::ClearConsoleReports()
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,16 +26,20 @@ public:
|
||||||
const nsACString& aMessageName,
|
const nsACString& aMessageName,
|
||||||
const nsTArray<nsString>& aStringParams) override;
|
const nsTArray<nsString>& aStringParams) override;
|
||||||
|
|
||||||
|
void
|
||||||
|
FlushReportsToConsole(uint64_t aInnerWindowID,
|
||||||
|
ReportAction aAction = ReportAction::Forget) override;
|
||||||
|
|
||||||
void
|
void
|
||||||
FlushConsoleReports(nsIDocument* aDocument,
|
FlushConsoleReports(nsIDocument* aDocument,
|
||||||
ReportAction aAction = ReportAction::Forget) override;
|
ReportAction aAction = ReportAction::Forget) override;
|
||||||
|
|
||||||
void
|
void
|
||||||
FlushConsoleReports(nsIConsoleReportCollector* aCollector) override;
|
FlushConsoleReports(nsILoadGroup* aLoadGroup,
|
||||||
|
ReportAction aAction = ReportAction::Forget) override;
|
||||||
|
|
||||||
void
|
void
|
||||||
FlushReportsByWindowId(uint64_t aWindowId,
|
FlushConsoleReports(nsIConsoleReportCollector* aCollector) override;
|
||||||
ReportAction aAction = ReportAction::Forget) override;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ClearConsoleReports() override;
|
ClearConsoleReports() override;
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
with Files("**"):
|
||||||
|
BUG_COMPONENT = ("Core", "DOM")
|
||||||
|
|
||||||
XPIDL_SOURCES += [
|
XPIDL_SOURCES += [
|
||||||
'nsIConsoleAPIStorage.idl',
|
'nsIConsoleAPIStorage.idl',
|
||||||
]
|
]
|
||||||
|
|
|
@ -74,6 +74,15 @@ public:
|
||||||
Save
|
Save
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Flush all pending reports to the console. May be called from any thread.
|
||||||
|
//
|
||||||
|
// aInnerWindowID A inner window ID representing where to flush the reports.
|
||||||
|
// aAction An action to determine whether to reserve the pending
|
||||||
|
// reports. Defalut action is to forget the report.
|
||||||
|
virtual void
|
||||||
|
FlushReportsToConsole(uint64_t aInnerWindowID,
|
||||||
|
ReportAction aAction = ReportAction::Forget) = 0;
|
||||||
|
|
||||||
// Flush all pending reports to the console. Main thread only.
|
// Flush all pending reports to the console. Main thread only.
|
||||||
//
|
//
|
||||||
// aDocument An optional document representing where to flush the
|
// aDocument An optional document representing where to flush the
|
||||||
|
@ -86,6 +95,19 @@ public:
|
||||||
FlushConsoleReports(nsIDocument* aDocument,
|
FlushConsoleReports(nsIDocument* aDocument,
|
||||||
ReportAction aAction = ReportAction::Forget) = 0;
|
ReportAction aAction = ReportAction::Forget) = 0;
|
||||||
|
|
||||||
|
// Flush all pending reports to the console. May be called from any thread.
|
||||||
|
//
|
||||||
|
// aLoadGroup An optional loadGroup representing where to flush the
|
||||||
|
// reports. If provided, then the corresponding window's
|
||||||
|
// web console will get the reports. Otherwise the reports
|
||||||
|
// go to the browser console.
|
||||||
|
// aAction An action to determine whether to reserve the pending
|
||||||
|
// reports. Defalut action is to forget the report.
|
||||||
|
virtual void
|
||||||
|
FlushConsoleReports(nsILoadGroup* aLoadGroup,
|
||||||
|
ReportAction aAction = ReportAction::Forget) = 0;
|
||||||
|
|
||||||
|
|
||||||
// Flush all pending reports to another collector. May be called from any
|
// Flush all pending reports to another collector. May be called from any
|
||||||
// thread.
|
// thread.
|
||||||
//
|
//
|
||||||
|
@ -94,17 +116,6 @@ public:
|
||||||
virtual void
|
virtual void
|
||||||
FlushConsoleReports(nsIConsoleReportCollector* aCollector) = 0;
|
FlushConsoleReports(nsIConsoleReportCollector* aCollector) = 0;
|
||||||
|
|
||||||
// Flush all pending reports to the console accroding to window ID. Main
|
|
||||||
// thread only.
|
|
||||||
//
|
|
||||||
// aWindowId A window ID representing where to flush the reports and it's
|
|
||||||
// typically the inner window ID.
|
|
||||||
//
|
|
||||||
// aAction An action to decide whether free the pending reports or not.
|
|
||||||
virtual void
|
|
||||||
FlushReportsByWindowId(uint64_t aWindowId,
|
|
||||||
ReportAction aAction = ReportAction::Forget) = 0;
|
|
||||||
|
|
||||||
// Clear all pending reports.
|
// Clear all pending reports.
|
||||||
virtual void
|
virtual void
|
||||||
ClearConsoleReports() = 0;
|
ClearConsoleReports() = 0;
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
with Files("**"):
|
||||||
|
BUG_COMPONENT = ("Core", "DOM: Security")
|
||||||
|
|
||||||
EXPORTS.mozilla.dom += [
|
EXPORTS.mozilla.dom += [
|
||||||
'CryptoBuffer.h',
|
'CryptoBuffer.h',
|
||||||
'CryptoKey.h',
|
'CryptoKey.h',
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
with Files("**"):
|
||||||
|
BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
|
||||||
|
|
||||||
|
|
||||||
EXPORTS += [
|
EXPORTS += [
|
||||||
'DeviceStorage.h',
|
'DeviceStorage.h',
|
||||||
'DeviceStorageFileDescriptor.h',
|
'DeviceStorageFileDescriptor.h',
|
||||||
|
|
|
@ -100,7 +100,7 @@ class MainThreadFetchResolver final : public FetchDriverObserver
|
||||||
RefPtr<Promise> mPromise;
|
RefPtr<Promise> mPromise;
|
||||||
RefPtr<Response> mResponse;
|
RefPtr<Response> mResponse;
|
||||||
|
|
||||||
nsCOMPtr<nsIDocument> mDocument;
|
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||||
|
|
||||||
NS_DECL_OWNINGTHREAD
|
NS_DECL_OWNINGTHREAD
|
||||||
public:
|
public:
|
||||||
|
@ -109,9 +109,9 @@ public:
|
||||||
void
|
void
|
||||||
OnResponseAvailableInternal(InternalResponse* aResponse) override;
|
OnResponseAvailableInternal(InternalResponse* aResponse) override;
|
||||||
|
|
||||||
void SetDocument(nsIDocument* aDocument)
|
void SetLoadGroup(nsILoadGroup* aLoadGroup)
|
||||||
{
|
{
|
||||||
mDocument = aDocument;
|
mLoadGroup = aLoadGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void OnResponseEnd() override
|
virtual void OnResponseEnd() override
|
||||||
|
@ -124,7 +124,7 @@ private:
|
||||||
|
|
||||||
void FlushConsoleReport() override
|
void FlushConsoleReport() override
|
||||||
{
|
{
|
||||||
mReporter->FlushConsoleReports(mDocument);
|
mReporter->FlushConsoleReports(mLoadGroup);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
|
||||||
RefPtr<MainThreadFetchResolver> resolver = new MainThreadFetchResolver(p);
|
RefPtr<MainThreadFetchResolver> resolver = new MainThreadFetchResolver(p);
|
||||||
RefPtr<FetchDriver> fetch = new FetchDriver(r, principal, loadGroup);
|
RefPtr<FetchDriver> fetch = new FetchDriver(r, principal, loadGroup);
|
||||||
fetch->SetDocument(doc);
|
fetch->SetDocument(doc);
|
||||||
resolver->SetDocument(doc);
|
resolver->SetLoadGroup(loadGroup);
|
||||||
aRv = fetch->Fetch(resolver);
|
aRv = fetch->Fetch(resolver);
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -453,7 +453,7 @@ WorkerFetchResolver::FlushConsoleReport()
|
||||||
|
|
||||||
workers::WorkerPrivate* worker = mPromiseProxy->GetWorkerPrivate();
|
workers::WorkerPrivate* worker = mPromiseProxy->GetWorkerPrivate();
|
||||||
if (!worker) {
|
if (!worker) {
|
||||||
mReporter->FlushConsoleReports((nsIDocument*)nullptr);
|
mReporter->FlushReportsToConsole(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,7 +461,7 @@ WorkerFetchResolver::FlushConsoleReport()
|
||||||
// Flush to service worker
|
// Flush to service worker
|
||||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||||
if (!swm) {
|
if (!swm) {
|
||||||
mReporter->FlushConsoleReports((nsIDocument*)nullptr);
|
mReporter->FlushReportsToConsole(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,7 +476,7 @@ WorkerFetchResolver::FlushConsoleReport()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush to dedicated worker
|
// Flush to dedicated worker
|
||||||
mReporter->FlushConsoleReports(worker->GetDocument());
|
mReporter->FlushConsoleReports(worker->GetLoadGroup());
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "mozilla/dom/BlobBinding.h"
|
#include "mozilla/dom/BlobBinding.h"
|
||||||
#include "mozilla/dom/DOMError.h"
|
#include "mozilla/dom/DOMError.h"
|
||||||
#include "mozilla/dom/FileBinding.h"
|
#include "mozilla/dom/FileBinding.h"
|
||||||
|
#include "mozilla/dom/FileSystemUtils.h"
|
||||||
#include "mozilla/dom/WorkerPrivate.h"
|
#include "mozilla/dom/WorkerPrivate.h"
|
||||||
#include "mozilla/dom/WorkerRunnable.h"
|
#include "mozilla/dom/WorkerRunnable.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
@ -470,15 +471,18 @@ File::GetName(nsAString& aFileName) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
File::GetPath(nsAString& aPath) const
|
File::GetRelativePath(nsAString& aPath) const
|
||||||
{
|
{
|
||||||
mImpl->GetPath(aPath);
|
aPath.Truncate();
|
||||||
}
|
|
||||||
|
|
||||||
void
|
nsAutoString path;
|
||||||
File::SetPath(const nsAString& aPath)
|
mImpl->GetDOMPath(path);
|
||||||
{
|
|
||||||
mImpl->SetPath(aPath);
|
// WebkitRelativePath doesn't start with '/'
|
||||||
|
if (!path.IsEmpty()) {
|
||||||
|
MOZ_ASSERT(path[0] == FILESYSTEM_DOM_PATH_SEPARATOR_CHAR);
|
||||||
|
aPath.Assign(Substring(path, 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Date
|
Date
|
||||||
|
@ -670,14 +674,14 @@ BlobImplBase::GetName(nsAString& aName) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BlobImplBase::GetPath(nsAString& aPath) const
|
BlobImplBase::GetDOMPath(nsAString& aPath) const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mIsFile, "Should only be called on files");
|
MOZ_ASSERT(mIsFile, "Should only be called on files");
|
||||||
aPath = mPath;
|
aPath = mPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BlobImplBase::SetPath(const nsAString& aPath)
|
BlobImplBase::SetDOMPath(const nsAString& aPath)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mIsFile, "Should only be called on files");
|
MOZ_ASSERT(mIsFile, "Should only be called on files");
|
||||||
mPath = aPath;
|
mPath = aPath;
|
||||||
|
|
|
@ -225,13 +225,7 @@ public:
|
||||||
|
|
||||||
Date GetLastModifiedDate(ErrorResult& aRv);
|
Date GetLastModifiedDate(ErrorResult& aRv);
|
||||||
|
|
||||||
// GetPath and SetPath are currently used only for the webkitRelativePath
|
void GetRelativePath(nsAString& aPath) const;
|
||||||
// attribute and they are only used when this File object is created from a
|
|
||||||
// Directory, generated by a Directory Picker.
|
|
||||||
|
|
||||||
void GetPath(nsAString& aName) const;
|
|
||||||
|
|
||||||
void SetPath(const nsAString& aName);
|
|
||||||
|
|
||||||
void GetMozFullPath(nsAString& aFilename, SystemCallerGuarantee aGuarantee,
|
void GetMozFullPath(nsAString& aFilename, SystemCallerGuarantee aGuarantee,
|
||||||
ErrorResult& aRv) const;
|
ErrorResult& aRv) const;
|
||||||
|
@ -260,9 +254,9 @@ public:
|
||||||
|
|
||||||
virtual void GetName(nsAString& aName) const = 0;
|
virtual void GetName(nsAString& aName) const = 0;
|
||||||
|
|
||||||
virtual void GetPath(nsAString& aName) const = 0;
|
virtual void GetDOMPath(nsAString& aName) const = 0;
|
||||||
|
|
||||||
virtual void SetPath(const nsAString& aName) = 0;
|
virtual void SetDOMPath(const nsAString& aName) = 0;
|
||||||
|
|
||||||
virtual int64_t GetLastModified(ErrorResult& aRv) = 0;
|
virtual int64_t GetLastModified(ErrorResult& aRv) = 0;
|
||||||
|
|
||||||
|
@ -406,9 +400,9 @@ public:
|
||||||
|
|
||||||
virtual void GetName(nsAString& aName) const override;
|
virtual void GetName(nsAString& aName) const override;
|
||||||
|
|
||||||
virtual void GetPath(nsAString& aName) const override;
|
virtual void GetDOMPath(nsAString& aName) const override;
|
||||||
|
|
||||||
virtual void SetPath(const nsAString& aName) override;
|
virtual void SetDOMPath(const nsAString& aName) override;
|
||||||
|
|
||||||
virtual int64_t GetLastModified(ErrorResult& aRv) override;
|
virtual int64_t GetLastModified(ErrorResult& aRv) override;
|
||||||
|
|
||||||
|
|
|
@ -2071,10 +2071,10 @@ public:
|
||||||
GetName(nsAString& aName) const override;
|
GetName(nsAString& aName) const override;
|
||||||
|
|
||||||
void
|
void
|
||||||
GetPath(nsAString& aPath) const override;
|
GetDOMPath(nsAString& aPath) const override;
|
||||||
|
|
||||||
void
|
void
|
||||||
SetPath(const nsAString& aPath) override;
|
SetDOMPath(const nsAString& aPath) override;
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
GetLastModified(ErrorResult& aRv) override;
|
GetLastModified(ErrorResult& aRv) override;
|
||||||
|
@ -2175,7 +2175,7 @@ RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
|
||||||
BlobImpl* aRemoteBlobImpl,
|
BlobImpl* aRemoteBlobImpl,
|
||||||
const nsAString& aName,
|
const nsAString& aName,
|
||||||
const nsAString& aContentType,
|
const nsAString& aContentType,
|
||||||
const nsAString& aPath,
|
const nsAString& aDOMPath,
|
||||||
uint64_t aLength,
|
uint64_t aLength,
|
||||||
int64_t aModDate,
|
int64_t aModDate,
|
||||||
BlobImplIsDirectory aIsDirectory,
|
BlobImplIsDirectory aIsDirectory,
|
||||||
|
@ -2185,7 +2185,7 @@ RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
|
||||||
, mMutex("BlobChild::RemoteBlobImpl::mMutex")
|
, mMutex("BlobChild::RemoteBlobImpl::mMutex")
|
||||||
, mIsSlice(false), mIsDirectory(aIsDirectory == eDirectory)
|
, mIsSlice(false), mIsDirectory(aIsDirectory == eDirectory)
|
||||||
{
|
{
|
||||||
SetPath(aPath);
|
SetDOMPath(aDOMPath);
|
||||||
|
|
||||||
if (aIsSameProcessBlob) {
|
if (aIsSameProcessBlob) {
|
||||||
MOZ_ASSERT(aRemoteBlobImpl);
|
MOZ_ASSERT(aRemoteBlobImpl);
|
||||||
|
@ -2843,16 +2843,16 @@ RemoteBlobImpl::GetName(nsAString& aName) const
|
||||||
|
|
||||||
void
|
void
|
||||||
BlobParent::
|
BlobParent::
|
||||||
RemoteBlobImpl::GetPath(nsAString& aPath) const
|
RemoteBlobImpl::GetDOMPath(nsAString& aPath) const
|
||||||
{
|
{
|
||||||
mBlobImpl->GetPath(aPath);
|
mBlobImpl->GetDOMPath(aPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BlobParent::
|
BlobParent::
|
||||||
RemoteBlobImpl::SetPath(const nsAString& aPath)
|
RemoteBlobImpl::SetDOMPath(const nsAString& aPath)
|
||||||
{
|
{
|
||||||
mBlobImpl->SetPath(aPath);
|
mBlobImpl->SetDOMPath(aPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
|
@ -3196,8 +3196,8 @@ BlobChild::CommonInit(BlobChild* aOther, BlobImpl* aBlobImpl)
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
otherImpl->GetName(name);
|
otherImpl->GetName(name);
|
||||||
|
|
||||||
nsAutoString path;
|
nsAutoString domPath;
|
||||||
otherImpl->GetPath(path);
|
otherImpl->GetDOMPath(domPath);
|
||||||
|
|
||||||
int64_t modDate = otherImpl->GetLastModified(rv);
|
int64_t modDate = otherImpl->GetLastModified(rv);
|
||||||
MOZ_ASSERT(!rv.Failed());
|
MOZ_ASSERT(!rv.Failed());
|
||||||
|
@ -3207,7 +3207,7 @@ BlobChild::CommonInit(BlobChild* aOther, BlobImpl* aBlobImpl)
|
||||||
RemoteBlobImpl::BlobImplIsDirectory::eNotDirectory;
|
RemoteBlobImpl::BlobImplIsDirectory::eNotDirectory;
|
||||||
|
|
||||||
remoteBlob =
|
remoteBlob =
|
||||||
new RemoteBlobImpl(this, otherImpl, name, contentType, path,
|
new RemoteBlobImpl(this, otherImpl, name, contentType, domPath,
|
||||||
length, modDate, directory,
|
length, modDate, directory,
|
||||||
false /* SameProcessBlobImpl */);
|
false /* SameProcessBlobImpl */);
|
||||||
} else {
|
} else {
|
||||||
|
@ -3291,8 +3291,8 @@ BlobChild::CommonInit(const ChildBlobConstructorParams& aParams)
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
blobImpl->GetName(name);
|
blobImpl->GetName(name);
|
||||||
|
|
||||||
nsAutoString path;
|
nsAutoString domPath;
|
||||||
blobImpl->GetPath(path);
|
blobImpl->GetDOMPath(domPath);
|
||||||
|
|
||||||
int64_t lastModifiedDate = blobImpl->GetLastModified(rv);
|
int64_t lastModifiedDate = blobImpl->GetLastModified(rv);
|
||||||
MOZ_ASSERT(!rv.Failed());
|
MOZ_ASSERT(!rv.Failed());
|
||||||
|
@ -3307,7 +3307,7 @@ BlobChild::CommonInit(const ChildBlobConstructorParams& aParams)
|
||||||
blobImpl,
|
blobImpl,
|
||||||
name,
|
name,
|
||||||
contentType,
|
contentType,
|
||||||
path,
|
domPath,
|
||||||
size,
|
size,
|
||||||
lastModifiedDate,
|
lastModifiedDate,
|
||||||
directory,
|
directory,
|
||||||
|
@ -3490,14 +3490,14 @@ BlobChild::GetOrCreateFromImpl(ChildManagerType* aManager,
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
aBlobImpl->GetName(name);
|
aBlobImpl->GetName(name);
|
||||||
|
|
||||||
nsAutoString path;
|
nsAutoString domPath;
|
||||||
aBlobImpl->GetPath(path);
|
aBlobImpl->GetDOMPath(domPath);
|
||||||
|
|
||||||
int64_t modDate = aBlobImpl->GetLastModified(rv);
|
int64_t modDate = aBlobImpl->GetLastModified(rv);
|
||||||
MOZ_ASSERT(!rv.Failed());
|
MOZ_ASSERT(!rv.Failed());
|
||||||
|
|
||||||
blobParams =
|
blobParams =
|
||||||
FileBlobConstructorParams(name, contentType, path, length, modDate,
|
FileBlobConstructorParams(name, contentType, domPath, length, modDate,
|
||||||
aBlobImpl->IsDirectory(), blobData);
|
aBlobImpl->IsDirectory(), blobData);
|
||||||
} else {
|
} else {
|
||||||
blobParams = NormalBlobConstructorParams(contentType, length, blobData);
|
blobParams = NormalBlobConstructorParams(contentType, length, blobData);
|
||||||
|
@ -4043,14 +4043,14 @@ BlobParent::GetOrCreateFromImpl(ParentManagerType* aManager,
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
aBlobImpl->GetName(name);
|
aBlobImpl->GetName(name);
|
||||||
|
|
||||||
nsAutoString path;
|
nsAutoString domPath;
|
||||||
aBlobImpl->GetPath(path);
|
aBlobImpl->GetDOMPath(domPath);
|
||||||
|
|
||||||
int64_t modDate = aBlobImpl->GetLastModified(rv);
|
int64_t modDate = aBlobImpl->GetLastModified(rv);
|
||||||
MOZ_ASSERT(!rv.Failed());
|
MOZ_ASSERT(!rv.Failed());
|
||||||
|
|
||||||
blobParams =
|
blobParams =
|
||||||
FileBlobConstructorParams(name, contentType, path, length, modDate,
|
FileBlobConstructorParams(name, contentType, domPath, length, modDate,
|
||||||
aBlobImpl->IsDirectory(), void_t());
|
aBlobImpl->IsDirectory(), void_t());
|
||||||
} else {
|
} else {
|
||||||
blobParams = NormalBlobConstructorParams(contentType, length, void_t());
|
blobParams = NormalBlobConstructorParams(contentType, length, void_t());
|
||||||
|
|
|
@ -23,6 +23,7 @@ EXPORTS.mozilla.dom += [
|
||||||
'File.h',
|
'File.h',
|
||||||
'FileList.h',
|
'FileList.h',
|
||||||
'FileReader.h',
|
'FileReader.h',
|
||||||
|
'MultipartBlobImpl.h',
|
||||||
'MutableBlobStorage.h',
|
'MutableBlobStorage.h',
|
||||||
'MutableBlobStreamListener.h',
|
'MutableBlobStreamListener.h',
|
||||||
]
|
]
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче