mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central to mozilla-inbound
This commit is contained in:
commit
7310f91fa1
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e5d666d6f62480ced56c6d9352f5e12befb5a862"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="824a61cccec4c69be9a86ad5cb629a1f61fa142f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e5d666d6f62480ced56c6d9352f5e12befb5a862"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="824a61cccec4c69be9a86ad5cb629a1f61fa142f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e5d666d6f62480ced56c6d9352f5e12befb5a862"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="824a61cccec4c69be9a86ad5cb629a1f61fa142f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0870da2b5a71b6f48be8222e3f056498fea66e10"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e5d666d6f62480ced56c6d9352f5e12befb5a862"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="824a61cccec4c69be9a86ad5cb629a1f61fa142f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e5d666d6f62480ced56c6d9352f5e12befb5a862"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="824a61cccec4c69be9a86ad5cb629a1f61fa142f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e5d666d6f62480ced56c6d9352f5e12befb5a862"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="824a61cccec4c69be9a86ad5cb629a1f61fa142f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e5d666d6f62480ced56c6d9352f5e12befb5a862"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="824a61cccec4c69be9a86ad5cb629a1f61fa142f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0870da2b5a71b6f48be8222e3f056498fea66e10"/>
|
||||
@ -122,7 +122,7 @@
|
||||
<!-- Flame specific things -->
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="e8a318f7690092e639ba88891606f4183e846d3f"/>
|
||||
<project name="device/qcom/common" path="device/qcom/common" revision="878804e0becfe5635bb8ccbf2671333d546c6fb6"/>
|
||||
<project name="device-flame" path="device/t2m/flame" remote="b2g" revision="b04c1a7d96f01a743f23a544870cd5be2c8d172e"/>
|
||||
<project name="device-flame" path="device/t2m/flame" remote="b2g" revision="47f828c8a9a6673bbe05ac8868634d04a1798305"/>
|
||||
<project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="49417cfc622074daa3c76b345a199f6731375800"/>
|
||||
<project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="6f00133ac0f47e90027bd7e263a16b405bfac503"/>
|
||||
<project name="platform_bootable_recovery" path="bootable/recovery" remote="b2g" revision="e81502511cda303c803e63f049574634bc96f9f2"/>
|
||||
|
@ -4,6 +4,6 @@
|
||||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "8879d60a0cc3d69720c7335370d29d5a44523d0c",
|
||||
"revision": "487b237115841c62d1ca385fce8261dedeec2cda",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e5d666d6f62480ced56c6d9352f5e12befb5a862"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="824a61cccec4c69be9a86ad5cb629a1f61fa142f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e5d666d6f62480ced56c6d9352f5e12befb5a862"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="824a61cccec4c69be9a86ad5cb629a1f61fa142f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e5d666d6f62480ced56c6d9352f5e12befb5a862"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="824a61cccec4c69be9a86ad5cb629a1f61fa142f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0870da2b5a71b6f48be8222e3f056498fea66e10"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e5d666d6f62480ced56c6d9352f5e12befb5a862"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="824a61cccec4c69be9a86ad5cb629a1f61fa142f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -183,7 +183,7 @@ pref("app.update.metro.enabled", true);
|
||||
pref("app.update.silent", false);
|
||||
|
||||
// If set to true, the hamburger button will show badges for update events.
|
||||
#ifdef MOZ_DEV_EDITION
|
||||
#ifndef RELEASE_BUILD
|
||||
pref("app.update.badge", true);
|
||||
#else
|
||||
pref("app.update.badge", false);
|
||||
|
@ -7305,9 +7305,13 @@ let gPrivateBrowsingUI = {
|
||||
|
||||
if (gURLBar &&
|
||||
!PrivateBrowsingUtils.permanentPrivateBrowsing) {
|
||||
// Disable switch to tab autocompletion for private windows
|
||||
// (not for "Always use private browsing" mode)
|
||||
gURLBar.setAttribute("autocompletesearchparam", "");
|
||||
// Disable switch to tab autocompletion for private windows.
|
||||
// We leave it enabled for permanent private browsing mode though.
|
||||
let value = gURLBar.getAttribute("autocompletesearchparam") || "";
|
||||
if (!value.contains("disable-private-actions")) {
|
||||
gURLBar.setAttribute("autocompletesearchparam",
|
||||
value + " disable-private-actions");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1773,31 +1773,18 @@ nsContextMenu.prototype = {
|
||||
},
|
||||
|
||||
_getTelemetryPageContextInfo: function() {
|
||||
if (this.isContentSelected) {
|
||||
return "selection";
|
||||
let rv = [];
|
||||
for (let k of ["isContentSelected", "onLink", "onImage", "onCanvas", "onVideo", "onAudio",
|
||||
"onTextInput", "onSocial"]) {
|
||||
if (this[k]) {
|
||||
rv.push(k.replace(/^(?:is|on)(.)/, (match, firstLetter) => firstLetter.toLowerCase()));
|
||||
}
|
||||
if (this.onLink) {
|
||||
if (this.onImage || this.onCanvas) {
|
||||
return "image-link";
|
||||
}
|
||||
return "link";
|
||||
if (!rv.length) {
|
||||
rv.push('other');
|
||||
}
|
||||
if (this.onImage) {
|
||||
return "image"
|
||||
}
|
||||
if (this.onCanvas) {
|
||||
return "canvas";
|
||||
}
|
||||
if (this.onVideo || this.onAudio) {
|
||||
return "media";
|
||||
}
|
||||
if (this.onTextInput) {
|
||||
return "input";
|
||||
}
|
||||
if (this.onSocial) {
|
||||
return "social";
|
||||
}
|
||||
return "other";
|
||||
|
||||
return JSON.stringify(rv);
|
||||
},
|
||||
|
||||
_checkTelemetryForMenu: function(aXulMenu) {
|
||||
|
@ -276,8 +276,6 @@ skip-if = e10s
|
||||
[browser_bug767836_perwindowpb.js]
|
||||
[browser_bug771331.js]
|
||||
[browser_bug783614.js]
|
||||
[browser_bug816527.js]
|
||||
skip-if = e10s # Bug 1093373 - relies on browser.sessionHistory
|
||||
[browser_bug817947.js]
|
||||
[browser_bug822367.js]
|
||||
[browser_bug832435.js]
|
||||
@ -412,8 +410,10 @@ support-files =
|
||||
[browser_subframe_favicons_not_used.js]
|
||||
[browser_tabDrop.js]
|
||||
skip-if = buildapp == 'mulet' || e10s
|
||||
[browser_tabMatchesInAwesomebar_perwindowpb.js]
|
||||
[browser_tabMatchesInAwesomebar.js]
|
||||
skip-if = e10s # Bug 1093206 - need to re-enable tests relying on swapFrameLoaders et al for e10s (test calls gBrowser.swapBrowsersAndCloseOther)
|
||||
[browser_tabMatchesInAwesomebar_perwindowpb.js]
|
||||
skip-if = e10s # Bug 1093373 - relies on browser.sessionHistory
|
||||
[browser_tab_drag_drop_perwindow.js]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[browser_tab_dragdrop.js]
|
||||
|
@ -1,122 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let testURL = "http://example.org/browser/browser/base/content/test/general/dummy_page.html";
|
||||
|
||||
function testOnWindow(aOptions, aCallback) {
|
||||
whenNewWindowLoaded(aOptions, function(aWin) {
|
||||
// execute should only be called when need, like when you are opening
|
||||
// web pages on the test. If calling executeSoon() is not necesary, then
|
||||
// call whenNewWindowLoaded() instead of testOnWindow() on your test.
|
||||
executeSoon(function() aCallback(aWin));
|
||||
});
|
||||
};
|
||||
|
||||
testOnWindow({}, function(aNormalWindow) {
|
||||
testOnWindow({private: true}, function(aPrivateWindow) {
|
||||
runTest(aNormalWindow, aPrivateWindow, false, function() {
|
||||
aNormalWindow.close();
|
||||
aPrivateWindow.close();
|
||||
testOnWindow({}, function(aNormalWindow) {
|
||||
testOnWindow({private: true}, function(aPrivateWindow) {
|
||||
runTest(aPrivateWindow, aNormalWindow, false, function() {
|
||||
aNormalWindow.close();
|
||||
aPrivateWindow.close();
|
||||
testOnWindow({private: true}, function(aPrivateWindow) {
|
||||
runTest(aPrivateWindow, aPrivateWindow, false, function() {
|
||||
aPrivateWindow.close();
|
||||
testOnWindow({}, function(aNormalWindow) {
|
||||
runTest(aNormalWindow, aNormalWindow, true, function() {
|
||||
aNormalWindow.close();
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function runTest(aSourceWindow, aDestWindow, aExpectSuccess, aCallback) {
|
||||
// Open the base tab
|
||||
let baseTab = aSourceWindow.gBrowser.addTab(testURL);
|
||||
baseTab.linkedBrowser.addEventListener("load", function() {
|
||||
// Wait for the tab to be fully loaded so matching happens correctly
|
||||
if (baseTab.linkedBrowser.currentURI.spec == "about:blank")
|
||||
return;
|
||||
baseTab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
let testTab = aDestWindow.gBrowser.addTab();
|
||||
|
||||
waitForFocus(function() {
|
||||
// Select the testTab
|
||||
aDestWindow.gBrowser.selectedTab = testTab;
|
||||
|
||||
// Ensure that this tab has no history entries
|
||||
ok(testTab.linkedBrowser.sessionHistory.count < 2,
|
||||
"The test tab has 1 or less history entries");
|
||||
// Ensure that this tab is on about:blank
|
||||
is(testTab.linkedBrowser.currentURI.spec, "about:blank",
|
||||
"The test tab is on about:blank");
|
||||
// Ensure that this tab's document has no child nodes
|
||||
ok(!testTab.linkedBrowser.contentDocument.body.hasChildNodes(),
|
||||
"The test tab has no child nodes");
|
||||
ok(!testTab.hasAttribute("busy"),
|
||||
"The test tab doesn't have the busy attribute");
|
||||
|
||||
// Set the urlbar to include the moz-action
|
||||
aDestWindow.gURLBar.value = "moz-action:switchtab," + JSON.stringify({url: testURL});
|
||||
// Focus the urlbar so we can press enter
|
||||
aDestWindow.gURLBar.focus();
|
||||
|
||||
// We want to see if the switchtab action works. If it does, the
|
||||
// current tab will get closed, and that's what we detect with the
|
||||
// TabClose handler. If pressing enter triggers a load in that tab,
|
||||
// then the load handler will get called. Neither of these are
|
||||
// the desired effect here. So if the test goes successfully, it is
|
||||
// the timeout handler which gets called.
|
||||
//
|
||||
// The reason that we can't avoid the timeout here is because we are
|
||||
// trying to test something which should not happen, so we just need
|
||||
// to wait for a while and then check whether any bad things have
|
||||
// happened.
|
||||
|
||||
function onTabClose(aEvent) {
|
||||
aDestWindow.gBrowser.tabContainer.removeEventListener("TabClose", onTabClose, false);
|
||||
aDestWindow.gBrowser.removeEventListener("load", onLoad, false);
|
||||
clearTimeout(timeout);
|
||||
// Should only happen when we expect success
|
||||
ok(aExpectSuccess, "Tab closed as expected");
|
||||
aCallback();
|
||||
}
|
||||
function onLoad(aEvent) {
|
||||
aDestWindow.gBrowser.tabContainer.removeEventListener("TabClose", onTabClose, false);
|
||||
aDestWindow.gBrowser.removeEventListener("load", onLoad, false);
|
||||
clearTimeout(timeout);
|
||||
// Should only happen when we expect success
|
||||
ok(aExpectSuccess, "Tab loaded as expected");
|
||||
aCallback();
|
||||
}
|
||||
|
||||
aDestWindow.gBrowser.tabContainer.addEventListener("TabClose", onTabClose, false);
|
||||
aDestWindow.gBrowser.addEventListener("load", onLoad, false);
|
||||
let timeout = setTimeout(function() {
|
||||
aDestWindow.gBrowser.tabContainer.removeEventListener("TabClose", onTabClose, false);
|
||||
aDestWindow.gBrowser.removeEventListener("load", onLoad, false);
|
||||
aCallback();
|
||||
}, 500);
|
||||
|
||||
// Press enter!
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
}, aDestWindow);
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,249 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
* vim:set ts=2 sw=2 sts=2 et:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const TEST_URL_BASES = [
|
||||
"http://example.org/browser/browser/base/content/test/general/dummy_page.html#tabmatch",
|
||||
"http://example.org/browser/browser/base/content/test/general/moz.png#tabmatch"
|
||||
];
|
||||
|
||||
var gController = Cc["@mozilla.org/autocomplete/controller;1"].
|
||||
getService(Ci.nsIAutoCompleteController);
|
||||
|
||||
var gTabWaitCount = 0;
|
||||
var gTabCounter = 0;
|
||||
|
||||
var gTestSteps = [
|
||||
function() {
|
||||
info("Running step 1");
|
||||
for (let i = 0; i < 10; i++) {
|
||||
let tab = gBrowser.addTab();
|
||||
loadTab(tab, TEST_URL_BASES[0] + (++gTabCounter));
|
||||
}
|
||||
},
|
||||
function() {
|
||||
info("Running step 2");
|
||||
gBrowser.selectTabAtIndex(1);
|
||||
gBrowser.removeCurrentTab();
|
||||
gBrowser.selectTabAtIndex(1);
|
||||
gBrowser.removeCurrentTab();
|
||||
for (let i = 1; i < gBrowser.tabs.length; i++)
|
||||
loadTab(gBrowser.tabs[i], TEST_URL_BASES[1] + (++gTabCounter));
|
||||
},
|
||||
function() {
|
||||
info("Running step 3");
|
||||
for (let i = 1; i < gBrowser.tabs.length; i++)
|
||||
loadTab(gBrowser.tabs[i], TEST_URL_BASES[0] + gTabCounter);
|
||||
},
|
||||
function() {
|
||||
info("Running step 4 - ensure we don't register subframes as open pages");
|
||||
let tab = gBrowser.addTab();
|
||||
tab.linkedBrowser.addEventListener("load", function () {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
// Start the sub-document load.
|
||||
executeSoon(function () {
|
||||
tab.linkedBrowser.addEventListener("load", function (e) {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
}, true);
|
||||
tab.linkedBrowser.contentDocument.querySelector("iframe").src = "http://test2.example.org/";
|
||||
});
|
||||
}, true);
|
||||
tab.linkedBrowser.loadURI('data:text/html,<body><iframe src=""></iframe></body>');
|
||||
},
|
||||
function() {
|
||||
info("Running step 5 - remove tab immediately");
|
||||
let tab = gBrowser.addTab("about:logo");
|
||||
gBrowser.removeTab(tab);
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
},
|
||||
function() {
|
||||
info("Running step 6 - check swapBrowsersAndCloseOther preserves registered switch-to-tab result");
|
||||
let tabToKeep = gBrowser.addTab();
|
||||
let tab = gBrowser.addTab();
|
||||
tab.linkedBrowser.addEventListener("load", function () {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
gBrowser.swapBrowsersAndCloseOther(tabToKeep, tab);
|
||||
ensure_opentabs_match_db(function () {
|
||||
gBrowser.removeTab(tabToKeep);
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
});
|
||||
}, true);
|
||||
tab.linkedBrowser.loadURI("about:mozilla");
|
||||
},
|
||||
function() {
|
||||
info("Running step 7 - close all tabs");
|
||||
|
||||
Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand");
|
||||
|
||||
gBrowser.addTab("about:blank", {skipAnimation: true});
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
info("Removing tab: " + gBrowser.tabs[0].linkedBrowser.currentURI.spec);
|
||||
gBrowser.selectTabAtIndex(0);
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
nextStep();
|
||||
}
|
||||
|
||||
function loadTab(tab, url) {
|
||||
// Because adding visits is async, we will not be notified immediately.
|
||||
let visited = false;
|
||||
let loaded = false;
|
||||
|
||||
function maybeCheckResults() {
|
||||
if (visited && loaded && --gTabWaitCount == 0) {
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
}
|
||||
}
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function () {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
loaded = true;
|
||||
maybeCheckResults();
|
||||
}, true);
|
||||
|
||||
if (!visited) {
|
||||
Services.obs.addObserver(
|
||||
function (aSubject, aTopic, aData) {
|
||||
if (url != aSubject.QueryInterface(Ci.nsIURI).spec)
|
||||
return;
|
||||
Services.obs.removeObserver(arguments.callee, aTopic);
|
||||
visited = true;
|
||||
maybeCheckResults();
|
||||
},
|
||||
"uri-visit-saved",
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
gTabWaitCount++;
|
||||
info("Loading page: " + url);
|
||||
tab.linkedBrowser.loadURI(url);
|
||||
}
|
||||
|
||||
function waitForRestoredTab(tab) {
|
||||
gTabWaitCount++;
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function () {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
if (--gTabWaitCount == 0) {
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
||||
function nextStep() {
|
||||
if (gTestSteps.length == 0) {
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.selectTabAtIndex(1);
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
|
||||
waitForClearHistory(finish);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var stepFunc = gTestSteps.shift();
|
||||
stepFunc();
|
||||
}
|
||||
|
||||
function ensure_opentabs_match_db(aCallback) {
|
||||
var tabs = {};
|
||||
|
||||
var winEnum = Services.wm.getEnumerator("navigator:browser");
|
||||
while (winEnum.hasMoreElements()) {
|
||||
let browserWin = winEnum.getNext();
|
||||
// skip closed-but-not-destroyed windows
|
||||
if (browserWin.closed)
|
||||
continue;
|
||||
|
||||
for (let i = 0; i < browserWin.gBrowser.tabContainer.childElementCount; i++) {
|
||||
let browser = browserWin.gBrowser.getBrowserAtIndex(i);
|
||||
let url = browser.currentURI.spec;
|
||||
if (browserWin.isBlankPageURL(url))
|
||||
continue;
|
||||
if (!(url in tabs))
|
||||
tabs[url] = 1;
|
||||
else
|
||||
tabs[url]++;
|
||||
}
|
||||
}
|
||||
|
||||
checkAutocompleteResults(tabs, aCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears history invoking callback when done.
|
||||
*/
|
||||
function waitForClearHistory(aCallback) {
|
||||
const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
|
||||
aCallback();
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
|
||||
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
}
|
||||
|
||||
function checkAutocompleteResults(aExpected, aCallback)
|
||||
{
|
||||
gController.input = {
|
||||
timeout: 10,
|
||||
textValue: "",
|
||||
searches: ["history"],
|
||||
searchParam: "enable-actions",
|
||||
popupOpen: false,
|
||||
minResultsForPopup: 0,
|
||||
invalidate: function() {},
|
||||
disableAutoComplete: false,
|
||||
completeDefaultIndex: false,
|
||||
get popup() { return this; },
|
||||
onSearchBegin: function() {},
|
||||
onSearchComplete: function ()
|
||||
{
|
||||
info("Found " + gController.matchCount + " matches.");
|
||||
// Check to see the expected uris and titles match up (in any order)
|
||||
for (let i = 0; i < gController.matchCount; i++) {
|
||||
let uri = gController.getValueAt(i).replace(/^moz-action:[^,]+,/i, "");
|
||||
|
||||
info("Search for '" + uri + "' in open tabs.");
|
||||
let expected = uri in aExpected;
|
||||
ok(expected, uri + " was found in autocomplete, was " + (expected ? "" : "not ") + "expected");
|
||||
// Remove the found entry from expected results.
|
||||
delete aExpected[uri];
|
||||
}
|
||||
|
||||
// Make sure there is no reported open page that is not open.
|
||||
for (let entry in aExpected) {
|
||||
ok(false, "'" + entry + "' should be found in autocomplete");
|
||||
}
|
||||
|
||||
executeSoon(aCallback);
|
||||
},
|
||||
setSelectedIndex: function() {},
|
||||
get searchCount() { return this.searches.length; },
|
||||
getSearchAt: function(aIndex) this.searches[aIndex],
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIAutoCompleteInput,
|
||||
Ci.nsIAutoCompletePopup,
|
||||
])
|
||||
};
|
||||
|
||||
info("Searching open pages.");
|
||||
gController.startSearch(Services.prefs.getCharPref("browser.urlbar.restrict.openpage"));
|
||||
}
|
@ -1,249 +1,122 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
* vim:set ts=2 sw=2 sts=2 et:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const TEST_URL_BASES = [
|
||||
"http://example.org/browser/browser/base/content/test/general/dummy_page.html#tabmatch",
|
||||
"http://example.org/browser/browser/base/content/test/general/moz.png#tabmatch"
|
||||
];
|
||||
|
||||
var gController = Cc["@mozilla.org/autocomplete/controller;1"].
|
||||
getService(Ci.nsIAutoCompleteController);
|
||||
|
||||
var gTabWaitCount = 0;
|
||||
var gTabCounter = 0;
|
||||
|
||||
var gTestSteps = [
|
||||
function() {
|
||||
info("Running step 1");
|
||||
for (let i = 0; i < 10; i++) {
|
||||
let tab = gBrowser.addTab();
|
||||
loadTab(tab, TEST_URL_BASES[0] + (++gTabCounter));
|
||||
}
|
||||
},
|
||||
function() {
|
||||
info("Running step 2");
|
||||
gBrowser.selectTabAtIndex(1);
|
||||
gBrowser.removeCurrentTab();
|
||||
gBrowser.selectTabAtIndex(1);
|
||||
gBrowser.removeCurrentTab();
|
||||
for (let i = 1; i < gBrowser.tabs.length; i++)
|
||||
loadTab(gBrowser.tabs[i], TEST_URL_BASES[1] + (++gTabCounter));
|
||||
},
|
||||
function() {
|
||||
info("Running step 3");
|
||||
for (let i = 1; i < gBrowser.tabs.length; i++)
|
||||
loadTab(gBrowser.tabs[i], TEST_URL_BASES[0] + gTabCounter);
|
||||
},
|
||||
function() {
|
||||
info("Running step 4 - ensure we don't register subframes as open pages");
|
||||
let tab = gBrowser.addTab();
|
||||
tab.linkedBrowser.addEventListener("load", function () {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
// Start the sub-document load.
|
||||
executeSoon(function () {
|
||||
tab.linkedBrowser.addEventListener("load", function (e) {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
}, true);
|
||||
tab.linkedBrowser.contentDocument.querySelector("iframe").src = "http://test2.example.org/";
|
||||
});
|
||||
}, true);
|
||||
tab.linkedBrowser.loadURI('data:text/html,<body><iframe src=""></iframe></body>');
|
||||
},
|
||||
function() {
|
||||
info("Running step 5 - remove tab immediately");
|
||||
let tab = gBrowser.addTab("about:logo");
|
||||
gBrowser.removeTab(tab);
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
},
|
||||
function() {
|
||||
info("Running step 6 - check swapBrowsersAndCloseOther preserves registered switch-to-tab result");
|
||||
let tabToKeep = gBrowser.addTab();
|
||||
let tab = gBrowser.addTab();
|
||||
tab.linkedBrowser.addEventListener("load", function () {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
gBrowser.swapBrowsersAndCloseOther(tabToKeep, tab);
|
||||
ensure_opentabs_match_db(function () {
|
||||
gBrowser.removeTab(tabToKeep);
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
});
|
||||
}, true);
|
||||
tab.linkedBrowser.loadURI("about:mozilla");
|
||||
},
|
||||
function() {
|
||||
info("Running step 7 - close all tabs");
|
||||
|
||||
Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand");
|
||||
|
||||
gBrowser.addTab("about:blank", {skipAnimation: true});
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
info("Removing tab: " + gBrowser.tabs[0].linkedBrowser.currentURI.spec);
|
||||
gBrowser.selectTabAtIndex(0);
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
nextStep();
|
||||
}
|
||||
|
||||
function loadTab(tab, url) {
|
||||
// Because adding visits is async, we will not be notified immediately.
|
||||
let visited = false;
|
||||
let loaded = false;
|
||||
let testURL = "http://example.org/browser/browser/base/content/test/general/dummy_page.html";
|
||||
|
||||
function maybeCheckResults() {
|
||||
if (visited && loaded && --gTabWaitCount == 0) {
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
}
|
||||
}
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function () {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
loaded = true;
|
||||
maybeCheckResults();
|
||||
}, true);
|
||||
|
||||
if (!visited) {
|
||||
Services.obs.addObserver(
|
||||
function (aSubject, aTopic, aData) {
|
||||
if (url != aSubject.QueryInterface(Ci.nsIURI).spec)
|
||||
return;
|
||||
Services.obs.removeObserver(arguments.callee, aTopic);
|
||||
visited = true;
|
||||
maybeCheckResults();
|
||||
},
|
||||
"uri-visit-saved",
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
gTabWaitCount++;
|
||||
info("Loading page: " + url);
|
||||
tab.linkedBrowser.loadURI(url);
|
||||
}
|
||||
|
||||
function waitForRestoredTab(tab) {
|
||||
gTabWaitCount++;
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function () {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
if (--gTabWaitCount == 0) {
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
||||
function nextStep() {
|
||||
if (gTestSteps.length == 0) {
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.selectTabAtIndex(1);
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
|
||||
waitForClearHistory(finish);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var stepFunc = gTestSteps.shift();
|
||||
stepFunc();
|
||||
}
|
||||
|
||||
function ensure_opentabs_match_db(aCallback) {
|
||||
var tabs = {};
|
||||
|
||||
var winEnum = Services.wm.getEnumerator("navigator:browser");
|
||||
while (winEnum.hasMoreElements()) {
|
||||
let browserWin = winEnum.getNext();
|
||||
// skip closed-but-not-destroyed windows
|
||||
if (browserWin.closed)
|
||||
continue;
|
||||
|
||||
for (let i = 0; i < browserWin.gBrowser.tabContainer.childElementCount; i++) {
|
||||
let browser = browserWin.gBrowser.getBrowserAtIndex(i);
|
||||
let url = browser.currentURI.spec;
|
||||
if (browserWin.isBlankPageURL(url))
|
||||
continue;
|
||||
if (!(url in tabs))
|
||||
tabs[url] = 1;
|
||||
else
|
||||
tabs[url]++;
|
||||
}
|
||||
}
|
||||
|
||||
checkAutocompleteResults(tabs, aCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears history invoking callback when done.
|
||||
*/
|
||||
function waitForClearHistory(aCallback) {
|
||||
const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
|
||||
aCallback();
|
||||
}
|
||||
function testOnWindow(aOptions, aCallback) {
|
||||
whenNewWindowLoaded(aOptions, function(aWin) {
|
||||
// execute should only be called when need, like when you are opening
|
||||
// web pages on the test. If calling executeSoon() is not necesary, then
|
||||
// call whenNewWindowLoaded() instead of testOnWindow() on your test.
|
||||
executeSoon(function() aCallback(aWin));
|
||||
});
|
||||
};
|
||||
Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
|
||||
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
}
|
||||
testOnWindow({}, function(aNormalWindow) {
|
||||
testOnWindow({private: true}, function(aPrivateWindow) {
|
||||
runTest(aNormalWindow, aPrivateWindow, false, function() {
|
||||
aNormalWindow.close();
|
||||
aPrivateWindow.close();
|
||||
testOnWindow({}, function(aNormalWindow) {
|
||||
testOnWindow({private: true}, function(aPrivateWindow) {
|
||||
runTest(aPrivateWindow, aNormalWindow, false, function() {
|
||||
aNormalWindow.close();
|
||||
aPrivateWindow.close();
|
||||
testOnWindow({private: true}, function(aPrivateWindow) {
|
||||
runTest(aPrivateWindow, aPrivateWindow, false, function() {
|
||||
aPrivateWindow.close();
|
||||
testOnWindow({}, function(aNormalWindow) {
|
||||
runTest(aNormalWindow, aNormalWindow, true, function() {
|
||||
aNormalWindow.close();
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function checkAutocompleteResults(aExpected, aCallback)
|
||||
{
|
||||
gController.input = {
|
||||
timeout: 10,
|
||||
textValue: "",
|
||||
searches: ["history"],
|
||||
searchParam: "enable-actions",
|
||||
popupOpen: false,
|
||||
minResultsForPopup: 0,
|
||||
invalidate: function() {},
|
||||
disableAutoComplete: false,
|
||||
completeDefaultIndex: false,
|
||||
get popup() { return this; },
|
||||
onSearchBegin: function() {},
|
||||
onSearchComplete: function ()
|
||||
{
|
||||
info("Found " + gController.matchCount + " matches.");
|
||||
// Check to see the expected uris and titles match up (in any order)
|
||||
for (let i = 0; i < gController.matchCount; i++) {
|
||||
let uri = gController.getValueAt(i).replace(/^moz-action:[^,]+,/i, "");
|
||||
function runTest(aSourceWindow, aDestWindow, aExpectSwitch, aCallback) {
|
||||
// Open the base tab
|
||||
let baseTab = aSourceWindow.gBrowser.addTab(testURL);
|
||||
baseTab.linkedBrowser.addEventListener("load", function() {
|
||||
// Wait for the tab to be fully loaded so matching happens correctly
|
||||
if (baseTab.linkedBrowser.currentURI.spec == "about:blank")
|
||||
return;
|
||||
baseTab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
info("Search for '" + uri + "' in open tabs.");
|
||||
let expected = uri in aExpected;
|
||||
ok(expected, uri + " was found in autocomplete, was " + (expected ? "" : "not ") + "expected");
|
||||
// Remove the found entry from expected results.
|
||||
delete aExpected[uri];
|
||||
}
|
||||
|
||||
// Make sure there is no reported open page that is not open.
|
||||
for (let entry in aExpected) {
|
||||
ok(false, "'" + entry + "' should be found in autocomplete");
|
||||
let testTab = aDestWindow.gBrowser.addTab();
|
||||
|
||||
waitForFocus(function() {
|
||||
// Select the testTab
|
||||
aDestWindow.gBrowser.selectedTab = testTab;
|
||||
|
||||
// Ensure that this tab has no history entries
|
||||
ok(testTab.linkedBrowser.sessionHistory.count < 2,
|
||||
"The test tab has 1 or less history entries");
|
||||
// Ensure that this tab is on about:blank
|
||||
is(testTab.linkedBrowser.currentURI.spec, "about:blank",
|
||||
"The test tab is on about:blank");
|
||||
// Ensure that this tab's document has no child nodes
|
||||
ok(!testTab.linkedBrowser.contentDocument.body.hasChildNodes(),
|
||||
"The test tab has no child nodes");
|
||||
ok(!testTab.hasAttribute("busy"),
|
||||
"The test tab doesn't have the busy attribute");
|
||||
|
||||
let urlbar = aDestWindow.gURLBar;
|
||||
let controller = urlbar.controller;
|
||||
|
||||
// Focus URL bar, enter value, and start searching.
|
||||
urlbar.focus();
|
||||
urlbar.value = testURL;
|
||||
controller.startSearch(testURL);
|
||||
|
||||
// Wait for the Awesomebar popup to appear.
|
||||
promisePopupShown(aDestWindow.gURLBar.popup).then(() => {
|
||||
function searchIsComplete() {
|
||||
return controller.searchStatus ==
|
||||
Ci.nsIAutoCompleteController.STATUS_COMPLETE_MATCH;
|
||||
}
|
||||
|
||||
// Wait until the search is complete.
|
||||
waitForCondition(searchIsComplete, function () {
|
||||
if (aExpectSwitch) {
|
||||
// If we expect a tab switch then the current tab
|
||||
// will be closed and we switch to the other tab.
|
||||
let tabContainer = aDestWindow.gBrowser.tabContainer;
|
||||
tabContainer.addEventListener("TabClose", function onClose(event) {
|
||||
if (event.target == testTab) {
|
||||
tabContainer.removeEventListener("TabClose", onClose);
|
||||
executeSoon(aCallback);
|
||||
},
|
||||
setSelectedIndex: function() {},
|
||||
get searchCount() { return this.searches.length; },
|
||||
getSearchAt: function(aIndex) this.searches[aIndex],
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIAutoCompleteInput,
|
||||
Ci.nsIAutoCompletePopup,
|
||||
])
|
||||
};
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// If we don't expect a tab switch then wait for the tab to load.
|
||||
testTab.addEventListener("load", function onLoad() {
|
||||
testTab.removeEventListener("load", onLoad, true);
|
||||
executeSoon(aCallback);
|
||||
}, true);
|
||||
}
|
||||
|
||||
info("Searching open pages.");
|
||||
gController.startSearch(Services.prefs.getCharPref("browser.urlbar.restrict.openpage"));
|
||||
// Select the second match, if any.
|
||||
if (controller.matchCount > 1) {
|
||||
controller.handleKeyNavigation(KeyEvent.DOM_VK_DOWN);
|
||||
}
|
||||
|
||||
// Execute the selected action.
|
||||
controller.handleEnter(true);
|
||||
});
|
||||
});
|
||||
|
||||
}, aDestWindow);
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
|
@ -328,8 +328,8 @@ let MozLoopServiceInternal = {
|
||||
*/
|
||||
promiseRegisteredWithPushServer: function(sessionType) {
|
||||
if (!this.deferredRegistrations.has(sessionType)) {
|
||||
return Promise.reject("promiseRegisteredWithPushServer must be called while there is a " +
|
||||
"deferred in deferredRegistrations in order to prevent reentrancy");
|
||||
return Promise.reject(new Error("promiseRegisteredWithPushServer must be called while there is a " +
|
||||
"deferred in deferredRegistrations in order to prevent reentrancy"));
|
||||
}
|
||||
// Wrap push notification registration call-back in a Promise.
|
||||
function registerForNotification(channelID, onNotification) {
|
||||
@ -375,7 +375,7 @@ let MozLoopServiceInternal = {
|
||||
return Promise.all([callsRegFxA, roomsRegFxA]);
|
||||
}
|
||||
|
||||
return Promise.reject("promiseRegisteredWithPushServer: Invalid sessionType");
|
||||
return Promise.reject(new Error("promiseRegisteredWithPushServer: Invalid sessionType"));
|
||||
},
|
||||
|
||||
/**
|
||||
@ -593,7 +593,7 @@ let MozLoopServiceInternal = {
|
||||
}
|
||||
|
||||
if (!callsPushURL || !roomsPushURL) {
|
||||
return Promise.reject("Invalid sessionType or missing push URLs for registerWithLoopServer: " + sessionType);
|
||||
return Promise.reject(new Error("Invalid sessionType or missing push URLs for registerWithLoopServer: " + sessionType));
|
||||
}
|
||||
|
||||
// create a registration payload with a backwards compatible attribute (simplePushURL)
|
||||
@ -609,7 +609,7 @@ let MozLoopServiceInternal = {
|
||||
.then((response) => {
|
||||
// If this failed we got an invalid token.
|
||||
if (!this.storeSessionToken(sessionType, response.headers)) {
|
||||
return Promise.reject("session-token-wrong-size");
|
||||
return Promise.reject(new Error("session-token-wrong-size"));
|
||||
}
|
||||
|
||||
log.debug("Successfully registered with server for sessionType", sessionType);
|
||||
@ -1013,7 +1013,7 @@ this.MozLoopService = {
|
||||
|
||||
// Don't do anything if loop is not enabled.
|
||||
if (!Services.prefs.getBoolPref("loop.enabled")) {
|
||||
return Promise.reject("loop is not enabled");
|
||||
return Promise.reject(new Error("loop is not enabled"));
|
||||
}
|
||||
|
||||
if (Services.prefs.getPrefType("loop.fxa.enabled") == Services.prefs.PREF_BOOL) {
|
||||
|
@ -225,7 +225,10 @@ loop.shared.actions = (function() {
|
||||
* XXX: should move to some roomActions module - refs bug 1079284
|
||||
*/
|
||||
GetAllRoomsError: Action.define("getAllRoomsError", {
|
||||
error: Error
|
||||
// There's two types of error possible - one thrown by our code (and Error)
|
||||
// and the other is an Object about the error codes from the server as
|
||||
// returned by the Hawk request.
|
||||
error: [Error, Object]
|
||||
}),
|
||||
|
||||
/**
|
||||
|
@ -77,11 +77,6 @@ function promiseGetMozLoopAPI() {
|
||||
* This assumes that the tests are running in a generatorTest.
|
||||
*/
|
||||
function loadLoopPanel(aOverrideOptions = {}) {
|
||||
Services.prefs.setBoolPref("loop.rooms.enabled", false);
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref("loop.rooms.enabled");
|
||||
});
|
||||
|
||||
// Set prefs to ensure we don't access the network externally.
|
||||
Services.prefs.setCharPref("services.push.serverURL", aOverrideOptions.pushURL || "ws://localhost/");
|
||||
Services.prefs.setCharPref("loop.server", aOverrideOptions.loopURL || "http://localhost/");
|
||||
|
@ -20,7 +20,7 @@ add_test(function test_registration_handles_bogus_hawk_token() {
|
||||
do_throw("should not succeed with a bogus token");
|
||||
}, err => {
|
||||
|
||||
Assert.equal(err, "session-token-wrong-size", "Should cause an error to be" +
|
||||
Assert.equal(err.message, "session-token-wrong-size", "Should cause an error to be" +
|
||||
" called back if the session-token is not 64 characters long");
|
||||
|
||||
// for some reason, Assert.throw is misbehaving, so....
|
||||
|
@ -1012,7 +1012,7 @@ PropertyView.prototype = {
|
||||
{
|
||||
if (this.visible) {
|
||||
let isDark = this.tree._darkStripe = !this.tree._darkStripe;
|
||||
return isDark ? "property-view theme-bg-darker" : "property-view";
|
||||
return isDark ? "property-view row-striped" : "property-view";
|
||||
}
|
||||
return "property-view-hidden";
|
||||
},
|
||||
@ -1026,7 +1026,7 @@ PropertyView.prototype = {
|
||||
{
|
||||
if (this.visible) {
|
||||
let isDark = this.tree._darkStripe;
|
||||
return isDark ? "property-content theme-bg-darker" : "property-content";
|
||||
return isDark ? "property-content row-striped" : "property-content";
|
||||
}
|
||||
return "property-content-hidden";
|
||||
},
|
||||
|
@ -27,6 +27,10 @@ body {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.row-striped {
|
||||
background: var(--theme-body-background);
|
||||
}
|
||||
|
||||
.property-view-hidden,
|
||||
.property-content-hidden {
|
||||
display: none;
|
||||
|
@ -15,6 +15,7 @@
|
||||
--theme-toolbar-background: #343c45;
|
||||
--theme-selection-background: #1d4f73;
|
||||
--theme-selection-color: #f5f7fa;
|
||||
--theme-selection-background-semitransparent: rgba(29, 79, 115, .5);
|
||||
--theme-splitter-color: black;
|
||||
--theme-comment: #5c6773;
|
||||
|
||||
@ -50,7 +51,7 @@
|
||||
}
|
||||
|
||||
.theme-bg-darker {
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
background-color: var(--theme-selection-background-semitransparent);
|
||||
}
|
||||
|
||||
.theme-selected,
|
||||
|
@ -15,6 +15,7 @@
|
||||
--theme-toolbar-background: #f0f1f2;
|
||||
--theme-selection-background: #4c9ed9;
|
||||
--theme-selection-color: #f5f7fa;
|
||||
--theme-selection-background-semitransparent: rgba(76, 158, 217, .23);
|
||||
--theme-splitter-color: #aaaaaa;
|
||||
--theme-comment: hsl(90,2%,46%);
|
||||
|
||||
@ -50,7 +51,7 @@
|
||||
}
|
||||
|
||||
.theme-bg-darker {
|
||||
background: #EFEFEF;
|
||||
background: var(--theme-selection-background-semitransparent);
|
||||
}
|
||||
|
||||
.theme-selected,
|
||||
|
@ -199,12 +199,8 @@ a {
|
||||
border-color: #777;
|
||||
}
|
||||
|
||||
.theme-light .message:hover {
|
||||
background-color: rgba(76, 158, 217, 0.23) !important;
|
||||
}
|
||||
|
||||
.theme-dark .message:hover {
|
||||
background-color: rgba(29, 79, 115, 0.5) !important;
|
||||
.message:hover {
|
||||
background-color: var(--theme-selection-background-semitransparent) !important;
|
||||
}
|
||||
|
||||
.theme-light .message[severity=error] {
|
||||
|
@ -88,6 +88,7 @@ MACH_MODULES = [
|
||||
'tools/docs/mach_commands.py',
|
||||
'tools/mercurial/mach_commands.py',
|
||||
'tools/mach_commands.py',
|
||||
'mobile/android/mach_commands.py',
|
||||
]
|
||||
|
||||
|
||||
|
@ -305,7 +305,7 @@ MmsConnection.prototype = {
|
||||
this.hostsToRoute = [];
|
||||
this.networkInterface = null;
|
||||
|
||||
this.radioInterface.deactivateDataCallByType("mms");
|
||||
this.radioInterface.deactivateDataCallByType(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS);
|
||||
};
|
||||
|
||||
let promises =
|
||||
@ -441,7 +441,7 @@ MmsConnection.prototype = {
|
||||
|
||||
// Bug 1059110: Ensure all the initialization are done before setup data call.
|
||||
if (DEBUG) debug("acquire: buffer the MMS request and setup the MMS data call.");
|
||||
this.radioInterface.setupDataCallByType("mms");
|
||||
this.radioInterface.setupDataCallByType(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -345,7 +345,8 @@ GonkGPSGeolocationProvider::GetDataConnectionState()
|
||||
}
|
||||
|
||||
int32_t state;
|
||||
mRadioInterface->GetDataCallStateByType(NS_LITERAL_STRING("supl"), &state);
|
||||
mRadioInterface->GetDataCallStateByType(
|
||||
nsINetworkInterface::NETWORK_TYPE_MOBILE_SUPL, &state);
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -436,7 +437,7 @@ GonkGPSGeolocationProvider::RequestDataConnection()
|
||||
// We just get supl APN and make AGPS data connection state updated.
|
||||
RequestSettingValue("ril.supl.apn");
|
||||
} else {
|
||||
mRadioInterface->SetupDataCallByType(NS_LITERAL_STRING("supl"));
|
||||
mRadioInterface->SetupDataCallByType(nsINetworkInterface::NETWORK_TYPE_MOBILE_SUPL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,7 +450,7 @@ GonkGPSGeolocationProvider::ReleaseDataConnection()
|
||||
return;
|
||||
}
|
||||
|
||||
mRadioInterface->DeactivateDataCallByType(NS_LITERAL_STRING("supl"));
|
||||
mRadioInterface->DeactivateDataCallByType(nsINetworkInterface::NETWORK_TYPE_MOBILE_SUPL);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -888,7 +888,7 @@ NetworkManager.prototype = {
|
||||
let data = connection && connection.data;
|
||||
if (data && data.state === "registered") {
|
||||
this.dunRetryTimes = 0;
|
||||
ril.setupDataCallByType("dun");
|
||||
ril.setupDataCallByType(Ci.nsINetworkInterface.NETWORK_TYPE_DUN);
|
||||
this.dunConnectTimer.cancel();
|
||||
this.dunConnectTimer.
|
||||
initWithCallback(this.onDunConnectTimerTimeout.bind(this),
|
||||
@ -931,7 +931,7 @@ NetworkManager.prototype = {
|
||||
|
||||
if (dun && (dun.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED)) {
|
||||
this.mRil.getRadioInterface(this._dataDefaultServiceId)
|
||||
.deactivateDataCallByType("dun");
|
||||
.deactivateDataCallByType(Ci.nsINetworkInterface.NETWORK_TYPE_DUN);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -89,6 +89,14 @@ const HW_DEFAULT_CLIENT_ID = 0;
|
||||
|
||||
const INT32_MAX = 2147483647;
|
||||
|
||||
const NETWORK_TYPE_UNKNOWN = Ci.nsINetworkInterface.NETWORK_TYPE_UNKNOWN;
|
||||
const NETWORK_TYPE_WIFI = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
|
||||
const NETWORK_TYPE_MOBILE = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE;
|
||||
const NETWORK_TYPE_MOBILE_MMS = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS;
|
||||
const NETWORK_TYPE_MOBILE_SUPL = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL;
|
||||
const NETWORK_TYPE_MOBILE_IMS = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS;
|
||||
const NETWORK_TYPE_MOBILE_DUN = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN;
|
||||
|
||||
const RIL_IPC_ICCMANAGER_MSG_NAMES = [
|
||||
"RIL:GetRilContext",
|
||||
"RIL:SendStkResponse",
|
||||
@ -1008,17 +1016,17 @@ DataConnectionHandler.prototype = {
|
||||
_convertApnType: function(apnType) {
|
||||
switch(apnType) {
|
||||
case "default":
|
||||
return Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE;
|
||||
return NETWORK_TYPE_MOBILE;
|
||||
case "mms":
|
||||
return Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS;
|
||||
return NETWORK_TYPE_MOBILE_MMS;
|
||||
case "supl":
|
||||
return Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL;
|
||||
return NETWORK_TYPE_MOBILE_SUPL;
|
||||
case "ims":
|
||||
return Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS;
|
||||
return NETWORK_TYPE_MOBILE_IMS;
|
||||
case "dun":
|
||||
return Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN;
|
||||
return NETWORK_TYPE_MOBILE_DUN;
|
||||
default:
|
||||
return Ci.nsINetworkInterface.NETWORK_TYPE_UNKNOWN;
|
||||
return NETWORK_TYPE_UNKNOWN;
|
||||
}
|
||||
},
|
||||
|
||||
@ -1094,7 +1102,7 @@ DataConnectionHandler.prototype = {
|
||||
for (let i = 0; i < inputApnSetting.types.length; i++) {
|
||||
let apnType = inputApnSetting.types[i];
|
||||
let networkType = this._convertApnType(apnType);
|
||||
if (networkType === Ci.nsINetworkInterface.NETWORK_TYPE_UNKNOWN) {
|
||||
if (networkType === NETWORK_TYPE_UNKNOWN) {
|
||||
if (DEBUG) this.debug("Invalid apn type: " + apnType);
|
||||
continue;
|
||||
}
|
||||
@ -1121,7 +1129,7 @@ DataConnectionHandler.prototype = {
|
||||
inputApnSetting,
|
||||
dataCall);
|
||||
gNetworkManager.registerNetworkInterface(networkInterface);
|
||||
this.dataNetworkInterfaces.set(apnType, networkInterface);
|
||||
this.dataNetworkInterfaces.set(networkType, networkInterface);
|
||||
} catch (e) {
|
||||
if (DEBUG) {
|
||||
this.debug("Error setting up RILNetworkInterface for type " +
|
||||
@ -1174,7 +1182,7 @@ DataConnectionHandler.prototype = {
|
||||
},
|
||||
|
||||
updateRILNetworkInterface: function() {
|
||||
let networkInterface = this.dataNetworkInterfaces.get("default");
|
||||
let networkInterface = this.dataNetworkInterfaces.get(NETWORK_TYPE_MOBILE);
|
||||
if (!networkInterface) {
|
||||
if (DEBUG) {
|
||||
this.debug("No network interface for default data.");
|
||||
@ -1223,7 +1231,7 @@ DataConnectionHandler.prototype = {
|
||||
}
|
||||
let wifi_active = false;
|
||||
if (gNetworkManager.active &&
|
||||
gNetworkManager.active.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
|
||||
gNetworkManager.active.type == NETWORK_TYPE_WIFI) {
|
||||
wifi_active = true;
|
||||
}
|
||||
|
||||
@ -1283,22 +1291,45 @@ DataConnectionHandler.prototype = {
|
||||
networkInterface.connect();
|
||||
},
|
||||
|
||||
getDataCallStateByType: function(apnType) {
|
||||
let networkInterface = this.dataNetworkInterfaces.get(apnType);
|
||||
_isMobileNetworkType: function(networkType) {
|
||||
if (networkType === NETWORK_TYPE_MOBILE ||
|
||||
networkType === NETWORK_TYPE_MOBILE_MMS ||
|
||||
networkType === NETWORK_TYPE_MOBILE_SUPL ||
|
||||
networkType === NETWORK_TYPE_MOBILE_IMS ||
|
||||
networkType === NETWORK_TYPE_MOBILE_DUN) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
getDataCallStateByType: function(networkType) {
|
||||
if (!this._isMobileNetworkType(networkType)) {
|
||||
if (DEBUG) this.debug(networkType + " is not a mobile network type!");
|
||||
throw Cr.NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
let networkInterface = this.dataNetworkInterfaces.get(networkType);
|
||||
if (!networkInterface) {
|
||||
return RIL.GECKO_NETWORK_STATE_UNKNOWN;
|
||||
}
|
||||
return networkInterface.state;
|
||||
},
|
||||
|
||||
setupDataCallByType: function(apnType) {
|
||||
setupDataCallByType: function(networkType) {
|
||||
if (DEBUG) {
|
||||
this.debug("setupDataCallByType: " + apnType);
|
||||
this.debug("setupDataCallByType: " + networkType);
|
||||
}
|
||||
let networkInterface = this.dataNetworkInterfaces.get(apnType);
|
||||
|
||||
if (!this._isMobileNetworkType(networkType)) {
|
||||
if (DEBUG) this.debug(networkType + " is not a mobile network type!");
|
||||
throw Cr.NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
let networkInterface = this.dataNetworkInterfaces.get(networkType);
|
||||
if (!networkInterface) {
|
||||
if (DEBUG) {
|
||||
this.debug("No network interface for type: " + apnType);
|
||||
this.debug("No network interface for type: " + networkType);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1306,14 +1337,20 @@ DataConnectionHandler.prototype = {
|
||||
networkInterface.connect();
|
||||
},
|
||||
|
||||
deactivateDataCallByType: function(apnType) {
|
||||
deactivateDataCallByType: function(networkType) {
|
||||
if (DEBUG) {
|
||||
this.debug("deactivateDataCallByType: " + apnType);
|
||||
this.debug("deactivateDataCallByType: " + networkType);
|
||||
}
|
||||
let networkInterface = this.dataNetworkInterfaces.get(apnType);
|
||||
|
||||
if (!this._isMobileNetworkType(networkType)) {
|
||||
if (DEBUG) this.debug(networkType + " is not a mobile network type!");
|
||||
throw Cr.NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
let networkInterface = this.dataNetworkInterfaces.get(networkType);
|
||||
if (!networkInterface) {
|
||||
if (DEBUG) {
|
||||
this.debug("No network interface for type: " + apnType);
|
||||
this.debug("No network interface for type: " + networkType);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1346,7 +1383,7 @@ DataConnectionHandler.prototype = {
|
||||
*/
|
||||
handleDataCallError: function(message) {
|
||||
// Notify data call error only for data APN
|
||||
let networkInterface = this.dataNetworkInterfaces.get("default");
|
||||
let networkInterface = this.dataNetworkInterfaces.get(NETWORK_TYPE_MOBILE);
|
||||
if (networkInterface && networkInterface.enabled) {
|
||||
let dataCall = networkInterface.dataCall;
|
||||
// If there is a cid, compare cid; otherwise it is probably an error on
|
||||
@ -2893,8 +2930,8 @@ RadioInterface.prototype = {
|
||||
}
|
||||
|
||||
// SNTP can only update when we have mobile or Wifi connections.
|
||||
if (network.type != Ci.nsINetworkInterface.NETWORK_TYPE_WIFI &&
|
||||
network.type != Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
|
||||
if (network.type != NETWORK_TYPE_WIFI &&
|
||||
network.type != NETWORK_TYPE_MOBILE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3721,22 +3758,22 @@ RadioInterface.prototype = {
|
||||
|
||||
// TODO: Bug 928861 - B2G NetworkManager: Provide a more generic function
|
||||
// for connecting
|
||||
setupDataCallByType: function(apntype) {
|
||||
setupDataCallByType: function(networkType) {
|
||||
let connHandler = gDataConnectionManager.getConnectionHandler(this.clientId);
|
||||
connHandler.setupDataCallByType(apntype);
|
||||
connHandler.setupDataCallByType(networkType);
|
||||
},
|
||||
|
||||
// TODO: Bug 928861 - B2G NetworkManager: Provide a more generic function
|
||||
// for connecting
|
||||
deactivateDataCallByType: function(apntype) {
|
||||
deactivateDataCallByType: function(networkType) {
|
||||
let connHandler = gDataConnectionManager.getConnectionHandler(this.clientId);
|
||||
connHandler.deactivateDataCallByType(apntype);
|
||||
connHandler.deactivateDataCallByType(networkType);
|
||||
},
|
||||
|
||||
// TODO: Bug 904514 - [meta] NetworkManager enhancement
|
||||
getDataCallStateByType: function(apntype) {
|
||||
getDataCallStateByType: function(networkType) {
|
||||
let connHandler = gDataConnectionManager.getConnectionHandler(this.clientId);
|
||||
return connHandler.getDataCallStateByType(apntype);
|
||||
return connHandler.getDataCallStateByType(networkType);
|
||||
},
|
||||
|
||||
sendWorkerMessage: function(rilMessageType, message, callback) {
|
||||
@ -4271,7 +4308,7 @@ RILNetworkInterface.prototype = {
|
||||
},
|
||||
|
||||
get mmsc() {
|
||||
if (this.type != Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS) {
|
||||
if (this.type != NETWORK_TYPE_MOBILE_MMS) {
|
||||
if (DEBUG) this.debug("Error! Only MMS network can get MMSC.");
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
@ -4289,7 +4326,7 @@ RILNetworkInterface.prototype = {
|
||||
},
|
||||
|
||||
get mmsProxy() {
|
||||
if (this.type != Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS) {
|
||||
if (this.type != NETWORK_TYPE_MOBILE_MMS) {
|
||||
if (DEBUG) this.debug("Error! Only MMS network can get MMS proxy.");
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
@ -4307,7 +4344,7 @@ RILNetworkInterface.prototype = {
|
||||
},
|
||||
|
||||
get mmsPort() {
|
||||
if (this.type != Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS) {
|
||||
if (this.type != NETWORK_TYPE_MOBILE_MMS) {
|
||||
if (DEBUG) this.debug("Error! Only MMS network can get MMS port.");
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
@ -40,17 +40,21 @@ interface nsIRilSendWorkerMessageCallback : nsISupports
|
||||
boolean handleResponse(in jsval response);
|
||||
};
|
||||
|
||||
[scriptable, uuid(622e8809-1a89-45f7-9b35-7e49b5aaa69f)]
|
||||
[scriptable, uuid(dc874da3-5f74-49d4-8e1c-a58ed9a1c0ef)]
|
||||
interface nsIRadioInterface : nsISupports
|
||||
{
|
||||
readonly attribute nsIRilContext rilContext;
|
||||
|
||||
/**
|
||||
* PDP APIs
|
||||
*
|
||||
* @param networkType
|
||||
* Mobile network type, that is, nsINetworkInterface.NETWORK_TYPE_MOBILE
|
||||
* or one of the nsINetworkInterface.NETWORK_TYPE_MOBILE_* values.
|
||||
*/
|
||||
void setupDataCallByType(in DOMString apntype);
|
||||
void deactivateDataCallByType(in DOMString apntype);
|
||||
long getDataCallStateByType(in DOMString apntype);
|
||||
void setupDataCallByType(in long networkType);
|
||||
void deactivateDataCallByType(in long networkType);
|
||||
long getDataCallStateByType(in long networkType);
|
||||
|
||||
void updateRILNetworkInterface();
|
||||
|
||||
|
@ -9,6 +9,20 @@ const SETTINGS_KEY_DATA_APN_SETTINGS = "ril.data.apnSettings";
|
||||
const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
|
||||
const TOPIC_NETWORK_ACTIVE_CHANGED = "network-active-changed";
|
||||
|
||||
const NETWORK_TYPE_MOBILE = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE;
|
||||
const NETWORK_TYPE_MOBILE_MMS = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS;
|
||||
const NETWORK_TYPE_MOBILE_SUPL = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL;
|
||||
const NETWORK_TYPE_MOBILE_IMS = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS;
|
||||
const NETWORK_TYPE_MOBILE_DUN = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN;
|
||||
|
||||
const networkTypes = [
|
||||
NETWORK_TYPE_MOBILE,
|
||||
NETWORK_TYPE_MOBILE_MMS,
|
||||
NETWORK_TYPE_MOBILE_SUPL,
|
||||
NETWORK_TYPE_MOBILE_IMS,
|
||||
NETWORK_TYPE_MOBILE_DUN
|
||||
];
|
||||
|
||||
let Promise = Cu.import("resource://gre/modules/Promise.jsm").Promise;
|
||||
|
||||
let ril = Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer);
|
||||
@ -107,14 +121,6 @@ function waitForObserverEvent(aTopic) {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
let mobileTypeMapping = {
|
||||
"default": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE,
|
||||
"mms": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS,
|
||||
"supl": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL,
|
||||
"ims": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS,
|
||||
"dun": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the default data connection enabling state, wait for
|
||||
* "network-connection-state-changed" event and verify state.
|
||||
@ -132,8 +138,8 @@ function setDataEnabledAndWait(aEnabled) {
|
||||
.then(function(aSubject) {
|
||||
ok(aSubject instanceof Ci.nsIRilNetworkInterface,
|
||||
"subject should be an instance of nsIRILNetworkInterface");
|
||||
is(aSubject.type, Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE,
|
||||
"subject.type should be " + Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE);
|
||||
is(aSubject.type, NETWORK_TYPE_MOBILE,
|
||||
"subject.type should be " + NETWORK_TYPE_MOBILE);
|
||||
is(aSubject.state,
|
||||
aEnabled ? Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED
|
||||
: Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED,
|
||||
@ -150,26 +156,25 @@ function setDataEnabledAndWait(aEnabled) {
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
*
|
||||
* @param aType
|
||||
* The string of the type of data connection to setup.
|
||||
* @param aNetworkType
|
||||
* The mobile network type to setup.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function setupDataCallAndWait(aType) {
|
||||
log("setupDataCallAndWait: " + aType);
|
||||
function setupDataCallAndWait(aNetworkType) {
|
||||
log("setupDataCallAndWait: " + aNetworkType);
|
||||
|
||||
let promises = [];
|
||||
promises.push(waitForObserverEvent(TOPIC_CONNECTION_STATE_CHANGED)
|
||||
.then(function(aSubject) {
|
||||
let networkType = mobileTypeMapping[aType];
|
||||
ok(aSubject instanceof Ci.nsIRilNetworkInterface,
|
||||
"subject should be an instance of nsIRILNetworkInterface");
|
||||
is(aSubject.type, networkType,
|
||||
"subject.type should be " + networkType);
|
||||
is(aSubject.type, aNetworkType,
|
||||
"subject.type should be " + aNetworkType);
|
||||
is(aSubject.state, Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED,
|
||||
"subject.state should be CONNECTED");
|
||||
}));
|
||||
promises.push(radioInterface.setupDataCallByType(aType));
|
||||
promises.push(radioInterface.setupDataCallByType(aNetworkType));
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
@ -180,26 +185,25 @@ function setupDataCallAndWait(aType) {
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
*
|
||||
* @param aType
|
||||
* The string of the type of data connection to deactivate.
|
||||
* @param aNetworkType
|
||||
* The mobile network type to deactivate.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function deactivateDataCallAndWait(aType) {
|
||||
log("deactivateDataCallAndWait: " + aType);
|
||||
function deactivateDataCallAndWait(aNetworkType) {
|
||||
log("deactivateDataCallAndWait: " + aNetworkType);
|
||||
|
||||
let promises = [];
|
||||
promises.push(waitForObserverEvent(TOPIC_CONNECTION_STATE_CHANGED)
|
||||
.then(function(aSubject) {
|
||||
let networkType = mobileTypeMapping[aType];
|
||||
ok(aSubject instanceof Ci.nsIRilNetworkInterface,
|
||||
"subject should be an instance of nsIRILNetworkInterface");
|
||||
is(aSubject.type, networkType,
|
||||
"subject.type should be " + networkType);
|
||||
is(aSubject.type, aNetworkType,
|
||||
"subject.type should be " + aNetworkType);
|
||||
is(aSubject.state, Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED,
|
||||
"subject.state should be DISCONNECTED");
|
||||
}));
|
||||
promises.push(radioInterface.deactivateDataCallByType(aType));
|
||||
promises.push(radioInterface.deactivateDataCallByType(aNetworkType));
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
@ -53,10 +53,10 @@ function testNonDefaultDataConnection() {
|
||||
currentApn = value;
|
||||
})
|
||||
.then(setEmulatorAPN)
|
||||
.then(() => doTestNonDefaultDataConnection("mms"))
|
||||
.then(() => doTestNonDefaultDataConnection("supl"))
|
||||
.then(() => doTestNonDefaultDataConnection("ims"))
|
||||
.then(() => doTestNonDefaultDataConnection("dun"))
|
||||
.then(() => doTestNonDefaultDataConnection(NETWORK_TYPE_MOBILE_MMS))
|
||||
.then(() => doTestNonDefaultDataConnection(NETWORK_TYPE_MOBILE_SUPL))
|
||||
.then(() => doTestNonDefaultDataConnection(NETWORK_TYPE_MOBILE_IMS))
|
||||
.then(() => doTestNonDefaultDataConnection(NETWORK_TYPE_MOBILE_DUN))
|
||||
// Restore APN settings
|
||||
.then(() => setSettings(SETTINGS_KEY_DATA_APN_SETTINGS, currentApn));
|
||||
}
|
||||
|
@ -44,10 +44,9 @@ function testSetupConcurrentDataCalls() {
|
||||
log("= testSetupConcurrentDataCalls =");
|
||||
|
||||
let promise = Promise.resolve();
|
||||
let types = Object.keys(mobileTypeMapping);
|
||||
// Skip default mobile type.
|
||||
for (let i = 1; i < MAX_DATA_CONTEXTS; i++) {
|
||||
let type = types[i];
|
||||
let type = networkTypes[i];
|
||||
promise = promise.then(() => setupDataCallAndWait(type));
|
||||
}
|
||||
return promise;
|
||||
@ -57,10 +56,9 @@ function testDeactivateConcurrentDataCalls() {
|
||||
log("= testDeactivateConcurrentDataCalls =");
|
||||
|
||||
let promise = Promise.resolve();
|
||||
let types = Object.keys(mobileTypeMapping);
|
||||
// Skip default mobile type.
|
||||
for (let i = 1; i < MAX_DATA_CONTEXTS; i++) {
|
||||
let type = types[i];
|
||||
let type = networkTypes[i];
|
||||
promise = promise.then(() => deactivateDataCallAndWait(type));
|
||||
}
|
||||
return promise;
|
||||
|
@ -33,7 +33,7 @@ function testActiveNetworkChangedBySwitchingDataCall(aDataCallEnabled) {
|
||||
"subject should be an instance of nsINetworkInterface");
|
||||
ok(subject instanceof Ci.nsIRilNetworkInterface,
|
||||
"subject should be an instance of nsIRILNetworkInterface");
|
||||
is(subject.type, Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE,
|
||||
is(subject.type, NETWORK_TYPE_MOBILE,
|
||||
"subject.type should be NETWORK_TYPE_MOBILE");
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,13 @@ public:
|
||||
virtual int64_t getmtime(const String16& name) {return 0;}
|
||||
virtual int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey, int32_t destUid) {return 0;}
|
||||
virtual int32_t clear_uid(int64_t uid) {return 0;}
|
||||
#if ANDROID_VERSION == 18
|
||||
#if ANDROID_VERSION >= 21
|
||||
virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize, int32_t flags, Vector<sp<KeystoreArg> >* args) {return 0;}
|
||||
virtual int32_t is_hardware_backed(const String16& keyType) {return 0;}
|
||||
virtual int32_t reset_uid(int32_t uid) {return 0;}
|
||||
virtual int32_t sync_uid(int32_t sourceUid, int32_t targetUid) {return 0;}
|
||||
virtual int32_t password_uid(const String16& password, int32_t uid) {return 0;}
|
||||
#elif ANDROID_VERSION == 18
|
||||
virtual int32_t generate(const String16& name, int uid, int32_t flags) {return 0;}
|
||||
virtual int32_t is_hardware_backed() {return 0;}
|
||||
#else
|
||||
@ -156,7 +162,13 @@ public:
|
||||
int64_t getmtime(const String16& name) {return ::UNDEFINED_ACTION;}
|
||||
int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey, int32_t destUid) {return ::UNDEFINED_ACTION;}
|
||||
int32_t clear_uid(int64_t uid) {return ::UNDEFINED_ACTION;}
|
||||
#if ANDROID_VERSION == 18
|
||||
#if ANDROID_VERSION >= 21
|
||||
virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize, int32_t flags, Vector<sp<KeystoreArg> >* args) {return ::UNDEFINED_ACTION;}
|
||||
virtual int32_t is_hardware_backed(const String16& keyType) {return ::UNDEFINED_ACTION;}
|
||||
virtual int32_t reset_uid(int32_t uid) {return ::UNDEFINED_ACTION;;}
|
||||
virtual int32_t sync_uid(int32_t sourceUid, int32_t targetUid) {return ::UNDEFINED_ACTION;}
|
||||
virtual int32_t password_uid(const String16& password, int32_t uid) {return ::UNDEFINED_ACTION;}
|
||||
#elif ANDROID_VERSION == 18
|
||||
virtual int32_t generate(const String16& name, int uid, int32_t flags) {return ::UNDEFINED_ACTION;}
|
||||
virtual int32_t is_hardware_backed() {return ::UNDEFINED_ACTION;}
|
||||
#else
|
||||
|
@ -10,8 +10,7 @@ Instructions
|
||||
.. code-block:: shell
|
||||
|
||||
./mach build && ./mach package
|
||||
cd $OBJDIR/mobile/android
|
||||
./gradlew build
|
||||
./mach gradle build
|
||||
|
||||
The debug APK will be at
|
||||
``$OBJDIR/mobile/android/gradle/app/build/outputs/apk/app-debug.apk``.
|
||||
|
@ -62,6 +62,7 @@
|
||||
android:id="@+id/tabs"
|
||||
style="@style/UrlBar.ImageButton.NewTablet"
|
||||
android:layout_toLeftOf="@id/menu"
|
||||
android:layout_alignWithParentIfMissing="true"
|
||||
android:background="@drawable/new_tablet_action_bar_button"/>
|
||||
|
||||
<!-- In a 56x60dp space, centering 24dp image will leave 16x18dp. -->
|
||||
@ -81,7 +82,6 @@
|
||||
android:id="@+id/menu"
|
||||
style="@style/UrlBar.ImageButton.NewTablet"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="6dp"
|
||||
android:contentDescription="@string/menu"
|
||||
android:background="@drawable/new_tablet_action_bar_button"
|
||||
android:visibility="gone"/>
|
||||
|
@ -33,6 +33,7 @@
|
||||
<dimen name="new_tablet_site_security_padding_horizontal">8dp</dimen>
|
||||
<dimen name="new_tablet_site_security_right_margin">1dp</dimen>
|
||||
<dimen name="new_tablet_browser_toolbar_height">60dp</dimen>
|
||||
<dimen name="new_tablet_browser_toolbar_menu_right_margin">6dp</dimen>
|
||||
<dimen name="new_tablet_browser_toolbar_menu_item_width">56dp</dimen>
|
||||
<!-- Padding combines with an 18dp image to form the menu item width and height. -->
|
||||
<dimen name="new_tablet_browser_toolbar_menu_item_padding_horizontal">19dp</dimen>
|
||||
|
@ -10,7 +10,7 @@ import org.mozilla.gecko.animation.PropertyAnimator;
|
||||
import org.mozilla.gecko.animation.ViewHelper;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.content.res.Resources;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
/**
|
||||
@ -51,6 +51,16 @@ class BrowserToolbarNewTablet extends BrowserToolbarTabletBase {
|
||||
setButtonEnabled(forwardButton, true);
|
||||
|
||||
updateForwardButtonState(ForwardButtonState.HIDDEN);
|
||||
|
||||
setRightMargin();
|
||||
}
|
||||
|
||||
private void setRightMargin() {
|
||||
// TODO: Remove this hack in favor of resources when old tablet is removed.
|
||||
final Resources res = getContext().getResources();
|
||||
final int rightMargin =
|
||||
res.getDimensionPixelOffset(R.dimen.new_tablet_browser_toolbar_menu_right_margin);
|
||||
setPadding(getPaddingLeft(), getPaddingTop(), rightMargin, getPaddingBottom());
|
||||
}
|
||||
|
||||
private void updateForwardButtonState(final ForwardButtonState state) {
|
||||
|
36
mobile/android/mach_commands.py
Normal file
36
mobile/android/mach_commands.py
Normal file
@ -0,0 +1,36 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import mozpack.path as mozpath
|
||||
|
||||
from mozbuild.base import (
|
||||
MachCommandBase,
|
||||
MachCommandConditions as conditions,
|
||||
)
|
||||
|
||||
from mach.decorators import (
|
||||
CommandArgument,
|
||||
CommandProvider,
|
||||
Command,
|
||||
)
|
||||
|
||||
|
||||
@CommandProvider
|
||||
class MachCommands(MachCommandBase):
|
||||
@Command('gradle', category='devenv',
|
||||
description='Run gradle.',
|
||||
conditions=[conditions.is_android])
|
||||
@CommandArgument('args', nargs=argparse.REMAINDER)
|
||||
def gradle(self, args):
|
||||
# Avoid logging the command
|
||||
self.log_manager.terminal_handler.setLevel(logging.CRITICAL)
|
||||
|
||||
return self.run_process(['./gradlew'] + args,
|
||||
pass_thru=True, # Allow user to run gradle interactively.
|
||||
ensure_exit_code=False, # Don't throw on non-zero exit code.
|
||||
cwd=mozpath.join(self.topobjdir, 'mobile', 'android', 'gradle'))
|
@ -80,6 +80,8 @@ function skipTests(tests, startTestPattern, endTestPattern) {
|
||||
var test_path;
|
||||
if ((tests[i] instanceof Object) && ('test' in tests[i])) {
|
||||
test_path = tests[i]['test']['url'];
|
||||
} else if ((tests[i] instanceof Object) && ('url' in tests[i])) {
|
||||
test_path = tests[i]['url'];
|
||||
} else {
|
||||
test_path = tests[i];
|
||||
}
|
||||
|
@ -384,7 +384,7 @@ let EventTargetParent = {
|
||||
// Check if |target| is somewhere on the patch from the
|
||||
// <tabbrowser> up to the root element.
|
||||
let window = target.ownerDocument.defaultView;
|
||||
if (target.contains(window.gBrowser)) {
|
||||
if (window && target.contains(window.gBrowser)) {
|
||||
return window;
|
||||
}
|
||||
}
|
||||
|
@ -568,7 +568,10 @@ function Search(searchString, searchParam, autocompleteListener,
|
||||
// Set the default behavior for this search.
|
||||
this._behavior = this._searchString ? Prefs.defaultBehavior
|
||||
: Prefs.emptySearchDefaultBehavior;
|
||||
this._enableActions = searchParam.split(" ").indexOf("enable-actions") != -1;
|
||||
|
||||
let params = new Set(searchParam.split(" "));
|
||||
this._enableActions = params.has("enable-actions");
|
||||
this._disablePrivateActions = params.has("disable-private-actions");
|
||||
|
||||
this._searchTokens =
|
||||
this.filterTokens(getUnfilteredSearchTokens(this._searchString));
|
||||
@ -630,8 +633,14 @@ Search.prototype = {
|
||||
* @return true if the behavior is set, false otherwise.
|
||||
*/
|
||||
hasBehavior: function (type) {
|
||||
return this._behavior &
|
||||
Ci.mozIPlacesAutoComplete["BEHAVIOR_" + type.toUpperCase()];
|
||||
let behavior = Ci.mozIPlacesAutoComplete["BEHAVIOR_" + type.toUpperCase()];
|
||||
|
||||
if (this._disablePrivateActions &&
|
||||
behavior == Ci.mozIPlacesAutoComplete.BEHAVIOR_OPENPAGE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this._behavior & behavior;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -498,8 +498,9 @@ nsPlacesAutoComplete.prototype = {
|
||||
this._currentSearchString =
|
||||
fixupSearchText(this._originalSearchString.toLowerCase());
|
||||
|
||||
let searchParamParts = aSearchParam.split(" ");
|
||||
this._enableActions = searchParamParts.indexOf("enable-actions") != -1;
|
||||
let params = new Set(aSearchParam.split(" "));
|
||||
this._enableActions = params.has("enable-actions");
|
||||
this._disablePrivateActions = params.has("disable-private-actions");
|
||||
|
||||
this._listener = aListener;
|
||||
let result = Cc["@mozilla.org/autocomplete/simple-result;1"].
|
||||
@ -1293,8 +1294,14 @@ nsPlacesAutoComplete.prototype = {
|
||||
*/
|
||||
_hasBehavior: function PAC_hasBehavior(aType)
|
||||
{
|
||||
return (this._behavior &
|
||||
Ci.mozIPlacesAutoComplete["BEHAVIOR_" + aType.toUpperCase()]);
|
||||
let behavior = Ci.mozIPlacesAutoComplete["BEHAVIOR_" + aType.toUpperCase()];
|
||||
|
||||
if (this._disablePrivateActions &&
|
||||
behavior == Ci.mozIPlacesAutoComplete.BEHAVIOR_OPENPAGE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this._behavior & behavior;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -60,6 +60,23 @@ add_task(function* test_tab_matches() {
|
||||
{ uri: makeActionURI("switchtab", {url: "http://xyz.net/"}), title: "xyz.net - we're better than ABC", style: [ "action", "switchtab" ] } ]
|
||||
});
|
||||
|
||||
do_log_info("three results, no tab matches (disable-private-actions)");
|
||||
yield check_autocomplete({
|
||||
search: "abc",
|
||||
searchParam: "enable-actions disable-private-actions",
|
||||
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "abc", searchQuery: "abc"}), title: "MozSearch", style: [ "action", "searchengine" ] },
|
||||
{ uri: uri1, title: "ABC rocks", style: [ "favicon" ] },
|
||||
{ uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] } ]
|
||||
});
|
||||
|
||||
do_log_info("two results (actions disabled)");
|
||||
yield check_autocomplete({
|
||||
search: "abc",
|
||||
searchParam: "",
|
||||
matches: [ { uri: uri1, title: "ABC rocks", style: [ "favicon" ] },
|
||||
{ uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] } ]
|
||||
});
|
||||
|
||||
do_log_info("three results, no tab matches");
|
||||
removeOpenPages(uri1, 1);
|
||||
removeOpenPages(uri2, 6);
|
||||
|
@ -47,6 +47,15 @@ let WebProgressListener = {
|
||||
webProgress.addProgressListener(this._filter, Ci.nsIWebProgress.NOTIFY_ALL);
|
||||
},
|
||||
|
||||
uninit() {
|
||||
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
webProgress.removeProgressListener(this._filter);
|
||||
|
||||
this._filter.removeProgressListener(this);
|
||||
this._filter = null;
|
||||
},
|
||||
|
||||
_requestSpec: function (aRequest, aPropertyName) {
|
||||
if (!aRequest || !(aRequest instanceof Ci.nsIChannel))
|
||||
return null;
|
||||
@ -154,6 +163,9 @@ let WebProgressListener = {
|
||||
};
|
||||
|
||||
WebProgressListener.init();
|
||||
addEventListener("unload", () => {
|
||||
WebProgressListener.uninit();
|
||||
});
|
||||
|
||||
let WebNavigation = {
|
||||
init: function() {
|
||||
|
Loading…
Reference in New Issue
Block a user