зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-i to m-c, a=merge
MozReview-Commit-ID: Hm1RxN6OaoZ
This commit is contained in:
Коммит
0f32b67e2d
|
@ -90,6 +90,15 @@
|
|||
);
|
||||
} else {
|
||||
SimpleTest.ok(true, "Testing Firefox tabbrowser UI.");
|
||||
let newTabChildren = [];
|
||||
if (SpecialPowers.getBoolPref("privacy.userContext.enabled")) {
|
||||
newTabChildren = [
|
||||
{
|
||||
role: ROLE_MENUPOPUP,
|
||||
children: []
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
// NB: The (3) buttons are not visible, unless manually hovered,
|
||||
// probably due to size reduction in this test.
|
||||
|
@ -119,7 +128,7 @@
|
|||
{
|
||||
// xul:toolbarbutton ("Open a new tab")
|
||||
role: ROLE_PUSHBUTTON,
|
||||
children: []
|
||||
children: newTabChildren
|
||||
}
|
||||
// "List all tabs" dropdown
|
||||
// XXX: This child(?) is not present in this test.
|
||||
|
|
|
@ -7,6 +7,7 @@ support-files =
|
|||
invalid.json
|
||||
[browser_sdk_loader_sdk_modules.js]
|
||||
[browser_sdk_loader_sdk_gui_modules.js]
|
||||
skip-if = true # Bug 1315042
|
||||
[browser_sdk_loader_jsm_modules.js]
|
||||
[browser_sdk_loader_js_modules.js]
|
||||
[browser_sdk_loader_json.js]
|
||||
|
|
|
@ -93,6 +93,7 @@
|
|||
<command id="Browser:OpenLocation" oncommand="openLocation();"/>
|
||||
<command id="Browser:RestoreLastSession" oncommand="restoreLastSession();" disabled="true"/>
|
||||
<command id="Browser:NewUserContextTab" oncommand="openNewUserContextTab(event.sourceEvent);" reserved="true"/>
|
||||
<command id="Browser:OpenAboutContainers" oncommand="openPreferences('paneContainers');"/>
|
||||
|
||||
<command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
|
||||
<command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
|
||||
|
|
|
@ -119,6 +119,16 @@ tabbrowser {
|
|||
visibility: hidden; /* temporary space to keep a tab's close button under the cursor */
|
||||
}
|
||||
|
||||
.tabs-newtab-button > .toolbarbutton-menu-dropmarker,
|
||||
#new-tab-button > .toolbarbutton-menu-dropmarker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* override drop marker image padding */
|
||||
.tabs-newtab-button > .toolbarbutton-icon {
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
||||
.tabbrowser-tab {
|
||||
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tab");
|
||||
}
|
||||
|
@ -177,6 +187,7 @@ tabbrowser {
|
|||
transition: transform 200ms ease-out;
|
||||
}
|
||||
|
||||
.new-tab-popup,
|
||||
#alltabs-popup {
|
||||
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-alltabs-popup");
|
||||
}
|
||||
|
|
|
@ -269,66 +269,6 @@ function UpdateBackForwardCommands(aWebNavigation) {
|
|||
* XXXmano: should this live in toolbarbutton.xml?
|
||||
*/
|
||||
function SetClickAndHoldHandlers() {
|
||||
var timer;
|
||||
|
||||
function openMenu(aButton) {
|
||||
cancelHold(aButton);
|
||||
aButton.firstChild.hidden = false;
|
||||
aButton.open = true;
|
||||
}
|
||||
|
||||
function mousedownHandler(aEvent) {
|
||||
if (aEvent.button != 0 ||
|
||||
aEvent.currentTarget.open ||
|
||||
aEvent.currentTarget.disabled)
|
||||
return;
|
||||
|
||||
// Prevent the menupopup from opening immediately
|
||||
aEvent.currentTarget.firstChild.hidden = true;
|
||||
|
||||
aEvent.currentTarget.addEventListener("mouseout", mouseoutHandler, false);
|
||||
aEvent.currentTarget.addEventListener("mouseup", mouseupHandler, false);
|
||||
timer = setTimeout(openMenu, 500, aEvent.currentTarget);
|
||||
}
|
||||
|
||||
function mouseoutHandler(aEvent) {
|
||||
let buttonRect = aEvent.currentTarget.getBoundingClientRect();
|
||||
if (aEvent.clientX >= buttonRect.left &&
|
||||
aEvent.clientX <= buttonRect.right &&
|
||||
aEvent.clientY >= buttonRect.bottom)
|
||||
openMenu(aEvent.currentTarget);
|
||||
else
|
||||
cancelHold(aEvent.currentTarget);
|
||||
}
|
||||
|
||||
function mouseupHandler(aEvent) {
|
||||
cancelHold(aEvent.currentTarget);
|
||||
}
|
||||
|
||||
function cancelHold(aButton) {
|
||||
clearTimeout(timer);
|
||||
aButton.removeEventListener("mouseout", mouseoutHandler, false);
|
||||
aButton.removeEventListener("mouseup", mouseupHandler, false);
|
||||
}
|
||||
|
||||
function clickHandler(aEvent) {
|
||||
if (aEvent.button == 0 &&
|
||||
aEvent.target == aEvent.currentTarget &&
|
||||
!aEvent.currentTarget.open &&
|
||||
!aEvent.currentTarget.disabled) {
|
||||
let cmdEvent = document.createEvent("xulcommandevent");
|
||||
cmdEvent.initCommandEvent("command", true, true, window, 0,
|
||||
aEvent.ctrlKey, aEvent.altKey, aEvent.shiftKey,
|
||||
aEvent.metaKey, null);
|
||||
aEvent.currentTarget.dispatchEvent(cmdEvent);
|
||||
}
|
||||
}
|
||||
|
||||
function _addClickAndHoldListenersOnElement(aElm) {
|
||||
aElm.addEventListener("mousedown", mousedownHandler, true);
|
||||
aElm.addEventListener("click", clickHandler, true);
|
||||
}
|
||||
|
||||
// Bug 414797: Clone the back/forward buttons' context menu into both buttons.
|
||||
let popup = document.getElementById("backForwardMenu").cloneNode(true);
|
||||
popup.removeAttribute("id");
|
||||
|
@ -338,15 +278,107 @@ function SetClickAndHoldHandlers() {
|
|||
let backButton = document.getElementById("back-button");
|
||||
backButton.setAttribute("type", "menu");
|
||||
backButton.appendChild(popup);
|
||||
_addClickAndHoldListenersOnElement(backButton);
|
||||
gClickAndHoldListenersOnElement.add(backButton);
|
||||
|
||||
let forwardButton = document.getElementById("forward-button");
|
||||
popup = popup.cloneNode(true);
|
||||
forwardButton.setAttribute("type", "menu");
|
||||
forwardButton.appendChild(popup);
|
||||
_addClickAndHoldListenersOnElement(forwardButton);
|
||||
gClickAndHoldListenersOnElement.add(forwardButton);
|
||||
}
|
||||
|
||||
|
||||
const gClickAndHoldListenersOnElement = {
|
||||
_timers: new Map(),
|
||||
|
||||
_mousedownHandler(aEvent) {
|
||||
if (aEvent.button != 0 ||
|
||||
aEvent.currentTarget.open ||
|
||||
aEvent.currentTarget.disabled)
|
||||
return;
|
||||
|
||||
// Prevent the menupopup from opening immediately
|
||||
aEvent.currentTarget.firstChild.hidden = true;
|
||||
|
||||
aEvent.currentTarget.addEventListener("mouseout", this, false);
|
||||
aEvent.currentTarget.addEventListener("mouseup", this, false);
|
||||
this._timers.set(aEvent.currentTarget, setTimeout((b) => this._openMenu(b), 500, aEvent.currentTarget));
|
||||
},
|
||||
|
||||
_clickHandler(aEvent) {
|
||||
if (aEvent.button == 0 &&
|
||||
aEvent.target == aEvent.currentTarget &&
|
||||
!aEvent.currentTarget.open &&
|
||||
!aEvent.currentTarget.disabled) {
|
||||
let cmdEvent = document.createEvent("xulcommandevent");
|
||||
cmdEvent.initCommandEvent("command", true, true, window, 0,
|
||||
aEvent.ctrlKey, aEvent.altKey, aEvent.shiftKey,
|
||||
aEvent.metaKey, null);
|
||||
aEvent.currentTarget.dispatchEvent(cmdEvent);
|
||||
|
||||
// This is here to cancel the XUL default event
|
||||
// dom.click() triggers a command even if there is a click handler
|
||||
// however this can now be prevented with preventDefault().
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
_openMenu(aButton) {
|
||||
this._cancelHold(aButton);
|
||||
aButton.firstChild.hidden = false;
|
||||
aButton.open = true;
|
||||
},
|
||||
|
||||
_mouseoutHandler(aEvent) {
|
||||
let buttonRect = aEvent.currentTarget.getBoundingClientRect();
|
||||
if (aEvent.clientX >= buttonRect.left &&
|
||||
aEvent.clientX <= buttonRect.right &&
|
||||
aEvent.clientY >= buttonRect.bottom)
|
||||
this._openMenu(aEvent.currentTarget);
|
||||
else
|
||||
this._cancelHold(aEvent.currentTarget);
|
||||
},
|
||||
|
||||
_mouseupHandler(aEvent) {
|
||||
this._cancelHold(aEvent.currentTarget);
|
||||
},
|
||||
|
||||
_cancelHold(aButton) {
|
||||
clearTimeout(this._timers.get(aButton));
|
||||
aButton.removeEventListener("mouseout", this, false);
|
||||
aButton.removeEventListener("mouseup", this, false);
|
||||
},
|
||||
|
||||
handleEvent(e) {
|
||||
switch (e.type) {
|
||||
case "mouseout":
|
||||
this._mouseoutHandler(e);
|
||||
break;
|
||||
case "mousedown":
|
||||
this._mousedownHandler(e);
|
||||
break;
|
||||
case "click":
|
||||
this._clickHandler(e);
|
||||
break;
|
||||
case "mouseup":
|
||||
this._mouseupHandler(e);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
remove(aButton) {
|
||||
aButton.removeEventListener("mousedown", this, true);
|
||||
aButton.removeEventListener("click", this, true);
|
||||
},
|
||||
|
||||
add(aElm) {
|
||||
this._timers.delete(aElm);
|
||||
|
||||
aElm.addEventListener("mousedown", this, true);
|
||||
aElm.addEventListener("click", this, true);
|
||||
}
|
||||
};
|
||||
|
||||
const gSessionHistoryObserver = {
|
||||
observe: function(subject, topic, data)
|
||||
{
|
||||
|
@ -4100,22 +4132,25 @@ function updateUserContextUIIndicator()
|
|||
|
||||
let userContextId = gBrowser.selectedBrowser.getAttribute("usercontextid");
|
||||
if (!userContextId) {
|
||||
hbox.setAttribute("data-identity-color", "");
|
||||
hbox.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
let identity = ContextualIdentityService.getIdentityFromId(userContextId);
|
||||
if (!identity) {
|
||||
hbox.setAttribute("data-identity-color", "");
|
||||
hbox.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
hbox.setAttribute("data-identity-color", identity.color);
|
||||
|
||||
let label = document.getElementById("userContext-label");
|
||||
label.setAttribute('value', ContextualIdentityService.getUserContextLabel(userContextId));
|
||||
label.style.color = identity.color;
|
||||
label.setAttribute("value", ContextualIdentityService.getUserContextLabel(userContextId));
|
||||
|
||||
let indicator = document.getElementById("userContext-indicator");
|
||||
indicator.style.listStyleImage = "url(" + identity.icon + ")";
|
||||
indicator.setAttribute("data-identity-icon", identity.icon);
|
||||
|
||||
hbox.hidden = false;
|
||||
}
|
||||
|
|
|
@ -1867,7 +1867,7 @@ nsContextMenu.prototype = {
|
|||
},
|
||||
|
||||
createContainerMenu: function(aEvent) {
|
||||
return createUserContextMenu(aEvent, false,
|
||||
return createUserContextMenu(aEvent, true,
|
||||
gContextMenuContentData.userContextId);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -529,7 +529,7 @@ function openCacheEntry(key, cb)
|
|||
|
||||
function makeGeneralTab(metaViewRows, docInfo)
|
||||
{
|
||||
var title = (docInfo.title) ? gBundle.getFormattedString("pageTitle", [docInfo.title]) : gBundle.getString("noPageTitle");
|
||||
var title = (docInfo.title) ? docInfo.title : gBundle.getString("noPageTitle");
|
||||
document.getElementById("titletext").value = title;
|
||||
|
||||
var url = docInfo.location;
|
||||
|
|
|
@ -88,7 +88,6 @@
|
|||
<deck id="mainDeck" flex="1">
|
||||
<!-- General page information -->
|
||||
<vbox id="generalPanel">
|
||||
<textbox class="header" readonly="true" id="titletext"/>
|
||||
<grid id="generalGrid">
|
||||
<columns>
|
||||
<column/>
|
||||
|
@ -96,6 +95,11 @@
|
|||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows id="generalRows">
|
||||
<row id="generalTitle">
|
||||
<label control="titletext" value="&generalTitle;"/>
|
||||
<separator/>
|
||||
<textbox readonly="true" id="titletext"/>
|
||||
</row>
|
||||
<row id="generalURLRow">
|
||||
<label control="urltext" value="&generalURL;"/>
|
||||
<separator/>
|
||||
|
|
|
@ -5236,7 +5236,7 @@
|
|||
</xul:arrowscrollbox>
|
||||
</content>
|
||||
|
||||
<implementation implements="nsIDOMEventListener">
|
||||
<implementation implements="nsIDOMEventListener, nsIObserver">
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
this.mTabClipWidth = Services.prefs.getIntPref("browser.tabs.tabClipWidth");
|
||||
|
@ -5255,9 +5255,17 @@
|
|||
this._tabAnimationLoggingEnabled = false;
|
||||
}
|
||||
this._browserNewtabpageEnabled = Services.prefs.getBoolPref("browser.newtabpage.enabled");
|
||||
this.observe(null, "nsPref:changed", "privacy.userContext.enabled");
|
||||
Services.prefs.addObserver("privacy.userContext.enabled", this, false);
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<![CDATA[
|
||||
Services.prefs.removeObserver("privacy.userContext.enabled", this);
|
||||
]]>
|
||||
</destructor>
|
||||
|
||||
<field name="tabbrowser" readonly="true">
|
||||
document.getElementById(this.getAttribute("tabbrowser"));
|
||||
</field>
|
||||
|
@ -5283,6 +5291,53 @@
|
|||
<field name="_afterHoveredTab">null</field>
|
||||
<field name="_hoveredTab">null</field>
|
||||
|
||||
<method name="observe">
|
||||
<parameter name="aSubject"/>
|
||||
<parameter name="aTopic"/>
|
||||
<parameter name="aData"/>
|
||||
<body><![CDATA[
|
||||
switch (aTopic) {
|
||||
case "nsPref:changed":
|
||||
// This is the only pref observed.
|
||||
let containersEnabled = Services.prefs.getBoolPref("privacy.userContext.enabled");
|
||||
|
||||
const newTab = document.getElementById("new-tab-button");
|
||||
const newTab2 = document.getAnonymousElementByAttribute(this, "anonid", "tabs-newtab-button")
|
||||
|
||||
if (containersEnabled) {
|
||||
for (let parent of [newTab, newTab2]) {
|
||||
if (!parent)
|
||||
continue;
|
||||
let popup = document.createElementNS(
|
||||
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
||||
"menupopup");
|
||||
if (parent.id) {
|
||||
popup.id = "newtab-popup";
|
||||
} else {
|
||||
popup.setAttribute("anonid", "newtab-popup");
|
||||
}
|
||||
popup.className = "new-tab-popup";
|
||||
popup.setAttribute("position", "after_end");
|
||||
parent.appendChild(popup);
|
||||
|
||||
gClickAndHoldListenersOnElement.add(parent);
|
||||
parent.setAttribute("type", "menu");
|
||||
}
|
||||
} else {
|
||||
for (let parent of [newTab, newTab2]) {
|
||||
if (!parent)
|
||||
continue;
|
||||
gClickAndHoldListenersOnElement.remove(parent);
|
||||
parent.removeAttribute("type");
|
||||
parent.firstChild.remove();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<property name="_isCustomizing" readonly="true">
|
||||
<getter>
|
||||
let root = document.documentElement;
|
||||
|
@ -6963,12 +7018,17 @@
|
|||
<handlers>
|
||||
<handler event="popupshowing">
|
||||
<![CDATA[
|
||||
if (event.target.getAttribute('id') == "alltabs_containersMenuTab") {
|
||||
if (event.target.getAttribute("id") == "alltabs_containersMenuTab") {
|
||||
createUserContextMenu(event);
|
||||
return;
|
||||
}
|
||||
|
||||
let containersEnabled = Services.prefs.getBoolPref("privacy.userContext.enabled");
|
||||
|
||||
if (event.target.getAttribute("anonid") == "newtab-popup" ||
|
||||
event.target.id == "newtab-popup") {
|
||||
createUserContextMenu(event);
|
||||
} else {
|
||||
document.getElementById("alltabs-popup-separator-1").hidden = !containersEnabled;
|
||||
let containersTab = document.getElementById("alltabs_containersTab");
|
||||
|
||||
|
@ -6993,11 +7053,12 @@
|
|||
this._createTabMenuItem(tabs[i]);
|
||||
}
|
||||
this._updateTabsVisibilityStatus();
|
||||
}
|
||||
]]></handler>
|
||||
|
||||
<handler event="popuphidden">
|
||||
<![CDATA[
|
||||
if (event.target.getAttribute('id') == "alltabs_containersMenuTab") {
|
||||
if (event.target.getAttribute("id") == "alltabs_containersMenuTab") {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -7008,6 +7069,9 @@
|
|||
menuItem.tab.mCorrespondingMenuitem = null;
|
||||
this.removeChild(menuItem);
|
||||
}
|
||||
if (menuItem.hasAttribute("usercontextid")) {
|
||||
this.removeChild(menuItem);
|
||||
}
|
||||
}
|
||||
var tabcontainer = gBrowser.tabContainer;
|
||||
tabcontainer.mTabstrip.removeEventListener("scroll", this, false);
|
||||
|
|
|
@ -534,3 +534,4 @@ skip-if = !e10s
|
|||
tags = mcb
|
||||
[browser_newwindow_focus.js]
|
||||
skip-if = (os == "linux" && !e10s) # Bug 1263254 - Perma fails on Linux without e10s for some reason.
|
||||
[browser_bug1299667.js]
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const { addObserver, removeObserver } = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
|
||||
function receive(topic) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let timeout = setTimeout(() => {
|
||||
reject(new Error("Timeout"));
|
||||
}, 90000);
|
||||
|
||||
const observer = {
|
||||
observe: subject => {
|
||||
removeObserver(observer, topic);
|
||||
clearTimeout(timeout);
|
||||
resolve(subject);
|
||||
}
|
||||
};
|
||||
addObserver(observer, topic, false);
|
||||
});
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com");
|
||||
|
||||
yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
|
||||
content.history.pushState({}, "2", "2.html");
|
||||
});
|
||||
|
||||
yield receive("sessionstore-state-write-complete");
|
||||
|
||||
// Wait for the session data to be flushed before continuing the test
|
||||
yield new Promise(resolve => SessionStore.getSessionHistory(gBrowser.selectedTab, resolve));
|
||||
|
||||
var backButton = document.getElementById("back-button");
|
||||
var contextMenu = document.getElementById("backForwardMenu");
|
||||
|
||||
info("waiting for the history menu to open");
|
||||
|
||||
let popupShownPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
|
||||
EventUtils.synthesizeMouseAtCenter(backButton, {type: "contextmenu", button: 2});
|
||||
let event = yield popupShownPromise;
|
||||
|
||||
ok(true, "history menu opened");
|
||||
|
||||
// Wait for the session data to be flushed before continuing the test
|
||||
yield new Promise(resolve => SessionStore.getSessionHistory(gBrowser.selectedTab, resolve));
|
||||
|
||||
is(event.target.children.length, 2, "Two history items");
|
||||
|
||||
let node = event.target.firstChild;
|
||||
is(node.getAttribute("uri"), "http://example.com/2.html", "first item uri");
|
||||
is(node.getAttribute("index"), "1", "first item index");
|
||||
is(node.getAttribute("historyindex"), "0", "first item historyindex");
|
||||
|
||||
node = event.target.lastChild;
|
||||
is(node.getAttribute("uri"), "http://example.com/", "second item uri");
|
||||
is(node.getAttribute("index"), "0", "second item index");
|
||||
is(node.getAttribute("historyindex"), "-1", "second item historyindex");
|
||||
|
||||
let popupHiddenPromise = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden");
|
||||
event.target.hidePopup();
|
||||
yield popupHiddenPromise;
|
||||
info("Hidden popup");
|
||||
|
||||
let onClose = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabClose");
|
||||
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
yield onClose;
|
||||
info("Tab closed");
|
||||
});
|
|
@ -57,6 +57,7 @@ skip-if = !crashreporter
|
|||
[browser_CTP_iframe.js]
|
||||
[browser_CTP_multi_allow.js]
|
||||
[browser_CTP_nonplugins.js]
|
||||
skip-if = true # Bug 1315042
|
||||
[browser_CTP_notificationBar.js]
|
||||
[browser_CTP_outsideScrollArea.js]
|
||||
[browser_CTP_remove_navigate.js]
|
||||
|
|
|
@ -6,6 +6,7 @@ support-files =
|
|||
head.js
|
||||
|
||||
[browser_referrer_middle_click.js]
|
||||
skip-if = true # Bug 1315042
|
||||
[browser_referrer_middle_click_in_container.js]
|
||||
[browser_referrer_open_link_in_private.js]
|
||||
skip-if = os == 'linux' # Bug 1145199
|
||||
|
|
|
@ -83,5 +83,11 @@ function* testProbe(aProbe) {
|
|||
`Spinner probe should now have a value in some bucket`);
|
||||
}
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
add_task(testProbe.bind(null, "FX_TAB_SWITCH_SPINNER_VISIBLE_MS"));
|
||||
add_task(testProbe.bind(null, "FX_TAB_SWITCH_SPINNER_VISIBLE_LONG_MS"));
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
const kURL1 = "data:text/html,Should I stay or should I go?";
|
||||
const kURL2 = "data:text/html,I shouldn't be here!";
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Verify that if we open a new tab and try to make it the selected tab while
|
||||
* print preview is up, that doesn't happen.
|
||||
|
|
|
@ -9,3 +9,4 @@ skip-if = buildapp == 'mulet' || (os == "linux" && debug) # linux: bug 976544
|
|||
[browser_devices_get_user_media_anim.js]
|
||||
[browser_devices_get_user_media_in_frame.js]
|
||||
[browser_devices_get_user_media_tear_off_tab.js]
|
||||
skip-if = true # Bug 1315042
|
||||
|
|
|
@ -1539,7 +1539,8 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
let showNotification = aInput.shouldShowSearchSuggestionsNotification;
|
||||
if (showNotification) {
|
||||
let prefs = aInput._prefs;
|
||||
let date = parseInt((new Date()).toLocaleFormat("%Y%m%d"));
|
||||
let now = new Date();
|
||||
let date = now.getFullYear() * 10000 + (now.getMonth() + 1) * 100 + now.getDate();
|
||||
let previousDate = prefs.getIntPref("lastSuggestionsPromptDate");
|
||||
if (previousDate < date) {
|
||||
let remainingDays =
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="32" height="32" viewBox="0 0 32 32">
|
||||
<style>
|
||||
path, circle {
|
||||
fill: menutext;
|
||||
}
|
||||
path:not(:target),
|
||||
circle:not(:target) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<path id="dollar" d="M17.3857868,14.0527919 C14.2304569,13.0862944 13.4913706,12.4609137 13.4913706,11.0964467 C13.4913706,9.61827411 14.7137056,8.85076142 16.4192893,8.85076142 C17.9827411,8.85076142 19.3187817,9.33401015 20.5979695,10.4994924 L22.4456853,8.42436548 C21.1664975,7.20203046 19.3187819,6.26535905 17,6.00952148 L17,2 L15,2 L15,6.00952148 C12.3827412,6.43591742 9.76751269,8.53807107 9.76751269,11.3238579 C9.76751269,14.1664975 11.4730964,15.786802 15.4812183,17.0091371 C18.4375635,17.9187817 19.2335025,18.6294416 19.2335025,20.2213198 C19.2335025,22.0690355 17.7553299,23.035533 15.7370558,23.035533 C13.7756345,23.035533 12.2406091,22.3248731 10.9329949,21.1025381 L9,23.2345178 C10.4213198,24.6274112 12.8659899,25.8324934 15,26.0030518 L15,30 L17,30 L17,26.0030518 C20.7116753,25.4060974 22.9857868,22.893401 22.9857868,20.022335 C22.9857868,16.4690355 20.7116751,15.1045685 17.3857868,14.0527919 Z"/>
|
||||
<path id="briefcase" fill-rule="evenodd" d="M22,9.99887085 L21.635468,10 L29.0034652,10 C29.5538362,10 30,10.4449463 30,10.9933977 L30,27.0066023 C30,27.5552407 29.5601869,28 29.0034652,28 L2.99653482,28 C2.44616384,28 2,27.5550537 2,27.0066023 L2,10.9933977 C2,10.4447593 2.43981314,10 2.99653482,10 L8,10 L8,7.99922997 C8,5.79051625 10.0426627,4 12.5635454,4 L19.4364546,4 C21.9568311,4 24,5.79246765 24,7.99922997 L24,9.99267578 L22,9.99887085 L22,10 L10,10 L10,7.99922997 C10,6.89421235 11.0713286,6 12.3917227,6 L19.6082773,6 C20.9273761,6 22,6.89552665 22,7.99922997 L22,9.99887085 Z"/>
|
||||
<path id="fingerprint" d="M7.17741905,12 C7.10965537,12 7.041327,11.9953181 6.97243393,11.985018 C6.33263187,11.8918489 5.90515601,11.3862071 6.01809547,10.8552833 C7.41798011,4.26321358 12.2613889,2.57493207 15.0238882,2.15590491 C19.6448063,1.45690206 24.3408291,3.21541158 25.8344535,5.29743816 C26.1664955,5.76047488 25.9835336,6.35881757 25.4244832,6.63364321 C24.8654329,6.9098734 24.1437497,6.75583996 23.8122724,6.29327142 C22.8923805,5.01043967 19.1749781,3.51130562 15.4479759,4.07406612 C12.8080159,4.474834 9.43056132,6.03623689 8.33561323,11.1942506 C8.23453242,11.666651 7.73816348,12 7.17741905,12 Z M16.63127,26 C16.1452186,26 15.6509104,25.9658335 15.147795,25.8938767 C10.637921,25.257137 6.71207921,21.8114952 6.01575422,17.8807924 C5.91171832,17.2932317 6.33391695,16.7382846 6.95813239,16.6404441 C7.58454965,16.5343208 8.17298555,16.9406954 8.27757192,17.5272206 C8.80876054,20.5255916 11.9766264,23.26409 15.4885263,23.7610576 C17.3975027,24.02766 20.959494,23.8221432 23.3220449,19.3789425 C24.4625867,17.2331815 23.0049831,11.881462 19.9521622,9.34692739 C18.2380468,7.92384005 16.4573263,7.76905536 14.6628445,8.89499751 C13.26469,9.77142052 11.8070864,12.2857658 11.8665355,14.6287608 C11.9127737,16.4835887 12.8386382,17.9325598 14.6171568,18.9363308 C15.2210054,19.2764429 16.9411759,19.4933486 17.9424527,18.8296898 C18.7257495,18.3104622 18.9591422,17.2761485 18.6365758,15.7583267 C18.3822659,14.5650869 17.2219077,12.4452096 16.6664991,12.3711821 C16.6692513,12.3722175 16.4666841,12.4312324 16.1276041,12.9095636 C15.8545786,13.2936782 15.58981,14.7297074 15.9476054,15.3581643 C16.0142104,15.4761941 16.0725586,15.5465978 16.3202632,15.5465978 C16.9532859,15.5465978 17.46686,16.0290705 17.46686,16.6249139 C17.46686,17.2207573 16.9543868,17.7042653 16.3213641,17.7042653 C15.2644914,17.7042653 14.4140391,17.2336992 13.9268868,16.3774655 C13.1083609,14.9388479 13.5536787,12.6548678 14.2202791,11.7137354 C15.2540327,10.2564816 16.3631986,10.1151564 17.1123672,10.2564816 C19.7066595,10.7389543 20.8763754,15.2908666 20.8857331,15.3359043 C21.5303153,18.3648181 20.3594985,19.8665919 19.264094,20.593407 C17.4151172,21.8192603 14.6920186,21.493643 13.4380832,20.7859819 C10.3280151,19.0310652 9.62013053,16.497566 9.5744428,14.6805283 C9.49022326,11.3643051 11.4779146,8.30018945 13.391845,7.10021984 C16.0417332,5.43848454 18.9877658,5.66781436 21.4714167,7.72919442 C25.1176276,10.7565552 27.0871539,17.1229168 25.3746898,20.3433702 C23.4326862,23.9950465 20.2983981,26 16.63127,26 Z M16.0845157,30 C14.9348455,30 13.9050564,29.8557557 13.0394288,29.6610017 C10.2114238,29.0257442 7.58700058,27.4599412 6.18892823,25.5735955 C5.84440518,25.1078371 5.98426642,24.4803503 6.50105099,24.1700066 C7.01675554,23.8596629 7.71552172,23.986423 8.06112477,24.4507244 C9.89498097,26.9252176 15.9397944,29.9781448 22.2508301,26.1937972 C22.7676147,25.8844249 23.4658409,26.0087566 23.8109039,26.474515 C24.155427,26.9397877 24.0161057,27.5672745 23.4993212,27.8776182 C20.7987573,29.4963593 18.2315746,30 16.0845157,30 Z"/>
|
||||
<path id="cart" fill-rule="evenodd" d="M20.8195396,14 L15.1804604,14 L15.1804604,14 L15.8471271,18 L20.1528729,18 L20.8195396,14 Z M22.8471271,14 L27.6125741,14 L27.6125741,14 L26.2792408,18 L22.1804604,18 L22.8471271,14 Z M21.1528729,12 L14.8471271,12 L14.8471271,12 L14.1804604,8 L21.8195396,8 L21.1528729,12 Z M23.1804604,12 L28.2792408,12 L28.2792408,12 L29.6125741,8 L23.8471271,8 L23.1804604,12 Z M13.1528729,14 L8.47703296,14 L10.077033,18 L10.077033,18 L13.8195396,18 L13.1528729,14 Z M12.8195396,12 L7.67703296,12 L6.07703296,8 L12.1528729,8 L12.8195396,12 L12.8195396,12 Z M31.7207592,8 L32,8 L32,6 L31,6 L5.27703296,6 L5.27703296,6 L4,2.8074176 L4,2 L3,2 L1,2 L0,2 L0,4 L1,4 L2.32296704,4 L9.78931928,22.6658806 L9.78931928,22.6658806 C8.71085924,23.3823847 8,24.6081773 8,26 C8,28.209139 9.790861,30 12,30 C14.209139,30 16,28.209139 16,26 C16,25.2714257 15.8052114,24.5883467 15.4648712,24 L22.5351288,24 C22.1947886,24.5883467 22,25.2714257 22,26 C22,28.209139 23.790861,30 26,30 C28.209139,30 30,28.209139 30,26 C30,23.790861 28.209139,22 26,22 L11.677033,22 L10.877033,20 L27,20 L28,20 L28,19.1622777 L31.7207592,8 L31.7207592,8 Z M26,28 C27.1045695,28 28,27.1045695 28,26 C28,24.8954305 27.1045695,24 26,24 C24.8954305,24 24,24.8954305 24,26 C24,27.1045695 24.8954305,28 26,28 Z M12,28 C13.1045695,28 14,27.1045695 14,26 C14,24.8954305 13.1045695,24 12,24 C10.8954305,24 10,24.8954305 10,26 C10,27.1045695 10.8954305,28 12,28 Z"/>
|
||||
<circle id="circle" r="16" cx="16" cy="16" fill-rule="evenodd" />
|
||||
</svg>
|
||||
|
После Ширина: | Высота: | Размер: 6.5 KiB |
|
@ -438,9 +438,8 @@ function checkForMiddleClick(node, event) {
|
|||
}
|
||||
|
||||
// Populate a menu with user-context menu items. This method should be called
|
||||
// by onpopupshowing passing the event as first argument. addCommandAttribute
|
||||
// param is used to set the 'command' attribute in the new menuitem elements.
|
||||
function createUserContextMenu(event, addCommandAttribute = true, excludeUserContextId = 0) {
|
||||
// by onpopupshowing passing the event as first argument.
|
||||
function createUserContextMenu(event, isContextMenu = false, excludeUserContextId = 0) {
|
||||
while (event.target.hasChildNodes()) {
|
||||
event.target.removeChild(event.target.firstChild);
|
||||
}
|
||||
|
@ -455,9 +454,9 @@ function createUserContextMenu(event, addCommandAttribute = true, excludeUserCon
|
|||
menuitem.setAttribute("label", bundle.getString("userContextNone.label"));
|
||||
menuitem.setAttribute("accesskey", bundle.getString("userContextNone.accesskey"));
|
||||
|
||||
// We don't set an oncommand/command attribute attribute because if we have
|
||||
// We don't set an oncommand/command attribute because if we have
|
||||
// to exclude a userContextId we are generating the contextMenu and
|
||||
// addCommandAttribute will be false.
|
||||
// isContextMenu will be true.
|
||||
|
||||
docfrag.appendChild(menuitem);
|
||||
|
||||
|
@ -479,16 +478,29 @@ function createUserContextMenu(event, addCommandAttribute = true, excludeUserCon
|
|||
}
|
||||
|
||||
menuitem.classList.add("menuitem-iconic");
|
||||
menuitem.setAttribute("data-identity-color", identity.color);
|
||||
|
||||
if (addCommandAttribute) {
|
||||
if (!isContextMenu) {
|
||||
menuitem.setAttribute("command", "Browser:NewUserContextTab");
|
||||
}
|
||||
|
||||
menuitem.setAttribute("image", identity.icon);
|
||||
menuitem.setAttribute("data-identity-icon", identity.icon);
|
||||
|
||||
docfrag.appendChild(menuitem);
|
||||
});
|
||||
|
||||
if (!isContextMenu) {
|
||||
docfrag.appendChild(document.createElement("menuseparator"));
|
||||
|
||||
let menuitem = document.createElement("menuitem");
|
||||
menuitem.setAttribute("label",
|
||||
bundle.getString("userContext.aboutPage.label"));
|
||||
menuitem.setAttribute("accesskey",
|
||||
bundle.getString("userContext.aboutPage.accesskey"));
|
||||
menuitem.setAttribute("command", "Browser:OpenAboutContainers");
|
||||
docfrag.appendChild(menuitem);
|
||||
}
|
||||
|
||||
event.target.appendChild(docfrag);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -165,6 +165,7 @@ browser.jar:
|
|||
content/browser/tabbrowser.xml (content/tabbrowser.xml)
|
||||
content/browser/urlbarBindings.xml (content/urlbarBindings.xml)
|
||||
content/browser/utilityOverlay.js (content/utilityOverlay.js)
|
||||
content/browser/usercontext.svg (content/usercontext.svg)
|
||||
content/browser/web-panels.js (content/web-panels.js)
|
||||
* content/browser/web-panels.xul (content/web-panels.xul)
|
||||
* content/browser/baseMenuOverlay.xul (content/baseMenuOverlay.xul)
|
||||
|
|
|
@ -1,3 +1,63 @@
|
|||
[data-identity-color="blue"] {
|
||||
--identity-tab-color: #0996f8;
|
||||
--identity-icon-color: #00a7e0;
|
||||
}
|
||||
|
||||
[data-identity-color="turquoise"] {
|
||||
--identity-tab-color: #01bdad;
|
||||
--identity-icon-color: #01bdad;
|
||||
}
|
||||
|
||||
[data-identity-color="green"] {
|
||||
--identity-tab-color: #57bd35;
|
||||
--identity-icon-color: #7dc14c;
|
||||
}
|
||||
|
||||
[data-identity-color="yellow"] {
|
||||
--identity-tab-color: #ffcb00;
|
||||
--identity-icon-color: #ffcb00;
|
||||
}
|
||||
|
||||
[data-identity-color="orange"] {
|
||||
--identity-tab-color: #ff9216;
|
||||
--identity-icon-color: #ff9216;
|
||||
}
|
||||
|
||||
[data-identity-color="red"] {
|
||||
--identity-tab-color: #d92215;
|
||||
--identity-icon-color: #d92215;
|
||||
}
|
||||
|
||||
[data-identity-color="pink"] {
|
||||
--identity-tab-color: #ea385e;
|
||||
--identity-icon-color: #ee5195;
|
||||
}
|
||||
|
||||
[data-identity-color="purple"] {
|
||||
--identity-tab-color: #7a2f7a;
|
||||
--identity-icon-color: #7a2f7a;
|
||||
}
|
||||
|
||||
[data-identity-icon="fingerprint"] {
|
||||
--identity-icon: url("chrome://browser/content/usercontext.svg#fingerprint");
|
||||
}
|
||||
|
||||
[data-identity-icon="briefcase"] {
|
||||
--identity-icon: url("chrome://browser/content/usercontext.svg#briefcase");
|
||||
}
|
||||
|
||||
[data-identity-icon="dollar"] {
|
||||
--identity-icon: url("chrome://browser/content/usercontext.svg#dollar");
|
||||
}
|
||||
|
||||
[data-identity-icon="cart"] {
|
||||
--identity-icon: url("chrome://browser/content/usercontext.svg#cart");
|
||||
}
|
||||
|
||||
[data-identity-icon="circle"] {
|
||||
--identity-icon: url("chrome://browser/content/usercontext.svg#circle");
|
||||
}
|
||||
|
||||
#userContext-indicator {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
|
@ -5,9 +65,27 @@
|
|||
|
||||
#userContext-label {
|
||||
margin-inline-end: 3px;
|
||||
color: #909090;
|
||||
color: var(--identity-tab-color);
|
||||
}
|
||||
|
||||
#userContext-icons {
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
.tabbrowser-tab[usercontextid] {
|
||||
background-image: linear-gradient(to right, transparent 20%, var(--identity-tab-color) 30%, var(--identity-tab-color) 70%, transparent 80%);
|
||||
background-size: auto 2px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.userContext-icon,
|
||||
.menuitem-iconic[data-usercontextid] > .menu-iconic-left > .menu-iconic-icon,
|
||||
.subviewbutton[usercontextid] > .toolbarbutton-icon,
|
||||
#userContext-indicator {
|
||||
background-image: var(--identity-icon);
|
||||
filter: url(chrome://browser/skin/filters.svg#fill);
|
||||
fill: var(--identity-icon-color);
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ support-files =
|
|||
[browser_forgetAPI_cookie_getCookiesWithOriginAttributes.js]
|
||||
[browser_forgetAPI_EME_forgetThisSite.js]
|
||||
[browser_forgetAPI_quota_clearStoragesForPrincipal.js]
|
||||
[browser_newtabButton.js]
|
||||
[browser_usercontext.js]
|
||||
[browser_usercontextid_tabdrop.js]
|
||||
skip-if = os == "mac" || os == "win" # Intermittent failure - bug 1268276
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
"use strict";
|
||||
|
||||
// Testing that when the user opens the add tab menu and clicks menu items
|
||||
// the correct context id is opened
|
||||
|
||||
add_task(function* test() {
|
||||
yield SpecialPowers.pushPrefEnv({"set": [
|
||||
["privacy.userContext.enabled", true]
|
||||
]});
|
||||
|
||||
let newTab = document.getElementById('tabbrowser-tabs');
|
||||
let newTabButton = document.getAnonymousElementByAttribute(newTab, "anonid", "tabs-newtab-button");
|
||||
ok(newTabButton, "New tab button exists");
|
||||
ok(!newTabButton.hidden, "New tab button is visible");
|
||||
let popup = document.getAnonymousElementByAttribute(newTab, "anonid", "newtab-popup");
|
||||
|
||||
for (let i = 1; i <= 4; i++) {
|
||||
let popupShownPromise = BrowserTestUtils.waitForEvent(popup, "popupshown");
|
||||
EventUtils.synthesizeMouseAtCenter(newTabButton, {type: "mousedown"});
|
||||
|
||||
yield popupShownPromise;
|
||||
let contextIdItem = popup.querySelector(`menuitem[data-usercontextid="${i}"]`);
|
||||
|
||||
ok(contextIdItem, `User context id ${i} exists`);
|
||||
|
||||
let waitForTabPromise = BrowserTestUtils.waitForNewTab(gBrowser);
|
||||
EventUtils.synthesizeMouseAtCenter(contextIdItem, {});
|
||||
|
||||
let tab = yield waitForTabPromise;
|
||||
|
||||
is(tab.getAttribute('usercontextid'), i, `New tab has UCI equal ${i}`);
|
||||
yield BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
});
|
|
@ -25,7 +25,8 @@ add_task(function* setup() {
|
|||
// make sure userContext is enabled.
|
||||
yield new Promise(resolve => {
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["privacy.userContext.enabled", true]
|
||||
["privacy.userContext.enabled", true],
|
||||
["dom.ipc.processCount", 1]
|
||||
]}, resolve);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -29,7 +29,8 @@ add_task(function* setup() {
|
|||
// make sure userContext is enabled.
|
||||
yield new Promise(resolve => {
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["privacy.userContext.enabled", true]
|
||||
["privacy.userContext.enabled", true],
|
||||
["dom.ipc.processCount", 1]
|
||||
]}, resolve);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1108,8 +1108,10 @@ const CustomizableWidgets = [
|
|||
|
||||
let onItemCommand = function (aEvent) {
|
||||
let item = aEvent.target;
|
||||
if (item.hasAttribute("usercontextid")) {
|
||||
let userContextId = parseInt(item.getAttribute("usercontextid"));
|
||||
win.openUILinkIn(win.BROWSER_NEW_TAB_URL, "tab", {userContextId});
|
||||
}
|
||||
};
|
||||
items.addEventListener("command", onItemCommand);
|
||||
|
||||
|
@ -1134,20 +1136,29 @@ const CustomizableWidgets = [
|
|||
}
|
||||
|
||||
let fragment = doc.createDocumentFragment();
|
||||
let bundle = doc.getElementById("bundle_browser");
|
||||
|
||||
ContextualIdentityService.getIdentities().forEach(identity => {
|
||||
let bundle = doc.getElementById("bundle_browser");
|
||||
let label = ContextualIdentityService.getUserContextLabel(identity.userContextId);
|
||||
|
||||
let item = doc.createElementNS(kNSXUL, "toolbarbutton");
|
||||
item.setAttribute("label", label);
|
||||
item.setAttribute("usercontextid", identity.userContextId);
|
||||
item.setAttribute("class", "subviewbutton");
|
||||
item.setAttribute("image", identity.icon);
|
||||
item.setAttribute("data-identity-color", identity.color);
|
||||
item.setAttribute("data-identity-icon", identity.icon);
|
||||
|
||||
fragment.appendChild(item);
|
||||
});
|
||||
|
||||
fragment.appendChild(doc.createElementNS(kNSXUL, "menuseparator"));
|
||||
|
||||
let item = doc.createElementNS(kNSXUL, "toolbarbutton");
|
||||
item.setAttribute("label", bundle.getString("userContext.aboutPage.label"));
|
||||
item.setAttribute("command", "Browser:OpenAboutContainers");
|
||||
item.setAttribute("class", "subviewbutton");
|
||||
fragment.appendChild(item);
|
||||
|
||||
items.appendChild(fragment);
|
||||
},
|
||||
|
||||
|
|
|
@ -193,8 +193,9 @@ BrowserAction.prototype = {
|
|||
// be ready by the time we get a complete click.
|
||||
let tab = window.gBrowser.selectedTab;
|
||||
let popupURL = this.getProperty(tab, "popup");
|
||||
let enabled = this.getProperty(tab, "enabled");
|
||||
|
||||
if (popupURL) {
|
||||
if (popupURL && enabled) {
|
||||
this.pendingPopup = this.getPopup(window, popupURL);
|
||||
window.addEventListener("mouseup", this, true);
|
||||
} else {
|
||||
|
|
|
@ -78,15 +78,6 @@ XPCOMUtils.defineLazyGetter(this, "standaloneStylesheets", () => {
|
|||
return stylesheets;
|
||||
});
|
||||
|
||||
/* eslint-disable mozilla/balanced-listeners */
|
||||
extensions.on("page-shutdown", (type, context) => {
|
||||
if (context.viewType == "popup" && context.active) {
|
||||
// TODO(robwu): This is not webext-oop compatible.
|
||||
context.xulBrowser.contentWindow.close();
|
||||
}
|
||||
});
|
||||
/* eslint-enable mozilla/balanced-listeners */
|
||||
|
||||
class BasePopup {
|
||||
constructor(extension, viewNode, popupURL, browserStyle, fixedWidth = false) {
|
||||
this.extension = extension;
|
||||
|
@ -97,6 +88,8 @@ class BasePopup {
|
|||
this.destroyed = false;
|
||||
this.fixedWidth = fixedWidth;
|
||||
|
||||
extension.callOnClose(this);
|
||||
|
||||
this.contentReady = new Promise(resolve => {
|
||||
this._resolveContentReady = resolve;
|
||||
});
|
||||
|
@ -120,7 +113,13 @@ class BasePopup {
|
|||
return BasePopup.instances.get(window).get(extension);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.closePopup();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.extension.forgetOnClose(this);
|
||||
|
||||
this.destroyed = true;
|
||||
this.browserLoadedDeferred.reject(new Error("Popup destroyed"));
|
||||
return this.browserReady.then(() => {
|
||||
|
|
|
@ -53,6 +53,7 @@ tags = webextensions
|
|||
[browser_ext_popup_api_injection.js]
|
||||
[browser_ext_popup_background.js]
|
||||
[browser_ext_popup_corners.js]
|
||||
[browser_ext_popup_sendMessage.js]
|
||||
[browser_ext_popup_shutdown.js]
|
||||
[browser_ext_runtime_openOptionsPage.js]
|
||||
[browser_ext_runtime_openOptionsPage_uninstall.js]
|
||||
|
|
|
@ -273,7 +273,7 @@ add_task(function* testBrowserActionClickCanceled() {
|
|||
// We need to do these tests during the mouseup event cycle, since the click
|
||||
// and command events will be dispatched immediately after mouseup, and void
|
||||
// the results.
|
||||
let mouseUpPromise = BrowserTestUtils.waitForEvent(widget.node, "mouseup", event => {
|
||||
let mouseUpPromise = BrowserTestUtils.waitForEvent(widget.node, "mouseup", false, event => {
|
||||
isnot(browserAction.pendingPopup, null, "Pending popup was not cleared");
|
||||
isnot(browserAction.pendingPopupTimeout, null, "Have a pending popup timeout");
|
||||
return true;
|
||||
|
@ -291,3 +291,74 @@ add_task(function* testBrowserActionClickCanceled() {
|
|||
|
||||
yield extension.unload();
|
||||
});
|
||||
|
||||
add_task(function* testBrowserActionDisabled() {
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"browser_action": {
|
||||
"default_popup": "popup.html",
|
||||
"browser_style": true,
|
||||
},
|
||||
},
|
||||
|
||||
background() {
|
||||
browser.browserAction.disable();
|
||||
},
|
||||
|
||||
files: {
|
||||
"popup.html": `<!DOCTYPE html><html><head><meta charset="utf-8"><script src="popup.js"></script></head></html>`,
|
||||
"popup.js"() {
|
||||
browser.test.fail("Should not get here");
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
yield extension.startup();
|
||||
|
||||
const {GlobalManager, Management: {global: {browserActionFor}}} = Cu.import("resource://gre/modules/Extension.jsm", {});
|
||||
|
||||
let ext = GlobalManager.extensionMap.get(extension.id);
|
||||
let browserAction = browserActionFor(ext);
|
||||
|
||||
let widget = getBrowserActionWidget(extension).forWindow(window);
|
||||
|
||||
// Test canceled click.
|
||||
EventUtils.synthesizeMouseAtCenter(widget.node, {type: "mousedown", button: 0}, window);
|
||||
|
||||
is(browserAction.pendingPopup, null, "Have no pending popup");
|
||||
is(browserAction.pendingPopupTimeout, null, "Have no pending popup timeout");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(document.documentElement, {type: "mouseup", button: 0}, window);
|
||||
|
||||
is(browserAction.pendingPopup, null, "Have no pending popup");
|
||||
is(browserAction.pendingPopupTimeout, null, "Have no pending popup timeout");
|
||||
|
||||
|
||||
// Test completed click.
|
||||
EventUtils.synthesizeMouseAtCenter(widget.node, {type: "mousedown", button: 0}, window);
|
||||
|
||||
is(browserAction.pendingPopup, null, "Have no pending popup");
|
||||
is(browserAction.pendingPopupTimeout, null, "Have no pending popup timeout");
|
||||
|
||||
// We need to do these tests during the mouseup event cycle, since the click
|
||||
// and command events will be dispatched immediately after mouseup, and void
|
||||
// the results.
|
||||
let mouseUpPromise = BrowserTestUtils.waitForEvent(widget.node, "mouseup", false, event => {
|
||||
is(browserAction.pendingPopup, null, "Have no pending popup");
|
||||
is(browserAction.pendingPopupTimeout, null, "Have no pending popup timeout");
|
||||
return true;
|
||||
});
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(widget.node, {type: "mouseup", button: 0}, window);
|
||||
|
||||
yield mouseUpPromise;
|
||||
|
||||
is(browserAction.pendingPopup, null, "Have no pending popup");
|
||||
is(browserAction.pendingPopupTimeout, null, "Have no pending popup timeout");
|
||||
|
||||
// Give the popup a chance to load and trigger a failure, if it was
|
||||
// erroneously opened.
|
||||
yield new Promise(resolve => setTimeout(resolve, 250));
|
||||
|
||||
yield extension.unload();
|
||||
});
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
add_task(function* test_popup_sendMessage_reply() {
|
||||
let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head><body>${url}</body></html>`;
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"browser_action": {
|
||||
"default_popup": "popup.html",
|
||||
"browser_style": true,
|
||||
},
|
||||
|
||||
"page_action": {
|
||||
"default_popup": "popup.html",
|
||||
"browser_style": true,
|
||||
},
|
||||
},
|
||||
|
||||
files: {
|
||||
"popup.html": scriptPage("popup.js"),
|
||||
"popup.js": function() {
|
||||
browser.runtime.onMessage.addListener(msg => {
|
||||
if (msg == "popup-ping") {
|
||||
return Promise.resolve("popup-pong");
|
||||
}
|
||||
});
|
||||
|
||||
browser.runtime.sendMessage("background-ping").then(response => {
|
||||
browser.test.sendMessage("background-ping-response", response);
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
background() {
|
||||
browser.tabs.query({active: true, currentWindow: true}).then(([tab]) => {
|
||||
return browser.pageAction.show(tab.id);
|
||||
}).then(() => {
|
||||
browser.test.sendMessage("page-action-ready");
|
||||
});
|
||||
|
||||
browser.runtime.onMessage.addListener(msg => {
|
||||
if (msg == "background-ping") {
|
||||
browser.runtime.sendMessage("popup-ping").then(response => {
|
||||
browser.test.sendMessage("popup-ping-response", response);
|
||||
});
|
||||
|
||||
return new Promise(resolve => {
|
||||
// Wait long enough that we're relatively sure the docShells have
|
||||
// been swapped. Note that this value is fairly arbitrary. The load
|
||||
// event that triggers the swap should happen almost immediately
|
||||
// after the message is sent. The extra quarter of a second gives us
|
||||
// enough leeway that we can expect to respond after the swap in the
|
||||
// vast majority of cases.
|
||||
setTimeout(resolve, 250);
|
||||
}).then(() => {
|
||||
return "background-pong";
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
yield extension.startup();
|
||||
|
||||
{
|
||||
clickBrowserAction(extension);
|
||||
|
||||
let pong = yield extension.awaitMessage("background-ping-response");
|
||||
is(pong, "background-pong", "Got pong");
|
||||
|
||||
pong = yield extension.awaitMessage("popup-ping-response");
|
||||
is(pong, "popup-pong", "Got pong");
|
||||
|
||||
yield closeBrowserAction(extension);
|
||||
}
|
||||
|
||||
yield extension.awaitMessage("page-action-ready");
|
||||
|
||||
{
|
||||
clickPageAction(extension);
|
||||
|
||||
let pong = yield extension.awaitMessage("background-ping-response");
|
||||
is(pong, "background-pong", "Got pong");
|
||||
|
||||
pong = yield extension.awaitMessage("popup-ping-response");
|
||||
is(pong, "popup-pong", "Got pong");
|
||||
|
||||
yield closePageAction(extension);
|
||||
}
|
||||
|
||||
yield extension.unload();
|
||||
});
|
|
@ -74,7 +74,5 @@ add_task(function* testPageAction() {
|
|||
|
||||
yield extension.unload();
|
||||
|
||||
yield new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
is(panel.parentNode, null, "Panel should be removed from the document");
|
||||
});
|
||||
|
|
|
@ -33,6 +33,7 @@ support-files =
|
|||
worker_deblobify.js
|
||||
|
||||
[browser_broadcastChannel.js]
|
||||
[browser_cookieIsolation.js]
|
||||
[browser_favicon_firstParty.js]
|
||||
[browser_favicon_userContextId.js]
|
||||
[browser_firstPartyIsolation.js]
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Bug 1312541 - A test case for document.cookie isolation.
|
||||
*/
|
||||
|
||||
const TEST_PAGE = "http://mochi.test:8888/browser/browser/components/" +
|
||||
"originattributes/test/browser/file_firstPartyBasic.html";
|
||||
|
||||
// Use a random key so we don't access it in later tests.
|
||||
const key = "key" + Math.random().toString();
|
||||
const re = new RegExp(key + "=([0-9\.]+)");
|
||||
|
||||
// Define the testing function
|
||||
function* doTest(aBrowser) {
|
||||
return yield ContentTask.spawn(aBrowser, {key, re},
|
||||
function ({key, re}) {
|
||||
let result = re.exec(content.document.cookie);
|
||||
if (result) {
|
||||
return result[1];
|
||||
}
|
||||
// No value is found, so we create one.
|
||||
let value = Math.random().toString();
|
||||
content.document.cookie = key + "=" + value;
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.cookies.removeAll();
|
||||
});
|
||||
|
||||
IsolationTestTools.runTests(TEST_PAGE, doTest);
|
|
@ -0,0 +1,177 @@
|
|||
/* 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/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/ContextualIdentityService.jsm");
|
||||
|
||||
const containersBundle = Services.strings.createBundle("chrome://browser/locale/preferences/containers.properties");
|
||||
|
||||
const HTMLNS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
let gContainersManager = {
|
||||
icons: [
|
||||
"fingerprint",
|
||||
"briefcase",
|
||||
"dollar",
|
||||
"cart",
|
||||
"circle"
|
||||
],
|
||||
|
||||
colors: [
|
||||
"blue",
|
||||
"turquoise",
|
||||
"green",
|
||||
"yellow",
|
||||
"orange",
|
||||
"red",
|
||||
"pink",
|
||||
"purple"
|
||||
],
|
||||
|
||||
onLoad() {
|
||||
let params = window.arguments[0] || {};
|
||||
this.init(params);
|
||||
},
|
||||
|
||||
init(aParams) {
|
||||
this.userContextId = aParams.userContextId || null;
|
||||
this.identity = aParams.identity;
|
||||
|
||||
if (aParams.windowTitle) {
|
||||
document.title = aParams.windowTitle;
|
||||
}
|
||||
|
||||
const iconWrapper = document.getElementById("iconWrapper");
|
||||
iconWrapper.appendChild(this.createIconButtons());
|
||||
|
||||
const colorWrapper = document.getElementById("colorWrapper");
|
||||
colorWrapper.appendChild(this.createColorSwatches());
|
||||
|
||||
if (this.identity.name) {
|
||||
const name = document.getElementById("name");
|
||||
name.value = this.identity.name;
|
||||
this.checkForm();
|
||||
}
|
||||
|
||||
this.setLabelsMinWidth();
|
||||
|
||||
// This is to prevent layout jank caused by the svgs and outlines rendering at different times
|
||||
document.getElementById("containers-content").removeAttribute("hidden");
|
||||
},
|
||||
|
||||
setLabelsMinWidth() {
|
||||
const labelMinWidth = containersBundle.GetStringFromName("containers.labelMinWidth");
|
||||
const labels = [
|
||||
document.getElementById("nameLabel"),
|
||||
document.getElementById("iconLabel"),
|
||||
document.getElementById("colorLabel")
|
||||
];
|
||||
for (let label of labels) {
|
||||
label.style.minWidth = labelMinWidth;
|
||||
}
|
||||
},
|
||||
|
||||
uninit() {
|
||||
},
|
||||
|
||||
// Check if name string as to if the form can be submitted
|
||||
checkForm() {
|
||||
const name = document.getElementById("name");
|
||||
let btnApplyChanges = document.getElementById("btnApplyChanges");
|
||||
if (!name.value) {
|
||||
btnApplyChanges.setAttribute("disabled", true);
|
||||
} else {
|
||||
btnApplyChanges.removeAttribute("disabled");
|
||||
}
|
||||
},
|
||||
|
||||
createIconButtons(defaultIcon) {
|
||||
let radiogroup = document.createElement("radiogroup");
|
||||
radiogroup.setAttribute("id", "icon");
|
||||
radiogroup.className = "icon-buttons";
|
||||
|
||||
for (let icon of this.icons) {
|
||||
let iconSwatch = document.createElement("radio");
|
||||
iconSwatch.id = "iconbutton-" + icon;
|
||||
iconSwatch.name = "icon";
|
||||
iconSwatch.type = "radio";
|
||||
iconSwatch.value = icon;
|
||||
|
||||
if (this.identity.icon && this.identity.icon == icon) {
|
||||
iconSwatch.setAttribute("selected", true);
|
||||
}
|
||||
|
||||
iconSwatch.setAttribute("label",
|
||||
containersBundle.GetStringFromName(`containers.${icon}.label`));
|
||||
let iconElement = document.createElement("hbox");
|
||||
iconElement.className = 'userContext-icon';
|
||||
iconElement.setAttribute("data-identity-icon", icon);
|
||||
|
||||
iconSwatch.appendChild(iconElement);
|
||||
radiogroup.appendChild(iconSwatch);
|
||||
}
|
||||
|
||||
return radiogroup;
|
||||
},
|
||||
|
||||
createColorSwatches(defaultColor) {
|
||||
let radiogroup = document.createElement("radiogroup");
|
||||
radiogroup.setAttribute("id", "color");
|
||||
|
||||
for (let color of this.colors) {
|
||||
let colorSwatch = document.createElement("radio");
|
||||
colorSwatch.id = "colorswatch-" + color;
|
||||
colorSwatch.name = "color";
|
||||
colorSwatch.type = "radio";
|
||||
colorSwatch.value = color;
|
||||
|
||||
if (this.identity.color && this.identity.color == color) {
|
||||
colorSwatch.setAttribute("selected", true);
|
||||
}
|
||||
|
||||
colorSwatch.setAttribute("label",
|
||||
containersBundle.GetStringFromName(`containers.${color}.label`));
|
||||
let iconElement = document.createElement("hbox");
|
||||
iconElement.className = 'userContext-icon';
|
||||
iconElement.setAttribute("data-identity-icon", "circle");
|
||||
iconElement.setAttribute("data-identity-color", color);
|
||||
|
||||
colorSwatch.appendChild(iconElement);
|
||||
radiogroup.appendChild(colorSwatch);
|
||||
}
|
||||
return radiogroup;
|
||||
},
|
||||
|
||||
onApplyChanges() {
|
||||
let icon = document.getElementById("icon").value;
|
||||
let color = document.getElementById("color").value;
|
||||
let name = document.getElementById("name").value;
|
||||
let userContextId = false;
|
||||
|
||||
if (this.icons.indexOf(icon) == -1) {
|
||||
throw "Internal error. The icon value doesn't match.";
|
||||
}
|
||||
|
||||
if (this.colors.indexOf(color) == -1) {
|
||||
throw "Internal error. The color value doesn't match.";
|
||||
}
|
||||
|
||||
if (this.userContextId) {
|
||||
ContextualIdentityService.update(this.userContextId,
|
||||
name,
|
||||
icon,
|
||||
color);
|
||||
} else {
|
||||
ContextualIdentityService.create(name,
|
||||
icon,
|
||||
color);
|
||||
}
|
||||
window.parent.location.reload()
|
||||
},
|
||||
|
||||
onWindowKeyPress(aEvent) {
|
||||
if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE)
|
||||
window.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/preferences/containers.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE dialog SYSTEM "chrome://browser/locale/preferences/containers.dtd" >
|
||||
|
||||
<window id="ContainersDialog" class="windowDialog"
|
||||
windowtype="Browser:Permissions"
|
||||
title="&window.title;"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
style="width: &window.width;;"
|
||||
onload="gContainersManager.onLoad();"
|
||||
onunload="gContainersManager.uninit();"
|
||||
persist="screenX screenY width height"
|
||||
onkeypress="gContainersManager.onWindowKeyPress(event);">
|
||||
|
||||
<script src="chrome://global/content/treeUtils.js"/>
|
||||
<script src="chrome://browser/content/preferences/containers.js"/>
|
||||
|
||||
<stringbundle id="bundlePreferences"
|
||||
src="chrome://browser/locale/preferences/preferences.properties"/>
|
||||
|
||||
<keyset>
|
||||
<key key="&windowClose.key;" modifiers="accel" oncommand="window.close();"/>
|
||||
</keyset>
|
||||
|
||||
<vbox class="contentPane largeDialogContainer" flex="1" hidden="true" id="containers-content">
|
||||
<description id="permissionsText" control="url"/>
|
||||
<separator class="thin"/>
|
||||
<hbox align="start">
|
||||
<label id="nameLabel" control="url" value="&name.label;" accesskey="&name.accesskey;"/>
|
||||
<textbox id="name" flex="1" onkeyup="gContainersManager.checkForm();" />
|
||||
</hbox>
|
||||
<hbox align="center" id="iconWrapper">
|
||||
<label id="iconLabel" control="url" value="&icon.label;" accesskey="&icon.accesskey;"/>
|
||||
</hbox>
|
||||
<hbox align="center" id="colorWrapper">
|
||||
<label id="colorLabel" control="url" value="&color.label;" accesskey="&color.accesskey;"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
<vbox>
|
||||
<hbox class="actionButtons" align="right" flex="1">
|
||||
<button id="btnApplyChanges" disabled="true" oncommand="gContainersManager.onApplyChanges();" icon="save"
|
||||
label="&button.ok.label;" accesskey="&button.ok.accesskey;"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</window>
|
|
@ -10,6 +10,10 @@
|
|||
-moz-binding: url("chrome://browser/content/preferences/handlers.xml#handler-selected");
|
||||
}
|
||||
|
||||
#containersView > richlistitem {
|
||||
-moz-binding: url("chrome://browser/content/preferences/handlers.xml#container");
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the icons appear.
|
||||
* Note: we display the icon box for every item whether or not it has an icon
|
||||
|
|
|
@ -69,6 +69,29 @@
|
|||
|
||||
</binding>
|
||||
|
||||
<binding id="container">
|
||||
<content>
|
||||
<xul:hbox flex="1" equalsize="always">
|
||||
<xul:hbox flex="1" align="center">
|
||||
<xul:hbox xbl:inherits="data-identity-icon=containerIcon,data-identity-color=containerColor" height="24" width="24" class="userContext-icon"/>
|
||||
<xul:label flex="1" crop="end" xbl:inherits="value=containerName"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox flex="1" align="right">
|
||||
<xul:button anonid="preferencesButton"
|
||||
xbl:inherits="value=userContextId"
|
||||
onclick="gContainersPane.onPeferenceClick(event.originalTarget)">
|
||||
Preferences
|
||||
</xul:button>
|
||||
<xul:button anonid="removeButton"
|
||||
xbl:inherits="value=userContextId"
|
||||
onclick="gContainersPane.onRemoveClick(event.originalTarget)">
|
||||
Remove
|
||||
</xul:button>
|
||||
</xul:hbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="offlineapp"
|
||||
extends="chrome://global/content/bindings/listbox.xml#listitem">
|
||||
<content>
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/* 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/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/AppConstants.jsm");
|
||||
Components.utils.import("resource://gre/modules/ContextualIdentityService.jsm");
|
||||
|
||||
const containersBundle = Services.strings.createBundle("chrome://browser/locale/preferences/containers.properties");
|
||||
|
||||
const defaultContainerIcon = "fingerprint";
|
||||
const defaultContainerColor = "blue";
|
||||
|
||||
let gContainersPane = {
|
||||
|
||||
init() {
|
||||
this._list = document.getElementById("containersView");
|
||||
|
||||
document.getElementById("backContainersLink").addEventListener("click", function () {
|
||||
gotoPref("privacy");
|
||||
});
|
||||
|
||||
this._rebuildView();
|
||||
},
|
||||
|
||||
_rebuildView() {
|
||||
const containers = ContextualIdentityService.getIdentities();
|
||||
while (this._list.firstChild) {
|
||||
this._list.firstChild.remove();
|
||||
}
|
||||
for (let container of containers) {
|
||||
let item = document.createElement("richlistitem");
|
||||
item.setAttribute("containerName", ContextualIdentityService.getUserContextLabel(container.userContextId));
|
||||
item.setAttribute("containerIcon", container.icon);
|
||||
item.setAttribute("containerColor", container.color);
|
||||
item.setAttribute("userContextId", container.userContextId);
|
||||
|
||||
this._list.appendChild(item);
|
||||
}
|
||||
},
|
||||
|
||||
onRemoveClick(button) {
|
||||
let userContextId = button.getAttribute("value");
|
||||
ContextualIdentityService.remove(userContextId);
|
||||
this._rebuildView();
|
||||
},
|
||||
onPeferenceClick(button) {
|
||||
this.openPreferenceDialog(button.getAttribute("value"));
|
||||
},
|
||||
|
||||
onAddButtonClick(button) {
|
||||
this.openPreferenceDialog(null);
|
||||
},
|
||||
|
||||
openPreferenceDialog(userContextId) {
|
||||
let identity = {
|
||||
name: "",
|
||||
icon: defaultContainerIcon,
|
||||
color: defaultContainerColor
|
||||
};
|
||||
let title;
|
||||
if (userContextId) {
|
||||
identity = ContextualIdentityService.getIdentityFromId(userContextId);
|
||||
// This is required to get the translation string from defaults
|
||||
identity.name = ContextualIdentityService.getUserContextLabel(identity.userContextId);
|
||||
title = containersBundle.formatStringFromName("containers.updateContainerTitle", [identity.name], 1);
|
||||
}
|
||||
|
||||
const params = { userContextId, identity, windowTitle: title };
|
||||
gSubDialog.open("chrome://browser/content/preferences/containers.xul",
|
||||
null, params);
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,54 @@
|
|||
# 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/.
|
||||
|
||||
<!-- Containers panel -->
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/preferences/in-content/containers.js"/>
|
||||
|
||||
<preferences id="containerPreferences" hidden="true" data-category="paneContainer">
|
||||
<!-- Containers -->
|
||||
<preference id="privacy.userContext.enabled"
|
||||
name="privacy.userContext.enabled"
|
||||
type="bool"/>
|
||||
|
||||
</preferences>
|
||||
|
||||
<hbox hidden="true"
|
||||
class="container-header-links"
|
||||
data-category="paneContainers">
|
||||
<label class="text-link" id="backContainersLink" value="&backLink.label;" />
|
||||
</hbox>
|
||||
|
||||
<hbox id="header-containers"
|
||||
class="header"
|
||||
hidden="true"
|
||||
data-category="paneContainers">
|
||||
<label class="header-name" flex="1">&paneContainers.title;</label>
|
||||
<button class="help-button"
|
||||
aria-label="&helpButton.label;"/>
|
||||
</hbox>
|
||||
|
||||
<!-- Containers -->
|
||||
<groupbox id="browserContainersGroup" data-category="paneContainers" hidden="true">
|
||||
<vbox id="browserContainersbox">
|
||||
|
||||
<richlistbox id="containersView" orient="vertical" persist="lastSelectedType"
|
||||
flex="1">
|
||||
<listheader equalsize="always">
|
||||
<treecol id="typeColumn" label="&label.label;" value="type"
|
||||
persist="sortDirection"
|
||||
flex="1" sortDirection="ascending"/>
|
||||
<treecol id="actionColumn" value="action"
|
||||
persist="sortDirection"
|
||||
flex="1"/>
|
||||
</listheader>
|
||||
</richlistbox>
|
||||
</vbox>
|
||||
<vbox>
|
||||
<hbox flex="1">
|
||||
<button onclick="gContainersPane.onAddButtonClick();" accesskey="&addButton.accesskey;" label="&addButton.label;"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</groupbox>
|
|
@ -9,6 +9,7 @@ browser.jar:
|
|||
|
||||
content/browser/preferences/in-content/main.js
|
||||
content/browser/preferences/in-content/privacy.js
|
||||
content/browser/preferences/in-content/containers.js
|
||||
content/browser/preferences/in-content/advanced.js
|
||||
content/browser/preferences/in-content/applications.js
|
||||
content/browser/preferences/in-content/content.js
|
||||
|
|
|
@ -61,6 +61,7 @@ function init_all() {
|
|||
register_module("paneGeneral", gMainPane);
|
||||
register_module("paneSearch", gSearchPane);
|
||||
register_module("panePrivacy", gPrivacyPane);
|
||||
register_module("paneContainers", gContainersPane);
|
||||
register_module("paneAdvanced", gAdvancedPane);
|
||||
register_module("paneApplications", gApplicationsPane);
|
||||
register_module("paneContent", gContentPane);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
href="chrome://browser/content/preferences/handlers.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/preferences/applications.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/preferences/in-content/search.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/preferences/in-content/containers.css"?>
|
||||
|
||||
<!DOCTYPE page [
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
|
@ -26,6 +27,8 @@
|
|||
<!ENTITY % syncDTD SYSTEM "chrome://browser/locale/preferences/sync.dtd">
|
||||
<!ENTITY % securityDTD SYSTEM
|
||||
"chrome://browser/locale/preferences/security.dtd">
|
||||
<!ENTITY % containersDTD SYSTEM
|
||||
"chrome://browser/locale/preferences/containers.dtd">
|
||||
<!ENTITY % sanitizeDTD SYSTEM "chrome://browser/locale/sanitize.dtd">
|
||||
<!ENTITY % mainDTD SYSTEM "chrome://browser/locale/preferences/main.dtd">
|
||||
<!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
|
||||
|
@ -43,6 +46,7 @@
|
|||
%syncBrandDTD;
|
||||
%syncDTD;
|
||||
%securityDTD;
|
||||
%containersDTD;
|
||||
%sanitizeDTD;
|
||||
%mainDTD;
|
||||
%aboutHomeDTD;
|
||||
|
@ -137,6 +141,12 @@
|
|||
<label class="category-name" flex="1">&panePrivacy.title;</label>
|
||||
</richlistitem>
|
||||
|
||||
<richlistitem id="category-containers"
|
||||
class="category"
|
||||
value="paneContainers"
|
||||
helpTopic="prefs-containers"
|
||||
hidden="true"/>
|
||||
|
||||
<richlistitem id="category-security"
|
||||
class="category"
|
||||
value="paneSecurity"
|
||||
|
@ -173,6 +183,7 @@
|
|||
#include main.xul
|
||||
#include search.xul
|
||||
#include privacy.xul
|
||||
#include containers.xul
|
||||
#include advanced.xul
|
||||
#include applications.xul
|
||||
#include content.xul
|
||||
|
|
|
@ -178,6 +178,8 @@ var gPrivacyPane = {
|
|||
gPrivacyPane.showBlockLists);
|
||||
setEventListener("browserContainersCheckbox", "command",
|
||||
gPrivacyPane._checkBrowserContainers);
|
||||
setEventListener("browserContainersSettings", "command",
|
||||
gPrivacyPane.showContainerSettings);
|
||||
},
|
||||
|
||||
// TRACKING PROTECTION MODE
|
||||
|
@ -475,6 +477,13 @@ var gPrivacyPane = {
|
|||
null, params);
|
||||
},
|
||||
|
||||
/**
|
||||
* Displays container panel for customising and adding containers.
|
||||
*/
|
||||
showContainerSettings() {
|
||||
gotoPref("containers");
|
||||
},
|
||||
|
||||
/**
|
||||
* Displays the available block lists for tracking protection.
|
||||
*/
|
||||
|
@ -678,6 +687,26 @@ var gPrivacyPane = {
|
|||
var sanitizeOnShutdownPref = document.getElementById("privacy.sanitize.sanitizeOnShutdown");
|
||||
|
||||
settingsButton.disabled = !sanitizeOnShutdownPref.value;
|
||||
},
|
||||
|
||||
// CONTAINERS
|
||||
|
||||
/*
|
||||
* preferences:
|
||||
*
|
||||
* privacy.userContext.enabled
|
||||
* - true if containers is enabled
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enables/disables the Settings button used to configure containers
|
||||
*/
|
||||
readBrowserContainersCheckbox: function ()
|
||||
{
|
||||
var pref = document.getElementById("privacy.userContext.enabled");
|
||||
var settings = document.getElementById("browserContainersSettings");
|
||||
|
||||
settings.disabled = !pref.value;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -289,8 +289,20 @@
|
|||
<label id="browserContainersLearnMore" class="text-link"
|
||||
value="&browserContainersLearnMore.label;"/>
|
||||
</label></caption>
|
||||
<hbox align="start">
|
||||
<vbox>
|
||||
<checkbox id="browserContainersCheckbox"
|
||||
label="&browserContainersEnabled.label;"
|
||||
accesskey="&browserContainersEnabled.accesskey;" />
|
||||
accesskey="&browserContainersEnabled.accesskey;"
|
||||
preference="privacy.userContext.enabled"
|
||||
onsyncfrompreference="return gPrivacyPane.readBrowserContainersCheckbox();"/>
|
||||
</vbox>
|
||||
<spacer flex="1"/>
|
||||
<vbox>
|
||||
<button id="browserContainersSettings"
|
||||
label="&browserContainersSettings.label;"
|
||||
accesskey="&browserContainersSettings.accesskey;"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</groupbox>
|
||||
|
|
|
@ -20,6 +20,8 @@ browser.jar:
|
|||
* content/browser/preferences/languages.xul
|
||||
content/browser/preferences/languages.js
|
||||
content/browser/preferences/permissions.xul
|
||||
content/browser/preferences/containers.xul
|
||||
content/browser/preferences/containers.js
|
||||
content/browser/preferences/permissions.js
|
||||
content/browser/preferences/sanitize.xul
|
||||
content/browser/preferences/sanitize.js
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
// Step 3: load a page in the tab from step 1 that checks the value of test2 is value2 and the total count in non-private storage is 1
|
||||
// Step 4: load a page in the tab from step 2 that checks the value of test is value and the total count in private storage is 1
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function test() {
|
||||
let prefix = 'http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent_page.html';
|
||||
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
let win = yield BrowserTestUtils.openNewBrowserWindow();
|
||||
|
||||
|
|
|
@ -691,6 +691,9 @@ userContextBanking.accesskey = B
|
|||
userContextShopping.accesskey = S
|
||||
userContextNone.accesskey = N
|
||||
|
||||
userContext.aboutPage.label = Manage containers
|
||||
userContext.aboutPage.accesskey = O
|
||||
|
||||
userContextOpenLink.label = Open Link in New %S Tab
|
||||
|
||||
muteTab.label = Mute Tab
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
<!ENTITY generalTab "General">
|
||||
<!ENTITY generalTab.accesskey "G">
|
||||
<!ENTITY generalTitle "Title:">
|
||||
<!ENTITY generalURL "Address:">
|
||||
<!ENTITY generalType "Type:">
|
||||
<!ENTITY generalMode "Render Mode:">
|
||||
|
|
|
@ -6,7 +6,6 @@ pageInfo.page.title=Page Info - %S
|
|||
pageInfo.frame.title=Frame Info - %S
|
||||
|
||||
noPageTitle=Untitled Page:
|
||||
pageTitle=%S:
|
||||
unknown=Unknown
|
||||
notset=Not specified
|
||||
yes=Yes
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<!-- 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/. -->
|
||||
|
||||
<!ENTITY label.label "Name">
|
||||
<!ENTITY addButton.label "Add New Container">
|
||||
<!ENTITY addButton.accesskey "A">
|
||||
<!-- « is « however it's not defined in XML -->
|
||||
<!ENTITY backLink.label "« Go Back to Privacy">
|
||||
|
||||
<!ENTITY window.title "Add New Container">
|
||||
<!ENTITY window.width "45em">
|
||||
|
||||
<!ENTITY name.label "Name:">
|
||||
<!ENTITY name.accesskey "N">
|
||||
<!ENTITY icon.label "Icon:">
|
||||
<!ENTITY icon.accesskey "I">
|
||||
<!ENTITY color.label "Color:">
|
||||
<!ENTITY color.accesskey "o">
|
||||
<!ENTITY windowClose.key "w">
|
||||
|
||||
<!ENTITY button.ok.label "Done">
|
||||
<!ENTITY button.ok.accesskey "D">
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
# 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/.
|
||||
|
||||
containers.removeButton = Remove
|
||||
containers.preferencesButton = Preferences
|
||||
containers.colorHeading = Color:
|
||||
containers.labelMinWidth = 4rem
|
||||
containers.nameLabel = Name:
|
||||
containers.namePlaceholder = Enter a container name
|
||||
containers.submitButton = Done
|
||||
containers.iconHeading = Icon:
|
||||
containers.updateContainerTitle = %S Container Preferences
|
||||
|
||||
containers.blue.label = Blue
|
||||
containers.turquoise.label = Turquoise
|
||||
containers.green.label = Green
|
||||
containers.yellow.label = Yellow
|
||||
containers.orange.label = Orange
|
||||
containers.red.label = Red
|
||||
containers.pink.label = Pink
|
||||
containers.purple.label = Purple
|
||||
|
||||
containers.fingerprint.label = Fingerprint
|
||||
containers.briefcase.label = Briefcase
|
||||
# LOCALIZATION NOTE (containers.dollar.label)
|
||||
# String represents a money sign but currently uses a dollar sign so don't change to local currency
|
||||
# See Bug 1291672
|
||||
containers.dollar.label = Dollar sign
|
||||
containers.cart.label = Shopping cart
|
||||
containers.circle.label = Dot
|
|
@ -19,6 +19,7 @@
|
|||
<!ENTITY paneContent.title "Content">
|
||||
<!ENTITY paneApplications.title "Applications">
|
||||
<!ENTITY panePrivacy.title "Privacy">
|
||||
<!ENTITY paneContainers.title "Container Tabs">
|
||||
<!ENTITY paneSecurity.title "Security">
|
||||
<!ENTITY paneAdvanced.title "Advanced">
|
||||
|
||||
|
|
|
@ -109,3 +109,5 @@
|
|||
<!ENTITY browserContainersLearnMore.label "Learn more">
|
||||
<!ENTITY browserContainersEnabled.label "Enable Container Tabs">
|
||||
<!ENTITY browserContainersEnabled.accesskey "n">
|
||||
<!ENTITY browserContainersSettings.label "Settings…">
|
||||
<!ENTITY browserContainersSettings.accesskey "i">
|
||||
|
|
|
@ -75,8 +75,10 @@
|
|||
locale/browser/preferences/permissions.dtd (%chrome/browser/preferences/permissions.dtd)
|
||||
locale/browser/preferences/preferences.dtd (%chrome/browser/preferences/preferences.dtd)
|
||||
locale/browser/preferences/preferences.properties (%chrome/browser/preferences/preferences.properties)
|
||||
locale/browser/preferences/containers.properties (%chrome/browser/preferences/containers.properties)
|
||||
locale/browser/preferences/privacy.dtd (%chrome/browser/preferences/privacy.dtd)
|
||||
locale/browser/preferences/security.dtd (%chrome/browser/preferences/security.dtd)
|
||||
locale/browser/preferences/containers.dtd (%chrome/browser/preferences/containers.dtd)
|
||||
locale/browser/preferences/sync.dtd (%chrome/browser/preferences/sync.dtd)
|
||||
locale/browser/preferences/tabs.dtd (%chrome/browser/preferences/tabs.dtd)
|
||||
locale/browser/preferences/search.dtd (%chrome/browser/preferences/search.dtd)
|
||||
|
|
|
@ -11,26 +11,16 @@ Components.utils.import("resource://gre/modules/Services.jsm");
|
|||
|
||||
var URLBarZoom = {
|
||||
|
||||
init(aWindow) {
|
||||
init: function(aWindow) {
|
||||
// Register ourselves with the service so we know when the zoom prefs change.
|
||||
Services.obs.addObserver(this, "browser-fullZoom:zoomChange", false);
|
||||
Services.obs.addObserver(this, "browser-fullZoom:zoomReset", false);
|
||||
Services.obs.addObserver(this, "browser-fullZoom:location-change", false);
|
||||
Services.obs.addObserver(updateZoomButton, "browser-fullZoom:zoomChange", false);
|
||||
Services.obs.addObserver(updateZoomButton, "browser-fullZoom:zoomReset", false);
|
||||
Services.obs.addObserver(updateZoomButton, "browser-fullZoom:location-change", false);
|
||||
},
|
||||
|
||||
observe(aSubject, aTopic) {
|
||||
this.updateZoomButton(aSubject, aTopic);
|
||||
},
|
||||
|
||||
updateZoomButton(aSubject, aTopic) {
|
||||
// aSubject.ownerGlobal may no longer exist if a tab has been dragged to a
|
||||
// new window. In this case, aSubject.ownerGlobal will be supplied by
|
||||
// updateZoomButton() called in XULBrowserWindow.onLocationChange().
|
||||
if (!aSubject.ownerGlobal) {
|
||||
return;
|
||||
}
|
||||
|
||||
let win = aSubject.ownerGlobal;
|
||||
function updateZoomButton(aSubject, aTopic) {
|
||||
let win = aSubject.ownerDocument.defaultView;
|
||||
let customizableZoomControls = win.document.getElementById("zoom-controls");
|
||||
let zoomResetButton = win.document.getElementById("urlbar-zoom-button");
|
||||
let zoomFactor = Math.round(win.ZoomManager.zoom * 100);
|
||||
|
@ -54,9 +44,8 @@ var URLBarZoom = {
|
|||
}
|
||||
zoomResetButton.setAttribute("label",
|
||||
win.gNavigatorBundle.getFormattedString("urlbar-zoom-button.label", [zoomFactor]));
|
||||
} else {
|
||||
// Hide button if zoom is at 100%
|
||||
} else {
|
||||
zoomResetButton.hidden = true;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/* Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
%include ../../../components/contextualidentity/content/usercontext.css
|
||||
|
||||
.container-header-links {
|
||||
margin-block-end: 15px;
|
||||
}
|
||||
|
||||
[data-identity-icon] {
|
||||
margin: 0;
|
||||
margin-inline-end: 16px;
|
||||
}
|
||||
|
||||
#containersView {
|
||||
border: 0 none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#containersView richlistitem {
|
||||
margin: 0px;
|
||||
margin-inline-end: 8px;
|
||||
padding: 0;
|
||||
padding-block-end: 8px;
|
||||
border-block-end: 1px solid var(--in-content-header-border-color);
|
||||
}
|
||||
|
||||
#containersView richlistitem:last-of-type {
|
||||
border-block-end: 0 none;
|
||||
margin-block-end: 8px;
|
||||
}
|
|
@ -77,6 +77,8 @@
|
|||
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico)
|
||||
skin/classic/browser/preferences/in-content/icons.svg (../shared/incontentprefs/icons.svg)
|
||||
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css)
|
||||
* skin/classic/browser/preferences/in-content/containers.css (../shared/incontentprefs/containers.css)
|
||||
* skin/classic/browser/preferences/containers.css (../shared/preferences/containers.css)
|
||||
skin/classic/browser/fxa/default-avatar.svg (../shared/fxa/default-avatar.svg)
|
||||
skin/classic/browser/fxa/logo.png (../shared/fxa/logo.png)
|
||||
skin/classic/browser/fxa/logo@2x.png (../shared/fxa/logo@2x.png)
|
||||
|
@ -148,7 +150,3 @@
|
|||
skin/classic/browser/devedition/urlbar-history-dropmarker.svg (../shared/devedition/urlbar-history-dropmarker.svg)
|
||||
skin/classic/browser/urlbar-star.svg (../shared/urlbar-star.svg)
|
||||
skin/classic/browser/urlbar-tab.svg (../shared/urlbar-tab.svg)
|
||||
skin/classic/browser/usercontext/personal.svg (../shared/usercontext/personal.svg)
|
||||
skin/classic/browser/usercontext/work.svg (../shared/usercontext/work.svg)
|
||||
skin/classic/browser/usercontext/banking.svg (../shared/usercontext/banking.svg)
|
||||
skin/classic/browser/usercontext/shopping.svg (../shared/usercontext/shopping.svg)
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/* Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
%include ../../../components/contextualidentity/content/usercontext.css
|
||||
|
||||
:root {
|
||||
--preference-selected-color: #0996f8;
|
||||
--preference-unselected-color: #333;
|
||||
--preference-active-color: #858585;
|
||||
}
|
||||
|
||||
radiogroup {
|
||||
display: flex;
|
||||
margin-inline-start: 0.35rem;
|
||||
}
|
||||
|
||||
radio {
|
||||
flex: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
-moz-user-select: none;
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 4px;
|
||||
-moz-outline-radius: 100%;
|
||||
min-block-size: 24px;
|
||||
min-inline-size: 24px;
|
||||
border-radius: 50%;
|
||||
padding: 2px;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.icon-buttons > radio > [data-identity-icon] {
|
||||
fill: #4d4d4d;
|
||||
}
|
||||
|
||||
radio > [data-identity-icon] {
|
||||
inline-size: 22px;
|
||||
block-size: 22px;
|
||||
}
|
||||
|
||||
radio[selected=true] {
|
||||
outline-color: var(--preference-unselected-color);
|
||||
}
|
||||
|
||||
radio[focused=true] {
|
||||
outline-color: var(--preference-selected-color);
|
||||
}
|
||||
|
||||
radio:hover:active {
|
||||
outline-color: var(--preference-active-color);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="#7dc14c" d="M17.3857868,14.0527919 C14.2304569,13.0862944 13.4913706,12.4609137 13.4913706,11.0964467 C13.4913706,9.61827411 14.7137056,8.85076142 16.4192893,8.85076142 C17.9827411,8.85076142 19.3187817,9.33401015 20.5979695,10.4994924 L22.4456853,8.42436548 C21.1664975,7.20203046 19.3187819,6.26535905 17,6.00952148 L17,2 L15,2 L15,6.00952148 C12.3827412,6.43591742 9.76751269,8.53807107 9.76751269,11.3238579 C9.76751269,14.1664975 11.4730964,15.786802 15.4812183,17.0091371 C18.4375635,17.9187817 19.2335025,18.6294416 19.2335025,20.2213198 C19.2335025,22.0690355 17.7553299,23.035533 15.7370558,23.035533 C13.7756345,23.035533 12.2406091,22.3248731 10.9329949,21.1025381 L9,23.2345178 C10.4213198,24.6274112 12.8659899,25.8324934 15,26.0030518 L15,30 L17,30 L17,26.0030518 C20.7116753,25.4060974 22.9857868,22.893401 22.9857868,20.022335 C22.9857868,16.4690355 20.7116751,15.1045685 17.3857868,14.0527919 Z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 1.2 KiB |
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="#00a7e0" d="M7.17741905,12 C7.10965537,12 7.041327,11.9953181 6.97243393,11.985018 C6.33263187,11.8918489 5.90515601,11.3862071 6.01809547,10.8552833 C7.41798011,4.26321358 12.2613889,2.57493207 15.0238882,2.15590491 C19.6448063,1.45690206 24.3408291,3.21541158 25.8344535,5.29743816 C26.1664955,5.76047488 25.9835336,6.35881757 25.4244832,6.63364321 C24.8654329,6.9098734 24.1437497,6.75583996 23.8122724,6.29327142 C22.8923805,5.01043967 19.1749781,3.51130562 15.4479759,4.07406612 C12.8080159,4.474834 9.43056132,6.03623689 8.33561323,11.1942506 C8.23453242,11.666651 7.73816348,12 7.17741905,12 Z M16.63127,26 C16.1452186,26 15.6509104,25.9658335 15.147795,25.8938767 C10.637921,25.257137 6.71207921,21.8114952 6.01575422,17.8807924 C5.91171832,17.2932317 6.33391695,16.7382846 6.95813239,16.6404441 C7.58454965,16.5343208 8.17298555,16.9406954 8.27757192,17.5272206 C8.80876054,20.5255916 11.9766264,23.26409 15.4885263,23.7610576 C17.3975027,24.02766 20.959494,23.8221432 23.3220449,19.3789425 C24.4625867,17.2331815 23.0049831,11.881462 19.9521622,9.34692739 C18.2380468,7.92384005 16.4573263,7.76905536 14.6628445,8.89499751 C13.26469,9.77142052 11.8070864,12.2857658 11.8665355,14.6287608 C11.9127737,16.4835887 12.8386382,17.9325598 14.6171568,18.9363308 C15.2210054,19.2764429 16.9411759,19.4933486 17.9424527,18.8296898 C18.7257495,18.3104622 18.9591422,17.2761485 18.6365758,15.7583267 C18.3822659,14.5650869 17.2219077,12.4452096 16.6664991,12.3711821 C16.6692513,12.3722175 16.4666841,12.4312324 16.1276041,12.9095636 C15.8545786,13.2936782 15.58981,14.7297074 15.9476054,15.3581643 C16.0142104,15.4761941 16.0725586,15.5465978 16.3202632,15.5465978 C16.9532859,15.5465978 17.46686,16.0290705 17.46686,16.6249139 C17.46686,17.2207573 16.9543868,17.7042653 16.3213641,17.7042653 C15.2644914,17.7042653 14.4140391,17.2336992 13.9268868,16.3774655 C13.1083609,14.9388479 13.5536787,12.6548678 14.2202791,11.7137354 C15.2540327,10.2564816 16.3631986,10.1151564 17.1123672,10.2564816 C19.7066595,10.7389543 20.8763754,15.2908666 20.8857331,15.3359043 C21.5303153,18.3648181 20.3594985,19.8665919 19.264094,20.593407 C17.4151172,21.8192603 14.6920186,21.493643 13.4380832,20.7859819 C10.3280151,19.0310652 9.62013053,16.497566 9.5744428,14.6805283 C9.49022326,11.3643051 11.4779146,8.30018945 13.391845,7.10021984 C16.0417332,5.43848454 18.9877658,5.66781436 21.4714167,7.72919442 C25.1176276,10.7565552 27.0871539,17.1229168 25.3746898,20.3433702 C23.4326862,23.9950465 20.2983981,26 16.63127,26 Z M16.0845157,30 C14.9348455,30 13.9050564,29.8557557 13.0394288,29.6610017 C10.2114238,29.0257442 7.58700058,27.4599412 6.18892823,25.5735955 C5.84440518,25.1078371 5.98426642,24.4803503 6.50105099,24.1700066 C7.01675554,23.8596629 7.71552172,23.986423 8.06112477,24.4507244 C9.89498097,26.9252176 15.9397944,29.9781448 22.2508301,26.1937972 C22.7676147,25.8844249 23.4658409,26.0087566 23.8109039,26.474515 C24.155427,26.9397877 24.0161057,27.5672745 23.4993212,27.8776182 C20.7987573,29.4963593 18.2315746,30 16.0845157,30 Z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 3.3 KiB |
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="#ee5195" fill-rule="evenodd" d="M20.8195396,14 L15.1804604,14 L15.1804604,14 L15.8471271,18 L20.1528729,18 L20.8195396,14 Z M22.8471271,14 L27.6125741,14 L27.6125741,14 L26.2792408,18 L22.1804604,18 L22.8471271,14 Z M21.1528729,12 L14.8471271,12 L14.8471271,12 L14.1804604,8 L21.8195396,8 L21.1528729,12 Z M23.1804604,12 L28.2792408,12 L28.2792408,12 L29.6125741,8 L23.8471271,8 L23.1804604,12 Z M13.1528729,14 L8.47703296,14 L10.077033,18 L10.077033,18 L13.8195396,18 L13.1528729,14 Z M12.8195396,12 L7.67703296,12 L6.07703296,8 L12.1528729,8 L12.8195396,12 L12.8195396,12 Z M31.7207592,8 L32,8 L32,6 L31,6 L5.27703296,6 L5.27703296,6 L4,2.8074176 L4,2 L3,2 L1,2 L0,2 L0,4 L1,4 L2.32296704,4 L9.78931928,22.6658806 L9.78931928,22.6658806 C8.71085924,23.3823847 8,24.6081773 8,26 C8,28.209139 9.790861,30 12,30 C14.209139,30 16,28.209139 16,26 C16,25.2714257 15.8052114,24.5883467 15.4648712,24 L22.5351288,24 C22.1947886,24.5883467 22,25.2714257 22,26 C22,28.209139 23.790861,30 26,30 C28.209139,30 30,28.209139 30,26 C30,23.790861 28.209139,22 26,22 L11.677033,22 L10.877033,20 L27,20 L28,20 L28,19.1622777 L31.7207592,8 L31.7207592,8 Z M26,28 C27.1045695,28 28,27.1045695 28,26 C28,24.8954305 27.1045695,24 26,24 C24.8954305,24 24,24.8954305 24,26 C24,27.1045695 24.8954305,28 26,28 Z M12,28 C13.1045695,28 14,27.1045695 14,26 C14,24.8954305 13.1045695,24 12,24 C10.8954305,24 10,24.8954305 10,26 C10,27.1045695 10.8954305,28 12,28 Z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 1.8 KiB |
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="#f89c24" fill-rule="evenodd" d="M22,9.99887085 L21.635468,10 L29.0034652,10 C29.5538362,10 30,10.4449463 30,10.9933977 L30,27.0066023 C30,27.5552407 29.5601869,28 29.0034652,28 L2.99653482,28 C2.44616384,28 2,27.5550537 2,27.0066023 L2,10.9933977 C2,10.4447593 2.43981314,10 2.99653482,10 L8,10 L8,7.99922997 C8,5.79051625 10.0426627,4 12.5635454,4 L19.4364546,4 C21.9568311,4 24,5.79246765 24,7.99922997 L24,9.99267578 L22,9.99887085 L22,10 L10,10 L10,7.99922997 C10,6.89421235 11.0713286,6 12.3917227,6 L19.6082773,6 C20.9273761,6 22,6.89552665 22,7.99922997 L22,9.99887085 Z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 941 B |
|
@ -263,7 +263,7 @@ case "$target" in
|
|||
break
|
||||
fi
|
||||
done
|
||||
if test "$android_build_tools_version" == ""; then
|
||||
if test "$android_build_tools_version" = ""; then
|
||||
version=$(echo $2 | cut -d" " -f1)
|
||||
AC_MSG_ERROR([You must install the Android build-tools version $version. Try |mach bootstrap|. (Looked for "$android_build_tools_base"/$version)])
|
||||
fi
|
||||
|
|
|
@ -18,6 +18,7 @@ add_task(function* () {
|
|||
["dom.serviceWorkers.testing.enabled", true],
|
||||
["dom.serviceWorkers.idle_timeout", SW_TIMEOUT],
|
||||
["dom.serviceWorkers.idle_extended_timeout", SW_TIMEOUT],
|
||||
["dom.ipc.processCount", 1],
|
||||
]
|
||||
});
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ add_task(function* () {
|
|||
let options = { "set": [
|
||||
// Accept workers from mochitest's http.
|
||||
["dom.serviceWorkers.testing.enabled", true],
|
||||
["dom.ipc.processCount", 1],
|
||||
]};
|
||||
SpecialPowers.pushPrefEnv(options, done);
|
||||
});
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
|
||||
const TAB_URL = "data:text/html,<title>foo</title>";
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
let { tab, document } = yield openAboutDebugging("tabs");
|
||||
|
||||
|
|
|
@ -4,6 +4,12 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
// Test that the spacebar key press toggles the toggleAll button state
|
||||
// when a node with no animation is selected.
|
||||
// This test doesn't need to test if animations actually pause/resume
|
||||
|
|
|
@ -37,6 +37,7 @@ support-files =
|
|||
[browser_toolbox_computed_view.js]
|
||||
[browser_toolbox_rule_view.js]
|
||||
[browser_toolbox_swap_browsers.js]
|
||||
skip-if = true # Bug 1315042
|
||||
[browser_touch_simulation.js]
|
||||
[browser_viewport_basics.js]
|
||||
[browser_window_close.js]
|
||||
|
|
|
@ -13,6 +13,12 @@ const TEST_DOC = "https://example.com/browser/devtools/client/webconsole/" +
|
|||
"test/test_bug1092055_shouldwarn.html";
|
||||
const SAMPLE_MSG = "specified a header that could not be parsed successfully.";
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
let { browser } = yield loadTab(TEST_URI);
|
||||
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
const TEST_URI = "data:text/html;charset=utf-8,Web Console test for splitting";
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount", 1]]}, runTest);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
// Test is slow on Linux EC2 instances - Bug 962931
|
||||
requestLongerTimeout(2);
|
||||
|
||||
|
|
|
@ -4,6 +4,12 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
// Check that the duration, iterationCount and delay are retrieved correctly for
|
||||
// multiple animations.
|
||||
|
||||
|
|
|
@ -241,8 +241,8 @@ EdgeInclusiveIntersection(const nsRect& aRect, const nsRect& aOtherRect)
|
|||
void
|
||||
DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time)
|
||||
{
|
||||
Element* root;
|
||||
nsIFrame* rootFrame;
|
||||
Element* root = nullptr;
|
||||
nsIFrame* rootFrame = nullptr;
|
||||
nsRect rootRect;
|
||||
|
||||
if (mRoot) {
|
||||
|
|
|
@ -16,7 +16,9 @@ DocGroup::GetKey(nsIPrincipal* aPrincipal, nsACString& aKey)
|
|||
aKey.Truncate();
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// GetBaseDomain works fine if |uri| is null, but it outputs a warning
|
||||
// which ends up cluttering the logs.
|
||||
if (NS_SUCCEEDED(rv) && uri) {
|
||||
nsCOMPtr<nsIEffectiveTLDService> tldService =
|
||||
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
|
||||
if (tldService) {
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "mozilla/AnimationComparator.h"
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/ContentEvents.h"
|
||||
#include "mozilla/DeclarationBlockInlines.h"
|
||||
#include "mozilla/EffectSet.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
|
@ -1967,7 +1968,7 @@ Element::GetSMILOverrideStyle()
|
|||
return slots->mSMILOverrideStyle;
|
||||
}
|
||||
|
||||
css::Declaration*
|
||||
DeclarationBlock*
|
||||
Element::GetSMILOverrideStyleDeclaration()
|
||||
{
|
||||
Element::nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
|
@ -1975,7 +1976,7 @@ Element::GetSMILOverrideStyleDeclaration()
|
|||
}
|
||||
|
||||
nsresult
|
||||
Element::SetSMILOverrideStyleDeclaration(css::Declaration* aDeclaration,
|
||||
Element::SetSMILOverrideStyleDeclaration(DeclarationBlock* aDeclaration,
|
||||
bool aNotify)
|
||||
{
|
||||
Element::nsDOMSlots *slots = DOMSlots();
|
||||
|
|
|
@ -271,15 +271,15 @@ public:
|
|||
* Get the SMIL override style declaration for this element. If the
|
||||
* rule hasn't been created, this method simply returns null.
|
||||
*/
|
||||
virtual css::Declaration* GetSMILOverrideStyleDeclaration();
|
||||
virtual DeclarationBlock* GetSMILOverrideStyleDeclaration();
|
||||
|
||||
/**
|
||||
* Set the SMIL override style declaration for this element. If
|
||||
* aNotify is true, this method will notify the document's pres
|
||||
* context, so that the style changes will be noticed.
|
||||
*/
|
||||
virtual nsresult SetSMILOverrideStyleDeclaration(css::Declaration* aDeclaration,
|
||||
bool aNotify);
|
||||
virtual nsresult SetSMILOverrideStyleDeclaration(
|
||||
DeclarationBlock* aDeclaration, bool aNotify);
|
||||
|
||||
/**
|
||||
* Returns a new nsISMILAttr that allows the caller to animate the given
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "mozilla/dom/FragmentOrElement.h"
|
||||
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/DeclarationBlockInlines.h"
|
||||
#include "mozilla/EffectSet.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
|
|
|
@ -33,9 +33,7 @@ class nsDOMStringMap;
|
|||
class nsIURI;
|
||||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
class Declaration;
|
||||
} // namespace css
|
||||
class DeclarationBlock;
|
||||
namespace dom {
|
||||
class DOMIntersectionObserver;
|
||||
class Element;
|
||||
|
@ -284,7 +282,7 @@ public:
|
|||
/**
|
||||
* Holds any SMIL override style declaration for this element.
|
||||
*/
|
||||
RefPtr<mozilla::css::Declaration> mSMILOverrideStyleDeclaration;
|
||||
RefPtr<mozilla::DeclarationBlock> mSMILOverrideStyleDeclaration;
|
||||
|
||||
/**
|
||||
* An object implementing nsIDOMMozNamedAttrMap for this content (attributes)
|
||||
|
|
|
@ -1720,7 +1720,7 @@ nsAttrValue::ParseStyleAttribute(const nsAString& aString,
|
|||
|
||||
RefPtr<DeclarationBlock> decl;
|
||||
if (ownerDoc->GetStyleBackendType() == StyleBackendType::Servo) {
|
||||
decl = ServoDeclarationBlock::FromStyleAttribute(aString);
|
||||
decl = ServoDeclarationBlock::FromCssText(aString);
|
||||
} else {
|
||||
css::Loader* cssLoader = ownerDoc->CSSLoader();
|
||||
nsCSSParser cssParser(cssLoader);
|
||||
|
|
|
@ -1068,7 +1068,7 @@ nsTreeSanitizer::SanitizeStyleDeclaration(mozilla::css::Declaration* aDeclaratio
|
|||
nsAutoString& aRuleText)
|
||||
{
|
||||
bool didSanitize = aDeclaration->HasProperty(eCSSProperty_binding);
|
||||
aDeclaration->RemoveProperty(eCSSProperty_binding);
|
||||
aDeclaration->RemovePropertyByID(eCSSProperty_binding);
|
||||
aDeclaration->ToString(aRuleText);
|
||||
return didSanitize;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ tags = mcb
|
|||
[browser_bug1011748.js]
|
||||
[browser_bug1058164.js]
|
||||
[browser_messagemanager_loadprocessscript.js]
|
||||
skip-if = true # Bug 1315042
|
||||
[browser_messagemanager_targetframeloader.js]
|
||||
[browser_messagemanager_unload.js]
|
||||
[browser_pagehide_on_tab_close.js]
|
||||
|
|
|
@ -83,6 +83,7 @@ skip-if = (toolkit == 'gonk' && !debug)
|
|||
# skip-if = (toolkit == 'gonk') # Disabled on emulator. See bug 1144015 comment 8
|
||||
disabled = Disabling some OOP tests for WebIDL scope changes
|
||||
[test_browserElement_oop_PrivateBrowsing.html]
|
||||
skip-if = true # Bug 1315042
|
||||
[test_browserElement_oop_PromptCheck.html]
|
||||
[test_browserElement_oop_PromptConfirm.html]
|
||||
# Disabled on B2G Emulator because permission cannot be asserted in content process,
|
||||
|
|
|
@ -2686,7 +2686,7 @@ GetFontStyleContext(Element* aElement, const nsAString& aFont,
|
|||
// parsed (including having line-height removed). (Older drafts of
|
||||
// the spec required font sizes be converted to pixels, but that no
|
||||
// longer seems to be required.)
|
||||
decl->GetValue(eCSSProperty_font, aOutUsedFont);
|
||||
decl->GetPropertyValueByID(eCSSProperty_font, aOutUsedFont);
|
||||
|
||||
return sc.forget();
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace dom {
|
|||
void
|
||||
CanvasRenderingContextHelper::ToBlob(JSContext* aCx,
|
||||
nsIGlobalObject* aGlobal,
|
||||
FileCallback& aCallback,
|
||||
BlobCallback& aCallback,
|
||||
const nsAString& aType,
|
||||
JS::Handle<JS::Value> aParams,
|
||||
ErrorResult& aRv)
|
||||
|
@ -31,9 +31,9 @@ CanvasRenderingContextHelper::ToBlob(JSContext* aCx,
|
|||
class EncodeCallback : public EncodeCompleteCallback
|
||||
{
|
||||
public:
|
||||
EncodeCallback(nsIGlobalObject* aGlobal, FileCallback* aCallback)
|
||||
EncodeCallback(nsIGlobalObject* aGlobal, BlobCallback* aCallback)
|
||||
: mGlobal(aGlobal)
|
||||
, mFileCallback(aCallback) {}
|
||||
, mBlobCallback(aCallback) {}
|
||||
|
||||
// This is called on main thread.
|
||||
nsresult ReceiveBlob(already_AddRefed<Blob> aBlob)
|
||||
|
@ -53,16 +53,16 @@ CanvasRenderingContextHelper::ToBlob(JSContext* aCx,
|
|||
|
||||
RefPtr<Blob> newBlob = Blob::Create(mGlobal, blob->Impl());
|
||||
|
||||
mFileCallback->Call(*newBlob, rv);
|
||||
mBlobCallback->Call(*newBlob, rv);
|
||||
|
||||
mGlobal = nullptr;
|
||||
mFileCallback = nullptr;
|
||||
mBlobCallback = nullptr;
|
||||
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
RefPtr<FileCallback> mFileCallback;
|
||||
RefPtr<BlobCallback> mBlobCallback;
|
||||
};
|
||||
|
||||
RefPtr<EncodeCompleteCallback> callback =
|
||||
|
|
|
@ -18,8 +18,8 @@ class ErrorResult;
|
|||
|
||||
namespace dom {
|
||||
|
||||
class BlobCallback;
|
||||
class EncodeCompleteCallback;
|
||||
class FileCallback;
|
||||
|
||||
enum class CanvasContextType : uint8_t {
|
||||
NoContext,
|
||||
|
@ -55,7 +55,7 @@ protected:
|
|||
nsAString& outParams,
|
||||
bool* const outCustomParseOptions);
|
||||
|
||||
void ToBlob(JSContext* aCx, nsIGlobalObject* global, FileCallback& aCallback,
|
||||
void ToBlob(JSContext* aCx, nsIGlobalObject* global, BlobCallback& aCallback,
|
||||
const nsAString& aType, JS::Handle<JS::Value> aParams,
|
||||
ErrorResult& aRv);
|
||||
|
||||
|
|
|
@ -326,9 +326,9 @@ DataTransferItem::GetAsEntry(nsIPrincipal& aSubjectPrincipal,
|
|||
}
|
||||
|
||||
RefPtr<Directory> directory = Directory::Create(global, directoryFile);
|
||||
entry = new FileSystemDirectoryEntry(global, directory, fs);
|
||||
entry = new FileSystemDirectoryEntry(global, directory, nullptr, fs);
|
||||
} else {
|
||||
entry = new FileSystemFileEntry(global, file, fs);
|
||||
entry = new FileSystemFileEntry(global, file, nullptr, fs);
|
||||
}
|
||||
|
||||
Sequence<RefPtr<FileSystemEntry>> entries;
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CallbackRunnables.h"
|
||||
#include "mozilla/dom/Directory.h"
|
||||
#include "mozilla/dom/DirectoryBinding.h"
|
||||
#include "mozilla/dom/DOMError.h"
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/FileBinding.h"
|
||||
#include "mozilla/dom/FileSystemDirectoryReaderBinding.h"
|
||||
|
@ -55,8 +56,8 @@ ErrorCallbackRunnable::Run()
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<DOMError> error = new DOMError(window, mError);
|
||||
mCallback->HandleEvent(*error);
|
||||
RefPtr<DOMException> exception = DOMException::Create(mError);
|
||||
mCallback->HandleEvent(*exception);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -74,18 +75,24 @@ EmptyEntriesCallbackRunnable::Run()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
GetEntryHelper::GetEntryHelper(nsIGlobalObject* aGlobalObject,
|
||||
GetEntryHelper::GetEntryHelper(FileSystemDirectoryEntry* aParentEntry,
|
||||
Directory* aDirectory,
|
||||
nsTArray<nsString>& aParts,
|
||||
FileSystem* aFileSystem,
|
||||
FileSystemEntryCallback* aSuccessCallback,
|
||||
ErrorCallback* aErrorCallback,
|
||||
FileSystemDirectoryEntry::GetInternalType aType)
|
||||
: mGlobal(aGlobalObject)
|
||||
: mParentEntry(aParentEntry)
|
||||
, mDirectory(aDirectory)
|
||||
, mParts(aParts)
|
||||
, mFileSystem(aFileSystem)
|
||||
, mSuccessCallback(aSuccessCallback)
|
||||
, mErrorCallback(aErrorCallback)
|
||||
, mType(aType)
|
||||
{
|
||||
MOZ_ASSERT(aGlobalObject);
|
||||
MOZ_ASSERT(aParentEntry);
|
||||
MOZ_ASSERT(aDirectory);
|
||||
MOZ_ASSERT(!aParts.IsEmpty());
|
||||
MOZ_ASSERT(aFileSystem);
|
||||
MOZ_ASSERT(aSuccessCallback || aErrorCallback);
|
||||
}
|
||||
|
@ -93,6 +100,23 @@ GetEntryHelper::GetEntryHelper(nsIGlobalObject* aGlobalObject,
|
|||
GetEntryHelper::~GetEntryHelper()
|
||||
{}
|
||||
|
||||
void
|
||||
GetEntryHelper::Run()
|
||||
{
|
||||
MOZ_ASSERT(!mParts.IsEmpty());
|
||||
|
||||
ErrorResult rv;
|
||||
RefPtr<Promise> promise = mDirectory->Get(mParts[0], rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
rv.SuppressException();
|
||||
Error(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
mParts.RemoveElementAt(0);
|
||||
promise->AppendNativeHandler(this);
|
||||
}
|
||||
|
||||
void
|
||||
GetEntryHelper::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
|
@ -102,15 +126,30 @@ GetEntryHelper::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
|
|||
|
||||
JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
|
||||
|
||||
// This is not the last part of the path.
|
||||
if (!mParts.IsEmpty()) {
|
||||
ContinueRunning(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
CompleteOperation(obj);
|
||||
}
|
||||
|
||||
void
|
||||
GetEntryHelper::CompleteOperation(JSObject* aObj)
|
||||
{
|
||||
MOZ_ASSERT(mParts.IsEmpty());
|
||||
|
||||
if (mType == FileSystemDirectoryEntry::eGetFile) {
|
||||
RefPtr<File> file;
|
||||
if (NS_FAILED(UNWRAP_OBJECT(File, obj, file))) {
|
||||
if (NS_FAILED(UNWRAP_OBJECT(File, aObj, file))) {
|
||||
Error(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<FileSystemFileEntry> entry =
|
||||
new FileSystemFileEntry(mGlobal, file, mFileSystem);
|
||||
new FileSystemFileEntry(mParentEntry->GetParentObject(), file,
|
||||
mParentEntry, mFileSystem);
|
||||
mSuccessCallback->HandleEvent(*entry);
|
||||
return;
|
||||
}
|
||||
|
@ -118,16 +157,39 @@ GetEntryHelper::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
|
|||
MOZ_ASSERT(mType == FileSystemDirectoryEntry::eGetDirectory);
|
||||
|
||||
RefPtr<Directory> directory;
|
||||
if (NS_FAILED(UNWRAP_OBJECT(Directory, obj, directory))) {
|
||||
if (NS_FAILED(UNWRAP_OBJECT(Directory, aObj, directory))) {
|
||||
Error(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<FileSystemDirectoryEntry> entry =
|
||||
new FileSystemDirectoryEntry(mGlobal, directory, mFileSystem);
|
||||
new FileSystemDirectoryEntry(mParentEntry->GetParentObject(), directory,
|
||||
mParentEntry, mFileSystem);
|
||||
mSuccessCallback->HandleEvent(*entry);
|
||||
}
|
||||
|
||||
void
|
||||
GetEntryHelper::ContinueRunning(JSObject* aObj)
|
||||
{
|
||||
MOZ_ASSERT(!mParts.IsEmpty());
|
||||
|
||||
RefPtr<Directory> directory;
|
||||
if (NS_FAILED(UNWRAP_OBJECT(Directory, aObj, directory))) {
|
||||
Error(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<FileSystemDirectoryEntry> entry =
|
||||
new FileSystemDirectoryEntry(mParentEntry->GetParentObject(), directory,
|
||||
mParentEntry, mFileSystem);
|
||||
|
||||
// Update the internal values.
|
||||
mParentEntry = entry;
|
||||
mDirectory = directory;
|
||||
|
||||
Run();
|
||||
}
|
||||
|
||||
void
|
||||
GetEntryHelper::RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
|
@ -141,7 +203,8 @@ GetEntryHelper::Error(nsresult aError)
|
|||
|
||||
if (mErrorCallback) {
|
||||
RefPtr<ErrorCallbackRunnable> runnable =
|
||||
new ErrorCallbackRunnable(mGlobal, mErrorCallback, aError);
|
||||
new ErrorCallbackRunnable(mParentEntry->GetParentObject(),
|
||||
mErrorCallback, aError);
|
||||
DebugOnly<nsresult> rv = NS_DispatchToMainThread(runnable);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
|
||||
}
|
||||
|
@ -149,6 +212,21 @@ GetEntryHelper::Error(nsresult aError)
|
|||
|
||||
NS_IMPL_ISUPPORTS0(GetEntryHelper);
|
||||
|
||||
/* static */ void
|
||||
FileSystemEntryCallbackHelper::Call(const Optional<OwningNonNull<FileSystemEntryCallback>>& aEntryCallback,
|
||||
FileSystemEntry* aEntry)
|
||||
{
|
||||
MOZ_ASSERT(aEntry);
|
||||
|
||||
if (aEntryCallback.WasPassed()) {
|
||||
RefPtr<EntryCallbackRunnable> runnable =
|
||||
new EntryCallbackRunnable(&aEntryCallback.Value(), aEntry);
|
||||
|
||||
DebugOnly<nsresult> rv = NS_DispatchToMainThread(runnable);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ErrorCallbackHelper::Call(nsIGlobalObject* aGlobal,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback,
|
||||
|
|
|
@ -65,12 +65,17 @@ class GetEntryHelper final : public PromiseNativeHandler
|
|||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
GetEntryHelper(nsIGlobalObject* aGlobalObject,
|
||||
GetEntryHelper(FileSystemDirectoryEntry* aParentEntry,
|
||||
Directory* aDirectory,
|
||||
nsTArray<nsString>& aParts,
|
||||
FileSystem* aFileSystem,
|
||||
FileSystemEntryCallback* aSuccessCallback,
|
||||
ErrorCallback* aErrorCallback,
|
||||
FileSystemDirectoryEntry::GetInternalType aType);
|
||||
|
||||
void
|
||||
Run();
|
||||
|
||||
virtual void
|
||||
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
||||
|
||||
|
@ -83,13 +88,31 @@ private:
|
|||
void
|
||||
Error(nsresult aError);
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
void
|
||||
ContinueRunning(JSObject* aObj);
|
||||
|
||||
void
|
||||
CompleteOperation(JSObject* aObj);
|
||||
|
||||
RefPtr<FileSystemDirectoryEntry> mParentEntry;
|
||||
RefPtr<Directory> mDirectory;
|
||||
nsTArray<nsString> mParts;
|
||||
RefPtr<FileSystem> mFileSystem;
|
||||
|
||||
RefPtr<FileSystemEntryCallback> mSuccessCallback;
|
||||
RefPtr<ErrorCallback> mErrorCallback;
|
||||
|
||||
FileSystemDirectoryEntry::GetInternalType mType;
|
||||
};
|
||||
|
||||
class FileSystemEntryCallbackHelper
|
||||
{
|
||||
public:
|
||||
static void
|
||||
Call(const Optional<OwningNonNull<FileSystemEntryCallback>>& aEntryCallback,
|
||||
FileSystemEntry* aEntry);
|
||||
};
|
||||
|
||||
class ErrorCallbackHelper
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -25,8 +25,9 @@ NS_INTERFACE_MAP_END_INHERITING(FileSystemEntry)
|
|||
|
||||
FileSystemDirectoryEntry::FileSystemDirectoryEntry(nsIGlobalObject* aGlobal,
|
||||
Directory* aDirectory,
|
||||
FileSystemDirectoryEntry* aParentEntry,
|
||||
FileSystem* aFileSystem)
|
||||
: FileSystemEntry(aGlobal, aFileSystem)
|
||||
: FileSystemEntry(aGlobal, aParentEntry, aFileSystem)
|
||||
, mDirectory(aDirectory)
|
||||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
|
@ -57,12 +58,12 @@ FileSystemDirectoryEntry::GetFullPath(nsAString& aPath, ErrorResult& aRv) const
|
|||
}
|
||||
|
||||
already_AddRefed<FileSystemDirectoryReader>
|
||||
FileSystemDirectoryEntry::CreateReader() const
|
||||
FileSystemDirectoryEntry::CreateReader()
|
||||
{
|
||||
MOZ_ASSERT(mDirectory);
|
||||
|
||||
RefPtr<FileSystemDirectoryReader> reader =
|
||||
new FileSystemDirectoryReader(GetParentObject(), Filesystem(), mDirectory);
|
||||
new FileSystemDirectoryReader(this, Filesystem(), mDirectory);
|
||||
return reader.forget();
|
||||
}
|
||||
|
||||
|
@ -71,7 +72,7 @@ FileSystemDirectoryEntry::GetInternal(const nsAString& aPath,
|
|||
const FileSystemFlags& aFlag,
|
||||
const Optional<OwningNonNull<FileSystemEntryCallback>>& aSuccessCallback,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback,
|
||||
GetInternalType aType) const
|
||||
GetInternalType aType)
|
||||
{
|
||||
MOZ_ASSERT(mDirectory);
|
||||
|
||||
|
@ -92,30 +93,14 @@ FileSystemDirectoryEntry::GetInternal(const nsAString& aPath,
|
|||
return;
|
||||
}
|
||||
|
||||
ErrorResult error;
|
||||
RefPtr<Promise> promise = mDirectory->Get(aPath, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
ErrorCallbackHelper::Call(GetParentObject(), aErrorCallback,
|
||||
error.StealNSResult());
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<GetEntryHelper> handler =
|
||||
new GetEntryHelper(GetParentObject(), Filesystem(),
|
||||
RefPtr<GetEntryHelper> helper =
|
||||
new GetEntryHelper(this, mDirectory, parts, Filesystem(),
|
||||
aSuccessCallback.WasPassed()
|
||||
? &aSuccessCallback.Value() : nullptr,
|
||||
aErrorCallback.WasPassed()
|
||||
? &aErrorCallback.Value() : nullptr,
|
||||
aType);
|
||||
promise->AppendNativeHandler(handler);
|
||||
}
|
||||
|
||||
void
|
||||
FileSystemDirectoryEntry::RemoveRecursively(VoidCallback& aSuccessCallback,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback) const
|
||||
{
|
||||
ErrorCallbackHelper::Call(GetParentObject(), aErrorCallback,
|
||||
NS_ERROR_DOM_SECURITY_ERR);
|
||||
helper->Run();
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#ifndef mozilla_dom_FileSystemDirectoryEntry_h
|
||||
#define mozilla_dom_FileSystemDirectoryEntry_h
|
||||
|
||||
#include "mozilla/dom/FileSystemBinding.h"
|
||||
#include "mozilla/dom/FileSystemEntry.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -25,6 +24,7 @@ public:
|
|||
|
||||
FileSystemDirectoryEntry(nsIGlobalObject* aGlobalObject,
|
||||
Directory* aDirectory,
|
||||
FileSystemDirectoryEntry* aParentEntry,
|
||||
FileSystem* aFileSystem);
|
||||
|
||||
virtual JSObject*
|
||||
|
@ -43,35 +43,33 @@ public:
|
|||
GetFullPath(nsAString& aFullPath, ErrorResult& aRv) const override;
|
||||
|
||||
virtual already_AddRefed<FileSystemDirectoryReader>
|
||||
CreateReader() const;
|
||||
CreateReader();
|
||||
|
||||
void
|
||||
GetFile(const nsAString& aPath, const FileSystemFlags& aFlag,
|
||||
GetFile(const Optional<nsAString>& aPath, const FileSystemFlags& aFlag,
|
||||
const Optional<OwningNonNull<FileSystemEntryCallback>>& aSuccessCallback,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback) const
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback)
|
||||
{
|
||||
GetInternal(aPath, aFlag, aSuccessCallback, aErrorCallback, eGetFile);
|
||||
GetInternal(aPath.WasPassed() ? aPath.Value() : EmptyString(),
|
||||
aFlag, aSuccessCallback, aErrorCallback, eGetFile);
|
||||
}
|
||||
|
||||
void
|
||||
GetDirectory(const nsAString& aPath, const FileSystemFlags& aFlag,
|
||||
GetDirectory(const Optional<nsAString>& aPath, const FileSystemFlags& aFlag,
|
||||
const Optional<OwningNonNull<FileSystemEntryCallback>>& aSuccessCallback,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback) const
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback)
|
||||
{
|
||||
GetInternal(aPath, aFlag, aSuccessCallback, aErrorCallback, eGetDirectory);
|
||||
GetInternal(aPath.WasPassed() ? aPath.Value() : EmptyString(),
|
||||
aFlag, aSuccessCallback, aErrorCallback, eGetDirectory);
|
||||
}
|
||||
|
||||
void
|
||||
RemoveRecursively(VoidCallback& aSuccessCallback,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback) const;
|
||||
|
||||
enum GetInternalType { eGetFile, eGetDirectory };
|
||||
|
||||
virtual void
|
||||
GetInternal(const nsAString& aPath, const FileSystemFlags& aFlag,
|
||||
const Optional<OwningNonNull<FileSystemEntryCallback>>& aSuccessCallback,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback,
|
||||
GetInternalType aType) const;
|
||||
GetInternalType aType);
|
||||
|
||||
protected:
|
||||
virtual ~FileSystemDirectoryEntry();
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "mozilla/dom/DirectoryBinding.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -24,16 +23,16 @@ class PromiseHandler final : public PromiseNativeHandler
|
|||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
PromiseHandler(nsIGlobalObject* aGlobalObject,
|
||||
PromiseHandler(FileSystemDirectoryEntry* aParentEntry,
|
||||
FileSystem* aFileSystem,
|
||||
FileSystemEntriesCallback* aSuccessCallback,
|
||||
ErrorCallback* aErrorCallback)
|
||||
: mGlobal(aGlobalObject)
|
||||
: mParentEntry(aParentEntry)
|
||||
, mFileSystem(aFileSystem)
|
||||
, mSuccessCallback(aSuccessCallback)
|
||||
, mErrorCallback(aErrorCallback)
|
||||
{
|
||||
MOZ_ASSERT(aGlobalObject);
|
||||
MOZ_ASSERT(aParentEntry);
|
||||
MOZ_ASSERT(aFileSystem);
|
||||
MOZ_ASSERT(aSuccessCallback);
|
||||
}
|
||||
|
@ -72,7 +71,8 @@ public:
|
|||
RefPtr<File> file;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(File, valueObj, file))) {
|
||||
RefPtr<FileSystemFileEntry> entry =
|
||||
new FileSystemFileEntry(mGlobal, file, mFileSystem);
|
||||
new FileSystemFileEntry(mParentEntry->GetParentObject(), file,
|
||||
mParentEntry, mFileSystem);
|
||||
sequence[i] = entry;
|
||||
continue;
|
||||
}
|
||||
|
@ -84,7 +84,8 @@ public:
|
|||
}
|
||||
|
||||
RefPtr<FileSystemDirectoryEntry> entry =
|
||||
new FileSystemDirectoryEntry(mGlobal, directory, mFileSystem);
|
||||
new FileSystemDirectoryEntry(mParentEntry->GetParentObject(), directory,
|
||||
mParentEntry, mFileSystem);
|
||||
sequence[i] = entry;
|
||||
}
|
||||
|
||||
|
@ -96,7 +97,8 @@ public:
|
|||
{
|
||||
if (mErrorCallback) {
|
||||
RefPtr<ErrorCallbackRunnable> runnable =
|
||||
new ErrorCallbackRunnable(mGlobal, mErrorCallback,
|
||||
new ErrorCallbackRunnable(mParentEntry->GetParentObject(),
|
||||
mErrorCallback,
|
||||
NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
DebugOnly<nsresult> rv = NS_DispatchToMainThread(runnable);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
|
||||
|
@ -106,7 +108,7 @@ public:
|
|||
private:
|
||||
~PromiseHandler() {}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
RefPtr<FileSystemDirectoryEntry> mParentEntry;
|
||||
RefPtr<FileSystem> mFileSystem;
|
||||
RefPtr<FileSystemEntriesCallback> mSuccessCallback;
|
||||
RefPtr<ErrorCallback> mErrorCallback;
|
||||
|
@ -116,7 +118,7 @@ NS_IMPL_ISUPPORTS0(PromiseHandler);
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FileSystemDirectoryReader, mParent,
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FileSystemDirectoryReader, mParentEntry,
|
||||
mDirectory, mFileSystem)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(FileSystemDirectoryReader)
|
||||
|
@ -127,15 +129,15 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FileSystemDirectoryReader)
|
|||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
FileSystemDirectoryReader::FileSystemDirectoryReader(nsIGlobalObject* aGlobal,
|
||||
FileSystemDirectoryReader::FileSystemDirectoryReader(FileSystemDirectoryEntry* aParentEntry,
|
||||
FileSystem* aFileSystem,
|
||||
Directory* aDirectory)
|
||||
: mParent(aGlobal)
|
||||
: mParentEntry(aParentEntry)
|
||||
, mFileSystem(aFileSystem)
|
||||
, mDirectory(aDirectory)
|
||||
, mAlreadyRead(false)
|
||||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
MOZ_ASSERT(aParentEntry);
|
||||
MOZ_ASSERT(aFileSystem);
|
||||
}
|
||||
|
||||
|
@ -176,7 +178,7 @@ FileSystemDirectoryReader::ReadEntries(FileSystemEntriesCallback& aSuccessCallba
|
|||
}
|
||||
|
||||
RefPtr<PromiseHandler> handler =
|
||||
new PromiseHandler(GetParentObject(), mFileSystem, &aSuccessCallback,
|
||||
new PromiseHandler(mParentEntry, mFileSystem, &aSuccessCallback,
|
||||
aErrorCallback.WasPassed()
|
||||
? &aErrorCallback.Value() : nullptr);
|
||||
promise->AppendNativeHandler(handler);
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class nsIGlobalObject;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -30,14 +28,14 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(FileSystemDirectoryReader)
|
||||
|
||||
explicit FileSystemDirectoryReader(nsIGlobalObject* aGlobalObject,
|
||||
explicit FileSystemDirectoryReader(FileSystemDirectoryEntry* aDirectoryEntry,
|
||||
FileSystem* aFileSystem,
|
||||
Directory* aDirectory);
|
||||
|
||||
nsIGlobalObject*
|
||||
GetParentObject() const
|
||||
{
|
||||
return mParent;
|
||||
return mParentEntry->GetParentObject();
|
||||
}
|
||||
|
||||
virtual JSObject*
|
||||
|
@ -52,7 +50,7 @@ protected:
|
|||
virtual ~FileSystemDirectoryReader();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIGlobalObject> mParent;
|
||||
RefPtr<FileSystemDirectoryEntry> mParentEntry;
|
||||
RefPtr<FileSystem> mFileSystem;
|
||||
RefPtr<Directory> mDirectory;
|
||||
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FileSystemEntry, mParent, mFileSystem)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FileSystemEntry, mParent, mParentEntry,
|
||||
mFileSystem)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(FileSystemEntry)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(FileSystemEntry)
|
||||
|
@ -35,11 +36,13 @@ FileSystemEntry::Create(nsIGlobalObject* aGlobalObject,
|
|||
if (aFileOrDirectory.IsFile()) {
|
||||
entry = new FileSystemFileEntry(aGlobalObject,
|
||||
aFileOrDirectory.GetAsFile(),
|
||||
nullptr,
|
||||
aFileSystem);
|
||||
} else {
|
||||
MOZ_ASSERT(aFileOrDirectory.IsDirectory());
|
||||
entry = new FileSystemDirectoryEntry(aGlobalObject,
|
||||
aFileOrDirectory.GetAsDirectory(),
|
||||
nullptr,
|
||||
aFileSystem);
|
||||
}
|
||||
|
||||
|
@ -47,8 +50,10 @@ FileSystemEntry::Create(nsIGlobalObject* aGlobalObject,
|
|||
}
|
||||
|
||||
FileSystemEntry::FileSystemEntry(nsIGlobalObject* aGlobal,
|
||||
FileSystemEntry* aParentEntry,
|
||||
FileSystem* aFileSystem)
|
||||
: mParent(aGlobal)
|
||||
, mParentEntry(aParentEntry)
|
||||
, mFileSystem(aFileSystem)
|
||||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
|
@ -64,5 +69,21 @@ FileSystemEntry::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
|||
return FileSystemEntryBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
FileSystemEntry::GetParent(const Optional<OwningNonNull<FileSystemEntryCallback>>& aSuccessCallback,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback)
|
||||
{
|
||||
if (!aSuccessCallback.WasPassed() && !aErrorCallback.WasPassed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mParentEntry) {
|
||||
FileSystemEntryCallbackHelper::Call(aSuccessCallback, mParentEntry);
|
||||
return;
|
||||
}
|
||||
|
||||
FileSystemEntryCallbackHelper::Call(aSuccessCallback, this);
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/FileSystemBinding.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
@ -60,6 +61,10 @@ public:
|
|||
virtual void
|
||||
GetFullPath(nsAString& aFullPath, ErrorResult& aRv) const = 0;
|
||||
|
||||
void
|
||||
GetParent(const Optional<OwningNonNull<FileSystemEntryCallback>>& aSuccessCallback,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback);
|
||||
|
||||
FileSystem*
|
||||
Filesystem() const
|
||||
{
|
||||
|
@ -68,11 +73,13 @@ public:
|
|||
|
||||
protected:
|
||||
FileSystemEntry(nsIGlobalObject* aGlobalObject,
|
||||
FileSystemEntry* aParentEntry,
|
||||
FileSystem* aFileSystem);
|
||||
virtual ~FileSystemEntry();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIGlobalObject> mParent;
|
||||
RefPtr<FileSystemEntry> mParentEntry;
|
||||
RefPtr<FileSystem> mFileSystem;
|
||||
};
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@ namespace dom {
|
|||
|
||||
namespace {
|
||||
|
||||
class BlobCallbackRunnable final : public Runnable
|
||||
class FileCallbackRunnable final : public Runnable
|
||||
{
|
||||
public:
|
||||
BlobCallbackRunnable(BlobCallback* aCallback, File* aFile)
|
||||
FileCallbackRunnable(FileCallback* aCallback, File* aFile)
|
||||
: mCallback(aCallback)
|
||||
, mFile(aFile)
|
||||
{
|
||||
|
@ -28,12 +28,12 @@ public:
|
|||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
mCallback->HandleEvent(mFile);
|
||||
mCallback->HandleEvent(*mFile);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<BlobCallback> mCallback;
|
||||
RefPtr<FileCallback> mCallback;
|
||||
RefPtr<File> mFile;
|
||||
};
|
||||
|
||||
|
@ -49,8 +49,9 @@ NS_INTERFACE_MAP_END_INHERITING(FileSystemEntry)
|
|||
|
||||
FileSystemFileEntry::FileSystemFileEntry(nsIGlobalObject* aGlobal,
|
||||
File* aFile,
|
||||
FileSystemDirectoryEntry* aParentEntry,
|
||||
FileSystem* aFileSystem)
|
||||
: FileSystemEntry(aGlobal, aFileSystem)
|
||||
: FileSystemEntry(aGlobal, aParentEntry, aFileSystem)
|
||||
, mFile(aFile)
|
||||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
|
@ -98,11 +99,11 @@ FileSystemFileEntry::CreateWriter(VoidCallback& aSuccessCallback,
|
|||
}
|
||||
|
||||
void
|
||||
FileSystemFileEntry::GetFile(BlobCallback& aSuccessCallback,
|
||||
FileSystemFileEntry::GetFile(FileCallback& aSuccessCallback,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback) const
|
||||
{
|
||||
RefPtr<BlobCallbackRunnable> runnable =
|
||||
new BlobCallbackRunnable(&aSuccessCallback, mFile);
|
||||
RefPtr<FileCallbackRunnable> runnable =
|
||||
new FileCallbackRunnable(&aSuccessCallback, mFile);
|
||||
DebugOnly<nsresult> rv = NS_DispatchToMainThread(runnable);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ namespace mozilla {
|
|||
namespace dom {
|
||||
|
||||
class File;
|
||||
class BlobCallback;
|
||||
class FileCallback;
|
||||
class FileSystemDirectoryEntry;
|
||||
|
||||
class FileSystemFileEntry final : public FileSystemEntry
|
||||
{
|
||||
|
@ -22,6 +23,7 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FileSystemFileEntry, FileSystemEntry)
|
||||
|
||||
FileSystemFileEntry(nsIGlobalObject* aGlobalObject, File* aFile,
|
||||
FileSystemDirectoryEntry* aParentEntry,
|
||||
FileSystem* aFileSystem);
|
||||
|
||||
virtual JSObject*
|
||||
|
@ -44,7 +46,7 @@ public:
|
|||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback) const;
|
||||
|
||||
void
|
||||
GetFile(BlobCallback& aSuccessCallback,
|
||||
GetFile(FileCallback& aSuccessCallback,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback) const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -23,7 +23,7 @@ NS_INTERFACE_MAP_END_INHERITING(FileSystemDirectoryEntry)
|
|||
FileSystemRootDirectoryEntry::FileSystemRootDirectoryEntry(nsIGlobalObject* aGlobal,
|
||||
const Sequence<RefPtr<FileSystemEntry>>& aEntries,
|
||||
FileSystem* aFileSystem)
|
||||
: FileSystemDirectoryEntry(aGlobal, nullptr, aFileSystem)
|
||||
: FileSystemDirectoryEntry(aGlobal, nullptr, nullptr, aFileSystem)
|
||||
, mEntries(aEntries)
|
||||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
|
@ -45,11 +45,10 @@ FileSystemRootDirectoryEntry::GetFullPath(nsAString& aPath, ErrorResult& aRv) co
|
|||
}
|
||||
|
||||
already_AddRefed<FileSystemDirectoryReader>
|
||||
FileSystemRootDirectoryEntry::CreateReader() const
|
||||
FileSystemRootDirectoryEntry::CreateReader()
|
||||
{
|
||||
RefPtr<FileSystemDirectoryReader> reader =
|
||||
new FileSystemRootDirectoryReader(GetParentObject(), Filesystem(),
|
||||
mEntries);
|
||||
new FileSystemRootDirectoryReader(this, Filesystem(), mEntries);
|
||||
return reader.forget();
|
||||
}
|
||||
|
||||
|
@ -58,7 +57,7 @@ FileSystemRootDirectoryEntry::GetInternal(const nsAString& aPath,
|
|||
const FileSystemFlags& aFlag,
|
||||
const Optional<OwningNonNull<FileSystemEntryCallback>>& aSuccessCallback,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback,
|
||||
GetInternalType aType) const
|
||||
GetInternalType aType)
|
||||
{
|
||||
if (!aSuccessCallback.WasPassed() && !aErrorCallback.WasPassed()) {
|
||||
return;
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
GetFullPath(nsAString& aFullPath, ErrorResult& aRv) const override;
|
||||
|
||||
virtual already_AddRefed<FileSystemDirectoryReader>
|
||||
CreateReader() const override;
|
||||
CreateReader() override;
|
||||
|
||||
private:
|
||||
~FileSystemRootDirectoryEntry();
|
||||
|
@ -38,7 +38,7 @@ private:
|
|||
GetInternal(const nsAString& aPath, const FileSystemFlags& aFlag,
|
||||
const Optional<OwningNonNull<FileSystemEntryCallback>>& aSuccessCallback,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback,
|
||||
GetInternalType aType) const override;
|
||||
GetInternalType aType) override;
|
||||
|
||||
void
|
||||
Error(const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback,
|
||||
|
|
|
@ -56,14 +56,14 @@ NS_IMPL_RELEASE_INHERITED(FileSystemRootDirectoryReader,
|
|||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FileSystemRootDirectoryReader)
|
||||
NS_INTERFACE_MAP_END_INHERITING(FileSystemDirectoryReader)
|
||||
|
||||
FileSystemRootDirectoryReader::FileSystemRootDirectoryReader(nsIGlobalObject* aGlobal,
|
||||
FileSystemRootDirectoryReader::FileSystemRootDirectoryReader(FileSystemDirectoryEntry* aParentEntry,
|
||||
FileSystem* aFileSystem,
|
||||
const Sequence<RefPtr<FileSystemEntry>>& aEntries)
|
||||
: FileSystemDirectoryReader(aGlobal, aFileSystem, nullptr)
|
||||
: FileSystemDirectoryReader(aParentEntry, aFileSystem, nullptr)
|
||||
, mEntries(aEntries)
|
||||
, mAlreadyRead(false)
|
||||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
MOZ_ASSERT(aParentEntry);
|
||||
MOZ_ASSERT(aFileSystem);
|
||||
}
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче