mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge branch 'mozilla-central'
This commit is contained in:
commit
8d90872877
@ -14,9 +14,8 @@ using namespace mozilla::a11y;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DocAccessibleWrap::
|
||||
DocAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
|
||||
nsIPresShell* aPresShell) :
|
||||
DocAccessible(aDocument, aRootContent, aPresShell), mActivated(false)
|
||||
DocAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell) :
|
||||
DocAccessible(aDocument, aPresShell), mActivated(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,7 @@ namespace a11y {
|
||||
class DocAccessibleWrap : public DocAccessible
|
||||
{
|
||||
public:
|
||||
DocAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
|
||||
nsIPresShell* aPresShell);
|
||||
DocAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell);
|
||||
virtual ~DocAccessibleWrap();
|
||||
|
||||
bool mActivated;
|
||||
|
@ -470,17 +470,15 @@ DocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
|
||||
|
||||
// We only create root accessibles for the true root, otherwise create a
|
||||
// doc accessible.
|
||||
nsIContent *rootElm = nsCoreUtils::GetRoleContent(aDocument);
|
||||
RefPtr<DocAccessible> docAcc = isRootDoc ?
|
||||
new RootAccessibleWrap(aDocument, rootElm, presShell) :
|
||||
new DocAccessibleWrap(aDocument, rootElm, presShell);
|
||||
new RootAccessibleWrap(aDocument, presShell) :
|
||||
new DocAccessibleWrap(aDocument, presShell);
|
||||
|
||||
// Cache the document accessible into document cache.
|
||||
mDocAccessibleCache.Put(aDocument, docAcc);
|
||||
|
||||
// Initialize the document accessible.
|
||||
docAcc->Init();
|
||||
docAcc->SetRoleMapEntry(aria::GetRoleMap(aDocument));
|
||||
|
||||
// Bind the document to the tree.
|
||||
if (isRootDoc) {
|
||||
|
@ -76,9 +76,8 @@ static const uint32_t kRelationAttrsLen = ArrayLength(kRelationAttrs);
|
||||
// Constructor/desctructor
|
||||
|
||||
DocAccessible::
|
||||
DocAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
|
||||
nsIPresShell* aPresShell) :
|
||||
HyperTextAccessibleWrap(aRootContent, this),
|
||||
DocAccessible(nsIDocument* aDocument, nsIPresShell* aPresShell) :
|
||||
HyperTextAccessibleWrap(nullptr, this),
|
||||
// XXX aaronl should we use an algorithm for the initial cache size?
|
||||
mAccessibleCache(kDefaultCacheLength),
|
||||
mNodeToAccessibleMap(kDefaultCacheLength),
|
||||
@ -1465,7 +1464,7 @@ DocAccessible::DoInitialUpdate()
|
||||
// miss the notification (since content tree change notifications are ignored
|
||||
// prior to initial update). Make sure the content element is valid.
|
||||
nsIContent* contentElm = nsCoreUtils::GetRoleContent(mDocumentNode);
|
||||
if (mContent != contentElm) {
|
||||
if (contentElm) {
|
||||
mContent = contentElm;
|
||||
SetRoleMapEntry(aria::GetRoleMap(mContent));
|
||||
}
|
||||
|
@ -50,8 +50,7 @@ class DocAccessible : public HyperTextAccessibleWrap,
|
||||
|
||||
public:
|
||||
|
||||
DocAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
|
||||
nsIPresShell* aPresShell);
|
||||
DocAccessible(nsIDocument* aDocument, nsIPresShell* aPresShell);
|
||||
|
||||
// nsIScrollPositionListener
|
||||
virtual void ScrollPositionWillChange(nscoord aX, nscoord aY) override {}
|
||||
|
@ -59,9 +59,8 @@ NS_IMPL_ISUPPORTS_INHERITED0(RootAccessible, DocAccessible)
|
||||
// Constructor/destructor
|
||||
|
||||
RootAccessible::
|
||||
RootAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
|
||||
nsIPresShell* aPresShell) :
|
||||
DocAccessibleWrap(aDocument, aRootContent, aPresShell)
|
||||
RootAccessible(nsIDocument* aDocument, nsIPresShell* aPresShell) :
|
||||
DocAccessibleWrap(aDocument, aPresShell)
|
||||
{
|
||||
mType = eRootType;
|
||||
}
|
||||
|
@ -22,8 +22,7 @@ class RootAccessible : public DocAccessibleWrap,
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
public:
|
||||
RootAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
|
||||
nsIPresShell* aPresShell);
|
||||
RootAccessible(nsIDocument* aDocument, nsIPresShell* aPresShell);
|
||||
|
||||
// nsIDOMEventListener
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override;
|
||||
|
@ -344,7 +344,7 @@ this.AccessFu = { // jshint ignore:line
|
||||
{
|
||||
// Ignore notifications that aren't from a BrowserOrApp
|
||||
let frameLoader = aSubject.QueryInterface(Ci.nsIFrameLoader);
|
||||
if (!frameLoader.ownerIsBrowserOrAppFrame) {
|
||||
if (!frameLoader.ownerIsMozBrowserOrAppFrame) {
|
||||
return;
|
||||
}
|
||||
this._handleMessageManager(frameLoader.messageManager);
|
||||
|
@ -14,8 +14,7 @@ namespace a11y {
|
||||
class DocAccessibleWrap : public DocAccessible
|
||||
{
|
||||
public:
|
||||
DocAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
|
||||
nsIPresShell* aPresShell);
|
||||
DocAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell);
|
||||
virtual ~DocAccessibleWrap();
|
||||
|
||||
};
|
||||
|
@ -10,9 +10,8 @@
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
DocAccessibleWrap::
|
||||
DocAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
|
||||
nsIPresShell* aPresShell) :
|
||||
DocAccessible(aDocument, aRootContent, aPresShell)
|
||||
DocAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell) :
|
||||
DocAccessible(aDocument, aPresShell)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,7 @@ namespace a11y {
|
||||
class RootAccessibleWrap : public RootAccessible
|
||||
{
|
||||
public:
|
||||
RootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
|
||||
nsIPresShell* aPresShell);
|
||||
RootAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell);
|
||||
virtual ~RootAccessibleWrap();
|
||||
|
||||
Class GetNativeType ();
|
||||
|
@ -16,9 +16,8 @@
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
RootAccessibleWrap::
|
||||
RootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
|
||||
nsIPresShell* aPresShell) :
|
||||
RootAccessible(aDocument, aRootContent, aPresShell)
|
||||
RootAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell) :
|
||||
RootAccessible(aDocument, aPresShell)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -20,8 +20,6 @@
|
||||
src="../value.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
|
||||
/**
|
||||
* Do tests.
|
||||
*/
|
||||
@ -132,6 +130,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
function changeSelectValue(aID, aKey, aValue)
|
||||
{
|
||||
this.eventSeq = [new invokerChecker(EVENT_TEXT_VALUE_CHANGE, aID)];
|
||||
|
||||
this.invoke = function changeSelectValue_invoke()
|
||||
{
|
||||
getNode(aID).focus();
|
||||
synthesizeKey(aKey, {}, window);
|
||||
}
|
||||
|
||||
this.finalCheck = function changeSelectValue_finalCheck()
|
||||
{
|
||||
is(getAccessible(aID).value, aValue, "Wrong value for " + prettyName(aID));
|
||||
}
|
||||
|
||||
this.getID = function changeSelectValue_getID()
|
||||
{
|
||||
return `${prettyName(aID)} closed select value change on '${aKey}'' key press`;
|
||||
}
|
||||
}
|
||||
|
||||
//enableLogging("DOMEvents");
|
||||
//gA11yEventDumpToConsole = true;
|
||||
function doTests()
|
||||
{
|
||||
// Test initial values
|
||||
@ -155,6 +176,9 @@
|
||||
gQueue.push(new changeProgressValue("progress", "50"));
|
||||
gQueue.push(new changeRangeValue("range"));
|
||||
|
||||
gQueue.push(new changeSelectValue("select", "VK_DOWN", "2nd"));
|
||||
gQueue.push(new changeSelectValue("select", "3", "3rd"));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -221,5 +245,10 @@
|
||||
<!-- input@type="range" -->
|
||||
<input type="range" id="range" min="0" max="10" value="6">
|
||||
|
||||
<select id="select">
|
||||
<option>1st</option>
|
||||
<option>2nd</option>
|
||||
<option>3rd</option>
|
||||
</select>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -25,9 +25,8 @@ using namespace mozilla::a11y;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DocAccessibleWrap::
|
||||
DocAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
|
||||
nsIPresShell* aPresShell) :
|
||||
DocAccessible(aDocument, aRootContent, aPresShell), mHWND(nullptr)
|
||||
DocAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell) :
|
||||
DocAccessible(aDocument, aPresShell), mHWND(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -15,8 +15,7 @@ namespace a11y {
|
||||
class DocAccessibleWrap : public DocAccessible
|
||||
{
|
||||
public:
|
||||
DocAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
|
||||
nsIPresShell* aPresShell);
|
||||
DocAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell);
|
||||
virtual ~DocAccessibleWrap();
|
||||
|
||||
DECL_IUNKNOWN_INHERITED
|
||||
|
@ -15,9 +15,8 @@ using namespace mozilla::a11y;
|
||||
// Constructor/desctructor
|
||||
|
||||
RootAccessibleWrap::
|
||||
RootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
|
||||
nsIPresShell* aPresShell) :
|
||||
RootAccessible(aDocument, aRootContent, aPresShell)
|
||||
RootAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell) :
|
||||
RootAccessible(aDocument, aPresShell)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,7 @@ namespace a11y {
|
||||
class RootAccessibleWrap : public RootAccessible
|
||||
{
|
||||
public:
|
||||
RootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
|
||||
nsIPresShell* aPresShell);
|
||||
RootAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell);
|
||||
virtual ~RootAccessibleWrap();
|
||||
|
||||
// RootAccessible
|
||||
|
@ -67,8 +67,9 @@ var internal = ns();
|
||||
// menu
|
||||
var lastContextProcessId = null;
|
||||
|
||||
var uuidModule = require('./util/uuid');
|
||||
function uuid() {
|
||||
return require('./util/uuid').uuid().toString();
|
||||
return uuidModule.uuid().toString();
|
||||
}
|
||||
|
||||
function getScheme(spec) {
|
||||
|
@ -57,7 +57,7 @@ AppRunner.prototype = {
|
||||
// get a ref to the app <iframe>
|
||||
frameLoader.QueryInterface(Ci.nsIFrameLoader);
|
||||
// Ignore notifications that aren't from a BrowserOrApp
|
||||
if (!frameLoader.ownerIsBrowserOrAppFrame) {
|
||||
if (!frameLoader.ownerIsMozBrowserOrAppFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ this.AboutServiceWorkers = {
|
||||
!message.principal.origin ||
|
||||
!message.principal.originAttributes ||
|
||||
!message.principal.originAttributes.appId ||
|
||||
(message.principal.originAttributes.inBrowser == null)) {
|
||||
(message.principal.originAttributes.inIsolatedMozBrowser == null)) {
|
||||
self.sendError(message.id, "MissingPrincipal");
|
||||
return;
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ var ErrorPage = {
|
||||
observe: function errorPageObserve(aSubject, aTopic, aData) {
|
||||
let frameLoader = aSubject.QueryInterface(Ci.nsIFrameLoader);
|
||||
// Ignore notifications that aren't from a BrowserOrApp
|
||||
if (!frameLoader.ownerIsBrowserOrAppFrame) {
|
||||
if (!frameLoader.ownerIsMozBrowserOrAppFrame) {
|
||||
return;
|
||||
}
|
||||
this._listenError(frameLoader);
|
||||
|
@ -1377,6 +1377,9 @@ pref("browser.newtabpage.directory.ping", "https://tiles.services.mozilla.com/v3
|
||||
// activates the remote-hosted newtab page
|
||||
pref("browser.newtabpage.remote", false);
|
||||
|
||||
// Toggles endpoints allowed for remote newtab communications
|
||||
pref("browser.newtabpage.remote.mode", "production");
|
||||
|
||||
// Enable the DOM fullscreen API.
|
||||
pref("full-screen-api.enabled", true);
|
||||
|
||||
@ -1655,3 +1658,6 @@ pref("media.webspeech.synth.enabled", true);
|
||||
pref("browser.esedbreader.loglevel", "Error");
|
||||
|
||||
pref("browser.laterrun.enabled", false);
|
||||
|
||||
// Enable browser frames for use on desktop. Only exposed to chrome callers.
|
||||
pref("dom.mozBrowserFramesEnabled", true);
|
||||
|
@ -1379,9 +1379,6 @@ var BookmarkingUI = {
|
||||
aHeaderItem.nextSibling.remove();
|
||||
}
|
||||
|
||||
PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
|
||||
.asyncExecuteLegacyQueries([query], 1, options, {
|
||||
handleResult: function (aResultSet) {
|
||||
let onItemCommand = function (aEvent) {
|
||||
let item = aEvent.target;
|
||||
openUILink(item.getAttribute("targetURI"), aEvent);
|
||||
@ -1389,11 +1386,13 @@ var BookmarkingUI = {
|
||||
};
|
||||
|
||||
let fragment = document.createDocumentFragment();
|
||||
let row;
|
||||
while ((row = aResultSet.getNextRow())) {
|
||||
let uri = row.getResultByIndex(1);
|
||||
let title = row.getResultByIndex(2);
|
||||
let icon = row.getResultByIndex(6);
|
||||
let root = PlacesUtils.history.executeQuery(query, options).root;
|
||||
root.containerOpen = true;
|
||||
for (let i = 0; i < root.childCount; i++) {
|
||||
let node = root.getChild(i);
|
||||
let uri = node.uri;
|
||||
let title = node.title;
|
||||
let icon = node.icon;
|
||||
|
||||
let item =
|
||||
document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
||||
@ -1409,15 +1408,9 @@ var BookmarkingUI = {
|
||||
}
|
||||
fragment.appendChild(item);
|
||||
}
|
||||
root.containerOpen = false;
|
||||
aHeaderItem.parentNode.insertBefore(fragment, aHeaderItem.nextSibling);
|
||||
},
|
||||
handleError: function (aError) {
|
||||
Cu.reportError("Error while attempting to show recent bookmarks: " + aError);
|
||||
},
|
||||
handleCompletion: function (aReason) {
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles star styling based on page proxy state changes.
|
||||
|
@ -252,7 +252,8 @@ ContentSearchUIController.prototype = {
|
||||
let searchText = this.input;
|
||||
let searchTerms;
|
||||
if (this._table.hidden ||
|
||||
aEvent.originalTarget.id == "contentSearchDefaultEngineHeader") {
|
||||
aEvent.originalTarget.id == "contentSearchDefaultEngineHeader" ||
|
||||
aEvent instanceof KeyboardEvent) {
|
||||
searchTerms = searchText.value;
|
||||
}
|
||||
else {
|
||||
|
@ -290,7 +290,6 @@ skip-if = os == 'win' || e10s # Bug 1159268 - Need a content-process safe versio
|
||||
[browser_bug1070778.js]
|
||||
[browser_accesskeys.js]
|
||||
[browser_canonizeURL.js]
|
||||
skip-if = e10s # Bug 1094510 - test hits the network in e10s mode only
|
||||
[browser_clipboard.js]
|
||||
[browser_contentAreaClick.js]
|
||||
[browser_contextmenu.js]
|
||||
|
@ -1,8 +1,3 @@
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
testNext();
|
||||
}
|
||||
|
||||
var pairs = [
|
||||
["example", "http://www.example.net/"],
|
||||
["ex-ample", "http://www.ex-ample.net/"],
|
||||
@ -20,37 +15,56 @@ var pairs = [
|
||||
["ex ample", Services.search.defaultEngine.getSubmission("ex ample", null, "keyword").uri.spec],
|
||||
];
|
||||
|
||||
function testNext() {
|
||||
if (!pairs.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
add_task(function*() {
|
||||
for (let [inputValue, expectedURL] of pairs) {
|
||||
let focusEventPromise = BrowserTestUtils.waitForEvent(gURLBar, "focus");
|
||||
let messagePromise = BrowserTestUtils.waitForMessage(gBrowser.selectedBrowser.messageManager,
|
||||
"browser_canonizeURL:start");
|
||||
|
||||
let [inputValue, expectedURL] = pairs.shift();
|
||||
|
||||
gBrowser.addProgressListener({
|
||||
onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
let stoppedLoadPromise = ContentTask.spawn(gBrowser.selectedBrowser, [inputValue, expectedURL],
|
||||
function([inputValue, expectedURL]) {
|
||||
return new Promise(resolve => {
|
||||
let wpl = {
|
||||
onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if (aStateFlags & Ci.nsIWebProgressListener.STATE_START &&
|
||||
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) {
|
||||
if (!aRequest || !(aRequest instanceof Ci.nsIChannel)) {
|
||||
return;
|
||||
}
|
||||
aRequest.QueryInterface(Ci.nsIChannel);
|
||||
is(aRequest.originalURI.spec, expectedURL,
|
||||
"entering '" + inputValue + "' loads expected URL");
|
||||
|
||||
gBrowser.removeProgressListener(this);
|
||||
gBrowser.stop();
|
||||
|
||||
executeSoon(testNext);
|
||||
webProgress.removeProgressListener(filter);
|
||||
filter.removeProgressListener(wpl);
|
||||
docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
docShell.stop(docShell.STOP_ALL);
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
let filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
|
||||
.createInstance(Ci.nsIWebProgress);
|
||||
filter.addProgressListener(wpl, Ci.nsIWebProgress.NOTIFY_ALL);
|
||||
|
||||
gURLBar.addEventListener("focus", function onFocus() {
|
||||
gURLBar.removeEventListener("focus", onFocus);
|
||||
gURLBar.inputField.value = inputValue.slice(0, -1);
|
||||
EventUtils.synthesizeKey(inputValue.slice(-1) , {});
|
||||
EventUtils.synthesizeKey("VK_RETURN", { shiftKey: true });
|
||||
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);
|
||||
// We're sending this off to trigger the start of the this test, when all the
|
||||
// listeners are in place:
|
||||
sendAsyncMessage("browser_canonizeURL:start");
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
gBrowser.selectedBrowser.focus();
|
||||
gURLBar.focus();
|
||||
|
||||
}
|
||||
yield Promise.all([focusEventPromise, messagePromise]);
|
||||
|
||||
gURLBar.inputField.value = inputValue.slice(0, -1);
|
||||
EventUtils.synthesizeKey(inputValue.slice(-1) , {});
|
||||
EventUtils.synthesizeKey("VK_RETURN", { shiftKey: true });
|
||||
yield stoppedLoadPromise;
|
||||
}
|
||||
});
|
||||
|
@ -105,7 +105,7 @@
|
||||
when-connection="secure secure-ev"/>
|
||||
</vbox>
|
||||
|
||||
<vbox id="identity-popup-securityView-body">
|
||||
<vbox id="identity-popup-securityView-body" flex="1">
|
||||
<!-- (EV) Certificate Information -->
|
||||
<description id="identity-popup-content-verified-by"
|
||||
when-connection="secure-ev">&identity.connectionVerified1;</description>
|
||||
@ -168,7 +168,9 @@
|
||||
label="&identity.enableMixedContentBlocking.label;"
|
||||
accesskey="&identity.enableMixedContentBlocking.accesskey;"
|
||||
oncommand="gIdentityHandler.enableMixedContentProtection()"/>
|
||||
</vbox>
|
||||
|
||||
<vbox id="identity-popup-securityView-footer">
|
||||
<!-- More Security Information -->
|
||||
<button label="&identity.moreInfoLinkText2;"
|
||||
oncommand="gIdentityHandler.handleMoreInfoClick(event);"/>
|
||||
|
@ -346,11 +346,47 @@ DistributionCustomizer.prototype = {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
||||
var usedPreferences = [];
|
||||
|
||||
if (sections["Preferences-" + this._locale]) {
|
||||
for (let key of enumerate(this._ini.getKeys("Preferences-" + this._locale))) {
|
||||
try {
|
||||
let value = this._ini.getString("Preferences-" + this._locale, key);
|
||||
if (value) {
|
||||
Preferences.set(key, parseValue(value));
|
||||
}
|
||||
usedPreferences.push(key);
|
||||
} catch (e) { /* ignore bad prefs and move on */ }
|
||||
}
|
||||
}
|
||||
|
||||
if (sections["Preferences-" + this._language]) {
|
||||
for (let key of enumerate(this._ini.getKeys("Preferences-" + this._language))) {
|
||||
if (usedPreferences.indexOf(key) > -1) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
let value = this._ini.getString("Preferences-" + this._language, key);
|
||||
if (value) {
|
||||
Preferences.set(key, parseValue(value));
|
||||
}
|
||||
usedPreferences.push(key);
|
||||
} catch (e) { /* ignore bad prefs and move on */ }
|
||||
}
|
||||
}
|
||||
|
||||
if (sections["Preferences"]) {
|
||||
for (let key of enumerate(this._ini.getKeys("Preferences"))) {
|
||||
if (usedPreferences.indexOf(key) > -1) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
let value = parseValue(this._ini.getString("Preferences", key));
|
||||
Preferences.set(key, value);
|
||||
let value = this._ini.getString("Preferences", key);
|
||||
if (value) {
|
||||
value = value.replace(/%LOCALE%/g, this._locale);
|
||||
value = value.replace(/%LANGUAGE%/g, this._language);
|
||||
Preferences.set(key, parseValue(value));
|
||||
}
|
||||
} catch (e) { /* ignore bad prefs and move on */ }
|
||||
}
|
||||
}
|
||||
@ -363,8 +399,9 @@ DistributionCustomizer.prototype = {
|
||||
if (sections["LocalizablePreferences-" + this._locale]) {
|
||||
for (let key of enumerate(this._ini.getKeys("LocalizablePreferences-" + this._locale))) {
|
||||
try {
|
||||
let value = parseValue(this._ini.getString("LocalizablePreferences-" + this._locale, key));
|
||||
if (value !== undefined) {
|
||||
let value = this._ini.getString("LocalizablePreferences-" + this._locale, key);
|
||||
if (value) {
|
||||
value = parseValue(value);
|
||||
localizedStr.data = "data:text/plain," + key + "=" + value;
|
||||
defaults._prefBranch.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
|
||||
}
|
||||
@ -379,8 +416,9 @@ DistributionCustomizer.prototype = {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
let value = parseValue(this._ini.getString("LocalizablePreferences-" + this._language, key));
|
||||
if (value !== undefined) {
|
||||
let value = this._ini.getString("LocalizablePreferences-" + this._language, key);
|
||||
if (value) {
|
||||
value = parseValue(value);
|
||||
localizedStr.data = "data:text/plain," + key + "=" + value;
|
||||
defaults._prefBranch.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
|
||||
}
|
||||
@ -395,13 +433,14 @@ DistributionCustomizer.prototype = {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
let value = parseValue(this._ini.getString("LocalizablePreferences", key));
|
||||
if (value !== undefined) {
|
||||
let value = this._ini.getString("LocalizablePreferences", key);
|
||||
if (value) {
|
||||
value = parseValue(value);
|
||||
value = value.replace(/%LOCALE%/g, this._locale);
|
||||
value = value.replace(/%LANGUAGE%/g, this._language);
|
||||
localizedStr.data = "data:text/plain," + key + "=" + value;
|
||||
defaults._prefBranch.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
|
||||
}
|
||||
defaults._prefBranch.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
|
||||
} catch (e) { /* ignore bad prefs and move on */ }
|
||||
}
|
||||
}
|
||||
|
@ -125,6 +125,19 @@ global.makeWidgetId = id => {
|
||||
return id.replace(/[^a-z0-9_-]/g, "_");
|
||||
};
|
||||
|
||||
function promisePopupShown(popup) {
|
||||
return new Promise(resolve => {
|
||||
if (popup.state == "open") {
|
||||
resolve();
|
||||
} else {
|
||||
popup.addEventListener("popupshown", function onPopupShown(event) {
|
||||
popup.removeEventListener("popupshown", onPopupShown);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
class BasePopup {
|
||||
constructor(extension, viewNode, popupURL) {
|
||||
let popupURI = Services.io.newURI(popupURL, null, extension.baseURI);
|
||||
@ -254,6 +267,10 @@ class BasePopup {
|
||||
|
||||
// Resizes the browser to match the preferred size of the content.
|
||||
resizeBrowser() {
|
||||
if (!this.browser) {
|
||||
return;
|
||||
}
|
||||
|
||||
let width, height;
|
||||
try {
|
||||
let w = {}, h = {};
|
||||
@ -310,8 +327,13 @@ global.PanelPopup = class PanelPopup extends BasePopup {
|
||||
}
|
||||
|
||||
closePopup() {
|
||||
promisePopupShown(this.viewNode).then(() => {
|
||||
// Make sure we're not already destroyed.
|
||||
if (this.viewNode) {
|
||||
this.viewNode.hidePopup();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
global.ViewPopup = class ViewPopup extends BasePopup {
|
||||
|
@ -3,6 +3,8 @@
|
||||
"use strict";
|
||||
|
||||
function* testInArea(area) {
|
||||
let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head></html>`;
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"background": {
|
||||
@ -14,17 +16,22 @@ function* testInArea(area) {
|
||||
},
|
||||
|
||||
files: {
|
||||
"popup-a.html": `<script src="popup-a.js"></script>`,
|
||||
"popup-a.html": scriptPage("popup-a.js"),
|
||||
"popup-a.js": function() {
|
||||
browser.runtime.sendMessage("from-popup-a");
|
||||
browser.runtime.onMessage.addListener(msg => {
|
||||
if (msg == "close-popup") {
|
||||
window.close();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
"data/popup-b.html": `<script src="popup-b.js"></script>`,
|
||||
"data/popup-b.html": scriptPage("popup-b.js"),
|
||||
"data/popup-b.js": function() {
|
||||
browser.runtime.sendMessage("from-popup-b");
|
||||
},
|
||||
|
||||
"data/background.html": `<script src="background.js"></script>`,
|
||||
"data/background.html": scriptPage("background.js"),
|
||||
|
||||
"data/background.js": function() {
|
||||
let sendClick;
|
||||
@ -51,26 +58,36 @@ function* testInArea(area) {
|
||||
},
|
||||
() => {
|
||||
browser.browserAction.setPopup({popup: "/popup-a.html"});
|
||||
sendClick({expectEvent: false, expectPopup: "a"});
|
||||
sendClick({expectEvent: false, expectPopup: "a", runNextTest: true});
|
||||
},
|
||||
() => {
|
||||
browser.test.sendMessage("next-test", {expectClosed: true});
|
||||
},
|
||||
];
|
||||
|
||||
let expect = {};
|
||||
sendClick = ({expectEvent, expectPopup}) => {
|
||||
expect = {event: expectEvent, popup: expectPopup};
|
||||
sendClick = ({expectEvent, expectPopup, runNextTest}) => {
|
||||
expect = {event: expectEvent, popup: expectPopup, runNextTest};
|
||||
browser.test.sendMessage("send-click");
|
||||
};
|
||||
|
||||
browser.runtime.onMessage.addListener(msg => {
|
||||
if (expect.popup) {
|
||||
if (msg == "close-popup") {
|
||||
return;
|
||||
} else if (expect.popup) {
|
||||
browser.test.assertEq(msg, `from-popup-${expect.popup}`,
|
||||
"expected popup opened");
|
||||
} else {
|
||||
browser.test.fail("unexpected popup");
|
||||
browser.test.fail(`unexpected popup: ${msg}`);
|
||||
}
|
||||
|
||||
expect.popup = null;
|
||||
if (expect.runNextTest) {
|
||||
expect.runNextTest = false;
|
||||
tests.shift()();
|
||||
} else {
|
||||
browser.test.sendMessage("next-test");
|
||||
}
|
||||
});
|
||||
|
||||
browser.browserAction.onClicked.addListener(() => {
|
||||
@ -85,6 +102,11 @@ function* testInArea(area) {
|
||||
});
|
||||
|
||||
browser.test.onMessage.addListener((msg) => {
|
||||
if (msg == "close-popup") {
|
||||
browser.runtime.sendMessage("close-popup");
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg != "next-test") {
|
||||
browser.test.fail("Expecting 'next-test' message");
|
||||
}
|
||||
@ -107,13 +129,23 @@ function* testInArea(area) {
|
||||
});
|
||||
|
||||
let widget;
|
||||
extension.onMessage("next-test", Task.async(function* () {
|
||||
extension.onMessage("next-test", Task.async(function* (expecting = {}) {
|
||||
if (!widget) {
|
||||
widget = getBrowserActionWidget(extension);
|
||||
CustomizableUI.addWidgetToArea(widget.id, area);
|
||||
}
|
||||
if (expecting.expectClosed) {
|
||||
let panel = getBrowserActionPopup(extension);
|
||||
ok(panel, "Expect panel to exist");
|
||||
yield promisePopupShown(panel);
|
||||
|
||||
extension.sendMessage("close-popup");
|
||||
|
||||
yield promisePopupHidden(panel);
|
||||
ok(true, "Panel is closed");
|
||||
} else {
|
||||
yield closeBrowserAction(extension);
|
||||
}
|
||||
|
||||
extension.sendMessage("next-test");
|
||||
}));
|
||||
|
@ -19,6 +19,11 @@ add_task(function* testPageActionPopup() {
|
||||
"popup-a.html": scriptPage("popup-a.js"),
|
||||
"popup-a.js": function() {
|
||||
browser.runtime.sendMessage("from-popup-a");
|
||||
browser.runtime.onMessage.addListener(msg => {
|
||||
if (msg == "close-popup") {
|
||||
window.close();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
"data/popup-b.html": scriptPage("popup-b.js"),
|
||||
@ -55,26 +60,36 @@ add_task(function* testPageActionPopup() {
|
||||
},
|
||||
() => {
|
||||
browser.pageAction.setPopup({tabId, popup: "/popup-a.html"});
|
||||
sendClick({expectEvent: false, expectPopup: "a"});
|
||||
sendClick({expectEvent: false, expectPopup: "a", runNextTest: true});
|
||||
},
|
||||
() => {
|
||||
browser.test.sendMessage("next-test", {expectClosed: true});
|
||||
},
|
||||
];
|
||||
|
||||
let expect = {};
|
||||
sendClick = ({expectEvent, expectPopup}) => {
|
||||
expect = {event: expectEvent, popup: expectPopup};
|
||||
sendClick = ({expectEvent, expectPopup, runNextTest}) => {
|
||||
expect = {event: expectEvent, popup: expectPopup, runNextTest};
|
||||
browser.test.sendMessage("send-click");
|
||||
};
|
||||
|
||||
browser.runtime.onMessage.addListener(msg => {
|
||||
if (expect.popup) {
|
||||
if (msg == "close-popup") {
|
||||
return;
|
||||
} else if (expect.popup) {
|
||||
browser.test.assertEq(msg, `from-popup-${expect.popup}`,
|
||||
"expected popup opened");
|
||||
} else {
|
||||
browser.test.fail("unexpected popup");
|
||||
browser.test.fail(`unexpected popup: ${msg}`);
|
||||
}
|
||||
|
||||
expect.popup = null;
|
||||
if (expect.runNextTest) {
|
||||
expect.runNextTest = false;
|
||||
tests.shift()();
|
||||
} else {
|
||||
browser.test.sendMessage("next-test");
|
||||
}
|
||||
});
|
||||
|
||||
browser.pageAction.onClicked.addListener(() => {
|
||||
@ -89,6 +104,11 @@ add_task(function* testPageActionPopup() {
|
||||
});
|
||||
|
||||
browser.test.onMessage.addListener((msg) => {
|
||||
if (msg == "close-popup") {
|
||||
browser.runtime.sendMessage("close-popup");
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg != "next-test") {
|
||||
browser.test.fail("Expecting 'next-test' message");
|
||||
}
|
||||
@ -118,12 +138,22 @@ add_task(function* testPageActionPopup() {
|
||||
clickPageAction(extension);
|
||||
});
|
||||
|
||||
extension.onMessage("next-test", Task.async(function* () {
|
||||
extension.onMessage("next-test", Task.async(function* (expecting = {}) {
|
||||
let panel = document.getElementById(panelId);
|
||||
if (panel) {
|
||||
if (expecting.expectClosed) {
|
||||
ok(panel, "Expect panel to exist");
|
||||
yield promisePopupShown(panel);
|
||||
|
||||
extension.sendMessage("close-popup");
|
||||
|
||||
yield promisePopupHidden(panel);
|
||||
ok(true, `Panel is closed`);
|
||||
} else if (panel) {
|
||||
yield promisePopupShown(panel);
|
||||
panel.hidePopup();
|
||||
}
|
||||
|
||||
if (panel) {
|
||||
panel = document.getElementById(panelId);
|
||||
is(panel, null, "panel successfully removed from document after hiding");
|
||||
}
|
||||
|
@ -138,6 +138,9 @@ add_task(function* testWebNavigationFrames() {
|
||||
is(getAllFramesDetails.length, collectedDetails.length,
|
||||
"number of frames found should equal the number onCompleted events collected");
|
||||
|
||||
is(getAllFramesDetails[0].frameId, 0, "the root frame has the expected frameId");
|
||||
is(getAllFramesDetails[0].parentFrameId, -1, "the root frame has the expected parentFrameId");
|
||||
|
||||
// ordered by frameId
|
||||
let sortByFrameId = (el1, el2) => {
|
||||
let val1 = el1 ? el1.frameId : -1;
|
||||
|
@ -7,7 +7,7 @@
|
||||
* clickBrowserAction clickPageAction
|
||||
* getBrowserActionPopup getPageActionPopup
|
||||
* closeBrowserAction closePageAction
|
||||
* promisePopupShown
|
||||
* promisePopupShown promisePopupHidden
|
||||
*/
|
||||
|
||||
var {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
@ -59,6 +59,16 @@ function promisePopupShown(popup) {
|
||||
});
|
||||
}
|
||||
|
||||
function promisePopupHidden(popup) {
|
||||
return new Promise(resolve => {
|
||||
let onPopupHidden = event => {
|
||||
popup.removeEventListener("popuphidden", onPopupHidden);
|
||||
resolve();
|
||||
};
|
||||
popup.addEventListener("popuphidden", onPopupHidden);
|
||||
});
|
||||
}
|
||||
|
||||
function getBrowserActionWidget(extension) {
|
||||
return CustomizableUI.getWidget(makeWidgetId(extension.id) + "-browser-action");
|
||||
}
|
||||
@ -68,6 +78,8 @@ function getBrowserActionPopup(extension, win = window) {
|
||||
|
||||
if (group.areaType == CustomizableUI.TYPE_TOOLBAR) {
|
||||
return win.document.getElementById("customizationui-widget-panel");
|
||||
} else {
|
||||
return win.PanelUI.panel;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ XPCOMUtils.defineLazyGetter(this, "EventEmitter", function() {
|
||||
// Supported prefs and data type
|
||||
const gPrefsMap = new Map([
|
||||
["browser.newtabpage.remote", "bool"],
|
||||
["browser.newtabpage.remote.mode", "str"],
|
||||
["browser.newtabpage.enabled", "bool"],
|
||||
["browser.newtabpage.enhanced", "bool"],
|
||||
["browser.newtabpage.pinned", "str"],
|
||||
|
13
browser/components/newtab/NewTabRemoteResources.jsm
Normal file
13
browser/components/newtab/NewTabRemoteResources.jsm
Normal file
@ -0,0 +1,13 @@
|
||||
/* exported MODE_CHANNEL_MAP */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["MODE_CHANNEL_MAP"];
|
||||
|
||||
const MODE_CHANNEL_MAP = {
|
||||
"production": {origin: "https://content.cdn.mozilla.net"},
|
||||
"staging": {origin: "https://content-cdn.stage.mozaws.net"},
|
||||
"test": {origin: "https://example.com"},
|
||||
"test2": {origin: "http://mochi.test:8888"},
|
||||
"dev": {origin: "http://localhost:8888"}
|
||||
};
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/* globals XPCOMUtils, NewTabPrefsProvider, Services,
|
||||
Locale, UpdateUtils
|
||||
Locale, UpdateUtils, MODE_CHANNEL_MAP
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
@ -20,11 +20,12 @@ XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
|
||||
"resource:///modules/NewTabPrefsProvider.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Locale",
|
||||
"resource://gre/modules/Locale.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "MODE_CHANNEL_MAP",
|
||||
"resource:///modules/NewTabRemoteResources.jsm");
|
||||
|
||||
const LOCAL_NEWTAB_URL = "chrome://browser/content/newtab/newTab.xhtml";
|
||||
|
||||
const REMOTE_NEWTAB_URL = "https://newtab.cdn.mozilla.net/" +
|
||||
"v%VERSION%/%CHANNEL%/%LOCALE%/index.html";
|
||||
const REMOTE_NEWTAB_PATH = "/v%VERSION%/%CHANNEL%/%LOCALE%/index.html";
|
||||
|
||||
const ABOUT_URL = "about:newtab";
|
||||
|
||||
@ -37,6 +38,9 @@ const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS";
|
||||
// The preference that tells what locale the user selected
|
||||
const PREF_SELECTED_LOCALE = "general.useragent.locale";
|
||||
|
||||
// The preference that tells what remote mode is enabled.
|
||||
const PREF_REMOTE_MODE = "browser.newtabpage.remote.mode";
|
||||
|
||||
const VALID_CHANNELS = new Set(["esr", "release", "beta", "aurora", "nightly"]);
|
||||
|
||||
const REMOTE_NEWTAB_VERSION = "0";
|
||||
@ -44,6 +48,8 @@ const REMOTE_NEWTAB_VERSION = "0";
|
||||
function AboutNewTabService() {
|
||||
NewTabPrefsProvider.prefs.on(PREF_REMOTE_ENABLED, this._handleToggleEvent.bind(this));
|
||||
|
||||
this._updateRemoteMaybe = this._updateRemoteMaybe.bind(this);
|
||||
|
||||
// trigger remote change if needed, according to pref
|
||||
this.toggleRemote(Services.prefs.getBoolPref(PREF_REMOTE_ENABLED));
|
||||
}
|
||||
@ -124,14 +130,18 @@ AboutNewTabService.prototype = {
|
||||
this._remoteURL = this.generateRemoteURL();
|
||||
NewTabPrefsProvider.prefs.on(
|
||||
PREF_SELECTED_LOCALE,
|
||||
this._updateRemoteMaybe.bind(this));
|
||||
this._updateRemoteMaybe);
|
||||
NewTabPrefsProvider.prefs.on(
|
||||
PREF_MATCH_OS_LOCALE,
|
||||
this._updateRemoteMaybe.bind(this));
|
||||
this._updateRemoteMaybe);
|
||||
NewTabPrefsProvider.prefs.on(
|
||||
PREF_REMOTE_MODE,
|
||||
this._updateRemoteMaybe);
|
||||
this._remoteEnabled = true;
|
||||
} else {
|
||||
NewTabPrefsProvider.prefs.off(PREF_SELECTED_LOCALE, this._updateRemoteMaybe);
|
||||
NewTabPrefsProvider.prefs.off(PREF_MATCH_OS_LOCALE, this._updateRemoteMaybe);
|
||||
NewTabPrefsProvider.prefs.off(PREF_REMOTE_MODE, this._updateRemoteMaybe);
|
||||
this._remoteEnabled = false;
|
||||
}
|
||||
this._newTabURL = ABOUT_URL;
|
||||
@ -139,15 +149,19 @@ AboutNewTabService.prototype = {
|
||||
},
|
||||
|
||||
/*
|
||||
* Generate a default url based on locale and update channel
|
||||
* Generate a default url based on remote mode, version, locale and update channel
|
||||
*/
|
||||
generateRemoteURL() {
|
||||
let releaseName = this.releaseFromUpdateChannel(UpdateUtils.UpdateChannel);
|
||||
let url = REMOTE_NEWTAB_URL
|
||||
let path = REMOTE_NEWTAB_PATH
|
||||
.replace("%VERSION%", REMOTE_NEWTAB_VERSION)
|
||||
.replace("%LOCALE%", Locale.getLocale())
|
||||
.replace("%CHANNEL%", releaseName);
|
||||
return url;
|
||||
let mode = Services.prefs.getCharPref(PREF_REMOTE_MODE, "production");
|
||||
if (!(mode in MODE_CHANNEL_MAP)) {
|
||||
mode = "production";
|
||||
}
|
||||
return MODE_CHANNEL_MAP[mode].origin + path;
|
||||
},
|
||||
|
||||
/*
|
||||
|
@ -12,6 +12,7 @@ XPCSHELL_TESTS_MANIFESTS += [
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'NewTabPrefsProvider.jsm',
|
||||
'NewTabRemoteResources.jsm',
|
||||
'NewTabURL.jsm',
|
||||
'PlacesProvider.jsm'
|
||||
]
|
||||
|
@ -105,13 +105,16 @@ add_task(function* test_updates() {
|
||||
Preferences.set("browser.newtabpage.remote", true);
|
||||
aboutNewTabService.resetNewTabURL(); // need to set manually because pref notifs are off
|
||||
let notificationPromise;
|
||||
let expectedHref = "https://newtab.cdn.mozilla.net" +
|
||||
`/v${aboutNewTabService.remoteVersion}` +
|
||||
let productionModeBaseUrl = "https://content.cdn.mozilla.net";
|
||||
let testModeBaseUrl = "https://example.com";
|
||||
let expectedPath = `/v${aboutNewTabService.remoteVersion}` +
|
||||
`/${aboutNewTabService.remoteReleaseName}` +
|
||||
"/en-GB" +
|
||||
"/index.html";
|
||||
let expectedHref = productionModeBaseUrl + expectedPath;
|
||||
Preferences.set("intl.locale.matchOS", true);
|
||||
Preferences.set("general.useragent.locale", "en-GB");
|
||||
Preferences.set("browser.newtabpage.remote.mode", "production");
|
||||
NewTabPrefsProvider.prefs.init();
|
||||
|
||||
// test update checks for prefs
|
||||
@ -123,7 +126,19 @@ add_task(function* test_updates() {
|
||||
notificationPromise = nextChangeNotificationPromise(
|
||||
DEFAULT_HREF, "Remote href changes back to default");
|
||||
Preferences.set("general.useragent.locale", "en-US");
|
||||
yield notificationPromise;
|
||||
|
||||
// test update fires when mode is changed
|
||||
expectedPath = expectedPath.replace("/en-GB/", "/en-US/");
|
||||
notificationPromise = nextChangeNotificationPromise(
|
||||
testModeBaseUrl + expectedPath, "Remote href changes back to origin of test mode");
|
||||
Preferences.set("browser.newtabpage.remote.mode", "test");
|
||||
yield notificationPromise;
|
||||
|
||||
// test invalid mode ends up pointing to production url
|
||||
notificationPromise = nextChangeNotificationPromise(
|
||||
DEFAULT_HREF, "Remote href changes back to production default");
|
||||
Preferences.set("browser.newtabpage.remote.mode", "invalid");
|
||||
yield notificationPromise;
|
||||
|
||||
// test update fires on override and reset
|
||||
|
@ -46,7 +46,6 @@ skip-if = e10s # Bug ?????? - test fails - "Number of dragged items should be th
|
||||
[browser_library_search.js]
|
||||
[browser_library_views_liveupdate.js]
|
||||
[browser_markPageAsFollowedLink.js]
|
||||
skip-if = e10s # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly (test does EventUtils.sendMouseEvent...)
|
||||
[browser_sidebarpanels_click.js]
|
||||
skip-if = true # temporarily disabled for breaking the treeview - bug 658744
|
||||
[browser_sort_in_library.js]
|
||||
|
@ -1,7 +1,3 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests that visits across frames are correctly represented in the database.
|
||||
*/
|
||||
@ -11,76 +7,61 @@ const PAGE_URL = BASE_URL + "/framedPage.html";
|
||||
const LEFT_URL = BASE_URL + "/frameLeft.html";
|
||||
const RIGHT_URL = BASE_URL + "/frameRight.html";
|
||||
|
||||
var gTabLoaded = false;
|
||||
var gLeftFrameVisited = false;
|
||||
add_task(function* test() {
|
||||
// We must wait for both frames to be loaded and the visits to be registered.
|
||||
let deferredLeftFrameVisit = PromiseUtils.defer();
|
||||
let deferredRightFrameVisit = PromiseUtils.defer();
|
||||
|
||||
var observer = {
|
||||
observe: function(aSubject, aTopic, aData)
|
||||
{
|
||||
let url = aSubject.QueryInterface(Ci.nsIURI).spec;
|
||||
Services.obs.addObserver(function observe(subject) {
|
||||
Task.spawn(function* () {
|
||||
let url = subject.QueryInterface(Ci.nsIURI).spec;
|
||||
if (url == LEFT_URL ) {
|
||||
is(getTransitionForUrl(url), null,
|
||||
is((yield getTransitionForUrl(url)), null,
|
||||
"Embed visits should not get a database entry.");
|
||||
gLeftFrameVisited = true;
|
||||
maybeClickLink();
|
||||
deferredLeftFrameVisit.resolve();
|
||||
}
|
||||
else if (url == RIGHT_URL ) {
|
||||
is(getTransitionForUrl(url), PlacesUtils.history.TRANSITION_FRAMED_LINK,
|
||||
is((yield getTransitionForUrl(url)),
|
||||
PlacesUtils.history.TRANSITION_FRAMED_LINK,
|
||||
"User activated visits should get a FRAMED_LINK transition.");
|
||||
finish();
|
||||
Services.obs.removeObserver(observe, "uri-visit-saved");
|
||||
deferredRightFrameVisit.resolve();
|
||||
}
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
|
||||
};
|
||||
Services.obs.addObserver(observer, "uri-visit-saved", false);
|
||||
});
|
||||
}, "uri-visit-saved", false);
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
gBrowser.selectedTab = gBrowser.addTab(PAGE_URL);
|
||||
let frameCount = 0;
|
||||
gBrowser.selectedBrowser.addEventListener("DOMContentLoaded",
|
||||
function (event)
|
||||
{
|
||||
// Wait for all the frames.
|
||||
if (frameCount++ < 2)
|
||||
return;
|
||||
gBrowser.selectedBrowser.removeEventListener("DOMContentLoaded", arguments.callee, false)
|
||||
gTabLoaded = true;
|
||||
maybeClickLink();
|
||||
}, false
|
||||
);
|
||||
}
|
||||
// Open a tab and wait for all the subframes to load.
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE_URL);
|
||||
|
||||
// Wait for the left frame visit to be registered.
|
||||
info("Waiting left frame visit");
|
||||
yield deferredLeftFrameVisit.promise;
|
||||
|
||||
function maybeClickLink() {
|
||||
if (gTabLoaded && gLeftFrameVisited) {
|
||||
// Click on the link in the left frame to cause a page load in the
|
||||
// right frame.
|
||||
EventUtils.sendMouseEvent({type: "click"}, "clickme", content.frames[0]);
|
||||
}
|
||||
}
|
||||
info("Clicking link");
|
||||
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
|
||||
content.frames[0].document.getElementById("clickme").click();
|
||||
});
|
||||
|
||||
function getTransitionForUrl(aUrl)
|
||||
{
|
||||
let dbConn = PlacesUtils.history
|
||||
.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
let stmt = dbConn.createStatement(
|
||||
"SELECT visit_type FROM moz_historyvisits WHERE place_id = " +
|
||||
"(SELECT id FROM moz_places WHERE url = :page_url)");
|
||||
stmt.params.page_url = aUrl;
|
||||
try {
|
||||
if (!stmt.executeStep()) {
|
||||
// Wait for the right frame visit to be registered.
|
||||
info("Waiting right frame visit");
|
||||
yield deferredRightFrameVisit.promise;
|
||||
|
||||
yield BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
||||
function* getTransitionForUrl(url) {
|
||||
// Ensure all the transactions completed.
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
let db = yield PlacesUtils.promiseDBConnection();
|
||||
let rows = yield db.execute(`
|
||||
SELECT visit_type
|
||||
FROM moz_historyvisits
|
||||
WHERE place_id = (SELECT id FROM moz_places WHERE url = :url)`,
|
||||
{ url });
|
||||
if (rows.length) {
|
||||
return rows[0].getResultByName("visit_type");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return stmt.row.visit_type;
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
registerCleanupFunction(function ()
|
||||
{
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
Services.obs.removeObserver(observer, "uri-visit-saved");
|
||||
})
|
||||
|
@ -145,6 +145,10 @@ var SessionHistoryInternal = {
|
||||
entry.originalURI = shEntry.originalURI.spec;
|
||||
}
|
||||
|
||||
if (shEntry.loadReplace) {
|
||||
entry.loadReplace = shEntry.loadReplace;
|
||||
}
|
||||
|
||||
if (shEntry.srcdocData)
|
||||
entry.srcdocData = shEntry.srcdocData;
|
||||
|
||||
@ -316,6 +320,9 @@ var SessionHistoryInternal = {
|
||||
if (entry.originalURI) {
|
||||
shEntry.originalURI = Utils.makeURI(entry.originalURI);
|
||||
}
|
||||
if (entry.loadReplace) {
|
||||
shEntry.loadReplace = entry.loadReplace;
|
||||
}
|
||||
if (entry.isSrcdocEntry)
|
||||
shEntry.srcdocData = entry.srcdocData;
|
||||
if (entry.baseURI)
|
||||
|
@ -13,6 +13,28 @@ distribution.test.string.noquotes=Test String
|
||||
distribution.test.int=777
|
||||
distribution.test.bool.true=true
|
||||
distribution.test.bool.false=false
|
||||
distribution.test.empty=
|
||||
|
||||
distribution.test.pref.locale="%LOCALE%"
|
||||
distribution.test.pref.language.reset="Preference Set"
|
||||
distribution.test.pref.locale.reset="Preference Set"
|
||||
distribution.test.pref.locale.set="Preference Set"
|
||||
distribution.test.pref.language.set="Preference Set"
|
||||
|
||||
[Preferences-en]
|
||||
distribution.test.pref.language.en="en"
|
||||
distribution.test.pref.language.reset=
|
||||
distribution.test.pref.language.set="Language Set"
|
||||
distribution.test.pref.locale.set="Language Set"
|
||||
|
||||
[Preferences-en-US]
|
||||
distribution.test.pref.locale.en-US="en-US"
|
||||
distribution.test.pref.locale.reset=
|
||||
distribution.test.pref.locale.set="Locale Set"
|
||||
|
||||
|
||||
[Preferences-de]
|
||||
distribution.test.pref.language.de="de"
|
||||
|
||||
[LocalizablePreferences]
|
||||
distribution.test.locale="%LOCALE%"
|
||||
@ -33,4 +55,4 @@ distribution.test.locale.reset=
|
||||
distribution.test.locale.set="Locale Set"
|
||||
|
||||
[LocalizablePreferences-de]
|
||||
distribution.test.locale.de="de"
|
||||
distribution.test.language.de="de"
|
||||
|
@ -71,10 +71,30 @@ add_task(function* () {
|
||||
Assert.equal(Services.prefs.getIntPref("distribution.test.int"), 777);
|
||||
Assert.equal(Services.prefs.getBoolPref("distribution.test.bool.true"), true);
|
||||
Assert.equal(Services.prefs.getBoolPref("distribution.test.bool.false"), false);
|
||||
|
||||
Assert.throws(() => Services.prefs.getCharPref("distribution.test.empty"));
|
||||
Assert.throws(() => Services.prefs.getIntPref("distribution.test.empty"));
|
||||
Assert.throws(() => Services.prefs.getBoolPref("distribution.test.empty"));
|
||||
|
||||
Assert.equal(Services.prefs.getCharPref("distribution.test.pref.locale"), "en-US");
|
||||
Assert.equal(Services.prefs.getCharPref("distribution.test.pref.language.en"), "en");
|
||||
Assert.equal(Services.prefs.getCharPref("distribution.test.pref.locale.en-US"), "en-US");
|
||||
Assert.throws(() => Services.prefs.getCharPref("distribution.test.pref.language.de"));
|
||||
// This value was never set because of the empty language specific pref
|
||||
Assert.throws(() => Services.prefs.getCharPref("distribution.test.pref.language.reset"));
|
||||
// This value was never set because of the empty locale specific pref
|
||||
Assert.throws(() => Services.prefs.getCharPref("distribution.test.pref.locale.reset"));
|
||||
// This value was overridden by a locale specific setting
|
||||
Assert.equal(Services.prefs.getCharPref("distribution.test.pref.locale.set"), "Locale Set");
|
||||
// This value was overridden by a language specific setting
|
||||
Assert.equal(Services.prefs.getCharPref("distribution.test.pref.language.set"), "Language Set");
|
||||
// Language should not override locale
|
||||
Assert.notEqual(Services.prefs.getCharPref("distribution.test.pref.locale.set"), "Language Set");
|
||||
|
||||
Assert.equal(Services.prefs.getComplexValue("distribution.test.locale", Ci.nsIPrefLocalizedString).data, "en-US");
|
||||
Assert.equal(Services.prefs.getComplexValue("distribution.test.language.en", Ci.nsIPrefLocalizedString).data, "en");
|
||||
Assert.equal(Services.prefs.getComplexValue("distribution.test.locale.en-US", Ci.nsIPrefLocalizedString).data, "en-US");
|
||||
Assert.throws(() => Services.prefs.getComplexValue("distribution.test.locale.de", Ci.nsIPrefLocalizedString));
|
||||
Assert.throws(() => Services.prefs.getComplexValue("distribution.test.language.de", Ci.nsIPrefLocalizedString));
|
||||
// This value was never set because of the empty language specific pref
|
||||
Assert.throws(() => Services.prefs.getComplexValue("distribution.test.language.reset", Ci.nsIPrefLocalizedString));
|
||||
// This value was never set because of the empty locale specific pref
|
||||
|
@ -61,6 +61,15 @@ var ContentClick = {
|
||||
|
||||
// Note: We don't need the sidebar code here.
|
||||
|
||||
// Mark the page as a user followed link. This is done so that history can
|
||||
// distinguish automatic embed visits from user activated ones. For example
|
||||
// pages loaded in frames are embed visits and lost with the session, while
|
||||
// visits across frames should be preserved.
|
||||
try {
|
||||
if (!PrivateBrowsingUtils.isWindowPrivate(window))
|
||||
PlacesUIUtils.markPageAsFollowedLink(json.href);
|
||||
} catch (ex) { /* Skip invalid URIs. */ }
|
||||
|
||||
// This part is based on handleLinkClick.
|
||||
var where = window.whereToOpenLink(json);
|
||||
if (where == "current")
|
||||
@ -73,14 +82,5 @@ var ContentClick = {
|
||||
referrerPolicy: json.referrerPolicy,
|
||||
noReferrer: json.noReferrer };
|
||||
window.openLinkIn(json.href, where, params);
|
||||
|
||||
// Mark the page as a user followed link. This is done so that history can
|
||||
// distinguish automatic embed visits from user activated ones. For example
|
||||
// pages loaded in frames are embed visits and lost with the session, while
|
||||
// visits across frames should be preserved.
|
||||
try {
|
||||
if (!PrivateBrowsingUtils.isWindowPrivate(window))
|
||||
PlacesUIUtils.markPageAsFollowedLink(json.href);
|
||||
} catch (ex) { /* Skip invalid URIs. */ }
|
||||
}
|
||||
};
|
||||
|
@ -17,6 +17,15 @@
|
||||
@hudButtonFocused@
|
||||
}
|
||||
|
||||
#identity-popup-multiView > .panel-viewcontainer > .panel-viewstack > .panel-subviews {
|
||||
border-bottom-right-radius: 3.5px;
|
||||
}
|
||||
|
||||
#identity-popup-multiView > .panel-viewcontainer > .panel-viewstack > .panel-subviews:-moz-locale-dir(rtl) {
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 3.5px;
|
||||
}
|
||||
|
||||
#tracking-action-block,
|
||||
#tracking-action-unblock,
|
||||
#tracking-action-unblock-private,
|
||||
|
@ -83,15 +83,9 @@
|
||||
|
||||
#identity-popup-multiView > .panel-viewcontainer > .panel-viewstack > .panel-subviews {
|
||||
background: var(--panel-arrowcontent-background);
|
||||
border-bottom-right-radius: 3.5px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#identity-popup-multiView > .panel-viewcontainer > .panel-viewstack > .panel-subviews:-moz-locale-dir(rtl) {
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 3.5px;
|
||||
}
|
||||
|
||||
.identity-popup-section:not(:first-child) {
|
||||
border-top: 1px solid var(--panel-separator-color);
|
||||
}
|
||||
@ -100,14 +94,19 @@
|
||||
#identity-popup-security-content,
|
||||
#identity-popup-permissions-content,
|
||||
#tracking-protection-content {
|
||||
padding: 0.5em 0 1em;
|
||||
-moz-padding-start: calc(2em + 24px);
|
||||
-moz-padding-end: 1em;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 1em 1em;
|
||||
background-size: 24px auto;
|
||||
}
|
||||
|
||||
#identity-popup-security-content,
|
||||
#identity-popup-permissions-content,
|
||||
#tracking-protection-content {
|
||||
padding: 0.5em 0 1em;
|
||||
-moz-padding-start: calc(2em + 24px);
|
||||
-moz-padding-end: 1em;
|
||||
}
|
||||
|
||||
#identity-popup-securityView:-moz-locale-dir(rtl),
|
||||
#identity-popup-security-content:-moz-locale-dir(rtl),
|
||||
#identity-popup-permissions-content:-moz-locale-dir(rtl),
|
||||
@ -208,7 +207,6 @@
|
||||
}
|
||||
|
||||
#identity-popup-securityView {
|
||||
padding-bottom: 2em;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@ -252,7 +250,14 @@
|
||||
color: Graytext;
|
||||
}
|
||||
|
||||
#identity-popup-securityView-header,
|
||||
#identity-popup-securityView-body {
|
||||
-moz-margin-start: calc(2em + 24px);
|
||||
-moz-margin-end: 1em;
|
||||
}
|
||||
|
||||
#identity-popup-securityView-header {
|
||||
margin-top: 0.5em;
|
||||
border-bottom: 1px solid var(--panel-separator-color);
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
@ -261,6 +266,30 @@
|
||||
-moz-padding-end: 1em;
|
||||
}
|
||||
|
||||
#identity-popup-securityView-footer {
|
||||
margin-top: 1em;
|
||||
background-color: hsla(210,4%,10%,.07);
|
||||
}
|
||||
|
||||
#identity-popup-securityView-footer > button {
|
||||
-moz-appearance: none;
|
||||
margin: 0;
|
||||
border: none;
|
||||
border-top: 1px solid #ccc;
|
||||
padding: 8px 20px;
|
||||
color: ButtonText;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#identity-popup-securityView-footer > button:hover,
|
||||
#identity-popup-securityView-footer > button:focus {
|
||||
background-color: hsla(210,4%,10%,.07);
|
||||
}
|
||||
|
||||
#identity-popup-securityView-footer > button:hover:active {
|
||||
background-color: hsla(210,4%,10%,.12);
|
||||
}
|
||||
|
||||
#identity-popup-content-verifier ~ description {
|
||||
margin-top: 1em;
|
||||
color: Graytext;
|
||||
|
@ -36,7 +36,7 @@ PrincipalOriginAttributes::InheritFromDocShellToDoc(const DocShellOriginAttribut
|
||||
const nsIURI* aURI)
|
||||
{
|
||||
mAppId = aAttrs.mAppId;
|
||||
mInBrowser = aAttrs.mInBrowser;
|
||||
mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser;
|
||||
|
||||
// addonId is computed from the principal URI and never propagated
|
||||
mUserContextId = aAttrs.mUserContextId;
|
||||
@ -51,7 +51,7 @@ void
|
||||
PrincipalOriginAttributes::InheritFromNecko(const NeckoOriginAttributes& aAttrs)
|
||||
{
|
||||
mAppId = aAttrs.mAppId;
|
||||
mInBrowser = aAttrs.mInBrowser;
|
||||
mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser;
|
||||
|
||||
// addonId is computed from the principal URI and never propagated
|
||||
mUserContextId = aAttrs.mUserContextId;
|
||||
@ -62,7 +62,7 @@ void
|
||||
DocShellOriginAttributes::InheritFromDocToChildDocShell(const PrincipalOriginAttributes& aAttrs)
|
||||
{
|
||||
mAppId = aAttrs.mAppId;
|
||||
mInBrowser = aAttrs.mInBrowser;
|
||||
mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser;
|
||||
|
||||
// addonId is computed from the principal URI and never propagated
|
||||
mUserContextId = aAttrs.mUserContextId;
|
||||
@ -77,7 +77,7 @@ void
|
||||
NeckoOriginAttributes::InheritFromDocToNecko(const PrincipalOriginAttributes& aAttrs)
|
||||
{
|
||||
mAppId = aAttrs.mAppId;
|
||||
mInBrowser = aAttrs.mInBrowser;
|
||||
mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser;
|
||||
|
||||
// addonId is computed from the principal URI and never propagated
|
||||
mUserContextId = aAttrs.mUserContextId;
|
||||
@ -91,7 +91,7 @@ void
|
||||
NeckoOriginAttributes::InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs)
|
||||
{
|
||||
mAppId = aAttrs.mAppId;
|
||||
mInBrowser = aAttrs.mInBrowser;
|
||||
mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser;
|
||||
|
||||
// addonId is computed from the principal URI and never propagated
|
||||
mUserContextId = aAttrs.mUserContextId;
|
||||
@ -119,7 +119,7 @@ OriginAttributes::CreateSuffix(nsACString& aStr) const
|
||||
params->Set(NS_LITERAL_STRING("appId"), value);
|
||||
}
|
||||
|
||||
if (mInBrowser) {
|
||||
if (mInIsolatedMozBrowser) {
|
||||
params->Set(NS_LITERAL_STRING("inBrowser"), NS_LITERAL_STRING("1"));
|
||||
}
|
||||
|
||||
@ -191,7 +191,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
mOriginAttributes->mInBrowser = true;
|
||||
mOriginAttributes->mInIsolatedMozBrowser = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -469,7 +469,7 @@ BasePrincipal::GetIsSystemPrincipal(bool* aResult)
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::GetJarPrefix(nsACString& aJarPrefix)
|
||||
{
|
||||
mozilla::GetJarPrefix(mOriginAttributes.mAppId, mOriginAttributes.mInBrowser, aJarPrefix);
|
||||
mozilla::GetJarPrefix(mOriginAttributes.mAppId, mOriginAttributes.mInIsolatedMozBrowser, aJarPrefix);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -523,9 +523,9 @@ BasePrincipal::GetUserContextId(uint32_t* aUserContextId)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BasePrincipal::GetIsInBrowserElement(bool* aIsInBrowserElement)
|
||||
BasePrincipal::GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement)
|
||||
{
|
||||
*aIsInBrowserElement = IsInBrowserElement();
|
||||
*aIsInIsolatedMozBrowserElement = IsInIsolatedMozBrowserElement();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
bool operator==(const OriginAttributes& aOther) const
|
||||
{
|
||||
return mAppId == aOther.mAppId &&
|
||||
mInBrowser == aOther.mInBrowser &&
|
||||
mInIsolatedMozBrowser == aOther.mInIsolatedMozBrowser &&
|
||||
mAddonId == aOther.mAddonId &&
|
||||
mUserContextId == aOther.mUserContextId &&
|
||||
mSignedPkg == aOther.mSignedPkg;
|
||||
@ -75,10 +75,10 @@ class PrincipalOriginAttributes : public OriginAttributes
|
||||
{
|
||||
public:
|
||||
PrincipalOriginAttributes() {}
|
||||
PrincipalOriginAttributes(uint32_t aAppId, bool aInBrowser)
|
||||
PrincipalOriginAttributes(uint32_t aAppId, bool aInIsolatedMozBrowser)
|
||||
{
|
||||
mAppId = aAppId;
|
||||
mInBrowser = aInBrowser;
|
||||
mInIsolatedMozBrowser = aInIsolatedMozBrowser;
|
||||
}
|
||||
|
||||
// Inheriting OriginAttributes from docshell to document when user navigates.
|
||||
@ -97,10 +97,10 @@ class DocShellOriginAttributes : public OriginAttributes
|
||||
{
|
||||
public:
|
||||
DocShellOriginAttributes() {}
|
||||
DocShellOriginAttributes(uint32_t aAppId, bool aInBrowser)
|
||||
DocShellOriginAttributes(uint32_t aAppId, bool aInIsolatedMozBrowser)
|
||||
{
|
||||
mAppId = aAppId;
|
||||
mInBrowser = aInBrowser;
|
||||
mInIsolatedMozBrowser = aInIsolatedMozBrowser;
|
||||
}
|
||||
|
||||
// Inheriting OriginAttributes from document to child docshell when an
|
||||
@ -116,10 +116,10 @@ class NeckoOriginAttributes : public OriginAttributes
|
||||
{
|
||||
public:
|
||||
NeckoOriginAttributes() {}
|
||||
NeckoOriginAttributes(uint32_t aAppId, bool aInBrowser)
|
||||
NeckoOriginAttributes(uint32_t aAppId, bool aInIsolatedMozBrowser)
|
||||
{
|
||||
mAppId = aAppId;
|
||||
mInBrowser = aInBrowser;
|
||||
mInIsolatedMozBrowser = aInIsolatedMozBrowser;
|
||||
}
|
||||
|
||||
// Inheriting OriginAttributes from document to necko when a network request
|
||||
@ -159,7 +159,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mInBrowser.WasPassed() && mInBrowser.Value() != aAttrs.mInBrowser) {
|
||||
if (mInIsolatedMozBrowser.WasPassed() && mInIsolatedMozBrowser.Value() != aAttrs.mInIsolatedMozBrowser) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -215,7 +215,7 @@ public:
|
||||
NS_IMETHOD GetOriginSuffix(nsACString& aOriginSuffix) final;
|
||||
NS_IMETHOD GetAppStatus(uint16_t* aAppStatus) final;
|
||||
NS_IMETHOD GetAppId(uint32_t* aAppStatus) final;
|
||||
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement) final;
|
||||
NS_IMETHOD GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement) final;
|
||||
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) final;
|
||||
NS_IMETHOD GetUserContextId(uint32_t* aUserContextId) final;
|
||||
|
||||
@ -231,7 +231,7 @@ public:
|
||||
const PrincipalOriginAttributes& OriginAttributesRef() { return mOriginAttributes; }
|
||||
uint32_t AppId() const { return mOriginAttributes.mAppId; }
|
||||
uint32_t UserContextId() const { return mOriginAttributes.mUserContextId; }
|
||||
bool IsInBrowserElement() const { return mOriginAttributes.mInBrowser; }
|
||||
bool IsInIsolatedMozBrowserElement() const { return mOriginAttributes.mInIsolatedMozBrowser; }
|
||||
|
||||
enum PrincipalKind {
|
||||
eNullPrincipal,
|
||||
|
@ -303,10 +303,13 @@ interface nsIPrincipal : nsISerializable
|
||||
[infallible] readonly attribute unsigned long userContextId;
|
||||
|
||||
/**
|
||||
* Returns true iff the principal is inside a browser element. (<iframe
|
||||
* mozbrowser mozapp> does not count as a browser element.)
|
||||
* Returns true iff the principal is inside an isolated mozbrowser element.
|
||||
* <iframe mozbrowser mozapp> and <xul:browser> are not considered to be
|
||||
* mozbrowser elements. <iframe mozbrowser noisolation> does not count as
|
||||
* isolated since isolation is disabled. Isolation can only be disabled if
|
||||
* the containing document is chrome.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isInBrowserElement;
|
||||
[infallible] readonly attribute boolean isInIsolatedMozBrowserElement;
|
||||
|
||||
/**
|
||||
* Returns true if this principal has an unknown appId. This shouldn't
|
||||
|
@ -260,13 +260,25 @@ uint16_t
|
||||
nsScriptSecurityManager::AppStatusForPrincipal(nsIPrincipal *aPrin)
|
||||
{
|
||||
uint32_t appId = aPrin->GetAppId();
|
||||
bool inMozBrowser = aPrin->GetIsInBrowserElement();
|
||||
|
||||
// After bug 1238160, the principal no longer knows how to answer "is this a
|
||||
// browser element", which is really what this code path wants. Currently,
|
||||
// desktop is the only platform where we intend to disable isolation on a
|
||||
// browser frame, so non-desktop should be able to assume that
|
||||
// inIsolatedMozBrowser is true for all mozbrowser frames. Additionally,
|
||||
// apps are no longer used on desktop, so appId is always NO_APP_ID. We use
|
||||
// a release assertion in nsFrameLoader::OwnerIsIsolatedMozBrowserFrame so
|
||||
// that platforms with apps can assume inIsolatedMozBrowser is true for all
|
||||
// mozbrowser frames.
|
||||
bool inIsolatedMozBrowser = aPrin->GetIsInIsolatedMozBrowserElement();
|
||||
|
||||
NS_WARN_IF_FALSE(appId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
|
||||
"Asking for app status on a principal with an unknown app id");
|
||||
// Installed apps have a valid app id (not NO_APP_ID or UNKNOWN_APP_ID)
|
||||
// and they are not inside a mozbrowser.
|
||||
if (appId == nsIScriptSecurityManager::NO_APP_ID ||
|
||||
appId == nsIScriptSecurityManager::UNKNOWN_APP_ID || inMozBrowser)
|
||||
appId == nsIScriptSecurityManager::UNKNOWN_APP_ID ||
|
||||
inIsolatedMozBrowser)
|
||||
{
|
||||
return nsIPrincipal::APP_STATUS_NOT_INSTALLED;
|
||||
}
|
||||
@ -291,7 +303,7 @@ nsScriptSecurityManager::AppStatusForPrincipal(nsIPrincipal *aPrin)
|
||||
|
||||
// The app could contain a cross-origin iframe - make sure that the content
|
||||
// is actually same-origin with the app.
|
||||
MOZ_ASSERT(inMozBrowser == false, "Checked this above");
|
||||
MOZ_ASSERT(inIsolatedMozBrowser == false, "Checked this above");
|
||||
PrincipalOriginAttributes attrs(appId, false);
|
||||
nsCOMPtr<nsIPrincipal> appPrin = BasePrincipal::CreateCodebasePrincipal(appURI, attrs);
|
||||
NS_ENSURE_TRUE(appPrin, nsIPrincipal::APP_STATUS_NOT_INSTALLED);
|
||||
@ -1170,13 +1182,13 @@ nsScriptSecurityManager::CreateExpandedPrincipal(nsIPrincipal** aPrincipalArray,
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::GetAppCodebasePrincipal(nsIURI* aURI,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowser,
|
||||
bool aInIsolatedMozBrowser,
|
||||
nsIPrincipal** aPrincipal)
|
||||
{
|
||||
NS_ENSURE_TRUE(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
|
||||
NS_ERROR_INVALID_ARG);
|
||||
|
||||
PrincipalOriginAttributes attrs(aAppId, aInMozBrowser);
|
||||
PrincipalOriginAttributes attrs(aAppId, aInIsolatedMozBrowser);
|
||||
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
|
||||
prin.forget(aPrincipal);
|
||||
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
|
||||
@ -1566,7 +1578,7 @@ nsScriptSecurityManager::InitPrefs()
|
||||
namespace mozilla {
|
||||
|
||||
void
|
||||
GetJarPrefix(uint32_t aAppId, bool aInMozBrowser, nsACString& aJarPrefix)
|
||||
GetJarPrefix(uint32_t aAppId, bool aInIsolatedMozBrowser, nsACString& aJarPrefix)
|
||||
{
|
||||
MOZ_ASSERT(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
||||
|
||||
@ -1577,14 +1589,14 @@ GetJarPrefix(uint32_t aAppId, bool aInMozBrowser, nsACString& aJarPrefix)
|
||||
aJarPrefix.Truncate();
|
||||
|
||||
// Fallback.
|
||||
if (aAppId == nsIScriptSecurityManager::NO_APP_ID && !aInMozBrowser) {
|
||||
if (aAppId == nsIScriptSecurityManager::NO_APP_ID && !aInIsolatedMozBrowser) {
|
||||
return;
|
||||
}
|
||||
|
||||
// aJarPrefix = appId + "+" + { 't', 'f' } + "+";
|
||||
aJarPrefix.AppendInt(aAppId);
|
||||
aJarPrefix.Append('+');
|
||||
aJarPrefix.Append(aInMozBrowser ? 't' : 'f');
|
||||
aJarPrefix.Append(aInIsolatedMozBrowser ? 't' : 'f');
|
||||
aJarPrefix.Append('+');
|
||||
|
||||
return;
|
||||
@ -1594,12 +1606,12 @@ GetJarPrefix(uint32_t aAppId, bool aInMozBrowser, nsACString& aJarPrefix)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::GetJarPrefix(uint32_t aAppId,
|
||||
bool aInMozBrowser,
|
||||
bool aInIsolatedMozBrowser,
|
||||
nsACString& aJarPrefix)
|
||||
{
|
||||
MOZ_ASSERT(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
||||
|
||||
mozilla::GetJarPrefix(aAppId, aInMozBrowser, aJarPrefix);
|
||||
mozilla::GetJarPrefix(aAppId, aInIsolatedMozBrowser, aJarPrefix);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1694,4 +1706,3 @@ nsScriptSecurityManager::PolicyAllowsScript(nsIURI* aURI, bool *aRv)
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ namespace mozilla {
|
||||
|
||||
void
|
||||
GetJarPrefix(uint32_t aAppid,
|
||||
bool aInMozBrowser,
|
||||
bool aInIsolatedMozBrowser,
|
||||
nsACString& aJarPrefix);
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -24,13 +24,13 @@ TEST(PrincipalOriginAttributes, Suffix_default)
|
||||
TestSuffix(attrs);
|
||||
}
|
||||
|
||||
TEST(PrincipalOriginAttributes, Suffix_appId_inBrowser)
|
||||
TEST(PrincipalOriginAttributes, Suffix_appId_inIsolatedMozBrowser)
|
||||
{
|
||||
PrincipalOriginAttributes attrs(1, true);
|
||||
TestSuffix(attrs);
|
||||
}
|
||||
|
||||
TEST(PrincipalOriginAttributes, Suffix_maxAppId_inBrowser)
|
||||
TEST(PrincipalOriginAttributes, Suffix_maxAppId_inIsolatedMozBrowser)
|
||||
{
|
||||
PrincipalOriginAttributes attrs(4294967295, true);
|
||||
TestSuffix(attrs);
|
||||
|
@ -33,6 +33,8 @@ SimpleTest.waitForExplicitFinish();
|
||||
* valid, the iframe will not be considered as a mozapp.
|
||||
* - browser: say if the iframe should be a mozbrowser. This is implicit when
|
||||
* app is set.
|
||||
* - isolated: if origin isolation is enabled with browser frames. Defaults to
|
||||
* true if unset.
|
||||
* - test: an array of tests to run for this test case:
|
||||
* - eo-unique: the extendedOrigin of the prinicpal must be unique in the
|
||||
* current list.
|
||||
@ -230,7 +232,7 @@ var gData = [
|
||||
},
|
||||
test: [ "child-has-different-eo", "child-has-same-appstatus", "child-has-same-appid" ],
|
||||
},
|
||||
// browser containing an iframe is part of the browser
|
||||
// browser containing an iframe that is part of the browser
|
||||
{
|
||||
src: "http://example.org/",
|
||||
isapp: false,
|
||||
@ -238,7 +240,50 @@ var gData = [
|
||||
child: {
|
||||
src: "http://example.org/chrome/",
|
||||
isapp: false,
|
||||
inBrowser: true,
|
||||
inIsolatedMozBrowser: true,
|
||||
},
|
||||
test: [ "child-has-same-eo" ],
|
||||
},
|
||||
// iframe containing a browser with isolation disabled
|
||||
// (only chrome documents can disable isolation)
|
||||
{
|
||||
src: "http://example.org/",
|
||||
isapp: false,
|
||||
browser: false,
|
||||
child: {
|
||||
src: "http://example.org/chrome/",
|
||||
isapp: false,
|
||||
browser: true,
|
||||
isolated: false,
|
||||
inIsolatedMozBrowser: true,
|
||||
},
|
||||
test: [ "child-has-different-eo" ],
|
||||
},
|
||||
// browser with isolation disabled containing an iframe that is part of the browser
|
||||
{
|
||||
src: "http://example.org/",
|
||||
isapp: false,
|
||||
browser: true,
|
||||
isolated: false,
|
||||
child: {
|
||||
src: "http://example.org/chrome/",
|
||||
isapp: false,
|
||||
inIsolatedMozBrowser: false,
|
||||
},
|
||||
test: [ "child-has-same-eo" ],
|
||||
},
|
||||
// iframe with isolation enabled containing an iframe with isolation disabled
|
||||
// (isolated only has an effect on browsers)
|
||||
{
|
||||
src: "http://example.org/",
|
||||
isapp: false,
|
||||
browser: false,
|
||||
isolated: true,
|
||||
child: {
|
||||
src: "http://example.org/chrome/",
|
||||
isapp: false,
|
||||
browser: false,
|
||||
isolated: false,
|
||||
},
|
||||
test: [ "child-has-same-eo" ],
|
||||
},
|
||||
@ -280,12 +325,15 @@ function checkIFrame(aFrame, data) {
|
||||
"principals from non-installed app should have NO_APP_ID");
|
||||
}
|
||||
|
||||
if (!data.isapp && !data.browser) {
|
||||
if (!data.isapp && !data.browser ||
|
||||
(data.browser && data.isolated === false)) {
|
||||
is(principal.jarPrefix, "",
|
||||
'jarPrefix should return an empty string for non-app and non-browsers principals');
|
||||
"jarPrefix should return an empty string for non-app, non-browsers, " +
|
||||
"and browsers with isolation disabled");
|
||||
} else {
|
||||
isnot(principal.jarPrefix, "",
|
||||
'jarPrefix should not return an empty string for apps or mozbrowsers');
|
||||
"jarPrefix should not return an empty string for apps or browsers " +
|
||||
"with isolation enabled");
|
||||
}
|
||||
|
||||
if (data.test.indexOf("eo-unique") != -1) {
|
||||
@ -297,8 +345,12 @@ function checkIFrame(aFrame, data) {
|
||||
"extended origin should be the same as the last inserted one");
|
||||
}
|
||||
|
||||
is(principal.isInBrowserElement, !!data.browser,
|
||||
"check principal.isInBrowserElement");
|
||||
let isolationExpected = false;
|
||||
if (data.isolated !== false) {
|
||||
isolationExpected = !!data.browser;
|
||||
}
|
||||
is(principal.isInIsolatedMozBrowserElement, isolationExpected,
|
||||
"check principal.isInIsolatedMozBrowserElement");
|
||||
|
||||
if (data.child) {
|
||||
let childPrincipal = aFrame.contentWindow.frames[0].document.nodePrincipal;
|
||||
@ -308,8 +360,15 @@ function checkIFrame(aFrame, data) {
|
||||
"child should be an installed app");
|
||||
}
|
||||
|
||||
is(childPrincipal.isInBrowserElement, !!data.child.browser || !!data.child.inBrowser,
|
||||
"check childPrincipal.isInBrowserElement");
|
||||
let childIsolationExpected = false;
|
||||
if (data.child.isolated !== false) {
|
||||
childIsolationExpected = !!data.child.browser;
|
||||
}
|
||||
if (data.child.inIsolatedMozBrowser !== undefined) {
|
||||
childIsolationExpected = data.child.inIsolatedMozBrowser;
|
||||
}
|
||||
is(childPrincipal.isInIsolatedMozBrowserElement, childIsolationExpected,
|
||||
"check childPrincipal.isInIsolatedMozBrowserElement");
|
||||
|
||||
if (data.test.indexOf("child-has-same-eo") != -1) {
|
||||
is(childPrincipal.jarPrefix + childPrincipal.origin,
|
||||
@ -392,6 +451,10 @@ function runTest() {
|
||||
childFrame.setAttribute('mozbrowser', '');
|
||||
}
|
||||
|
||||
if (data.child.isolated === false) {
|
||||
childFrame.setAttribute("noisolation", "");
|
||||
}
|
||||
|
||||
childFrame.src = data.child.src;
|
||||
|
||||
this.removeEventListener('load', this.addChild.bind(this));
|
||||
@ -407,6 +470,10 @@ function runTest() {
|
||||
iframe.setAttribute('mozbrowser', '');
|
||||
}
|
||||
|
||||
if (data.isolated === false) {
|
||||
iframe.setAttribute("noisolation", "");
|
||||
}
|
||||
|
||||
iframe.src = data.src;
|
||||
|
||||
if (data.child) {
|
||||
@ -423,8 +490,9 @@ function runTest() {
|
||||
|
||||
var gTestRunner = runTest();
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set':[["dom.mozBrowserFramesEnabled", true]]},
|
||||
function() { gTestRunner.next(); });
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.mozBrowserFramesEnabled", true],
|
||||
]}, function() { gTestRunner.next(); });
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
@ -24,7 +24,7 @@ function checkCrossOrigin(a, b) {
|
||||
function checkOriginAttributes(prin, attrs, suffix) {
|
||||
attrs = attrs || {};
|
||||
do_check_eq(prin.originAttributes.appId, attrs.appId || 0);
|
||||
do_check_eq(prin.originAttributes.inBrowser, attrs.inBrowser || false);
|
||||
do_check_eq(prin.originAttributes.inIsolatedMozBrowser, attrs.inIsolatedMozBrowser || false);
|
||||
do_check_eq(prin.originSuffix, suffix || '');
|
||||
do_check_eq(ChromeUtils.originAttributesToSuffix(attrs), suffix || '');
|
||||
do_check_true(ChromeUtils.originAttributesMatchPattern(prin.originAttributes, attrs));
|
||||
@ -40,7 +40,7 @@ function printAttrs(name, attrs) {
|
||||
do_print(name + " {\n" +
|
||||
"\tappId: " + attrs.appId + ",\n" +
|
||||
"\tuserContextId: " + attrs.userContextId + ",\n" +
|
||||
"\tinBrowser: " + attrs.inBrowser + ",\n" +
|
||||
"\tinIsolatedMozBrowser: " + attrs.inIsolatedMozBrowser + ",\n" +
|
||||
"\taddonId: '" + attrs.addonId + "',\n" +
|
||||
"\tsignedPkg: '" + attrs.signedPkg + "'\n}");
|
||||
}
|
||||
@ -52,7 +52,7 @@ function checkValues(attrs, values) {
|
||||
//printAttrs("values", values);
|
||||
do_check_eq(attrs.appId, values.appId || 0);
|
||||
do_check_eq(attrs.userContextId, values.userContextId || 0);
|
||||
do_check_eq(attrs.inBrowser, values.inBrowser || false);
|
||||
do_check_eq(attrs.inIsolatedMozBrowser, values.inIsolatedMozBrowser || false);
|
||||
do_check_eq(attrs.addonId, values.addonId || '');
|
||||
do_check_eq(attrs.signedPkg, values.signedPkg || '');
|
||||
}
|
||||
@ -99,22 +99,22 @@ function run_test() {
|
||||
do_check_eq(exampleOrg_app.origin, 'http://example.org^appId=42');
|
||||
|
||||
// Just browser.
|
||||
var exampleOrg_browser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inBrowser: true});
|
||||
var nullPrin_browser = ssm.createNullPrincipal({inBrowser: true});
|
||||
checkOriginAttributes(exampleOrg_browser, {inBrowser: true}, '^inBrowser=1');
|
||||
checkOriginAttributes(nullPrin_browser, {inBrowser: true}, '^inBrowser=1');
|
||||
var exampleOrg_browser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inIsolatedMozBrowser: true});
|
||||
var nullPrin_browser = ssm.createNullPrincipal({inIsolatedMozBrowser: true});
|
||||
checkOriginAttributes(exampleOrg_browser, {inIsolatedMozBrowser: true}, '^inBrowser=1');
|
||||
checkOriginAttributes(nullPrin_browser, {inIsolatedMozBrowser: true}, '^inBrowser=1');
|
||||
do_check_eq(exampleOrg_browser.origin, 'http://example.org^inBrowser=1');
|
||||
|
||||
// App and browser.
|
||||
var exampleOrg_appBrowser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inBrowser: true, appId: 42});
|
||||
var nullPrin_appBrowser = ssm.createNullPrincipal({inBrowser: true, appId: 42});
|
||||
checkOriginAttributes(exampleOrg_appBrowser, {appId: 42, inBrowser: true}, '^appId=42&inBrowser=1');
|
||||
checkOriginAttributes(nullPrin_appBrowser, {appId: 42, inBrowser: true}, '^appId=42&inBrowser=1');
|
||||
var exampleOrg_appBrowser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inIsolatedMozBrowser: true, appId: 42});
|
||||
var nullPrin_appBrowser = ssm.createNullPrincipal({inIsolatedMozBrowser: true, appId: 42});
|
||||
checkOriginAttributes(exampleOrg_appBrowser, {appId: 42, inIsolatedMozBrowser: true}, '^appId=42&inBrowser=1');
|
||||
checkOriginAttributes(nullPrin_appBrowser, {appId: 42, inIsolatedMozBrowser: true}, '^appId=42&inBrowser=1');
|
||||
do_check_eq(exampleOrg_appBrowser.origin, 'http://example.org^appId=42&inBrowser=1');
|
||||
|
||||
// App and browser, different domain.
|
||||
var exampleCom_appBrowser = ssm.createCodebasePrincipal(makeURI('https://www.example.com:123'), {appId: 42, inBrowser: true});
|
||||
checkOriginAttributes(exampleCom_appBrowser, {appId: 42, inBrowser: true}, '^appId=42&inBrowser=1');
|
||||
var exampleCom_appBrowser = ssm.createCodebasePrincipal(makeURI('https://www.example.com:123'), {appId: 42, inIsolatedMozBrowser: true});
|
||||
checkOriginAttributes(exampleCom_appBrowser, {appId: 42, inIsolatedMozBrowser: true}, '^appId=42&inBrowser=1');
|
||||
do_check_eq(exampleCom_appBrowser.origin, 'https://www.example.com:123^appId=42&inBrowser=1');
|
||||
|
||||
// Addon.
|
||||
@ -161,8 +161,8 @@ function run_test() {
|
||||
do_check_eq(exampleOrg_signedPkg.origin, 'http://example.org^signedPkg=whatever');
|
||||
|
||||
// signedPkg and browser
|
||||
var exampleOrg_signedPkg_browser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {signedPkg: 'whatever', inBrowser: true});
|
||||
checkOriginAttributes(exampleOrg_signedPkg_browser, { signedPkg: 'whatever', inBrowser: true }, '^inBrowser=1&signedPkg=whatever');
|
||||
var exampleOrg_signedPkg_browser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {signedPkg: 'whatever', inIsolatedMozBrowser: true});
|
||||
checkOriginAttributes(exampleOrg_signedPkg_browser, { signedPkg: 'whatever', inIsolatedMozBrowser: true }, '^inBrowser=1&signedPkg=whatever');
|
||||
do_check_eq(exampleOrg_signedPkg_browser.origin, 'http://example.org^inBrowser=1&signedPkg=whatever');
|
||||
|
||||
// Just signedPkg (but different value from 'exampleOrg_signedPkg_app')
|
||||
@ -212,10 +212,10 @@ function run_test() {
|
||||
[ "^appId=5", {appId: 5} ],
|
||||
[ "^userContextId=3", {userContextId: 3} ],
|
||||
[ "^addonId=fooBar", {addonId: "fooBar"} ],
|
||||
[ "^inBrowser=1", {inBrowser: true} ],
|
||||
[ "^inBrowser=1", {inIsolatedMozBrowser: true} ],
|
||||
[ "^signedPkg=bazQux", {signedPkg: "bazQux"} ],
|
||||
[ "^appId=3&inBrowser=1&userContextId=6",
|
||||
{appId: 3, userContextId: 6, inBrowser: true} ] ];
|
||||
{appId: 3, userContextId: 6, inIsolatedMozBrowser: true} ] ];
|
||||
|
||||
// check that we can create an origin attributes from an origin properly
|
||||
tests.forEach(function(t) {
|
||||
|
13
devtools/bootstrap.js
vendored
13
devtools/bootstrap.js
vendored
@ -8,6 +8,13 @@ const Cu = Components.utils;
|
||||
const Ci = Components.interfaces;
|
||||
const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
function actionOccurred(id) {
|
||||
let {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
let Telemetry = require("devtools/client/shared/telemetry");;
|
||||
let telemetry = new Telemetry();
|
||||
telemetry.actionOccurred(id);
|
||||
}
|
||||
|
||||
// Helper to listen to a key on all windows
|
||||
function MultiWindowKeyListener({ keyCode, ctrlKey, altKey, callback }) {
|
||||
let keyListener = function (event) {
|
||||
@ -150,6 +157,8 @@ function reload(event) {
|
||||
gDevTools.showToolbox(target);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
actionOccurred("reloadAddonReload");
|
||||
}
|
||||
|
||||
let listener;
|
||||
@ -165,5 +174,7 @@ function shutdown() {
|
||||
listener.stop();
|
||||
listener = null;
|
||||
}
|
||||
function install() {}
|
||||
function install() {
|
||||
actionOccurred("reloadAddonInstalled");
|
||||
}
|
||||
function uninstall() {}
|
||||
|
@ -82,7 +82,10 @@ const EVENTS = {
|
||||
OPTIONS_POPUP_HIDDEN: "Debugger:OptionsPopupHidden",
|
||||
|
||||
// When the widgets layout has been changed.
|
||||
LAYOUT_CHANGED: "Debugger:LayoutChanged"
|
||||
LAYOUT_CHANGED: "Debugger:LayoutChanged",
|
||||
|
||||
// When a worker has been selected.
|
||||
WORKER_SELECTED: "Debugger::WorkerSelected"
|
||||
};
|
||||
|
||||
// Descriptions for what a stack frame represents after the debugger pauses.
|
||||
@ -108,7 +111,7 @@ Cu.import("resource://devtools/client/shared/widgets/ViewHelpers.jsm");
|
||||
var L10N = new ViewHelpers.L10N(DBG_STRINGS_URI);
|
||||
|
||||
Cu.import("resource://devtools/client/shared/browser-loader.js");
|
||||
const require = BrowserLoader("resource://devtools/client/debugger/", this).require;
|
||||
const require = BrowserLoader("resource://devtools/client/debugger/", window).require;
|
||||
XPCOMUtils.defineConstant(this, "require", require);
|
||||
const { gDevTools } = require("devtools/client/framework/devtools");
|
||||
|
||||
@ -491,8 +494,8 @@ Workers.prototype = {
|
||||
|
||||
for (let workerActor in this._workerForms) {
|
||||
if (!(workerActor in workerForms)) {
|
||||
DebuggerView.Workers.removeWorker(this._workerForms[workerActor]);
|
||||
delete this._workerForms[workerActor];
|
||||
DebuggerView.Workers.removeWorker(workerActor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -500,7 +503,7 @@ Workers.prototype = {
|
||||
if (!(workerActor in this._workerForms)) {
|
||||
let workerForm = workerForms[workerActor];
|
||||
this._workerForms[workerActor] = workerForm;
|
||||
DebuggerView.Workers.addWorker(workerActor, workerForm.url);
|
||||
DebuggerView.Workers.addWorker(workerForm);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -510,10 +513,11 @@ Workers.prototype = {
|
||||
this._updateWorkerList();
|
||||
},
|
||||
|
||||
_onWorkerSelect: function (workerActor) {
|
||||
DebuggerController.client.attachWorker(workerActor, (response, workerClient) => {
|
||||
gDevTools.showToolbox(TargetFactory.forWorker(workerClient),
|
||||
_onWorkerSelect: function (workerForm) {
|
||||
DebuggerController.client.attachWorker(workerForm.actor, (response, workerClient) => {
|
||||
let toolbox = gDevTools.showToolbox(TargetFactory.forWorker(workerClient),
|
||||
"jsdebugger", Toolbox.HostType.WINDOW);
|
||||
window.emit(EVENTS.WORKER_SELECTED, toolbox);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -45,6 +45,9 @@ support-files =
|
||||
code_ugly-7.js
|
||||
code_ugly-8
|
||||
code_ugly-8^headers^
|
||||
code_worker-source-map.coffee
|
||||
code_worker-source-map.js
|
||||
code_worker-source-map.js.map
|
||||
code_WorkerActor.attach-worker1.js
|
||||
code_WorkerActor.attach-worker2.js
|
||||
code_WorkerActor.attachThread-worker.js
|
||||
@ -112,6 +115,7 @@ support-files =
|
||||
doc_watch-expressions.html
|
||||
doc_watch-expression-button.html
|
||||
doc_with-frame.html
|
||||
doc_worker-source-map.html
|
||||
doc_WorkerActor.attach-tab1.html
|
||||
doc_WorkerActor.attach-tab2.html
|
||||
doc_WorkerActor.attachThread-tab.html
|
||||
@ -592,6 +596,8 @@ skip-if = e10s && debug
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_worker-console.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_worker-source-map.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_worker-window.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_WorkerActor.attach.js]
|
||||
|
@ -0,0 +1,85 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_worker-source-map.html";
|
||||
const WORKER_URL = "code_worker-source-map.js";
|
||||
const COFFEE_URL = EXAMPLE_URL + "code_worker-source-map.coffee";
|
||||
|
||||
function selectWorker(aPanel, aURL) {
|
||||
let panelWin = aPanel.panelWin;
|
||||
let promise = waitForDebuggerEvents(aPanel, panelWin.EVENTS.WORKER_SELECTED);
|
||||
let Workers = panelWin.DebuggerView.Workers;
|
||||
let item = Workers.getItemForAttachment((workerForm) => {
|
||||
return workerForm.url === aURL;
|
||||
});
|
||||
Workers.selectedItem = item;
|
||||
return promise;
|
||||
}
|
||||
|
||||
function test() {
|
||||
return Task.spawn(function* () {
|
||||
yield pushPrefs(["devtools.debugger.workers", true]);
|
||||
|
||||
let [tab,, panel] = yield initDebugger(TAB_URL);
|
||||
let toolbox = yield selectWorker(panel, WORKER_URL);
|
||||
let workerPanel = toolbox.getCurrentPanel();
|
||||
yield waitForSourceShown(workerPanel, ".coffee");
|
||||
let panelWin = workerPanel.panelWin;
|
||||
let Sources = panelWin.DebuggerView.Sources;
|
||||
let editor = panelWin.DebuggerView.editor;
|
||||
let threadClient = panelWin.gThreadClient;
|
||||
|
||||
isnot(Sources.selectedItem.attachment.source.url.indexOf(".coffee"), -1,
|
||||
"The debugger should show the source mapped coffee source file.");
|
||||
is(Sources.selectedValue.indexOf(".js"), -1,
|
||||
"The debugger should not show the generated js source file.");
|
||||
is(editor.getText().indexOf("isnt"), 211,
|
||||
"The debugger's editor should have the coffee source source displayed.");
|
||||
is(editor.getText().indexOf("function"), -1,
|
||||
"The debugger's editor should not have the JS source displayed.");
|
||||
|
||||
yield threadClient.interrupt();
|
||||
let sourceForm = getSourceForm(Sources, COFFEE_URL);
|
||||
let source = threadClient.source(sourceForm);
|
||||
let response = yield source.setBreakpoint({ line: 5 });
|
||||
|
||||
ok(!response.error,
|
||||
"Should be able to set a breakpoint in a coffee source file.");
|
||||
ok(!response.actualLocation,
|
||||
"Should be able to set a breakpoint on line 5.");
|
||||
|
||||
let promise = new Promise((resolve) => {
|
||||
threadClient.addOneTimeListener("paused", (event, packet) => {
|
||||
is(packet.type, "paused",
|
||||
"We should now be paused again.");
|
||||
is(packet.why.type, "breakpoint",
|
||||
"and the reason we should be paused is because we hit a breakpoint.");
|
||||
|
||||
// Check that we stopped at the right place, by making sure that the
|
||||
// environment is in the state that we expect.
|
||||
is(packet.frame.environment.bindings.variables.start.value, 0,
|
||||
"'start' is 0.");
|
||||
is(packet.frame.environment.bindings.variables.stop.value.type, "undefined",
|
||||
"'stop' hasn't been assigned to yet.");
|
||||
is(packet.frame.environment.bindings.variables.pivot.value.type, "undefined",
|
||||
"'pivot' hasn't been assigned to yet.");
|
||||
|
||||
waitForCaretUpdated(workerPanel, 5).then(resolve);
|
||||
});
|
||||
});
|
||||
|
||||
// This will cause the breakpoint to be hit, and put us back in the
|
||||
// paused state.
|
||||
yield threadClient.resume();
|
||||
callInTab(tab, "binary_search", [0, 2, 3, 5, 7, 10], 5);
|
||||
yield promise;
|
||||
|
||||
yield threadClient.resume();
|
||||
yield toolbox.destroy();
|
||||
yield closeDebuggerAndFinish(panel);
|
||||
|
||||
yield popPrefs();
|
||||
});
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
# Uses a binary search algorithm to locate a value in the specified array.
|
||||
binary_search = (items, value) ->
|
||||
|
||||
start = 0
|
||||
stop = items.length - 1
|
||||
pivot = Math.floor (start + stop) / 2
|
||||
|
||||
while items[pivot] isnt value and start < stop
|
||||
|
||||
# Adjust the search area.
|
||||
stop = pivot - 1 if value < items[pivot]
|
||||
start = pivot + 1 if value > items[pivot]
|
||||
|
||||
# Recalculate the pivot.
|
||||
pivot = Math.floor (stop + start) / 2
|
||||
|
||||
# Make sure we've found the correct value.
|
||||
if items[pivot] is value then pivot else -1
|
||||
|
||||
self.onmessage = (event) ->
|
||||
data = event.data
|
||||
binary_search(data.items, data.value)
|
@ -0,0 +1,35 @@
|
||||
// Generated by CoffeeScript 1.10.0
|
||||
(function() {
|
||||
var binary_search;
|
||||
|
||||
binary_search = function(items, value) {
|
||||
var pivot, start, stop;
|
||||
start = 0;
|
||||
stop = items.length - 1;
|
||||
pivot = Math.floor((start + stop) / 2);
|
||||
while (items[pivot] !== value && start < stop) {
|
||||
if (value < items[pivot]) {
|
||||
stop = pivot - 1;
|
||||
}
|
||||
if (value > items[pivot]) {
|
||||
start = pivot + 1;
|
||||
}
|
||||
pivot = Math.floor((stop + start) / 2);
|
||||
}
|
||||
if (items[pivot] === value) {
|
||||
return pivot;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
self.onmessage = function(event) {
|
||||
console.log("EUTA");
|
||||
var data;
|
||||
data = event.data;
|
||||
return binary_search(data.items, data.value);
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
||||
//# sourceMappingURL=code_worker-source-map.js.map
|
@ -0,0 +1,10 @@
|
||||
{
|
||||
"version": 3,
|
||||
"file": "code_worker-source-map.js",
|
||||
"sourceRoot": "",
|
||||
"sources": [
|
||||
"code_worker-source-map.coffee"
|
||||
],
|
||||
"names": [],
|
||||
"mappings": ";AACA;AAAA,MAAA;;EAAA,aAAA,GAAgB,SAAC,KAAD,EAAQ,KAAR;AAEd,QAAA;IAAA,KAAA,GAAQ;IACR,IAAA,GAAQ,KAAK,CAAC,MAAN,GAAe;IACvB,KAAA,GAAQ,IAAI,CAAC,KAAL,CAAW,CAAC,KAAA,GAAQ,IAAT,CAAA,GAAiB,CAA5B;AAER,WAAM,KAAM,CAAA,KAAA,CAAN,KAAkB,KAAlB,IAA4B,KAAA,GAAQ,IAA1C;MAGE,IAAqB,KAAA,GAAQ,KAAM,CAAA,KAAA,CAAnC;QAAA,IAAA,GAAQ,KAAA,GAAQ,EAAhB;;MACA,IAAqB,KAAA,GAAQ,KAAM,CAAA,KAAA,CAAnC;QAAA,KAAA,GAAQ,KAAA,GAAQ,EAAhB;;MAGA,KAAA,GAAQ,IAAI,CAAC,KAAL,CAAW,CAAC,IAAA,GAAO,KAAR,CAAA,GAAiB,CAA5B;IAPV;IAUA,IAAG,KAAM,CAAA,KAAA,CAAN,KAAgB,KAAnB;aAA8B,MAA9B;KAAA,MAAA;aAAyC,CAAC,EAA1C;;EAhBc;;EAkBhB,IAAI,CAAC,SAAL,GAAiB,SAAC,KAAD;AACf,QAAA;IAAA,IAAA,GAAO,KAAK,CAAC;WACb,aAAA,CAAc,IAAI,CAAC,KAAnB,EAA0B,IAAI,CAAC,KAA/B;EAFe;AAlBjB"
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<script>
|
||||
var worker = new Worker("code_worker-source-map.js");
|
||||
|
||||
function binary_search(items, value) {
|
||||
worker.postMessage({
|
||||
items: items,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
@ -28,22 +28,24 @@ WorkersView.prototype = Heritage.extend(WidgetMethods, {
|
||||
this.widget.addEventListener("select", this._onWorkerSelect, false);
|
||||
},
|
||||
|
||||
addWorker: function (actor, name) {
|
||||
addWorker: function (workerForm) {
|
||||
let element = document.createElement("label");
|
||||
element.className = "plain dbg-worker-item";
|
||||
element.setAttribute("value", name);
|
||||
element.setAttribute("value", workerForm.url);
|
||||
element.setAttribute("flex", "1");
|
||||
|
||||
this.push([element, actor], {});
|
||||
this.push([element, workerForm.actor], {
|
||||
attachment: workerForm
|
||||
});
|
||||
},
|
||||
|
||||
removeWorker: function (actor) {
|
||||
this.remove(this.getItemByValue(actor));
|
||||
removeWorker: function (workerForm) {
|
||||
this.remove(this.getItemByValue(workerForm.actor));
|
||||
},
|
||||
|
||||
_onWorkerSelect: function () {
|
||||
if (this.selectedItem !== null) {
|
||||
DebuggerController.Workers._onWorkerSelect(this.selectedItem.value);
|
||||
DebuggerController.Workers._onWorkerSelect(this.selectedItem.attachment);
|
||||
this.selectedItem = null;
|
||||
}
|
||||
}
|
||||
|
@ -912,6 +912,10 @@ Toolbox.prototype = {
|
||||
if (!this.target.hasActor("gcli")) {
|
||||
return promise.resolve();
|
||||
}
|
||||
// Disable gcli in browser toolbox until there is usages of it
|
||||
if (this.target.chrome) {
|
||||
return promise.resolve();
|
||||
}
|
||||
|
||||
const options = {
|
||||
environment: CommandUtils.createEnvironment(this, '_target')
|
||||
|
@ -114,6 +114,7 @@ skip-if = e10s # Bug 1091612
|
||||
[browser_net_simple-request-details.js]
|
||||
[browser_net_simple-request.js]
|
||||
[browser_net_sort-01.js]
|
||||
skip-if = (e10s && debug && os == 'mac') # Bug 1253037
|
||||
[browser_net_sort-02.js]
|
||||
[browser_net_sort-03.js]
|
||||
[browser_net_statistics-01.js]
|
||||
|
@ -233,7 +233,15 @@ Telemetry.prototype = {
|
||||
histogram: "DEVTOOLS_CUSTOM_OPENED_COUNT",
|
||||
userHistogram: "DEVTOOLS_CUSTOM_OPENED_PER_USER_FLAG",
|
||||
timerHistogram: "DEVTOOLS_CUSTOM_TIME_ACTIVE_SECONDS"
|
||||
}
|
||||
},
|
||||
reloadAddonInstalled: {
|
||||
histogram: "DEVTOOLS_RELOAD_ADDON_INSTALLED_COUNT",
|
||||
userHistogram: "DEVTOOLS_RELOAD_ADDON_INSTALLED_PER_USER_FLAG",
|
||||
},
|
||||
reloadAddonReload: {
|
||||
histogram: "DEVTOOLS_RELOAD_ADDON_RELOAD_COUNT",
|
||||
userHistogram: "DEVTOOLS_RELOAD_ADDON_RELOAD_PER_USER_FLAG",
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -34,7 +34,7 @@ function getTopWindow(win) {
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
|
||||
if (!docShell.isBrowserOrApp) {
|
||||
if (!docShell.isMozBrowserOrApp) {
|
||||
return win.top;
|
||||
}
|
||||
|
||||
@ -94,7 +94,7 @@ function getParentWindow(win) {
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
|
||||
if (!docShell.isBrowserOrApp) {
|
||||
if (!docShell.isMozBrowserOrApp) {
|
||||
return win.parent;
|
||||
}
|
||||
|
||||
|
@ -172,13 +172,13 @@ LoadContext::SetRemoteTabs(bool aUseRemoteTabs)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadContext::GetIsInBrowserElement(bool* aIsInBrowserElement)
|
||||
LoadContext::GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement)
|
||||
{
|
||||
MOZ_ASSERT(mIsNotNull);
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aIsInBrowserElement);
|
||||
NS_ENSURE_ARG_POINTER(aIsInIsolatedMozBrowserElement);
|
||||
|
||||
*aIsInBrowserElement = mOriginAttributes.mInBrowser;
|
||||
*aIsInIsolatedMozBrowserElement = mOriginAttributes.mInIsolatedMozBrowser;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -39,8 +39,8 @@ public:
|
||||
NS_DECL_NSILOADCONTEXT
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
|
||||
// AppId/inBrowser arguments override those in SerializedLoadContext provided
|
||||
// by child process.
|
||||
// appId/inIsolatedMozBrowser arguments override those in SerializedLoadContext
|
||||
// provided by child process.
|
||||
LoadContext(const IPC::SerializedLoadContext& aToCopy,
|
||||
dom::Element* aTopFrameElement,
|
||||
DocShellOriginAttributes& aAttrs)
|
||||
@ -56,8 +56,8 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
// AppId/inBrowser arguments override those in SerializedLoadContext provided
|
||||
// by child process.
|
||||
// appId/inIsolatedMozBrowser arguments override those in SerializedLoadContext
|
||||
// provided by child process.
|
||||
LoadContext(const IPC::SerializedLoadContext& aToCopy,
|
||||
uint64_t aNestedFrameId,
|
||||
DocShellOriginAttributes& aAttrs)
|
||||
|
@ -332,7 +332,7 @@ nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel,
|
||||
curDocShellItem->GetParent(getter_AddRefs(parentDocShellItem))) &&
|
||||
parentDocShellItem) {
|
||||
nsCOMPtr<nsIDocShell> curDocShell = do_QueryInterface(curDocShellItem);
|
||||
if (curDocShell && curDocShell->GetIsBrowserOrApp()) {
|
||||
if (curDocShell && curDocShell->GetIsMozBrowserOrApp()) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -781,6 +781,7 @@ nsDocShell::nsDocShell()
|
||||
, mAllowKeywordFixup(false)
|
||||
, mIsOffScreenBrowser(false)
|
||||
, mIsActive(true)
|
||||
, mDisableMetaRefreshWhenInactive(false)
|
||||
, mIsPrerendered(false)
|
||||
, mIsAppTab(false)
|
||||
, mUseGlobalHistory(false)
|
||||
@ -806,6 +807,7 @@ nsDocShell::nsDocShell()
|
||||
, mDefaultLoadFlags(nsIRequest::LOAD_NORMAL)
|
||||
, mBlankTiming(false)
|
||||
, mFrameType(eFrameTypeRegular)
|
||||
, mIsInIsolatedMozBrowser(false)
|
||||
, mOwnOrContainingAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID)
|
||||
, mUserContextId(nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID)
|
||||
, mParentCharsetSource(0)
|
||||
@ -885,8 +887,6 @@ nsDocShell::Init()
|
||||
NS_ASSERTION(mLoadGroup, "Something went wrong!");
|
||||
|
||||
mContentListener = new nsDSURIContentListener(this);
|
||||
NS_ENSURE_TRUE(mContentListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = mContentListener->Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -894,7 +894,6 @@ nsDocShell::Init()
|
||||
// ref to us... use an InterfaceRequestorProxy to do this.
|
||||
nsCOMPtr<nsIInterfaceRequestor> proxy =
|
||||
new InterfaceRequestorProxy(static_cast<nsIInterfaceRequestor*>(this));
|
||||
NS_ENSURE_TRUE(proxy, NS_ERROR_OUT_OF_MEMORY);
|
||||
mLoadGroup->SetNotificationCallbacks(proxy);
|
||||
|
||||
rv = nsDocLoader::AddDocLoaderAsChildOfRoot(this);
|
||||
@ -1651,7 +1650,6 @@ NS_IMETHODIMP
|
||||
nsDocShell::CreateLoadInfo(nsIDocShellLoadInfo** aLoadInfo)
|
||||
{
|
||||
nsDocShellLoadInfo* loadInfo = new nsDocShellLoadInfo();
|
||||
NS_ENSURE_TRUE(loadInfo, NS_ERROR_OUT_OF_MEMORY);
|
||||
nsCOMPtr<nsIDocShellLoadInfo> localRef(loadInfo);
|
||||
|
||||
localRef.forget(aLoadInfo);
|
||||
@ -2573,7 +2571,7 @@ nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed)
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetFullscreenAllowed(bool aFullscreenAllowed)
|
||||
{
|
||||
if (!nsIDocShell::GetIsBrowserOrApp()) {
|
||||
if (!nsIDocShell::GetIsMozBrowserOrApp()) {
|
||||
// Only allow setting of fullscreenAllowed on content/process boundaries.
|
||||
// At non-boundaries the fullscreenAllowed attribute is calculated based on
|
||||
// whether all enclosing frames have the "mozFullscreenAllowed" attribute
|
||||
@ -2632,10 +2630,6 @@ nsDocShell::GetDocShellEnumerator(int32_t aItemType, int32_t aDirection,
|
||||
docShellEnum = new nsDocShellBackwardsEnumerator;
|
||||
}
|
||||
|
||||
if (!docShellEnum) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult rv = docShellEnum->SetEnumDocShellType(aItemType);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
@ -3385,7 +3379,7 @@ nsDocShell::GetSameTypeParent(nsIDocShellTreeItem** aParent)
|
||||
NS_ENSURE_ARG_POINTER(aParent);
|
||||
*aParent = nullptr;
|
||||
|
||||
if (nsIDocShell::GetIsBrowserOrApp()) {
|
||||
if (nsIDocShell::GetIsMozBrowserOrApp()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3521,7 +3515,8 @@ nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (targetDS->GetIsInBrowserElement() != accessingDS->GetIsInBrowserElement() ||
|
||||
if (targetDS->GetIsInIsolatedMozBrowserElement() !=
|
||||
accessingDS->GetIsInIsolatedMozBrowserElement() ||
|
||||
targetDS->GetAppId() != accessingDS->GetAppId()) {
|
||||
return false;
|
||||
}
|
||||
@ -4036,6 +4031,7 @@ nsDocShell::AddChild(nsIDocShellTreeItem* aChild)
|
||||
|
||||
aChild->SetTreeOwner(mTreeOwner);
|
||||
childDocShell->SetUserContextId(mUserContextId);
|
||||
childDocShell->SetIsInIsolatedMozBrowserElement(mIsInIsolatedMozBrowser);
|
||||
|
||||
nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild));
|
||||
if (!childAsDocShell) {
|
||||
@ -5656,6 +5652,10 @@ nsDocShell::Create()
|
||||
gAddedPreferencesVarCache = true;
|
||||
}
|
||||
|
||||
mDisableMetaRefreshWhenInactive =
|
||||
Preferences::GetBool("browser.meta_refresh_when_inactive.disabled",
|
||||
mDisableMetaRefreshWhenInactive);
|
||||
|
||||
mDeviceSizeIsPageSize =
|
||||
Preferences::GetBool("docshell.device_size_is_page_size",
|
||||
mDeviceSizeIsPageSize);
|
||||
@ -5841,10 +5841,14 @@ nsDocShell::SetPosition(int32_t aX, int32_t aY)
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY)
|
||||
{
|
||||
// Added to nsIBaseWindow in bug 1247335;
|
||||
// implement if a use-case is found.
|
||||
NS_ASSERTION(false, "implement me!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
|
||||
if (ownerWindow) {
|
||||
return ownerWindow->SetPositionDesktopPix(aX, aY);
|
||||
}
|
||||
|
||||
double scale = 1.0;
|
||||
GetDevicePixelsPerDesktopPixel(&scale);
|
||||
return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -6145,7 +6149,7 @@ nsDocShell::SetIsActiveInternal(bool aIsActive, bool aIsHidden)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!docshell->GetIsBrowserOrApp()) {
|
||||
if (!docshell->GetIsMozBrowserOrApp()) {
|
||||
if (aIsHidden) {
|
||||
docshell->SetIsActive(aIsActive);
|
||||
} else {
|
||||
@ -6154,6 +6158,15 @@ nsDocShell::SetIsActiveInternal(bool aIsActive, bool aIsHidden)
|
||||
}
|
||||
}
|
||||
|
||||
// Restart or stop meta refresh timers if necessary
|
||||
if (mDisableMetaRefreshWhenInactive) {
|
||||
if (mIsActive) {
|
||||
ResumeRefreshURIs();
|
||||
} else {
|
||||
SuspendRefreshURIs();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -6599,7 +6612,6 @@ nsDocShell::RefreshURI(nsIURI* aURI, int32_t aDelay, bool aRepeat,
|
||||
}
|
||||
|
||||
nsRefreshTimer* refreshTimer = new nsRefreshTimer();
|
||||
NS_ENSURE_TRUE(refreshTimer, NS_ERROR_OUT_OF_MEMORY);
|
||||
uint32_t busyFlags = 0;
|
||||
GetBusyFlags(&busyFlags);
|
||||
|
||||
@ -6616,10 +6628,9 @@ nsDocShell::RefreshURI(nsIURI* aURI, int32_t aDelay, bool aRepeat,
|
||||
NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
if (busyFlags & BUSY_FLAGS_BUSY) {
|
||||
// We are busy loading another page. Don't create the
|
||||
// timer right now. Instead queue up the request and trigger the
|
||||
// timer in EndPageLoad().
|
||||
if (busyFlags & BUSY_FLAGS_BUSY || (!mIsActive && mDisableMetaRefreshWhenInactive)) {
|
||||
// We don't want to create the timer right now. Instead queue up the request
|
||||
// and trigger the timer in EndPageLoad() or whenever we become active.
|
||||
mRefreshURIList->AppendElement(refreshTimer);
|
||||
} else {
|
||||
// There is no page loading going on right now. Create the
|
||||
@ -7572,6 +7583,7 @@ nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
|
||||
}
|
||||
// if there's a refresh header in the channel, this method
|
||||
// will set it up for us.
|
||||
if (mIsActive || !mDisableMetaRefreshWhenInactive)
|
||||
RefreshURIFromQueue();
|
||||
|
||||
// Test whether this is the top frame or a subframe
|
||||
@ -13910,13 +13922,6 @@ nsDocShell::SetUserContextId(uint32_t aUserContextId)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsBrowserElement(bool* aIsBrowser)
|
||||
{
|
||||
*aIsBrowser = (mFrameType == eFrameTypeBrowser);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsApp(bool* aIsApp)
|
||||
{
|
||||
@ -13925,15 +13930,15 @@ nsDocShell::GetIsApp(bool* aIsApp)
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsBrowserOrApp(bool* aIsBrowserOrApp)
|
||||
nsDocShell::GetIsMozBrowserOrApp(bool* aIsMozBrowserOrApp)
|
||||
{
|
||||
switch (mFrameType) {
|
||||
case eFrameTypeRegular:
|
||||
*aIsBrowserOrApp = false;
|
||||
*aIsMozBrowserOrApp = false;
|
||||
break;
|
||||
case eFrameTypeBrowser:
|
||||
case eFrameTypeApp:
|
||||
*aIsBrowserOrApp = true;
|
||||
*aIsMozBrowserOrApp = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -13959,22 +13964,42 @@ nsDocShell::GetInheritedFrameType()
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsInBrowserElement(bool* aIsInBrowserElement)
|
||||
nsDocShell::GetIsIsolatedMozBrowserElement(bool* aIsIsolatedMozBrowserElement)
|
||||
{
|
||||
*aIsInBrowserElement = (GetInheritedFrameType() == eFrameTypeBrowser);
|
||||
bool result = mFrameType == eFrameTypeBrowser && mIsInIsolatedMozBrowser;
|
||||
*aIsIsolatedMozBrowserElement = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsInBrowserOrApp(bool* aIsInBrowserOrApp)
|
||||
nsDocShell::GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement)
|
||||
{
|
||||
MOZ_ASSERT(!mIsInIsolatedMozBrowser ||
|
||||
(GetInheritedFrameType() == eFrameTypeBrowser),
|
||||
"Isolated mozbrowser should only be true inside browser frames");
|
||||
bool result = (GetInheritedFrameType() == eFrameTypeBrowser) &&
|
||||
mIsInIsolatedMozBrowser;
|
||||
*aIsInIsolatedMozBrowserElement = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::SetIsInIsolatedMozBrowserElement(bool aIsInIsolatedMozBrowserElement)
|
||||
{
|
||||
mIsInIsolatedMozBrowser = aIsInIsolatedMozBrowserElement;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsInMozBrowserOrApp(bool* aIsInMozBrowserOrApp)
|
||||
{
|
||||
switch (GetInheritedFrameType()) {
|
||||
case eFrameTypeRegular:
|
||||
*aIsInBrowserOrApp = false;
|
||||
*aIsInMozBrowserOrApp = false;
|
||||
break;
|
||||
case eFrameTypeBrowser:
|
||||
case eFrameTypeApp:
|
||||
*aIsInBrowserOrApp = true;
|
||||
*aIsInMozBrowserOrApp = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -14020,10 +14045,7 @@ nsDocShell::GetOriginAttributes()
|
||||
}
|
||||
|
||||
attrs.mUserContextId = mUserContextId;
|
||||
|
||||
if (mFrameType == eFrameTypeBrowser) {
|
||||
attrs.mInBrowser = true;
|
||||
}
|
||||
attrs.mInIsolatedMozBrowser = mIsInIsolatedMozBrowser;
|
||||
|
||||
return attrs;
|
||||
}
|
||||
|
@ -939,6 +939,7 @@ protected:
|
||||
bool mAllowKeywordFixup;
|
||||
bool mIsOffScreenBrowser;
|
||||
bool mIsActive;
|
||||
bool mDisableMetaRefreshWhenInactive;
|
||||
bool mIsPrerendered;
|
||||
bool mIsAppTab;
|
||||
bool mUseGlobalHistory;
|
||||
@ -1001,6 +1002,9 @@ protected:
|
||||
// Are we a regular frame, a browser frame, or an app frame?
|
||||
FrameType mFrameType;
|
||||
|
||||
// Whether we are in an isolated mozbrowser frame.
|
||||
bool mIsInIsolatedMozBrowser;
|
||||
|
||||
// We only expect mOwnOrContainingAppId to be something other than
|
||||
// UNKNOWN_APP_ID if mFrameType != eFrameTypeRegular. For vanilla iframes
|
||||
// inside an app, we'll retrieve the containing app-id by walking up the
|
||||
|
@ -765,44 +765,55 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
*/
|
||||
[noscript] void notifyScrollObservers();
|
||||
|
||||
/**
|
||||
* Returns true if this docshell corresponds to an <iframe mozbrowser>.
|
||||
* (<iframe mozapp mozbrowser> is not considered a browser.)
|
||||
*/
|
||||
[infallible] readonly attribute boolean isBrowserElement;
|
||||
|
||||
/**
|
||||
* Returns true iff the docshell corresponds to an <iframe mozapp>.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isApp;
|
||||
|
||||
/**
|
||||
* Returns isBrowserElement || isApp.
|
||||
* Returns true if this docshell corresponds to an <iframe mozbrowser> or
|
||||
* <iframe mozapp>. <xul:browser> returns false here.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isBrowserOrApp;
|
||||
[infallible] readonly attribute boolean isMozBrowserOrApp;
|
||||
|
||||
/**
|
||||
* Returns true if this docshell corresponds to an <iframe mozbrowser> or if
|
||||
* the docshell is contained in an <iframe mozbrowser>. (<iframe mozapp
|
||||
* mozbrowser> does not count as a browser.)
|
||||
* Returns true if this docshell corresponds to an isolated <iframe
|
||||
* mozbrowser>.
|
||||
*
|
||||
* <iframe mozbrowser mozapp> and <xul:browser> are not considered to be
|
||||
* mozbrowser elements. <iframe mozbrowser noisolation> does not count as
|
||||
* isolated since isolation is disabled. Isolation can only be disabled if
|
||||
* the containing document is chrome.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isIsolatedMozBrowserElement;
|
||||
|
||||
/**
|
||||
* Returns true if this docshell corresponds to an isolated <iframe
|
||||
* mozbrowser> or if the docshell is contained in an isolated <iframe
|
||||
* mozbrowser>.
|
||||
*
|
||||
* <iframe mozbrowser mozapp> and <xul:browser> are not considered to be
|
||||
* mozbrowser elements. <iframe mozbrowser noisolation> does not count as
|
||||
* isolated since isolation is disabled. Isolation can only be disabled if
|
||||
* the containing document is chrome.
|
||||
*
|
||||
* Our notion here of "contained in" means: Walk up the docshell hierarchy in
|
||||
* this process until we hit an <iframe mozapp> or <iframe mozbrowser> (or
|
||||
* until the hierarchy ends). Return true iff the docshell we stopped on has
|
||||
* isBrowserElement == true.
|
||||
* isIsolatedMozBrowserElement == true.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isInBrowserElement;
|
||||
[infallible] attribute boolean isInIsolatedMozBrowserElement;
|
||||
|
||||
/**
|
||||
* Returns true if this docshell corresponds to an <iframe mozbrowser> or
|
||||
* <iframe mozapp>, or if this docshell is contained in an <iframe mozbrowser>
|
||||
* or <iframe mozapp>.
|
||||
* or <iframe mozapp>. <xul:browser> returns false here.
|
||||
*
|
||||
* To compute this value, we walk up the docshell hierarchy. If we encounter
|
||||
* a docshell with isBrowserElement or isApp before we hit the end of the
|
||||
* hierarchy, we return true. Otherwise, we return false.
|
||||
* a docshell with isMozBrowserOrApp before we hit the end of the hierarchy,
|
||||
* we return true. Otherwise, we return false.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isInBrowserOrApp;
|
||||
[infallible] readonly attribute boolean isInMozBrowserOrApp;
|
||||
|
||||
/**
|
||||
* Indicate that this docshell corresponds to an app with the given app id.
|
||||
|
@ -116,9 +116,13 @@ interface nsILoadContext : nsISupports
|
||||
[noscript] void SetRemoteTabs(in boolean aUseRemoteTabs);
|
||||
|
||||
/**
|
||||
* Returns true iff the load is occurring inside a browser element.
|
||||
* Returns true iff the load is occurring inside an isolated mozbrowser
|
||||
* element. <iframe mozbrowser mozapp> and <xul:browser> are not considered to
|
||||
* be mozbrowser elements. <iframe mozbrowser noisolation> does not count as
|
||||
* isolated since isolation is disabled. Isolation can only be disabled if
|
||||
* the containing document is chrome.
|
||||
*/
|
||||
readonly attribute boolean isInBrowserElement;
|
||||
readonly attribute boolean isInIsolatedMozBrowserElement;
|
||||
|
||||
/**
|
||||
* Returns the app id of the app the load is occurring is in. Returns
|
||||
|
@ -91,6 +91,17 @@ public:
|
||||
*/
|
||||
virtual void NotifyAnimationUpdated(Animation& aAnimation);
|
||||
|
||||
/**
|
||||
* Returns true if any CSS animations, CSS transitions or Web animations are
|
||||
* currently associated with this timeline. As soon as an animation is
|
||||
* applied to an element it is associated with the timeline even if it has a
|
||||
* delayed start, so this includes animations that may not be active for some
|
||||
* time.
|
||||
*/
|
||||
bool HasAnimations() const {
|
||||
return !mAnimations.IsEmpty();
|
||||
}
|
||||
|
||||
void RemoveAnimation(Animation* aAnimation);
|
||||
|
||||
protected:
|
||||
|
@ -106,6 +106,10 @@ AppsService.prototype = {
|
||||
return DOMApplicationRegistry.getWebAppsBasePath();
|
||||
},
|
||||
|
||||
areAnyAppsInstalled: function() {
|
||||
return DOMApplicationRegistry.areAnyAppsInstalled();
|
||||
},
|
||||
|
||||
getAppInfo: function getAppInfo(aAppId) {
|
||||
debug("getAppInfo()");
|
||||
return DOMApplicationRegistry.getAppInfo(aAppId);
|
||||
|
@ -412,6 +412,10 @@ this.DOMApplicationRegistry = {
|
||||
return null;
|
||||
},
|
||||
|
||||
areAnyAppsInstalled: function() {
|
||||
return AppsUtils.areAnyAppsInstalled(this.webapps);
|
||||
},
|
||||
|
||||
getAppInfo: function getAppInfo(aAppId) {
|
||||
return AppsUtils.getAppInfo(this.webapps, aAppId);
|
||||
},
|
||||
|
@ -149,16 +149,17 @@ this.AppsUtils = {
|
||||
return obj;
|
||||
},
|
||||
|
||||
// Creates a nsILoadContext object with a given appId and isBrowser flag.
|
||||
createLoadContext: function createLoadContext(aAppId, aIsBrowser) {
|
||||
// Creates a nsILoadContext object with a given appId and inIsolatedMozBrowser
|
||||
// flag.
|
||||
createLoadContext: function createLoadContext(aAppId, aInIsolatedMozBrowser) {
|
||||
return {
|
||||
associatedWindow: null,
|
||||
topWindow : null,
|
||||
appId: aAppId,
|
||||
isInBrowserElement: aIsBrowser,
|
||||
isInIsolatedMozBrowserElement: aInIsolatedMozBrowser,
|
||||
originAttributes: {
|
||||
appId: aAppId,
|
||||
inBrowser: aIsBrowser
|
||||
inIsolatedMozBrowser: aInIsolatedMozBrowser
|
||||
},
|
||||
usePrivateBrowsing: false,
|
||||
isContent: false,
|
||||
@ -344,6 +345,10 @@ this.AppsUtils = {
|
||||
return "";
|
||||
},
|
||||
|
||||
areAnyAppsInstalled: function(aApps) {
|
||||
return Object.getOwnPropertyNames(aApps).length > 0;
|
||||
},
|
||||
|
||||
getCoreAppsBasePath: function getCoreAppsBasePath() {
|
||||
debug("getCoreAppsBasePath()");
|
||||
try {
|
||||
|
@ -183,7 +183,7 @@ WebappsRegistry.prototype = {
|
||||
topId: this._topId,
|
||||
requestID: requestID,
|
||||
appId: principal.appId,
|
||||
isBrowser: principal.isInBrowserElement,
|
||||
isBrowser: principal.isInIsolatedMozBrowserElement,
|
||||
isPackage: isPackage
|
||||
};
|
||||
},
|
||||
|
@ -3536,10 +3536,10 @@ this.DOMApplicationRegistry = {
|
||||
|
||||
// nsILoadContext
|
||||
appId: aOldApp.installerAppId,
|
||||
isInBrowserElement: aOldApp.installerIsBrowser,
|
||||
isInIsolatedMozBrowserElement: aOldApp.installerIsBrowser,
|
||||
originAttributes: {
|
||||
appId: aOldApp.installerAppId,
|
||||
inBrowser: aOldApp.installerIsBrowser
|
||||
inIsolatedMozBrowser: aOldApp.installerIsBrowser
|
||||
},
|
||||
usePrivateBrowsing: false,
|
||||
isContent: false,
|
||||
@ -4799,6 +4799,10 @@ this.DOMApplicationRegistry = {
|
||||
return OS.Path.dirname(this.appsFile);
|
||||
},
|
||||
|
||||
areAnyAppsInstalled: function() {
|
||||
return AppsUtils.areAnyAppsInstalled(this.webapps);
|
||||
},
|
||||
|
||||
updateDataStoreEntriesFromLocalId: function(aLocalId) {
|
||||
let app = appsService.getAppByLocalId(aLocalId);
|
||||
if (app) {
|
||||
@ -4902,7 +4906,7 @@ this.DOMApplicationRegistry = {
|
||||
_clearOriginData: function(appId, browserOnly) {
|
||||
let attributes = {appId: appId};
|
||||
if (browserOnly) {
|
||||
attributes.inBrowser = true;
|
||||
attributes.inIsolatedMozBrowser = true;
|
||||
}
|
||||
this._notifyCategoryAndObservers(null, "clear-origin-data", JSON.stringify(attributes));
|
||||
}
|
||||
|
@ -53,8 +53,8 @@ add_test(() => {
|
||||
Assert.equal(mozapp.principal.origin, expectedPrincipalOrigin,
|
||||
"app principal origin ok");
|
||||
Assert.equal(mozapp.principal.appId, app.localId, "app principal appId ok");
|
||||
Assert.equal(mozapp.principal.isInBrowserElement, false,
|
||||
"app principal isInBrowserElement ok");
|
||||
Assert.equal(mozapp.principal.isInIsolatedMozBrowserElement, false,
|
||||
"app principal isInIsolatedMozBrowserElement ok");
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
|
@ -108,7 +108,7 @@ ChromeUtils::IsOriginAttributesEqual(dom::GlobalObject& aGlobal,
|
||||
{
|
||||
return aA.mAddonId == aB.mAddonId &&
|
||||
aA.mAppId == aB.mAppId &&
|
||||
aA.mInBrowser == aB.mInBrowser &&
|
||||
aA.mInIsolatedMozBrowser == aB.mInIsolatedMozBrowser &&
|
||||
aA.mSignedPkg == aB.mSignedPkg &&
|
||||
aA.mUserContextId == aB.mUserContextId;
|
||||
}
|
||||
|
@ -135,14 +135,14 @@ PerformanceObserver::QueueEntry(PerformanceEntry* aEntry)
|
||||
mQueuedEntries.AppendElement(aEntry);
|
||||
}
|
||||
|
||||
static nsString sValidTypeNames[7] = {
|
||||
NS_LITERAL_STRING("composite"),
|
||||
NS_LITERAL_STRING("mark"),
|
||||
NS_LITERAL_STRING("measure"),
|
||||
NS_LITERAL_STRING("navigation"),
|
||||
NS_LITERAL_STRING("render"),
|
||||
NS_LITERAL_STRING("resource"),
|
||||
NS_LITERAL_STRING("server")
|
||||
static const char16_t* sValidTypeNames[7] = {
|
||||
MOZ_UTF16("composite"),
|
||||
MOZ_UTF16("mark"),
|
||||
MOZ_UTF16("measure"),
|
||||
MOZ_UTF16("navigation"),
|
||||
MOZ_UTF16("render"),
|
||||
MOZ_UTF16("resource"),
|
||||
MOZ_UTF16("server")
|
||||
};
|
||||
|
||||
void
|
||||
@ -156,7 +156,8 @@ PerformanceObserver::Observe(const PerformanceObserverInit& aOptions,
|
||||
|
||||
nsTArray<nsString> validEntryTypes;
|
||||
|
||||
for (const nsString& validTypeName : sValidTypeNames) {
|
||||
for (const char16_t* name : sValidTypeNames) {
|
||||
nsDependentString validTypeName(name);
|
||||
if (aOptions.mEntryTypes.Contains<nsString>(validTypeName) &&
|
||||
!validEntryTypes.Contains<nsString>(validTypeName)) {
|
||||
validEntryTypes.AppendElement(validTypeName);
|
||||
|
@ -349,9 +349,10 @@ AutoJSAPI::InitInternal(JSObject* aGlobal, JSContext* aCx, bool aIsMainThread)
|
||||
mAutoNullableCompartment.emplace(mCx, aGlobal);
|
||||
}
|
||||
|
||||
if (aIsMainThread) {
|
||||
JSRuntime* rt = JS_GetRuntime(aCx);
|
||||
mOldErrorReporter.emplace(JS_GetErrorReporter(rt));
|
||||
|
||||
if (aIsMainThread) {
|
||||
JS_SetErrorReporter(rt, xpc::SystemErrorReporter);
|
||||
}
|
||||
}
|
||||
@ -465,8 +466,21 @@ AutoJSAPI::InitWithLegacyErrorReporting(nsGlobalWindow* aWindow)
|
||||
void
|
||||
WarningOnlyErrorReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aRep)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(JSREPORT_IS_WARNING(aRep->flags));
|
||||
if (!NS_IsMainThread()) {
|
||||
// Reporting a warning on workers is a bit complicated because we have to
|
||||
// climb our parent chain until we get to the main thread. So go ahead and
|
||||
// just go through the worker ReportError codepath here.
|
||||
//
|
||||
// That said, it feels like we should be able to short-circuit things a bit
|
||||
// here by posting an appropriate runnable to the main thread directly...
|
||||
// Worth looking into sometime.
|
||||
workers::WorkerPrivate* worker = workers::GetWorkerPrivateFromContext(aCx);
|
||||
MOZ_ASSERT(worker);
|
||||
|
||||
worker->ReportError(aCx, aMessage, aRep);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
nsGlobalWindow* win = xpc::CurrentWindowOrNull(aCx);
|
||||
@ -484,13 +498,7 @@ AutoJSAPI::TakeOwnershipOfErrorReporting()
|
||||
JSRuntime *rt = JS_GetRuntime(cx());
|
||||
mOldAutoJSAPIOwnsErrorReporting = JS::ContextOptionsRef(cx()).autoJSAPIOwnsErrorReporting();
|
||||
JS::ContextOptionsRef(cx()).setAutoJSAPIOwnsErrorReporting(true);
|
||||
// Workers have their own error reporting mechanism which deals with warnings
|
||||
// as well, so don't change the worker error reporter for now. Once we switch
|
||||
// all of workers to TakeOwnershipOfErrorReporting(), we will just make the
|
||||
// default worker error reporter assert that it only sees warnings.
|
||||
if (mIsMainThread) {
|
||||
JS_SetErrorReporter(rt, WarningOnlyErrorReporter);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -548,6 +556,7 @@ AutoJSAPI::ReportException()
|
||||
}
|
||||
} else {
|
||||
NS_WARNING("OOMed while acquiring uncaught exception from JSAPI");
|
||||
ClearException();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,7 +422,7 @@ nsFrameLoader::ReallyStartLoadingInternal()
|
||||
int32_t flags = nsIWebNavigation::LOAD_FLAGS_NONE;
|
||||
|
||||
// Flags for browser frame:
|
||||
if (OwnerIsBrowserFrame()) {
|
||||
if (OwnerIsMozBrowserFrame()) {
|
||||
flags = nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
|
||||
nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
|
||||
}
|
||||
@ -1200,8 +1200,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (ourDocshell->GetIsBrowserElement() !=
|
||||
otherDocshell->GetIsBrowserElement() ||
|
||||
if (ourDocshell->GetIsIsolatedMozBrowserElement() !=
|
||||
otherDocshell->GetIsIsolatedMozBrowserElement() ||
|
||||
ourDocshell->GetIsApp() != otherDocshell->GetIsApp()) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
@ -1577,7 +1577,7 @@ nsFrameLoader::SetOwnerContent(Element* aContent)
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::OwnerIsBrowserOrAppFrame()
|
||||
nsFrameLoader::OwnerIsMozBrowserOrAppFrame()
|
||||
{
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
|
||||
return browserFrame ? browserFrame->GetReallyIsBrowserOrApp() : false;
|
||||
@ -1585,9 +1585,9 @@ nsFrameLoader::OwnerIsBrowserOrAppFrame()
|
||||
|
||||
// The xpcom getter version
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::GetOwnerIsBrowserOrAppFrame(bool* aResult)
|
||||
nsFrameLoader::GetOwnerIsMozBrowserOrAppFrame(bool* aResult)
|
||||
{
|
||||
*aResult = OwnerIsBrowserOrAppFrame();
|
||||
*aResult = OwnerIsMozBrowserOrAppFrame();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1615,9 +1615,66 @@ nsFrameLoader::OwnerIsAppFrame()
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::OwnerIsBrowserFrame()
|
||||
nsFrameLoader::OwnerIsMozBrowserFrame()
|
||||
{
|
||||
return OwnerIsBrowserOrAppFrame() && !OwnerIsAppFrame();
|
||||
return OwnerIsMozBrowserOrAppFrame() && !OwnerIsAppFrame();
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::OwnerIsIsolatedMozBrowserFrame()
|
||||
{
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
|
||||
if (!browserFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!OwnerIsMozBrowserFrame()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isolated = browserFrame->GetIsolated();
|
||||
if (isolated) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// After bug 1238160, which allows isolation to be disabled on mozbrowser
|
||||
// frames, we no longer have a way to tell from the principal alone if
|
||||
// something "is a mozbrowser". Instead, we now only know "is an isolated
|
||||
// mozbrowser". The following code paths would return invalid results if it
|
||||
// were possible to have apps *and* isolation could be disabled:
|
||||
// * CheckPermission in AppProcessChecker.cpp
|
||||
// * nsScriptSecurityManager::AppStatusForPrincipal
|
||||
// * init() in SystemMessageManager.js
|
||||
// Currently, desktop is the only platform where we intend to disable
|
||||
// isolation on a browser frame, so non-desktop should be able to assume that
|
||||
// inIsolatedMozBrowser is true for all mozbrowser frames. To enforce these
|
||||
// assumptions, we assert that there are no apps installed if we have tried
|
||||
// to disable isolation.
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
if (!appsService) {
|
||||
// If the apps service is not present, we assume this means there can't be
|
||||
// any apps at all, so there is no problem.
|
||||
return false;
|
||||
}
|
||||
bool appsInstalled;
|
||||
nsresult rv = appsService->AreAnyAppsInstalled(&appsInstalled);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
// The apps service exists, but it threw an error when checking if there are
|
||||
// any apps, so we don't know if we have them or not.
|
||||
return false;
|
||||
}
|
||||
#ifdef MOZ_B2G
|
||||
MOZ_RELEASE_ASSERT(!appsInstalled,
|
||||
"Disabling mozbrowser isolation is not currently "
|
||||
"allowed when apps are installed.");
|
||||
#else
|
||||
if (appsInstalled) {
|
||||
NS_WARNING("Disabling mozbrowser isolation is not currently allowed when "
|
||||
"apps are installed.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1692,7 +1749,7 @@ nsFrameLoader::ShouldUseRemoteProcess()
|
||||
|
||||
// If we're an <iframe mozbrowser> and we don't have a "remote" attribute,
|
||||
// fall back to the default.
|
||||
if (OwnerIsBrowserOrAppFrame() &&
|
||||
if (OwnerIsMozBrowserOrAppFrame() &&
|
||||
!mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::Remote)) {
|
||||
|
||||
return Preferences::GetBool("dom.ipc.browser_frames.oop_by_default", false);
|
||||
@ -1700,7 +1757,7 @@ nsFrameLoader::ShouldUseRemoteProcess()
|
||||
|
||||
// Otherwise, we're remote if we have "remote=true" and we're either a
|
||||
// browser frame or a XUL element.
|
||||
return (OwnerIsBrowserOrAppFrame() ||
|
||||
return (OwnerIsMozBrowserOrAppFrame() ||
|
||||
mOwnerContent->GetNameSpaceID() == kNameSpaceID_XUL) &&
|
||||
mOwnerContent->AttrValueIs(kNameSpaceID_None,
|
||||
nsGkAtoms::Remote,
|
||||
@ -1883,7 +1940,7 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
|
||||
if (OwnerIsAppFrame()) {
|
||||
// You can't be both an app and a browser frame.
|
||||
MOZ_ASSERT(!OwnerIsBrowserFrame());
|
||||
MOZ_ASSERT(!OwnerIsMozBrowserFrame());
|
||||
|
||||
nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
|
||||
MOZ_ASSERT(ownApp);
|
||||
@ -1895,7 +1952,7 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
mDocShell->SetIsApp(ownAppId);
|
||||
}
|
||||
|
||||
if (OwnerIsBrowserFrame()) {
|
||||
if (OwnerIsMozBrowserFrame()) {
|
||||
// You can't be both a browser and an app frame.
|
||||
MOZ_ASSERT(!OwnerIsAppFrame());
|
||||
|
||||
@ -1906,9 +1963,10 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
NS_ERROR_FAILURE);
|
||||
}
|
||||
mDocShell->SetIsBrowserInsideApp(containingAppId);
|
||||
mDocShell->SetIsInIsolatedMozBrowserElement(OwnerIsIsolatedMozBrowserFrame());
|
||||
}
|
||||
|
||||
if (OwnerIsBrowserOrAppFrame()) {
|
||||
if (OwnerIsMozBrowserOrAppFrame()) {
|
||||
// For inproc frames, set the docshell properties.
|
||||
nsCOMPtr<nsIDocShellTreeItem> item = do_GetInterface(docShell);
|
||||
nsAutoString name;
|
||||
@ -2249,7 +2307,7 @@ nsFrameLoader::TryRemoteBrowser()
|
||||
}
|
||||
|
||||
// <iframe mozbrowser> gets to skip these checks.
|
||||
if (!OwnerIsBrowserOrAppFrame()) {
|
||||
if (!OwnerIsMozBrowserOrAppFrame()) {
|
||||
if (parentDocShell->ItemType() != nsIDocShellTreeItem::typeChrome) {
|
||||
return false;
|
||||
}
|
||||
@ -2566,7 +2624,7 @@ nsFrameLoader::EnsureMessageManager()
|
||||
}
|
||||
|
||||
if (!mIsTopLevelContent &&
|
||||
!OwnerIsBrowserOrAppFrame() &&
|
||||
!OwnerIsMozBrowserOrAppFrame() &&
|
||||
!IsRemoteFrame() &&
|
||||
!(mOwnerContent->IsXULElement() &&
|
||||
mOwnerContent->AttrValueIs(kNameSpaceID_None,
|
||||
@ -2672,7 +2730,7 @@ nsFrameLoader::SwapRemoteBrowser(nsITabParent* aTabParent)
|
||||
NS_WARNING("Switching from in-process to out-of-process is not supported.");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
if (!OwnerIsBrowserOrAppFrame()) {
|
||||
if (!OwnerIsMozBrowserOrAppFrame()) {
|
||||
NS_WARNING("Switching process for non-mozbrowser/app frame is not supported.");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
@ -2823,7 +2881,7 @@ nsFrameLoader::ResetPermissionManagerStatus()
|
||||
uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
if (OwnerIsAppFrame()) {
|
||||
// You can't be both an app and a browser frame.
|
||||
MOZ_ASSERT(!OwnerIsBrowserFrame());
|
||||
MOZ_ASSERT(!OwnerIsMozBrowserFrame());
|
||||
|
||||
nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
|
||||
MOZ_ASSERT(ownApp);
|
||||
@ -2833,7 +2891,7 @@ nsFrameLoader::ResetPermissionManagerStatus()
|
||||
}
|
||||
}
|
||||
|
||||
if (OwnerIsBrowserFrame()) {
|
||||
if (OwnerIsMozBrowserFrame()) {
|
||||
// You can't be both a browser and an app frame.
|
||||
MOZ_ASSERT(!OwnerIsAppFrame());
|
||||
|
||||
@ -2971,7 +3029,7 @@ nsFrameLoader::GetLoadContext(nsILoadContext** aLoadContext)
|
||||
void
|
||||
nsFrameLoader::InitializeBrowserAPI()
|
||||
{
|
||||
if (OwnerIsBrowserOrAppFrame()) {
|
||||
if (OwnerIsMozBrowserOrAppFrame()) {
|
||||
if (!IsRemoteFrame()) {
|
||||
nsresult rv = EnsureMessageManager();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
@ -3066,7 +3124,7 @@ nsFrameLoader::GetNewTabContext(MutableTabContext* aTabContext,
|
||||
nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
|
||||
nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
|
||||
DocShellOriginAttributes attrs;
|
||||
attrs.mInBrowser = OwnerIsBrowserFrame();
|
||||
attrs.mInIsolatedMozBrowser = OwnerIsIsolatedMozBrowserFrame();
|
||||
|
||||
nsCString signedPkgOrigin;
|
||||
if (!aPackageId.IsEmpty()) {
|
||||
@ -3107,7 +3165,11 @@ nsFrameLoader::GetNewTabContext(MutableTabContext* aTabContext,
|
||||
}
|
||||
|
||||
bool tabContextUpdated =
|
||||
aTabContext->SetTabContext(ownApp, containingApp, attrs, signedPkgOrigin);
|
||||
aTabContext->SetTabContext(OwnerIsMozBrowserFrame(),
|
||||
ownApp,
|
||||
containingApp,
|
||||
attrs,
|
||||
signedPkgOrigin);
|
||||
NS_ENSURE_STATE(tabContextUpdated);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -242,8 +242,9 @@ private:
|
||||
* Is this a frameloader for a bona fide <iframe mozbrowser> or
|
||||
* <iframe mozapp>? (I.e., does the frame return true for
|
||||
* nsIMozBrowserFrame::GetReallyIsBrowserOrApp()?)
|
||||
* <xul:browser> is not a mozbrowser or app, so this is false for that case.
|
||||
*/
|
||||
bool OwnerIsBrowserOrAppFrame();
|
||||
bool OwnerIsMozBrowserOrAppFrame();
|
||||
|
||||
/**
|
||||
* Is this a frameloader for a bona fide <iframe mozwidget>? (I.e., does the
|
||||
@ -259,8 +260,18 @@ private:
|
||||
|
||||
/**
|
||||
* Is this a frame loader for a bona fide <iframe mozbrowser>?
|
||||
* <xul:browser> is not a mozbrowser, so this is false for that case.
|
||||
*/
|
||||
bool OwnerIsBrowserFrame();
|
||||
bool OwnerIsMozBrowserFrame();
|
||||
|
||||
/**
|
||||
* Is this a frame loader for an isolated <iframe mozbrowser>?
|
||||
*
|
||||
* By default, mozbrowser frames are isolated. Isolation can be disabled by
|
||||
* setting the frame's noisolation attribute. Disabling isolation is
|
||||
* only allowed if the containing document is chrome.
|
||||
*/
|
||||
bool OwnerIsIsolatedMozBrowserFrame();
|
||||
|
||||
/**
|
||||
* Get our owning element's app manifest URL, or return the empty string if
|
||||
|
@ -657,6 +657,7 @@ GK_ATOM(nodeSet, "node-set")
|
||||
GK_ATOM(noembed, "noembed")
|
||||
GK_ATOM(noframes, "noframes")
|
||||
GK_ATOM(nohref, "nohref")
|
||||
GK_ATOM(noisolation, "noisolation")
|
||||
GK_ATOM(nonce, "nonce")
|
||||
GK_ATOM(none, "none")
|
||||
GK_ATOM(noresize, "noresize")
|
||||
|
@ -457,8 +457,6 @@ nsGlobalWindow::DOMMinTimeoutValue() const {
|
||||
// CIDs
|
||||
static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID);
|
||||
|
||||
static const char sPopStatePrefStr[] = "browser.history.allowPopState";
|
||||
|
||||
#define NETWORK_UPLOAD_EVENT_NAME NS_LITERAL_STRING("moznetworkupload")
|
||||
#define NETWORK_DOWNLOAD_EVENT_NAME NS_LITERAL_STRING("moznetworkdownload")
|
||||
|
||||
@ -1158,6 +1156,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
|
||||
mIsPopupSpam(false),
|
||||
mBlockScriptedClosingFlag(false),
|
||||
mWasOffline(false),
|
||||
mHasHadSlowScript(false),
|
||||
mNotifyIdleObserversIdleOnThaw(false),
|
||||
mNotifyIdleObserversActiveOnThaw(false),
|
||||
mCreatingInnerWindow(false),
|
||||
@ -3801,7 +3800,7 @@ nsGlobalWindow::GetParentOuter()
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> parent;
|
||||
if (mDocShell->GetIsBrowserOrApp()) {
|
||||
if (mDocShell->GetIsMozBrowserOrApp()) {
|
||||
parent = AsOuter();
|
||||
} else {
|
||||
parent = GetParent();
|
||||
@ -3967,7 +3966,7 @@ nsGlobalWindow::GetContentInternal(ErrorResult& aError, bool aUnprivilegedCaller
|
||||
|
||||
// If we're contained in <iframe mozbrowser> or <iframe mozapp>, then
|
||||
// GetContent is the same as window.top.
|
||||
if (mDocShell && mDocShell->GetIsInBrowserOrApp()) {
|
||||
if (mDocShell && mDocShell->GetIsInMozBrowserOrApp()) {
|
||||
return GetTopOuter();
|
||||
}
|
||||
|
||||
@ -7175,7 +7174,7 @@ nsGlobalWindow::ResizeToOuter(int32_t aWidth, int32_t aHeight, ErrorResult& aErr
|
||||
* If caller is a browser-element then dispatch a resize event to
|
||||
* the embedder.
|
||||
*/
|
||||
if (mDocShell && mDocShell->GetIsBrowserOrApp()) {
|
||||
if (mDocShell && mDocShell->GetIsMozBrowserOrApp()) {
|
||||
CSSIntSize size(aWidth, aHeight);
|
||||
if (!DispatchResizeEvent(size)) {
|
||||
// The embedder chose to prevent the default action for this
|
||||
@ -7225,7 +7224,7 @@ nsGlobalWindow::ResizeByOuter(int32_t aWidthDif, int32_t aHeightDif,
|
||||
* If caller is a browser-element then dispatch a resize event to
|
||||
* parent.
|
||||
*/
|
||||
if (mDocShell && mDocShell->GetIsBrowserOrApp()) {
|
||||
if (mDocShell && mDocShell->GetIsMozBrowserOrApp()) {
|
||||
CSSIntSize size;
|
||||
if (NS_FAILED(GetInnerSize(size))) {
|
||||
return;
|
||||
@ -8174,7 +8173,7 @@ nsGlobalWindow::CloseOuter(bool aTrustedCaller)
|
||||
MOZ_RELEASE_ASSERT(IsOuterWindow());
|
||||
|
||||
if (!mDocShell || IsInModalState() ||
|
||||
(IsFrame() && !mDocShell->GetIsBrowserOrApp())) {
|
||||
(IsFrame() && !mDocShell->GetIsMozBrowserOrApp())) {
|
||||
// window.close() is called on a frame in a frameset, on a window
|
||||
// that's already closed, or on a window for which there's
|
||||
// currently a modal dialog open. Ignore such calls.
|
||||
@ -8701,7 +8700,7 @@ nsGlobalWindow::GetFrameElementOuter()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(IsOuterWindow());
|
||||
|
||||
if (!mDocShell || mDocShell->GetIsBrowserOrApp()) {
|
||||
if (!mDocShell || mDocShell->GetIsMozBrowserOrApp()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -9916,11 +9915,6 @@ nsGlobalWindow::DispatchSyncPopState()
|
||||
NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
|
||||
"Must be safe to run script here.");
|
||||
|
||||
// Check that PopState hasn't been pref'ed off.
|
||||
if (!Preferences::GetBool(sPopStatePrefStr, false)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Bail if the window is frozen.
|
||||
@ -10662,6 +10656,13 @@ nsGlobalWindow::ShowSlowScriptDialog()
|
||||
unsigned lineno;
|
||||
bool hasFrame = JS::DescribeScriptedCaller(cx, &filename, &lineno);
|
||||
|
||||
// Record the slow script event if we haven't done so already for this inner window
|
||||
// (which represents a particular page to the user).
|
||||
if (!mHasHadSlowScript) {
|
||||
Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_PAGE_COUNT, 1);
|
||||
}
|
||||
mHasHadSlowScript = true;
|
||||
|
||||
if (XRE_IsContentProcess() &&
|
||||
ProcessHangMonitor::Get()) {
|
||||
ProcessHangMonitor::SlowScriptAction action;
|
||||
|
@ -1685,6 +1685,11 @@ protected:
|
||||
// Window offline status. Checked to see if we need to fire offline event
|
||||
bool mWasOffline : 1;
|
||||
|
||||
// Represents whether the inner window's page has had a slow script notice.
|
||||
// Only used by inner windows; will always be false for outer windows.
|
||||
// This is used to implement Telemetry measures such as SLOW_SCRIPT_PAGE_COUNT.
|
||||
bool mHasHadSlowScript : 1;
|
||||
|
||||
// Track what sorts of events we need to fire when thawed
|
||||
bool mNotifyIdleObserversIdleOnThaw : 1;
|
||||
bool mNotifyIdleObserversActiveOnThaw : 1;
|
||||
|
@ -25,11 +25,6 @@
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
static const char* sAllowPushStatePrefStr =
|
||||
"browser.history.allowPushState";
|
||||
static const char* sAllowReplaceStatePrefStr =
|
||||
"browser.history.allowReplaceState";
|
||||
|
||||
//
|
||||
// History class implementation
|
||||
//
|
||||
@ -304,12 +299,6 @@ nsHistory::PushOrReplaceState(JSContext* aCx, JS::Handle<JS::Value> aData,
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that PushState hasn't been pref'ed off.
|
||||
if (!Preferences::GetBool(aReplace ? sAllowReplaceStatePrefStr :
|
||||
sAllowPushStatePrefStr, false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// AddState might run scripts, so we need to hold a strong reference to the
|
||||
// docShell here to keep it from going away.
|
||||
nsCOMPtr<nsIDocShell> docShell = win->GetDocShell();
|
||||
|
@ -196,14 +196,15 @@ interface nsIFrameLoader : nsISupports
|
||||
[infallible] attribute boolean visible;
|
||||
|
||||
/**
|
||||
* Find out whether the owner content really is a browser or app frame
|
||||
* Especially, a widget frame is regarded as an app frame.
|
||||
* Find out whether the owner content really is a mozbrowser or app frame
|
||||
* Especially, a widget frame is regarded as an app frame. <xul:browser> is
|
||||
* not considered to be a mozbrowser frame.
|
||||
*/
|
||||
readonly attribute boolean ownerIsBrowserOrAppFrame;
|
||||
readonly attribute boolean ownerIsMozBrowserOrAppFrame;
|
||||
|
||||
/**
|
||||
* Find out whether the owner content really is a widget. If this attribute
|
||||
* returns true, |ownerIsBrowserOrAppFrame| must return true.
|
||||
* returns true, |ownerIsMozBrowserOrAppFrame| must return true.
|
||||
*/
|
||||
readonly attribute boolean ownerIsWidget;
|
||||
|
||||
|
@ -1437,6 +1437,11 @@ TimeUntilNow(TimeStamp start)
|
||||
|
||||
struct CycleCollectorStats
|
||||
{
|
||||
MOZ_CONSTEXPR CycleCollectorStats() :
|
||||
mMaxGCDuration(0), mRanSyncForgetSkippable(false), mSuspected(0),
|
||||
mMaxSkippableDuration(0), mMaxSliceTime(0), mMaxSliceTimeSinceClear(0),
|
||||
mTotalSliceTime(0), mAnyLockedOut(false), mExtraForgetSkippableCalls(0) {}
|
||||
|
||||
void Init()
|
||||
{
|
||||
Clear();
|
||||
|
@ -259,6 +259,7 @@ support-files =
|
||||
file_change_policy_redirect.html
|
||||
file_bug1198095.js
|
||||
file_bug1250148.sjs
|
||||
mozbrowser_api_utils.js
|
||||
|
||||
[test_anonymousContent_api.html]
|
||||
[test_anonymousContent_append_after_reflow.html]
|
||||
@ -873,3 +874,5 @@ skip-if = buildapp == 'b2g' #no ssl support
|
||||
[test_bug769117.html]
|
||||
[test_bug1250148.html]
|
||||
[test_bug1240471.html]
|
||||
[test_mozbrowser_apis_allowed.html]
|
||||
[test_mozbrowser_apis_blocked.html]
|
||||
|
72
dom/base/test/mozbrowser_api_utils.js
Normal file
72
dom/base/test/mozbrowser_api_utils.js
Normal file
@ -0,0 +1,72 @@
|
||||
const FRAME_URL = "http://example.org/";
|
||||
|
||||
const METHODS = {
|
||||
setVisible: {},
|
||||
getVisible: {},
|
||||
setActive: {},
|
||||
getActive: {},
|
||||
addNextPaintListener: {},
|
||||
removeNextPaintListener: {},
|
||||
sendMouseEvent: {},
|
||||
sendTouchEvent: {},
|
||||
goBack: {},
|
||||
goForward: {},
|
||||
reload: {},
|
||||
stop: {},
|
||||
download: {},
|
||||
purgeHistory: {},
|
||||
getScreenshot: {},
|
||||
zoom: {},
|
||||
getCanGoBack: {},
|
||||
getCanGoForward: {},
|
||||
getContentDimensions: {},
|
||||
setInputMethodActive: { alwaysFails: true }, // needs input-manage
|
||||
setNFCFocus: { alwaysFails: true }, // needs nfc-manager
|
||||
findAll: {},
|
||||
findNext: {},
|
||||
clearMatch: {},
|
||||
executeScript: { alwaysFails: true }, // needs browser:universalxss
|
||||
getStructuredData: {},
|
||||
getWebManifest: {},
|
||||
mute: {},
|
||||
unmute: {},
|
||||
getMuted: {},
|
||||
setVolume: {},
|
||||
getVolume: {},
|
||||
};
|
||||
|
||||
const ATTRIBUTES = [
|
||||
"allowedAudioChannels",
|
||||
];
|
||||
|
||||
function once(target, eventName, useCapture = false) {
|
||||
info("Waiting for event: '" + eventName + "' on " + target + ".");
|
||||
|
||||
return new Promise(resolve => {
|
||||
for (let [add, remove] of [
|
||||
["addEventListener", "removeEventListener"],
|
||||
["addMessageListener", "removeMessageListener"],
|
||||
]) {
|
||||
if ((add in target) && (remove in target)) {
|
||||
target[add](eventName, function onEvent(...aArgs) {
|
||||
info("Got event: '" + eventName + "' on " + target + ".");
|
||||
target[remove](eventName, onEvent, useCapture);
|
||||
resolve(aArgs);
|
||||
}, useCapture);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function* loadFrame(attributes = {}) {
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.setAttribute("src", FRAME_URL);
|
||||
for (let key in attributes) {
|
||||
iframe.setAttribute(key, attributes[key]);
|
||||
}
|
||||
let loaded = once(iframe, "load");
|
||||
document.body.appendChild(iframe);
|
||||
yield loaded;
|
||||
return iframe;
|
||||
}
|
@ -34,8 +34,8 @@
|
||||
sendAsyncMessage(message.name, "principal.origin: " +
|
||||
("origin" in message.principal ? "OK" : "KO"));
|
||||
|
||||
sendAsyncMessage(message.name, "principal.isInBrowserElement: " +
|
||||
("isInBrowserElement" in message.principal ? "OK" : "KO"));
|
||||
sendAsyncMessage(message.name, "principal.isInIsolatedMozBrowserElement: " +
|
||||
("isInIsolatedMozBrowserElement" in message.principal ? "OK" : "KO"));
|
||||
|
||||
sendAsyncMessage(message.name, "DONE");
|
||||
});
|
||||
|
@ -38,8 +38,8 @@
|
||||
sendAsyncMessage("test:result", "principal.origin: " +
|
||||
("origin" in message.data ? "OK" : "KO"));
|
||||
|
||||
sendAsyncMessage("test:result", "principal.isInBrowserElement: " +
|
||||
("isInBrowserElement" in message.data ? "OK" : "KO"));
|
||||
sendAsyncMessage("test:result", "principal.isInIsolatedMozBrowserElement: " +
|
||||
("isInIsolatedMozBrowserElement" in message.data ? "OK" : "KO"));
|
||||
});
|
||||
|
||||
addMessageListener("test:system", function(message) {
|
||||
|
@ -110,7 +110,7 @@
|
||||
{ type: "browser", allow: 1, context: { url: principal.URI.spec,
|
||||
originAttributes: {
|
||||
appId: principal.appId,
|
||||
inBrowser: true }}}
|
||||
inIsolatedMozBrowser: true }}}
|
||||
], () => {
|
||||
SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
|
51
dom/base/test/test_mozbrowser_apis_allowed.html
Normal file
51
dom/base/test/test_mozbrowser_apis_allowed.html
Normal file
@ -0,0 +1,51 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Verify mozbrowser APIs are allowed with browser permission</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<script type="text/javascript" src="mozbrowser_api_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="application/javascript;version=1.8">
|
||||
add_task(function*() {
|
||||
yield new Promise(resolve => {
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{ "set": [["dom.mozBrowserFramesEnabled", true]] },
|
||||
resolve);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function*() {
|
||||
yield new Promise(resolve => {
|
||||
SpecialPowers.pushPermissions([
|
||||
{ "type": "browser", "allow": 1, "context": document }
|
||||
], resolve);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function*() {
|
||||
// Create <iframe mozbrowser>
|
||||
let frame = yield loadFrame({
|
||||
mozbrowser: "true"
|
||||
});
|
||||
|
||||
// Verify that mozbrowser APIs are accessible
|
||||
for (let method in METHODS) {
|
||||
let { alwaysFails } = METHODS[method];
|
||||
if (alwaysFails) {
|
||||
ok(!(method in frame), `frame does not have method ${method}, ` +
|
||||
`needs more permissions`);
|
||||
} else {
|
||||
ok(method in frame, `frame has method ${method}`);
|
||||
}
|
||||
}
|
||||
for (let attribute of ATTRIBUTES) {
|
||||
ok(attribute in frame, `frame has attribute ${attribute}`);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
37
dom/base/test/test_mozbrowser_apis_blocked.html
Normal file
37
dom/base/test/test_mozbrowser_apis_blocked.html
Normal file
@ -0,0 +1,37 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Verify mozbrowser APIs are blocked without browser permission</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<script type="text/javascript" src="mozbrowser_api_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="application/javascript;version=1.8">
|
||||
add_task(function*() {
|
||||
yield new Promise(resolve => {
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{ "set": [["dom.mozBrowserFramesEnabled", true]] },
|
||||
resolve);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function*() {
|
||||
// Create <iframe mozbrowser>
|
||||
let frame = yield loadFrame({
|
||||
mozbrowser: "true"
|
||||
});
|
||||
|
||||
// Verify that mozbrowser APIs are not accessible
|
||||
for (let method in METHODS) {
|
||||
ok(!(method in frame), `frame does not have method ${method}`);
|
||||
}
|
||||
for (let attribute of ATTRIBUTES) {
|
||||
ok(!(attribute in frame), `frame does not have attribute ${attribute}`);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -12187,6 +12187,15 @@ class CGDictionary(CGThing):
|
||||
return "DictionaryBase"
|
||||
|
||||
def initMethod(self):
|
||||
"""
|
||||
This function outputs the body of the Init() method for the dictionary.
|
||||
|
||||
For the most part, this is some bookkeeping for our atoms so
|
||||
we can avoid atomizing strings all the time, then we just spit
|
||||
out the getMemberConversion() output for each member,
|
||||
separated by newlines.
|
||||
|
||||
"""
|
||||
body = dedent("""
|
||||
// Passing a null JSContext is OK only if we're initing from null,
|
||||
// Since in that case we will not have to do any property gets
|
||||
@ -12504,6 +12513,25 @@ class CGDictionary(CGThing):
|
||||
return declType.define()
|
||||
|
||||
def getMemberConversion(self, memberInfo):
|
||||
"""
|
||||
A function that outputs the initialization of a single dictionary
|
||||
member from the given dictionary value.
|
||||
|
||||
We start with our conversionInfo, which tells us how to
|
||||
convert a JS::Value to whatever type this member is. We
|
||||
substiture the template from the conversionInfo with values
|
||||
that point to our "temp" JS::Value and our member (which is
|
||||
the C++ value we want to produce). The output is a string of
|
||||
code to do the conversion. We store this string in
|
||||
conversionReplacements["convert"].
|
||||
|
||||
Now we have three different ways we might use (or skip) this
|
||||
string of code, depending on whether the value is required,
|
||||
optional with default value, or optional without default
|
||||
value. We set up a template in the 'conversion' variable for
|
||||
exactly how to do this, then substitute into it from the
|
||||
conversionReplacements dictionary.
|
||||
"""
|
||||
member, conversionInfo = memberInfo
|
||||
replacements = {
|
||||
"val": "temp.ref()",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user