mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge fx-team to m-c
This commit is contained in:
commit
db9e1a87e5
@ -344,6 +344,14 @@ function showManage() {
|
||||
document.addEventListener("DOMContentLoaded", function onload() {
|
||||
document.removeEventListener("DOMContentLoaded", onload, true);
|
||||
init();
|
||||
var buttonGetStarted = document.getElementById('buttonGetStarted');
|
||||
buttonGetStarted.addEventListener('click', getStarted);
|
||||
|
||||
var oldsync = document.getElementById('oldsync');
|
||||
oldsync.addEventListener('click', handleOldSync);
|
||||
|
||||
var buttonOpenPrefs = document.getElementById('buttonOpenPrefs')
|
||||
buttonOpenPrefs.addEventListener('click', openPrefs);
|
||||
}, true);
|
||||
|
||||
function initObservers() {
|
||||
|
@ -46,7 +46,7 @@
|
||||
<div class="graphic graphic-sync-intro"> </div>
|
||||
|
||||
<div class="button-row">
|
||||
<a class="button" href="#" onclick="openPrefs()">&aboutAccountsConfig.manage.label;</a>
|
||||
<a id="buttonOpenPrefs" class="button" href="#">&aboutAccountsConfig.manage.label;</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@ -62,11 +62,11 @@
|
||||
<div class="description">&aboutAccountsConfig.description;</div>
|
||||
|
||||
<div class="button-row">
|
||||
<a class="button" href="#" onclick="getStarted()">&aboutAccountsConfig.startButton.label;</a>
|
||||
<a id="buttonGetStarted" class="button" href="#">&aboutAccountsConfig.startButton.label;</a>
|
||||
</div>
|
||||
|
||||
<div class="links">
|
||||
<a id="oldsync" class="no-underline" href="#" onclick="handleOldSync();">&aboutAccountsConfig.useOldSync.label;</a>
|
||||
<a id="oldsync" class="no-underline" href="#">&aboutAccountsConfig.useOldSync.label;</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
@ -863,9 +863,11 @@ var gBrowserInit = {
|
||||
}
|
||||
}
|
||||
|
||||
// Certain kinds of automigration rely on this notification to complete their
|
||||
// tasks BEFORE the browser window is shown.
|
||||
Services.obs.notifyObservers(null, "browser-window-before-show", "");
|
||||
// Certain kinds of automigration rely on this notification to complete
|
||||
// their tasks BEFORE the browser window is shown. SessionStore uses it to
|
||||
// restore tabs into windows AFTER important parts like gMultiProcessBrowser
|
||||
// have been initialized.
|
||||
Services.obs.notifyObservers(window, "browser-window-before-show", "");
|
||||
|
||||
// Set a sane starting width/height for all resolutions on new profiles.
|
||||
if (!document.documentElement.hasAttribute("width")) {
|
||||
|
@ -1407,19 +1407,6 @@ BrowserGlue.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
if (currentUIVersion < 6) {
|
||||
// convert tabsontop attribute to pref
|
||||
let toolboxResource = this._rdf.GetResource(BROWSER_DOCURL + "navigator-toolbox");
|
||||
let tabsOnTopResource = this._rdf.GetResource("tabsontop");
|
||||
let tabsOnTopAttribute = this._getPersist(toolboxResource, tabsOnTopResource);
|
||||
if (tabsOnTopAttribute)
|
||||
Services.prefs.setBoolPref("browser.tabs.onTop", tabsOnTopAttribute == "true");
|
||||
}
|
||||
|
||||
// Migration at version 7 only occurred for users who wanted to try the new
|
||||
// Downloads Panel feature before its release. Since migration at version
|
||||
// 9 adds the button by default, this step has been removed.
|
||||
|
||||
if (currentUIVersion < 8) {
|
||||
// Reset homepage pref for users who have it set to google.com/firefox
|
||||
let uri = Services.prefs.getComplexValue("browser.startup.homepage",
|
||||
@ -1512,8 +1499,6 @@ BrowserGlue.prototype = {
|
||||
OS.File.remove(path);
|
||||
}
|
||||
|
||||
// Version 15 was obsoleted in favour of 18.
|
||||
|
||||
if (currentUIVersion < 16) {
|
||||
let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "nav-bar");
|
||||
let collapsedResource = this._rdf.GetResource("collapsed");
|
||||
|
@ -30,7 +30,7 @@ const MAX_CONCURRENT_TAB_RESTORES = 3;
|
||||
|
||||
// global notifications observed
|
||||
const OBSERVING = [
|
||||
"domwindowopened", "domwindowclosed",
|
||||
"browser-window-before-show", "domwindowclosed",
|
||||
"quit-application-requested", "quit-application-granted",
|
||||
"browser-lastwindow-close-granted",
|
||||
"quit-application", "browser:purge-session-history",
|
||||
@ -540,8 +540,8 @@ let SessionStoreInternal = {
|
||||
*/
|
||||
observe: function ssi_observe(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "domwindowopened": // catch new windows
|
||||
this.onOpen(aSubject);
|
||||
case "browser-window-before-show": // catch new windows
|
||||
this.onBeforeBrowserWindowShown(aSubject);
|
||||
break;
|
||||
case "domwindowclosed": // catch closed windows
|
||||
this.onClose(aSubject);
|
||||
@ -919,71 +919,59 @@ let SessionStoreInternal = {
|
||||
},
|
||||
|
||||
/**
|
||||
* On window open
|
||||
* Called right before a new browser window is shown.
|
||||
* @param aWindow
|
||||
* Window reference
|
||||
*/
|
||||
onOpen: function ssi_onOpen(aWindow) {
|
||||
let onload = () => {
|
||||
aWindow.removeEventListener("load", onload);
|
||||
onBeforeBrowserWindowShown: function (aWindow) {
|
||||
// Just call onLoad() directly if we're initialized already.
|
||||
if (this._sessionInitialized) {
|
||||
this.onLoad(aWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
let windowType = aWindow.document.documentElement.getAttribute("windowtype");
|
||||
// The very first window that is opened creates a promise that is then
|
||||
// re-used by all subsequent windows. The promise will be used to tell
|
||||
// when we're ready for initialization.
|
||||
if (!this._promiseReadyForInitialization) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
// Ignore non-browser windows.
|
||||
if (windowType != "navigator:browser") {
|
||||
// Wait for the given window's delayed startup to be finished.
|
||||
Services.obs.addObserver(function obs(subject, topic) {
|
||||
if (aWindow == subject) {
|
||||
Services.obs.removeObserver(obs, topic);
|
||||
deferred.resolve();
|
||||
}
|
||||
}, "browser-delayed-startup-finished", false);
|
||||
|
||||
// We are ready for initialization as soon as the session file has been
|
||||
// read from disk and the initial window's delayed startup has finished.
|
||||
this._promiseReadyForInitialization =
|
||||
Promise.all([deferred.promise, gSessionStartup.onceInitialized]);
|
||||
}
|
||||
|
||||
// We can't call this.onLoad since initialization
|
||||
// hasn't completed, so we'll wait until it is done.
|
||||
// Even if additional windows are opened and wait
|
||||
// for initialization as well, the first opened
|
||||
// window should execute first, and this.onLoad
|
||||
// will be called with the initialState.
|
||||
this._promiseReadyForInitialization.then(() => {
|
||||
if (aWindow.closed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._sessionInitialized) {
|
||||
this.onLoad(aWindow);
|
||||
return;
|
||||
} else {
|
||||
let initialState = this.initSession();
|
||||
this._sessionInitialized = true;
|
||||
this.onLoad(aWindow, initialState);
|
||||
|
||||
// Let everyone know we're done.
|
||||
this._deferredInitialized.resolve();
|
||||
}
|
||||
|
||||
// The very first window that is opened creates a promise that is then
|
||||
// re-used by all subsequent windows. The promise will be used to tell
|
||||
// when we're ready for initialization.
|
||||
if (!this._promiseReadyForInitialization) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
// Wait for the given window's delayed startup to be finished.
|
||||
Services.obs.addObserver(function obs(subject, topic) {
|
||||
if (aWindow == subject) {
|
||||
Services.obs.removeObserver(obs, topic);
|
||||
deferred.resolve();
|
||||
}
|
||||
}, "browser-delayed-startup-finished", false);
|
||||
|
||||
// We are ready for initialization as soon as the session file has been
|
||||
// read from disk and the initial window's delayed startup has finished.
|
||||
this._promiseReadyForInitialization =
|
||||
Promise.all([deferred.promise, gSessionStartup.onceInitialized]);
|
||||
}
|
||||
|
||||
// We can't call this.onLoad since initialization
|
||||
// hasn't completed, so we'll wait until it is done.
|
||||
// Even if additional windows are opened and wait
|
||||
// for initialization as well, the first opened
|
||||
// window should execute first, and this.onLoad
|
||||
// will be called with the initialState.
|
||||
this._promiseReadyForInitialization.then(() => {
|
||||
if (aWindow.closed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._sessionInitialized) {
|
||||
this.onLoad(aWindow);
|
||||
} else {
|
||||
let initialState = this.initSession();
|
||||
this._sessionInitialized = true;
|
||||
this.onLoad(aWindow, initialState);
|
||||
|
||||
// Let everyone know we're done.
|
||||
this._deferredInitialized.resolve();
|
||||
}
|
||||
}, console.error);
|
||||
};
|
||||
|
||||
aWindow.addEventListener("load", onload);
|
||||
}, console.error);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -31,9 +31,7 @@ function test() {
|
||||
|
||||
// open a window and add the above closed tab list
|
||||
let newWin = openDialog(location, "", "chrome,all,dialog=no");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
newWin.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
promiseWindowLoaded(newWin).then(() => {
|
||||
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
|
||||
test_state.windows[0]._closedTabs.length);
|
||||
ss.setWindowState(newWin, JSON.stringify(test_state), true);
|
||||
@ -71,5 +69,5 @@ function test() {
|
||||
newWin.close();
|
||||
gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
|
||||
finish();
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
@ -52,9 +52,7 @@ function test() {
|
||||
|
||||
// open a window and add the above closed tab list
|
||||
let newWin = openDialog(location, "", "chrome,all,dialog=no");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
newWin.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
promiseWindowLoaded(newWin).then(() => {
|
||||
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
|
||||
test_state.windows[0]._closedTabs.length);
|
||||
ss.setWindowState(newWin, JSON.stringify(test_state), true);
|
||||
@ -83,5 +81,5 @@ function test() {
|
||||
gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
|
||||
finish();
|
||||
});
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
@ -15,9 +15,7 @@ function test() {
|
||||
|
||||
// open a window and set a value on it
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
newWin.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
promiseWindowLoaded(newWin).then(() => {
|
||||
ss.setWindowValue(newWin, uniqueKey1, uniqueValue1);
|
||||
|
||||
let newState = { windows: [{ tabs:[{ entries: [] }], extData: {} }] };
|
||||
@ -44,5 +42,5 @@ function test() {
|
||||
// clean up
|
||||
newWin.close();
|
||||
finish();
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
@ -7,9 +7,7 @@ function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
newWin.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
promiseWindowLoaded(newWin).then(() => {
|
||||
let newState = { windows: [{
|
||||
tabs: [{ entries: [] }],
|
||||
_closedTabs: [{
|
||||
@ -59,5 +57,5 @@ function test() {
|
||||
}, 0);
|
||||
}, 0);
|
||||
}, 0);
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
@ -80,8 +80,7 @@ function test() {
|
||||
|
||||
// open a window and add the above closed window list
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, false);
|
||||
promiseWindowLoaded(newWin).then(() => {
|
||||
gPrefService.setIntPref("browser.sessionstore.max_windows_undo",
|
||||
test_state._closedWindows.length);
|
||||
ss.setWindowState(newWin, JSON.stringify(test_state), true);
|
||||
@ -117,5 +116,5 @@ function test() {
|
||||
newWin.close();
|
||||
gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
|
||||
finish();
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
@ -8,47 +8,38 @@ function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no,toolbar=yes");
|
||||
newWin.addEventListener("load", function() {
|
||||
newWin.removeEventListener("load", arguments.callee, false);
|
||||
promiseWindowLoaded(newWin).then(() => {
|
||||
let state1 = ss.getWindowState(newWin);
|
||||
newWin.close();
|
||||
|
||||
executeSoon(function() {
|
||||
let state1 = ss.getWindowState(newWin);
|
||||
newWin = openDialog(location, "_blank",
|
||||
"chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar=no,location,personal,directories,dialog=no");
|
||||
promiseWindowLoaded(newWin).then(() => {
|
||||
let state2 = ss.getWindowState(newWin);
|
||||
newWin.close();
|
||||
|
||||
newWin = openDialog(location, "_blank",
|
||||
"chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar=no,location,personal,directories,dialog=no");
|
||||
newWin.addEventListener("load", function() {
|
||||
newWin.removeEventListener("load", arguments.callee, false);
|
||||
function testState(state, expected, callback) {
|
||||
let win = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||
promiseWindowLoaded(win).then(() => {
|
||||
|
||||
executeSoon(function() {
|
||||
let state2 = ss.getWindowState(newWin);
|
||||
newWin.close();
|
||||
is(win.gURLBar.readOnly, false,
|
||||
"URL bar should not be read-only before setting the state");
|
||||
is(win.gURLBar.getAttribute("enablehistory"), "true",
|
||||
"URL bar autocomplete should be enabled before setting the state");
|
||||
ss.setWindowState(win, state, true);
|
||||
is(win.gURLBar.readOnly, expected.readOnly,
|
||||
"URL bar read-only state should be restored correctly");
|
||||
is(win.gURLBar.getAttribute("enablehistory"), expected.enablehistory,
|
||||
"URL bar autocomplete state should be restored correctly");
|
||||
|
||||
function testState(state, expected, callback) {
|
||||
let win = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||
win.addEventListener("load", function() {
|
||||
win.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
is(win.gURLBar.readOnly, false,
|
||||
"URL bar should not be read-only before setting the state");
|
||||
is(win.gURLBar.getAttribute("enablehistory"), "true",
|
||||
"URL bar autocomplete should be enabled before setting the state");
|
||||
ss.setWindowState(win, state, true);
|
||||
is(win.gURLBar.readOnly, expected.readOnly,
|
||||
"URL bar read-only state should be restored correctly");
|
||||
is(win.gURLBar.getAttribute("enablehistory"), expected.enablehistory,
|
||||
"URL bar autocomplete state should be restored correctly");
|
||||
|
||||
win.close();
|
||||
executeSoon(callback);
|
||||
}, false);
|
||||
}
|
||||
|
||||
testState(state1, {readOnly: false, enablehistory: "true"}, function() {
|
||||
testState(state2, {readOnly: true, enablehistory: "false"}, finish);
|
||||
});
|
||||
win.close();
|
||||
executeSoon(callback);
|
||||
});
|
||||
}, false);
|
||||
}
|
||||
|
||||
testState(state1, {readOnly: false, enablehistory: "true"}, function() {
|
||||
testState(state2, {readOnly: true, enablehistory: "false"}, finish);
|
||||
});
|
||||
});
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
@ -17,11 +17,10 @@ function test() {
|
||||
browserWindowsCount(1);
|
||||
|
||||
var win = openDialog(location, "", "chrome,all,dialog=no");
|
||||
win.addEventListener("load", function () {
|
||||
win.removeEventListener("load", arguments.callee, false);
|
||||
promiseWindowLoaded(win).then(() => {
|
||||
browserWindowsCount(2);
|
||||
win.close();
|
||||
browserWindowsCount(1);
|
||||
finish();
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
@ -10,9 +10,7 @@ function test() {
|
||||
|
||||
// open a new window and setup the window state.
|
||||
newWin = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
|
||||
newWin.addEventListener("load", function onLoad(event) {
|
||||
this.removeEventListener("load", onLoad, false);
|
||||
|
||||
whenWindowLoaded(newWin, function () {
|
||||
let newState = {
|
||||
windows: [{
|
||||
tabs: [{
|
||||
@ -69,5 +67,5 @@ function test() {
|
||||
}
|
||||
newWin.addEventListener("tabviewshown", onTabViewShow, false);
|
||||
waitForFocus(function() { newWin.TabView.toggle(); });
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
@ -142,8 +142,10 @@ function afterAllTabsLoaded(callback, win) {
|
||||
browser.__SS_restoreState &&
|
||||
browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE);
|
||||
|
||||
if (isRestorable && browser.contentDocument.readyState != "complete" ||
|
||||
browser.webProgress.isLoadingDocument) {
|
||||
let isLoading = browser.webProgress.isLoadingDocument ||
|
||||
browser.contentDocument.readyState != "complete";
|
||||
|
||||
if (isRestorable && isLoading) {
|
||||
stillToLoad++;
|
||||
browser.addEventListener("load", onLoad, true);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ this.EXPORTED_SYMBOLS = ["Windows8WindowFrameColor"];
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/WindowsRegistry.jsm");
|
||||
let Registry = Cu.import("resource://gre/modules/WindowsRegistry.jsm").WindowsRegistry;
|
||||
|
||||
const Windows8WindowFrameColor = {
|
||||
_windowFrameColor: null,
|
||||
@ -18,16 +18,26 @@ const Windows8WindowFrameColor = {
|
||||
if (this._windowFrameColor)
|
||||
return this._windowFrameColor;
|
||||
|
||||
let windowFrameColor = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Microsoft\\Windows\\DWM",
|
||||
"ColorizationColor");
|
||||
const HKCU = Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER;
|
||||
const dwmKey = "Software\\Microsoft\\Windows\\DWM";
|
||||
let customizationColor = Registry.readRegKey(HKCU, dwmKey,
|
||||
"ColorizationColor");
|
||||
// The color returned from the Registry is in decimal form.
|
||||
let windowFrameColorHex = windowFrameColor.toString(16);
|
||||
let customizationColorHex = customizationColor.toString(16);
|
||||
// Zero-pad the number just to make sure that it is 8 digits.
|
||||
windowFrameColorHex = ("00000000" + windowFrameColorHex).substr(-8);
|
||||
let windowFrameColorArray = windowFrameColorHex.match(/../g);
|
||||
let [pixelA, pixelR, pixelG, pixelB] = windowFrameColorArray.map(function(val) parseInt(val, 16));
|
||||
customizationColorHex = ("00000000" + customizationColorHex).substr(-8);
|
||||
let customizationColorArray = customizationColorHex.match(/../g);
|
||||
let [unused, fgR, fgG, fgB] = customizationColorArray.map(function(val) parseInt(val, 16));
|
||||
let colorizationColorBalance = Registry.readRegKey(HKCU, dwmKey,
|
||||
"ColorizationColorBalance");
|
||||
// Window frame base color when Color Intensity is at 0, see bug 1004576.
|
||||
let frameBaseColor = 217;
|
||||
let alpha = colorizationColorBalance / 100;
|
||||
|
||||
return this._windowFrameColor = [pixelR, pixelG, pixelB];
|
||||
// Alpha-blend the foreground color with the frame base color.
|
||||
let r = Math.round(fgR * alpha + frameBaseColor * (1 - alpha));
|
||||
let g = Math.round(fgG * alpha + frameBaseColor * (1 - alpha));
|
||||
let b = Math.round(fgB * alpha + frameBaseColor * (1 - alpha));
|
||||
return this._windowFrameColor = [r, g, b];
|
||||
},
|
||||
};
|
||||
|
@ -202,6 +202,7 @@ browser.jar:
|
||||
skin/classic/browser/devtools/command-eyedropper.png (../shared/devtools/images/command-eyedropper.png)
|
||||
skin/classic/browser/devtools/command-eyedropper@2x.png (../shared/devtools/images/command-eyedropper@2x.png)
|
||||
skin/classic/browser/devtools/alerticon-warning.png (../shared/devtools/images/alerticon-warning.png)
|
||||
skin/classic/browser/devtools/alerticon-warning@2x.png (../shared/devtools/images/alerticon-warning@2x.png)
|
||||
* skin/classic/browser/devtools/ruleview.css (../shared/devtools/ruleview.css)
|
||||
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
||||
skin/classic/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
|
||||
|
@ -322,7 +322,8 @@ browser.jar:
|
||||
skin/classic/browser/devtools/command-console@2x.png (../shared/devtools/images/command-console@2x.png)
|
||||
skin/classic/browser/devtools/command-eyedropper.png (../shared/devtools/images/command-eyedropper.png)
|
||||
skin/classic/browser/devtools/command-eyedropper@2x.png (../shared/devtools/images/command-eyedropper@2x.png)
|
||||
skin/classic/browser/devtools/alerticon-warning.png (../shared/devtools/images/alerticon-warning.png)
|
||||
skin/classic/browser/devtools/alerticon-warning.png (../shared/devtools/images/alerticon-warning.png)
|
||||
skin/classic/browser/devtools/alerticon-warning@2x.png (../shared/devtools/images/alerticon-warning@2x.png)
|
||||
* skin/classic/browser/devtools/ruleview.css (../shared/devtools/ruleview.css)
|
||||
skin/classic/browser/devtools/commandline.css (devtools/commandline.css)
|
||||
skin/classic/browser/devtools/markup-view.css (../shared/devtools/markup-view.css)
|
||||
|
BIN
browser/themes/shared/devtools/images/alerticon-warning@2x.png
Normal file
BIN
browser/themes/shared/devtools/images/alerticon-warning@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 432 B |
@ -52,7 +52,8 @@
|
||||
}
|
||||
|
||||
.ruleview-warning {
|
||||
background: url("chrome://browser/skin/devtools/alerticon-warning.png");
|
||||
background-image: url(alerticon-warning.png);
|
||||
background-size: 13px 12px;
|
||||
-moz-margin-start: 5px;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
@ -60,6 +61,13 @@
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
.ruleview-warning {
|
||||
background-image: url(alerticon-warning@2x.png);
|
||||
}
|
||||
}
|
||||
|
||||
.ruleview-ruleopen {
|
||||
-moz-padding-end: 5px;
|
||||
}
|
||||
|
@ -113,8 +113,16 @@ text {
|
||||
*/
|
||||
|
||||
.web-audio-inspector .error {
|
||||
background-image: url(chrome://browser/skin/devtools/alerticon-warning.png);
|
||||
background-image: url(alerticon-warning.png);
|
||||
background-size: 13px 12px;
|
||||
-moz-appearance: none;
|
||||
opacity: 0;
|
||||
transition: opacity .5s ease-out 0s;
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
.web-audio-inspector .error {
|
||||
background-image: url(alerticon-warning@2x.png);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,6 +225,7 @@ browser.jar:
|
||||
* skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
|
||||
skin/classic/browser/devtools/commandline-icon.png (../shared/devtools/images/commandline-icon.png)
|
||||
skin/classic/browser/devtools/alerticon-warning.png (../shared/devtools/images/alerticon-warning.png)
|
||||
skin/classic/browser/devtools/alerticon-warning@2x.png (../shared/devtools/images/alerticon-warning@2x.png)
|
||||
* skin/classic/browser/devtools/ruleview.css (../shared/devtools/ruleview.css)
|
||||
skin/classic/browser/devtools/commandline.css (devtools/commandline.css)
|
||||
skin/classic/browser/devtools/command-paintflashing.png (../shared/devtools/images/command-paintflashing.png)
|
||||
@ -602,6 +603,7 @@ browser.jar:
|
||||
skin/classic/aero/browser/devtools/command-eyedropper.png (../shared/devtools/images/command-eyedropper.png)
|
||||
skin/classic/aero/browser/devtools/command-eyedropper@2x.png (../shared/devtools/images/command-eyedropper@2x.png)
|
||||
skin/classic/aero/browser/devtools/alerticon-warning.png (../shared/devtools/images/alerticon-warning.png)
|
||||
skin/classic/aero/browser/devtools/alerticon-warning@2x.png (../shared/devtools/images/alerticon-warning@2x.png)
|
||||
* skin/classic/aero/browser/devtools/ruleview.css (../shared/devtools/ruleview.css)
|
||||
skin/classic/aero/browser/devtools/commandline.css (devtools/commandline.css)
|
||||
skin/classic/aero/browser/devtools/markup-view.css (../shared/devtools/markup-view.css)
|
||||
|
@ -8390,6 +8390,12 @@ if test -n "$MOZ_CAPTIVEDETECT"; then
|
||||
AC_DEFINE(MOZ_CAPTIVEDETECT)
|
||||
fi
|
||||
|
||||
dnl Build second screen and casting features for external devices if required
|
||||
AC_SUBST(MOZ_DEVICES)
|
||||
if test -n "$MOZ_DEVICES"; then
|
||||
AC_DEFINE(MOZ_DEVICES)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
if test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC" -o "$MOZ_DMD"; then
|
||||
MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS=
|
||||
|
@ -9614,44 +9614,46 @@
|
||||
> testcase/MS
|
||||
46831a52679
|
||||
> testsuite/MS
|
||||
46925a52774
|
||||
46845a52694
|
||||
> textbox/SM
|
||||
46925a52775
|
||||
> theremin/MS
|
||||
47455c53304
|
||||
47455c53305
|
||||
< toolbar
|
||||
---
|
||||
> toolbar/MS
|
||||
47755a53605
|
||||
47755a53606
|
||||
> transfect/DSMG
|
||||
47774a53625,53626
|
||||
47774a53626,53627
|
||||
> transgenderism
|
||||
> transgene/MS
|
||||
47951c53803
|
||||
47951c53804
|
||||
< triage/M
|
||||
---
|
||||
> triage/MG
|
||||
48869a54722
|
||||
48869a54723
|
||||
> unlikeable
|
||||
49211c55064
|
||||
49211c55065
|
||||
< vagina/M
|
||||
---
|
||||
> vagina/MS
|
||||
49368,49369c55221
|
||||
49368,49369c55222
|
||||
< velour's
|
||||
< velours's
|
||||
---
|
||||
> velour/MS
|
||||
49478a55331
|
||||
49478a55332
|
||||
> vertices
|
||||
50148a56002
|
||||
50148a56003
|
||||
> weaponize/DSG
|
||||
50260,50261d56113
|
||||
50260,50261d56114
|
||||
< werwolf/M
|
||||
< werwolves
|
||||
50728c56580
|
||||
50728c56581
|
||||
< women
|
||||
---
|
||||
> women/M
|
||||
50794c56646
|
||||
50794c56647
|
||||
< wop/S!
|
||||
---
|
||||
> wop/MS!
|
||||
|
@ -1,4 +1,4 @@
|
||||
57468
|
||||
57469
|
||||
0/nm
|
||||
0th/pt
|
||||
1/n1
|
||||
@ -53044,6 +53044,7 @@ tetrahedron/SM
|
||||
tetrameter/MS
|
||||
text/FMS
|
||||
textbook/SM
|
||||
textbox/SM
|
||||
textile/MS
|
||||
textual/FY
|
||||
textural/Y
|
||||
|
@ -75,12 +75,14 @@
|
||||
android:icon="@drawable/icon"
|
||||
android:name="org.mozilla.gecko.GeckoApplication"
|
||||
android:hardwareAccelerated="true"
|
||||
#if MOZILLA_OFFICIAL
|
||||
#ifdef MOZILLA_OFFICIAL
|
||||
android:debuggable="false">
|
||||
#else
|
||||
android:debuggable="true">
|
||||
#endif
|
||||
|
||||
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true"/>
|
||||
|
||||
<!-- If the windowSoftInputMode adjust* flag changes below, the
|
||||
setSoftInputMode call in BrowserSearch#onStop must also be updated. -->
|
||||
<activity android:name=".App"
|
||||
@ -91,10 +93,19 @@
|
||||
android:windowSoftInputMode="stateUnspecified|adjustResize"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/Gecko.App">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER"/>
|
||||
</intent-filter>
|
||||
|
||||
<meta-data android:name="com.sec.minimode.icon.portrait.normal"
|
||||
android:resource="@drawable/icon"/>
|
||||
|
||||
<meta-data android:name="com.sec.minimode.icon.landscape.normal"
|
||||
android:resource="@drawable/icon" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="org.mozilla.gecko.ACTION_ALERT_CALLBACK" />
|
||||
</intent-filter>
|
||||
|
@ -164,4 +164,14 @@ public class AppConstants {
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
|
||||
// Official corresponds, roughly, to whether this build is performed on
|
||||
// Mozilla's continuous integration infrastructure. You should disable
|
||||
// developer-only functionality when this flag is set.
|
||||
public static final boolean MOZILLA_OFFICIAL =
|
||||
#ifdef MOZILLA_OFFICIAL
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
}
|
||||
|
@ -323,6 +323,16 @@ public class GeckoAppShell
|
||||
if (type != null)
|
||||
combinedArgs += " " + type;
|
||||
|
||||
// In un-official builds, we want to load Javascript resources fresh
|
||||
// with each build. In official builds, the startup cache is purged by
|
||||
// the buildid mechanism, but most un-official builds don't bump the
|
||||
// buildid, so we purge here instead.
|
||||
if (!AppConstants.MOZILLA_OFFICIAL) {
|
||||
Log.w(LOGTAG, "STARTUP PERFORMANCE WARNING: un-official build: purging the " +
|
||||
"startup (JavaScript) caches.");
|
||||
combinedArgs += " -purgecaches";
|
||||
}
|
||||
|
||||
DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
|
||||
combinedArgs += " -width " + metrics.widthPixels + " -height " + metrics.heightPixels;
|
||||
|
||||
|
@ -21,6 +21,7 @@ import android.util.Log;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class TabsAccessor {
|
||||
private static final String LOGTAG = "GeckoTabsAccessor";
|
||||
@ -49,6 +50,7 @@ public final class TabsAccessor {
|
||||
|
||||
private static final String LOCAL_CLIENT_SELECTION = BrowserContract.Clients.GUID + " IS NULL";
|
||||
private static final String LOCAL_TABS_SELECTION = BrowserContract.Tabs.CLIENT_GUID + " IS NULL";
|
||||
private static final Pattern FILTERED_URL_PATTERN = Pattern.compile("^(about|chrome|wyciwyg|file):");
|
||||
|
||||
public static class RemoteTab {
|
||||
public String title;
|
||||
@ -149,9 +151,9 @@ public final class TabsAccessor {
|
||||
|
||||
int position = 0;
|
||||
for (Tab tab : tabs) {
|
||||
// Skip this tab if it has a null URL or is in private browsing mode
|
||||
// Skip this tab if it has a null URL or is in private browsing mode, or is a filtered URL.
|
||||
String url = tab.getURL();
|
||||
if (url == null || tab.isPrivate())
|
||||
if (url == null || tab.isPrivate() || isFilteredURL(url))
|
||||
continue;
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
@ -192,4 +194,13 @@ public final class TabsAccessor {
|
||||
insertLocalTabs(cr, tabs);
|
||||
updateLocalClient(cr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the supplied URL string against the set of URLs to filter.
|
||||
*
|
||||
* @return true if the supplied URL should be skipped; false otherwise.
|
||||
*/
|
||||
private static boolean isFilteredURL(String url) {
|
||||
return FILTERED_URL_PATTERN.matcher(url).lookingAt();
|
||||
}
|
||||
}
|
||||
|
@ -509,7 +509,7 @@ ANDROID_GENERATED_RESFILES += [
|
||||
'res/values/strings.xml',
|
||||
]
|
||||
|
||||
for var in ('MOZ_ANDROID_ANR_REPORTER', 'MOZ_LINKER_EXTRACT'):
|
||||
for var in ('MOZ_ANDROID_ANR_REPORTER', 'MOZ_LINKER_EXTRACT', 'MOZILLA_OFFICIAL'):
|
||||
if CONFIG[var]:
|
||||
DEFINES[var] = 1
|
||||
|
||||
@ -518,7 +518,7 @@ for var in ('MOZ_UPDATER', 'MOZ_PKG_SPECIAL'):
|
||||
DEFINES[var] = CONFIG[var]
|
||||
|
||||
for var in ('ANDROID_PACKAGE_NAME', 'ANDROID_CPU_ARCH', 'CPU_ARCH',
|
||||
'GRE_MILESTONE', 'MOZILLA_OFFICIAL', 'MOZ_APP_BASENAME',
|
||||
'GRE_MILESTONE', 'MOZ_APP_BASENAME',
|
||||
'MOZ_APP_DISPLAYNAME', 'MOZ_APP_ID', 'MOZ_APP_NAME',
|
||||
'MOZ_APP_VENDOR', 'MOZ_APP_VERSION', 'MOZ_CHILD_PROCESS_NAME',
|
||||
'MOZ_CRASHREPORTER', 'MOZ_UPDATE_CHANNEL', 'OMNIJAR_NAME',
|
||||
|
@ -35,6 +35,7 @@ skip-if = android_version == "10" || processor == "x86"
|
||||
[testDoorHanger]
|
||||
# disabled on 2.3; bug 986172
|
||||
skip-if = android_version == "10"
|
||||
[testFilterOpenTab]
|
||||
[testFindInPage]
|
||||
# disabled on Android 2.3; bug 975155
|
||||
skip-if = android_version == "10"
|
||||
|
125
mobile/android/base/tests/testFilterOpenTab.java
Normal file
125
mobile/android/base/tests/testFilterOpenTab.java
Normal file
@ -0,0 +1,125 @@
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.mozilla.gecko.PrivateTab;
|
||||
import org.mozilla.gecko.Tab;
|
||||
import org.mozilla.gecko.TabsAccessor;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
import org.mozilla.gecko.db.TabsProvider;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
|
||||
/**
|
||||
* Tests that local tabs are filtered prior to upload.
|
||||
* - create a set of tabs and perists them through TabsAccessor.
|
||||
* - verifies that tabs are filtered by querying.
|
||||
*/
|
||||
public class testFilterOpenTab extends ContentProviderTest {
|
||||
private static final String[] TABS_PROJECTION_COLUMNS = new String[] {
|
||||
BrowserContract.Tabs.TITLE,
|
||||
BrowserContract.Tabs.URL,
|
||||
BrowserContract.Clients.GUID,
|
||||
BrowserContract.Clients.NAME
|
||||
};
|
||||
|
||||
private static final String LOCAL_TABS_SELECTION = BrowserContract.Tabs.CLIENT_GUID + " IS NULL";
|
||||
|
||||
/**
|
||||
* Factory function that makes new ContentProvider instances.
|
||||
* <p>
|
||||
* We want a fresh provider each test, so this should be invoked in
|
||||
* <code>setUp</code> before each individual test.
|
||||
*/
|
||||
protected static Callable<ContentProvider> sTabProviderCallable = new Callable<ContentProvider>() {
|
||||
@Override
|
||||
public ContentProvider call() {
|
||||
return new TabsProvider();
|
||||
}
|
||||
};
|
||||
|
||||
private Cursor getTabsFromLocalClient() throws Exception {
|
||||
return mProvider.query(BrowserContract.Tabs.CONTENT_URI,
|
||||
TABS_PROJECTION_COLUMNS,
|
||||
LOCAL_TABS_SELECTION,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
private Tab createTab(int id, String url, boolean external, int parentId, String title) {
|
||||
return new Tab((Context) getActivity(), id, url, external, parentId, title);
|
||||
}
|
||||
|
||||
private Tab createPrivateTab(int id, String url, boolean external, int parentId, String title) {
|
||||
return new PrivateTab((Context) getActivity(), id, url, external, parentId, title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp(sTabProviderCallable, BrowserContract.TABS_AUTHORITY, "tabs.db");
|
||||
mTests.add(new TestInsertLocalTabs());
|
||||
}
|
||||
|
||||
public void testFilterOpenTab() throws Exception {
|
||||
for (int i = 0; i < mTests.size(); i++) {
|
||||
Runnable test = mTests.get(i);
|
||||
|
||||
setTestName(test.getClass().getSimpleName());
|
||||
test.run();
|
||||
}
|
||||
}
|
||||
|
||||
private class TestInsertLocalTabs extends TestCase {
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
final String TITLE1 = "Google";
|
||||
final String URL1 = "http://www.google.com/";
|
||||
final String TITLE2 = "Mozilla Start Page";
|
||||
final String URL2 = "about:home";
|
||||
final String TITLE3 = "Chrome Weave URL";
|
||||
final String URL3 = "chrome://weave/";
|
||||
final String TITLE4 = "What You Cache Is What You Get";
|
||||
final String URL4 = "wyciwyg://1/test.com";
|
||||
final String TITLE5 = "Root Folder";
|
||||
final String URL5 = "file:///";
|
||||
|
||||
// Create a list of local tabs.
|
||||
List<Tab> tabs = new ArrayList<Tab>(6);
|
||||
Tab tab1 = createTab(1, URL1, false, 0, TITLE1);
|
||||
Tab tab2 = createTab(2, URL2, false, 0, TITLE2);
|
||||
Tab tab3 = createTab(3, URL3, false, 0, TITLE3);
|
||||
Tab tab4 = createTab(4, URL4, false, 0, TITLE4);
|
||||
Tab tab5 = createTab(5, URL5, false, 0, TITLE5);
|
||||
Tab tab6 = createPrivateTab(6, URL1, false, 0, TITLE1);
|
||||
tabs.add(tab1);
|
||||
tabs.add(tab2);
|
||||
tabs.add(tab3);
|
||||
tabs.add(tab4);
|
||||
tabs.add(tab5);
|
||||
tabs.add(tab6);
|
||||
|
||||
// Persist the created tabs.
|
||||
TabsAccessor.persistLocalTabs(mResolver, tabs);
|
||||
|
||||
// Get the persisted tab and check if urls are filtered.
|
||||
Cursor c = getTabsFromLocalClient();
|
||||
assertCountIsAndClose(c, 1, 1 + " tabs entries found");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the provided cursor has the expected number of rows,
|
||||
* closing the cursor afterwards.
|
||||
*/
|
||||
private void assertCountIsAndClose(Cursor c, int expectedCount, String message) {
|
||||
try {
|
||||
mAsserter.is(c.getCount(), expectedCount, message);
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
}
|
93
mobile/android/chrome/content/aboutDevices.js
Normal file
93
mobile/android/chrome/content/aboutDevices.js
Normal file
@ -0,0 +1,93 @@
|
||||
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm"); /*global Services */
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
Cu.import("resource://gre/modules/SimpleServiceDiscovery.jsm"); /*global SimpleServiceDiscovery */
|
||||
|
||||
const EVENT_SERVICE_FOUND = SimpleServiceDiscovery.EVENT_SERVICE_FOUND;
|
||||
const EVENT_SERVICE_LOST = SimpleServiceDiscovery.EVENT_SERVICE_LOST;
|
||||
|
||||
// We want to keep this page fresh while it is open, so we decrease
|
||||
// our time between searches when it is opened, and revert to the
|
||||
// former time between searches when it is closed.
|
||||
const SEARCH_INTERVAL_IN_MILLISECONDS = 5 * 1000;
|
||||
|
||||
function dump(s) {
|
||||
Services.console.logStringMessage("aboutDevices :: " + s);
|
||||
}
|
||||
|
||||
var Devices = {
|
||||
_savedSearchInterval: -1,
|
||||
|
||||
init: function() {
|
||||
dump("Initializing.");
|
||||
Services.obs.addObserver(this, EVENT_SERVICE_FOUND, false);
|
||||
Services.obs.addObserver(this, EVENT_SERVICE_LOST, false);
|
||||
|
||||
let button = document.getElementById("refresh");
|
||||
button.addEventListener("click", () => {
|
||||
this.updateDeviceList();
|
||||
}, false);
|
||||
|
||||
this._savedSearchInterval = SimpleServiceDiscovery.search(SEARCH_INTERVAL_IN_MILLISECONDS);
|
||||
|
||||
this.updateDeviceList();
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
dump("Uninitializing.");
|
||||
Services.obs.removeObserver(this, EVENT_SERVICE_FOUND);
|
||||
Services.obs.removeObserver(this, EVENT_SERVICE_LOST);
|
||||
|
||||
if (this._savedSearchInterval > 0) {
|
||||
SimpleServiceDiscovery.search(this._savedSearchInterval);
|
||||
}
|
||||
},
|
||||
|
||||
_createItemForDevice: function(device) {
|
||||
let item = document.createElement("div");
|
||||
|
||||
let friendlyName = document.createElement("div");
|
||||
friendlyName.classList.add("name");
|
||||
friendlyName.textContent = device.friendlyName;
|
||||
item.appendChild(friendlyName);
|
||||
|
||||
let location = document.createElement("div");
|
||||
location.classList.add("location");
|
||||
location.textContent = device.location;
|
||||
item.appendChild(location);
|
||||
|
||||
return item;
|
||||
},
|
||||
|
||||
updateDeviceList: function() {
|
||||
let services = SimpleServiceDiscovery.services;
|
||||
dump("Updating device list with " + services.length + " services.");
|
||||
|
||||
let list = document.getElementById("devices-list");
|
||||
while (list.firstChild) {
|
||||
list.removeChild(list.firstChild);
|
||||
}
|
||||
|
||||
for (let service of services) {
|
||||
let item = this._createItemForDevice(service);
|
||||
list.appendChild(item);
|
||||
}
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
if (topic == EVENT_SERVICE_FOUND || topic == EVENT_SERVICE_LOST) {
|
||||
this.updateDeviceList();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
window.addEventListener("load", Devices.init.bind(Devices), false);
|
||||
window.addEventListener("unload", Devices.uninit.bind(Devices), false);
|
35
mobile/android/chrome/content/aboutDevices.xhtml
Normal file
35
mobile/android/chrome/content/aboutDevices.xhtml
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
||||
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" [
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
|
||||
%brandDTD;
|
||||
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
|
||||
%globalDTD;
|
||||
<!ENTITY % aboutDTD SYSTEM "chrome://browser/locale/aboutDevices.dtd" >
|
||||
%aboutDTD;
|
||||
]>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&aboutDevices.title;</title>
|
||||
<meta name="viewport" content="width=device-width; user-scalable=0" />
|
||||
<link rel="icon" type="image/png" sizes="64x64" href="chrome://branding/content/favicon64.png" />
|
||||
<link rel="stylesheet" href="chrome://browser/skin/aboutBase.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/aboutDevices.css" type="text/css"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>&aboutDevices.header;</h1>
|
||||
|
||||
<ul id="devices-list"></ul>
|
||||
|
||||
<button id="refresh">&aboutDevices.refresh;</button>
|
||||
|
||||
<script type="text/javascript;version=1.8" src="chrome://browser/content/aboutDevices.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -56,6 +56,10 @@ chrome.jar:
|
||||
content/aboutHealthReport.xhtml (content/aboutHealthReport.xhtml)
|
||||
* content/aboutHealthReport.js (content/aboutHealthReport.js)
|
||||
#endif
|
||||
#ifdef MOZ_DEVICES
|
||||
content/aboutDevices.xhtml (content/aboutDevices.xhtml)
|
||||
content/aboutDevices.js (content/aboutDevices.js)
|
||||
#endif
|
||||
|
||||
% content branding %content/branding/
|
||||
|
||||
|
@ -78,6 +78,12 @@ let modules = {
|
||||
privileged: true
|
||||
},
|
||||
#endif
|
||||
#ifdef MOZ_DEVICES
|
||||
devices: {
|
||||
uri: "chrome://browser/content/aboutDevices.xhtml",
|
||||
privileged: true
|
||||
},
|
||||
#endif
|
||||
}
|
||||
|
||||
function AboutRedirector() {}
|
||||
|
@ -18,6 +18,9 @@ contract @mozilla.org/network/protocol/about;1?what=healthreport {322ba47e-7047-
|
||||
#ifdef MOZ_SAFE_BROWSING
|
||||
contract @mozilla.org/network/protocol/about;1?what=blocked {322ba47e-7047-4f71-aebf-cb7d69325cd9}
|
||||
#endif
|
||||
#ifdef MOZ_DEVICES
|
||||
contract @mozilla.org/network/protocol/about;1?what=devices {322ba47e-7047-4f71-aebf-cb7d69325cd9}
|
||||
#endif
|
||||
|
||||
# DirectoryProvider.js
|
||||
component {ef0f7a87-c1ee-45a8-8d67-26f586e46a4b} DirectoryProvider.js
|
||||
|
@ -69,3 +69,6 @@ MOZ_B2G_CERTDATA=1
|
||||
|
||||
# Enable the "synthetic APKs" implementation of Open Web Apps.
|
||||
MOZ_ANDROID_SYNTHAPKS=1
|
||||
|
||||
# Enable second screen and casting support for external devices.
|
||||
MOZ_DEVICES=1
|
||||
|
7
mobile/android/locales/en-US/chrome/aboutDevices.dtd
Normal file
7
mobile/android/locales/en-US/chrome/aboutDevices.dtd
Normal file
@ -0,0 +1,7 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!ENTITY aboutDevices.title "Devices">
|
||||
<!ENTITY aboutDevices.header "Your devices">
|
||||
<!ENTITY aboutDevices.refresh "Refresh">
|
@ -10,6 +10,9 @@
|
||||
locale/@AB_CD@/browser/aboutAddons.dtd (%chrome/aboutAddons.dtd)
|
||||
locale/@AB_CD@/browser/aboutAddons.properties (%chrome/aboutAddons.properties)
|
||||
locale/@AB_CD@/browser/aboutApps.dtd (%chrome/aboutApps.dtd)
|
||||
#ifdef MOZ_DEVICES
|
||||
locale/@AB_CD@/browser/aboutDevices.dtd (%chrome/aboutDevices.dtd)
|
||||
#endif
|
||||
locale/@AB_CD@/browser/aboutCertError.dtd (%chrome/aboutCertError.dtd)
|
||||
locale/@AB_CD@/browser/aboutDownloads.dtd (%chrome/aboutDownloads.dtd)
|
||||
locale/@AB_CD@/browser/aboutDownloads.properties (%chrome/aboutDownloads.properties)
|
||||
|
@ -37,11 +37,17 @@ const SSDP_DISCOVER_PACKET =
|
||||
|
||||
const SSDP_DISCOVER_TIMEOUT = 10000;
|
||||
|
||||
const EVENT_SERVICE_FOUND = "ssdp-service-found";
|
||||
const EVENT_SERVICE_LOST = "ssdp-service-lost";
|
||||
|
||||
/*
|
||||
* SimpleServiceDiscovery manages any discovered SSDP services. It uses a UDP
|
||||
* broadcast to locate available services on the local network.
|
||||
*/
|
||||
var SimpleServiceDiscovery = {
|
||||
get EVENT_SERVICE_FOUND() { return EVENT_SERVICE_FOUND; },
|
||||
get EVENT_SERVICE_LOST() { return EVENT_SERVICE_LOST; },
|
||||
|
||||
_targets: new Map(),
|
||||
_services: new Map(),
|
||||
_searchSocket: null,
|
||||
@ -107,12 +113,15 @@ var SimpleServiceDiscovery = {
|
||||
|
||||
// Start a search. Make it continuous by passing an interval (in milliseconds).
|
||||
// This will stop a current search loop because the timer resets itself.
|
||||
// Returns the existing search interval.
|
||||
search: function search(aInterval) {
|
||||
let existingSearchInterval = this._searchInterval;
|
||||
if (aInterval > 0) {
|
||||
this._searchInterval = aInterval || 0;
|
||||
this._searchRepeat.initWithCallback(this._search.bind(this), this._searchInterval, Ci.nsITimer.TYPE_REPEATING_SLACK);
|
||||
}
|
||||
this._search();
|
||||
return existingSearchInterval;
|
||||
},
|
||||
|
||||
// Stop the current continuous search
|
||||
@ -210,7 +219,7 @@ var SimpleServiceDiscovery = {
|
||||
// Clean out any stale services
|
||||
for (let [key, service] of this._services) {
|
||||
if (service.lastPing != this._searchTimestamp) {
|
||||
Services.obs.notifyObservers(null, "ssdp-service-lost", service.location);
|
||||
Services.obs.notifyObservers(null, EVENT_SERVICE_LOST, service.location);
|
||||
this._services.delete(service.location);
|
||||
}
|
||||
}
|
||||
@ -273,7 +282,7 @@ var SimpleServiceDiscovery = {
|
||||
// Only add and notify if we don't already know about this service
|
||||
if (!this._services.has(aService.location)) {
|
||||
this._services.set(aService.location, aService);
|
||||
Services.obs.notifyObservers(null, "ssdp-service-found", aService.location);
|
||||
Services.obs.notifyObservers(null, EVENT_SERVICE_FOUND, aService.location);
|
||||
}
|
||||
|
||||
// Make sure we remember this service is not stale
|
||||
|
8
mobile/android/themes/core/aboutDevices.css
Normal file
8
mobile/android/themes/core/aboutDevices.css
Normal file
@ -0,0 +1,8 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
@ -11,6 +11,9 @@ chrome.jar:
|
||||
* skin/aboutAddons.css (aboutAddons.css)
|
||||
skin/aboutApps.css (aboutApps.css)
|
||||
* skin/aboutBase.css (aboutBase.css)
|
||||
#ifdef MOZ_DEVICES
|
||||
skin/aboutDevices.css (aboutDevices.css)
|
||||
#endif
|
||||
* skin/aboutDownloads.css (aboutDownloads.css)
|
||||
skin/aboutFeedback.css (aboutFeedback.css)
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
|
@ -67,8 +67,6 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/AsyncShutdown.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/Promise.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository",
|
||||
@ -464,7 +462,6 @@ var gUpdateEnabled = true;
|
||||
var gAutoUpdateDefault = true;
|
||||
var gHotfixID = null;
|
||||
|
||||
var gUpdateCheckInProgress = false;
|
||||
/**
|
||||
* This is the real manager, kept here rather than in AddonManager to keep its
|
||||
* contents hidden from API users.
|
||||
@ -480,6 +477,7 @@ var AddonManagerInternal = {
|
||||
// Store telemetry details per addon provider
|
||||
telemetryDetails: {},
|
||||
|
||||
|
||||
// A read-only wrapper around the types dictionary
|
||||
typesProxy: Proxy.create({
|
||||
getOwnPropertyDescriptor: function typesProxy_getOwnPropertyDescriptor(aName) {
|
||||
@ -1134,121 +1132,120 @@ var AddonManagerInternal = {
|
||||
/**
|
||||
* Performs a background update check by starting an update for all add-ons
|
||||
* that can be updated.
|
||||
* @return Promise{null} resolves when the background update check is complete
|
||||
* (including all addon installs)
|
||||
*/
|
||||
backgroundUpdateCheck: function AMI_backgroundUpdateCheck() {
|
||||
if (!gStarted)
|
||||
throw Components.Exception("AddonManager is not initialized",
|
||||
Cr.NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
if (gUpdateCheckInProgress) {
|
||||
throw Components.Exception("Background update check already in progress",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
let hotfixID = this.hotfixID;
|
||||
|
||||
let checkHotfix = hotfixID &&
|
||||
Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) &&
|
||||
Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO);
|
||||
|
||||
if (!this.updateEnabled && !checkHotfix)
|
||||
return;
|
||||
|
||||
Services.obs.notifyObservers(null, "addons-background-update-start", null);
|
||||
|
||||
// Start this from one to ensure the whole of this function completes before
|
||||
// we can send the complete notification. Some parts can in some cases
|
||||
// complete synchronously before later parts have a chance to increment
|
||||
// pendingUpdates.
|
||||
let pendingUpdates = 1;
|
||||
|
||||
function notifyComplete() {
|
||||
if (--pendingUpdates == 0) {
|
||||
Services.obs.notifyObservers(null,
|
||||
"addons-background-update-complete",
|
||||
null);
|
||||
}
|
||||
}
|
||||
gUpdateCheckInProgress = true;
|
||||
|
||||
return Task.spawn(function* backgroundUpdateTask() {
|
||||
let hotfixID = this.hotfixID;
|
||||
|
||||
let checkHotfix = hotfixID &&
|
||||
Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) &&
|
||||
Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO);
|
||||
|
||||
if (!this.updateEnabled && !checkHotfix)
|
||||
return;
|
||||
|
||||
Services.obs.notifyObservers(null, "addons-background-update-start", null);
|
||||
|
||||
if (this.updateEnabled) {
|
||||
let scope = {};
|
||||
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", scope);
|
||||
scope.LightweightThemeManager.updateCurrentTheme();
|
||||
|
||||
let aAddons = yield new Promise((resolve, reject) => this.getAllAddons(resolve));
|
||||
if (this.updateEnabled) {
|
||||
let scope = {};
|
||||
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", scope);
|
||||
scope.LightweightThemeManager.updateCurrentTheme();
|
||||
|
||||
pendingUpdates++;
|
||||
this.getAllAddons(function getAddonsCallback(aAddons) {
|
||||
// If there is a known hotfix then exclude it from the list of add-ons to update.
|
||||
var ids = [a.id for each (a in aAddons) if (a.id != hotfixID)];
|
||||
|
||||
// Repopulate repository cache first, to ensure compatibility overrides
|
||||
// are up to date before checking for addon updates.
|
||||
yield new Promise((resolve, reject) => AddonRepository.backgroundUpdateCheck(ids, resolve));
|
||||
AddonRepository.backgroundUpdateCheck(
|
||||
ids, function BUC_backgroundUpdateCheckCallback() {
|
||||
pendingUpdates += aAddons.length;
|
||||
aAddons.forEach(function BUC_forEachCallback(aAddon) {
|
||||
if (aAddon.id == hotfixID) {
|
||||
notifyComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep track of all the async add-on updates happening in parallel
|
||||
let updates = [];
|
||||
|
||||
for (let aAddon of aAddons) {
|
||||
if (aAddon.id == hotfixID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check all add-ons for updates so that any compatibility updates will
|
||||
// be applied
|
||||
updates.push(new Promise((resolve, reject) => {
|
||||
// Check all add-ons for updates so that any compatibility updates will
|
||||
// be applied
|
||||
aAddon.findUpdates({
|
||||
onUpdateAvailable: function BUC_onUpdateAvailable(aAddon, aInstall) {
|
||||
// Start installing updates when the add-on can be updated and
|
||||
// background updates should be applied.
|
||||
if (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE &&
|
||||
AddonManager.shouldAutoUpdate(aAddon)) {
|
||||
// XXX we really should resolve when this install is done,
|
||||
// not when update-available check completes, no?
|
||||
aInstall.install();
|
||||
}
|
||||
},
|
||||
|
||||
onUpdateFinished: resolve
|
||||
onUpdateFinished: notifyComplete
|
||||
}, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
|
||||
}));
|
||||
}
|
||||
yield Promise.all(updates);
|
||||
}
|
||||
|
||||
if (checkHotfix) {
|
||||
var hotfixVersion = "";
|
||||
try {
|
||||
hotfixVersion = Services.prefs.getCharPref(PREF_EM_HOTFIX_LASTVERSION);
|
||||
}
|
||||
catch (e) { }
|
||||
|
||||
let url = null;
|
||||
if (Services.prefs.getPrefType(PREF_EM_HOTFIX_URL) == Ci.nsIPrefBranch.PREF_STRING)
|
||||
url = Services.prefs.getCharPref(PREF_EM_HOTFIX_URL);
|
||||
else
|
||||
url = Services.prefs.getCharPref(PREF_EM_UPDATE_BACKGROUND_URL);
|
||||
|
||||
// Build the URI from a fake add-on data.
|
||||
url = AddonManager.escapeAddonURI({
|
||||
id: hotfixID,
|
||||
version: hotfixVersion,
|
||||
userDisabled: false,
|
||||
appDisabled: false
|
||||
}, url);
|
||||
|
||||
Components.utils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm");
|
||||
let update = null;
|
||||
try {
|
||||
let foundUpdates = yield new Promise((resolve, reject) => {
|
||||
AddonUpdateChecker.checkForUpdates(hotfixID, null, url, {
|
||||
onUpdateCheckComplete: resolve,
|
||||
onUpdateCheckError: reject
|
||||
});
|
||||
});
|
||||
update = AddonUpdateChecker.getNewestCompatibleUpdate(foundUpdates);
|
||||
} catch (e) {
|
||||
// AUC.checkForUpdates already logged the error
|
||||
}
|
||||
|
||||
// Check that we have a hotfix update, and it's newer than the one we already
|
||||
// have installed (if any)
|
||||
if (update) {
|
||||
if (Services.vc.compare(hotfixVersion, update.version) < 0) {
|
||||
logger.debug("Downloading hotfix version " + update.version);
|
||||
let aInstall = yield new Promise((resolve, reject) =>
|
||||
AddonManager.getInstallForURL(update.updateURL, resolve,
|
||||
"application/x-xpinstall", update.updateHash, null,
|
||||
null, update.version));
|
||||
notifyComplete();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (checkHotfix) {
|
||||
var hotfixVersion = "";
|
||||
try {
|
||||
hotfixVersion = Services.prefs.getCharPref(PREF_EM_HOTFIX_LASTVERSION);
|
||||
}
|
||||
catch (e) { }
|
||||
|
||||
let url = null;
|
||||
if (Services.prefs.getPrefType(PREF_EM_HOTFIX_URL) == Ci.nsIPrefBranch.PREF_STRING)
|
||||
url = Services.prefs.getCharPref(PREF_EM_HOTFIX_URL);
|
||||
else
|
||||
url = Services.prefs.getCharPref(PREF_EM_UPDATE_BACKGROUND_URL);
|
||||
|
||||
// Build the URI from a fake add-on data.
|
||||
url = AddonManager.escapeAddonURI({
|
||||
id: hotfixID,
|
||||
version: hotfixVersion,
|
||||
userDisabled: false,
|
||||
appDisabled: false
|
||||
}, url);
|
||||
|
||||
pendingUpdates++;
|
||||
Components.utils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm");
|
||||
AddonUpdateChecker.checkForUpdates(hotfixID, null, url, {
|
||||
onUpdateCheckComplete: function BUC_onUpdateCheckComplete(aUpdates) {
|
||||
let update = AddonUpdateChecker.getNewestCompatibleUpdate(aUpdates);
|
||||
if (!update) {
|
||||
notifyComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
// If the available version isn't newer than the last installed
|
||||
// version then ignore it.
|
||||
if (Services.vc.compare(hotfixVersion, update.version) >= 0) {
|
||||
notifyComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug("Downloading hotfix version " + update.version);
|
||||
AddonManager.getInstallForURL(update.updateURL,
|
||||
function BUC_getInstallForURL(aInstall) {
|
||||
aInstall.addListener({
|
||||
onDownloadEnded: function BUC_onDownloadEnded(aInstall) {
|
||||
try {
|
||||
@ -1286,15 +1283,17 @@ var AddonManagerInternal = {
|
||||
});
|
||||
|
||||
aInstall.install();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gUpdateCheckInProgress = false;
|
||||
Services.obs.notifyObservers(null,
|
||||
"addons-background-update-complete",
|
||||
null);
|
||||
}.bind(this));
|
||||
notifyComplete();
|
||||
}, "application/x-xpinstall", update.updateHash, null,
|
||||
null, update.version);
|
||||
},
|
||||
|
||||
onUpdateCheckError: notifyComplete
|
||||
});
|
||||
}
|
||||
|
||||
notifyComplete();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -3610,13 +3610,7 @@ this.XPIProvider = {
|
||||
* The AddonInstall to remove
|
||||
*/
|
||||
removeActiveInstall: function XPI_removeActiveInstall(aInstall) {
|
||||
let where = this.installs.indexOf(aInstall);
|
||||
if (where == -1) {
|
||||
logger.warn("removeActiveInstall: could not find active install for "
|
||||
+ aInstall.sourceURI.spec);
|
||||
return;
|
||||
}
|
||||
this.installs.splice(where, 1);
|
||||
this.installs = this.installs.filter(function installFilter(i) i != aInstall);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -75,7 +75,7 @@ function install_test_addons(aCallback) {
|
||||
// Switch to the test update URL
|
||||
Services.prefs.setCharPref(PREF_UPDATEURL, TESTROOT + "browser_bug557956.rdf");
|
||||
|
||||
executeSoon(aCallback);
|
||||
aCallback();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -41,7 +41,7 @@ add_test(function () {
|
||||
gInstall = new MockInstall(undefined, undefined, addon);
|
||||
gInstall.addTestListener({
|
||||
onNewInstall: function () {
|
||||
executeSoon(run_next_test);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
gProvider.addInstall(gInstall);
|
||||
@ -65,7 +65,7 @@ add_test(function () {
|
||||
}
|
||||
}
|
||||
ok(false, "Item with correct name was not found");
|
||||
executeSoon(run_next_test);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
gInstall.install();
|
||||
|
@ -98,27 +98,9 @@ function test_confirmation(aWindow, aExpectedURLs) {
|
||||
aWindow.document.documentElement.cancelDialog();
|
||||
}
|
||||
|
||||
add_task(function* test_install_from_file() {
|
||||
gManagerWindow = yield open_manager("addons://list/extension");
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
open_manager("addons://list/extension", function(aWindow) {
|
||||
gManagerWindow = aWindow;
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
is(gSawInstallNotification, true, "Should have seen addon-install-started notification.");
|
||||
|
||||
MockFilePicker.cleanup();
|
||||
close_manager(gManagerWindow, function() {
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
add_test(function() {
|
||||
var filePaths = [
|
||||
get_addon_file_url("browser_bug567127_1.xpi"),
|
||||
get_addon_file_url("browser_bug567127_2.xpi")
|
||||
@ -128,9 +110,24 @@ add_test(function() {
|
||||
Services.obs.addObserver(gInstallNotificationObserver,
|
||||
"addon-install-started", false);
|
||||
|
||||
new WindowOpenListener(INSTALL_URI, function(aWindow) {
|
||||
test_confirmation(aWindow, filePaths.map(function(aPath) aPath.spec));
|
||||
}, run_next_test);
|
||||
// Set handler that executes the core test after the window opens,
|
||||
// and resolves the promise when the window closes
|
||||
let pInstallURIClosed = new Promise((resolve, reject) => {
|
||||
new WindowOpenListener(INSTALL_URI, function(aWindow) {
|
||||
try {
|
||||
test_confirmation(aWindow, filePaths.map(function(aPath) aPath.spec));
|
||||
} catch(e) {
|
||||
reject(e);
|
||||
}
|
||||
}, resolve);
|
||||
});
|
||||
|
||||
gManagerWindow.gViewController.doCommand("cmd_installFromFile");
|
||||
|
||||
yield pInstallURIClosed;
|
||||
|
||||
is(gSawInstallNotification, true, "Should have seen addon-install-started notification.");
|
||||
|
||||
MockFilePicker.cleanup();
|
||||
yield close_manager(gManagerWindow);
|
||||
});
|
||||
|
@ -21,18 +21,17 @@ var gTestInstallListener = {
|
||||
|
||||
onInstallEnded: function(aInstall) {
|
||||
check_hidden(false);
|
||||
executeSoon(run_next_test);
|
||||
run_next_test();
|
||||
},
|
||||
|
||||
onInstallCancelled: function(aInstall) {
|
||||
ok(gExpectedCancel, "Should expect install cancel");
|
||||
check_hidden(false);
|
||||
executeSoon(run_next_test);
|
||||
run_next_test();
|
||||
},
|
||||
|
||||
onInstallFailed: function(aInstall) {
|
||||
ok(false, "Did not expect onInstallFailed");
|
||||
executeSoon(run_next_test);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -40,7 +40,7 @@ function install_locale(aCallback) {
|
||||
gInstall.addTestListener({
|
||||
onInstallEnded: function(aInstall) {
|
||||
gInstall.removeTestListener(this);
|
||||
executeSoon(aCallback);
|
||||
aCallback();
|
||||
}
|
||||
});
|
||||
gInstall.install();
|
||||
|
@ -97,7 +97,7 @@ add_test(function() {
|
||||
},
|
||||
onInstallEnded: function() {
|
||||
check_list(gItem);
|
||||
executeSoon(run_next_test);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
|
||||
@ -136,7 +136,7 @@ add_test(function() {
|
||||
onInstallEnded: function() {
|
||||
check_list(null);
|
||||
extension.cancel();
|
||||
executeSoon(run_next_test);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -15,56 +15,51 @@ const PREF_APP_UPDATE_ENABLED = "app.update.enabled";
|
||||
|
||||
const HOTFIX_ID = "hotfix@tests.mozilla.org";
|
||||
|
||||
/*
|
||||
* Register an addon install listener and return a promise that:
|
||||
* resolves with the AddonInstall object if the install succeeds
|
||||
* rejects with the AddonInstall if the install fails
|
||||
*/
|
||||
function promiseInstallListener() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let listener = {
|
||||
onInstallEnded: ai => {
|
||||
AddonManager.removeInstallListener(listener);
|
||||
resolve(ai);
|
||||
},
|
||||
onDownloadCancelled: ai => {
|
||||
AddonManager.removeInstallListener(listener);
|
||||
reject(ai);
|
||||
}
|
||||
};
|
||||
AddonManager.addInstallListener(listener);
|
||||
});
|
||||
var gNextTest;
|
||||
|
||||
var SuccessfulInstallListener = {
|
||||
onDownloadCancelled: function(aInstall) {
|
||||
ok(false, "Should not have seen the download cancelled");
|
||||
is(aInstall.addon.id, HOTFIX_ID, "Should have seen the right add-on");
|
||||
|
||||
AddonManager.removeInstallListener(this);
|
||||
gNextTest();
|
||||
},
|
||||
|
||||
onInstallEnded: function(aInstall) {
|
||||
ok(true, "Should have seen the install complete");
|
||||
is(aInstall.addon.id, HOTFIX_ID, "Should have installed the right add-on");
|
||||
|
||||
AddonManager.removeInstallListener(this);
|
||||
aInstall.addon.uninstall();
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION);
|
||||
gNextTest();
|
||||
}
|
||||
}
|
||||
|
||||
function promiseSuccessfulInstall() {
|
||||
return promiseInstallListener().then(
|
||||
aInstall => {
|
||||
ok(true, "Should have seen the install complete");
|
||||
is(aInstall.addon.id, HOTFIX_ID, "Should have installed the right add-on");
|
||||
aInstall.addon.uninstall();
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION);
|
||||
},
|
||||
aInstall => {
|
||||
ok(false, "Should not have seen the download cancelled");
|
||||
is(aInstall.addon.id, HOTFIX_ID, "Should have seen the right add-on");
|
||||
});
|
||||
var FailedInstallListener = {
|
||||
onDownloadCancelled: function(aInstall) {
|
||||
ok(true, "Should have seen the download cancelled");
|
||||
is(aInstall.addon.id, HOTFIX_ID, "Should have seen the right add-on");
|
||||
|
||||
AddonManager.removeInstallListener(this);
|
||||
gNextTest();
|
||||
},
|
||||
|
||||
onInstallEnded: function(aInstall) {
|
||||
ok(false, "Should not have seen the install complete");
|
||||
is(aInstall.addon.id, HOTFIX_ID, "Should have installed the right add-on");
|
||||
|
||||
AddonManager.removeInstallListener(this);
|
||||
aInstall.addon.uninstall();
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION);
|
||||
gNextTest();
|
||||
}
|
||||
}
|
||||
|
||||
function promiseFailedInstall() {
|
||||
return promiseInstallListener().then(
|
||||
aInstall => {
|
||||
ok(false, "Should not have seen the install complete");
|
||||
is(aInstall.addon.id, HOTFIX_ID, "Should have installed the right add-on");
|
||||
aInstall.addon.uninstall();
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION);
|
||||
},
|
||||
aInstall => {
|
||||
ok(true, "Should have seen the download cancelled");
|
||||
is(aInstall.addon.id, HOTFIX_ID, "Should have seen the right add-on");
|
||||
});
|
||||
}
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
add_task(function setup() {
|
||||
Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, true);
|
||||
Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false);
|
||||
Services.prefs.setBoolPref(PREF_UPDATE_REQUIREBUILTINCERTS, false);
|
||||
@ -83,85 +78,109 @@ add_task(function setup() {
|
||||
var prefs = Services.prefs.getChildList(PREF_EM_HOTFIX_CERTS);
|
||||
prefs.forEach(Services.prefs.clearUserPref);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* check_no_cert_checks() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
finish();
|
||||
}
|
||||
|
||||
add_test(function check_no_cert_checks() {
|
||||
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, false);
|
||||
yield Promise.all([
|
||||
promiseSuccessfulInstall(),
|
||||
AddonManagerPrivate.backgroundUpdateCheck()
|
||||
]);
|
||||
AddonManager.addInstallListener(SuccessfulInstallListener);
|
||||
|
||||
gNextTest = run_next_test;
|
||||
|
||||
AddonManagerPrivate.backgroundUpdateCheck();
|
||||
});
|
||||
|
||||
add_task(function* check_wrong_cert_fingerprint() {
|
||||
add_test(function check_wrong_cert_fingerprint() {
|
||||
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true);
|
||||
Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "foo");
|
||||
|
||||
yield Promise.all([
|
||||
promiseFailedInstall(),
|
||||
AddonManagerPrivate.backgroundUpdateCheck()
|
||||
]);
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
|
||||
AddonManager.addInstallListener(FailedInstallListener);
|
||||
|
||||
gNextTest = function() {
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
|
||||
|
||||
run_next_test();
|
||||
};
|
||||
|
||||
AddonManagerPrivate.backgroundUpdateCheck();
|
||||
});
|
||||
|
||||
add_task(function* check_right_cert_fingerprint() {
|
||||
add_test(function check_right_cert_fingerprint() {
|
||||
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true);
|
||||
Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "3E:B9:4E:07:12:FE:3C:01:41:46:13:46:FC:84:52:1A:8C:BE:1D:A2");
|
||||
|
||||
yield Promise.all([
|
||||
promiseSuccessfulInstall(),
|
||||
AddonManagerPrivate.backgroundUpdateCheck()
|
||||
]);
|
||||
AddonManager.addInstallListener(SuccessfulInstallListener);
|
||||
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
|
||||
gNextTest = function() {
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
|
||||
|
||||
run_next_test();
|
||||
};
|
||||
|
||||
AddonManagerPrivate.backgroundUpdateCheck();
|
||||
});
|
||||
|
||||
add_task(function* check_multi_cert_fingerprint_1() {
|
||||
add_test(function check_multi_cert_fingerprint_1() {
|
||||
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true);
|
||||
Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "3E:B9:4E:07:12:FE:3C:01:41:46:13:46:FC:84:52:1A:8C:BE:1D:A2");
|
||||
Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint", "foo");
|
||||
|
||||
yield Promise.all([
|
||||
promiseSuccessfulInstall(),
|
||||
AddonManagerPrivate.backgroundUpdateCheck()
|
||||
]);
|
||||
AddonManager.addInstallListener(SuccessfulInstallListener);
|
||||
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint");
|
||||
gNextTest = function() {
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint");
|
||||
|
||||
run_next_test();
|
||||
};
|
||||
|
||||
AddonManagerPrivate.backgroundUpdateCheck();
|
||||
});
|
||||
|
||||
add_task(function* check_multi_cert_fingerprint_2() {
|
||||
add_test(function check_multi_cert_fingerprint_2() {
|
||||
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true);
|
||||
Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "foo");
|
||||
Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint", "3E:B9:4E:07:12:FE:3C:01:41:46:13:46:FC:84:52:1A:8C:BE:1D:A2");
|
||||
|
||||
yield Promise.all([
|
||||
promiseSuccessfulInstall(),
|
||||
AddonManagerPrivate.backgroundUpdateCheck()
|
||||
]);
|
||||
AddonManager.addInstallListener(SuccessfulInstallListener);
|
||||
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint");
|
||||
gNextTest = function() {
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "2.sha1Fingerprint");
|
||||
|
||||
run_next_test();
|
||||
};
|
||||
|
||||
AddonManagerPrivate.backgroundUpdateCheck();
|
||||
});
|
||||
|
||||
add_task(function* check_no_cert_no_checks() {
|
||||
add_test(function check_no_cert_no_checks() {
|
||||
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, false);
|
||||
Services.prefs.setCharPref(PREF_EM_HOTFIX_URL, TESTROOT + "unsigned_hotfix.rdf");
|
||||
|
||||
yield Promise.all([
|
||||
promiseSuccessfulInstall(),
|
||||
AddonManagerPrivate.backgroundUpdateCheck()
|
||||
]);
|
||||
AddonManager.addInstallListener(SuccessfulInstallListener);
|
||||
|
||||
gNextTest = run_next_test;
|
||||
|
||||
AddonManagerPrivate.backgroundUpdateCheck();
|
||||
});
|
||||
|
||||
add_task(function* check_no_cert_cert_fingerprint_check() {
|
||||
add_test(function check_no_cert_cert_fingerprint_check() {
|
||||
Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true);
|
||||
Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", "3E:B9:4E:07:12:FE:3C:01:41:46:13:46:FC:84:52:1A:8C:BE:1D:A2");
|
||||
|
||||
yield Promise.all([
|
||||
promiseFailedInstall(),
|
||||
AddonManagerPrivate.backgroundUpdateCheck()
|
||||
]);
|
||||
AddonManager.addInstallListener(FailedInstallListener);
|
||||
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
|
||||
gNextTest = function() {
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint");
|
||||
|
||||
run_next_test();
|
||||
};
|
||||
|
||||
AddonManagerPrivate.backgroundUpdateCheck();
|
||||
});
|
||||
|
@ -184,7 +184,7 @@ add_test(function() {
|
||||
is_element_hidden(item._installStatus, "Install progress widget should be hidden");
|
||||
|
||||
if (badgeUpdated)
|
||||
executeSoon(run_next_test);
|
||||
run_next_test();
|
||||
else
|
||||
installCompleted = true;
|
||||
}
|
||||
|
@ -566,7 +566,7 @@ add_test(function() {
|
||||
|
||||
is(installBtn.hidden, true, "Install button should be hidden after install ended");
|
||||
check_filtered_results(QUERY, "relevancescore", false);
|
||||
executeSoon(run_next_test);
|
||||
run_next_test();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ function install_test_addon(aCallback) {
|
||||
onInstallEnded: function() {
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) {
|
||||
gTestAddon = addon;
|
||||
executeSoon(aCallback);
|
||||
aCallback();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -336,6 +336,7 @@ function open_manager(aView, aCallback, aLoadCallback, aLongerTimeout) {
|
||||
}
|
||||
});
|
||||
|
||||
// The promise resolves with the manager window, so it is passed to the callback
|
||||
return log_callback(p, aCallback);
|
||||
}
|
||||
|
||||
@ -347,13 +348,19 @@ function close_manager(aManagerWindow, aCallback, aLongerTimeout) {
|
||||
is(aManagerWindow.location, MANAGER_URI, "Should be closing window with correct URI");
|
||||
|
||||
aManagerWindow.addEventListener("unload", function() {
|
||||
info("Manager window unloaded");
|
||||
this.removeEventListener("unload", arguments.callee, false);
|
||||
resolve();
|
||||
try {
|
||||
dump("Manager window unload handler");
|
||||
this.removeEventListener("unload", arguments.callee, false);
|
||||
resolve();
|
||||
} catch(e) {
|
||||
reject(e);
|
||||
}
|
||||
}, false);
|
||||
});
|
||||
|
||||
info("Telling manager window to close");
|
||||
aManagerWindow.close();
|
||||
info("Manager window close() call returned");
|
||||
|
||||
return log_callback(p, aCallback);
|
||||
}
|
||||
|
@ -1775,9 +1775,43 @@ RENDER_AGAIN:
|
||||
|
||||
DrawThemeBackground(theme, hdc, MENU_POPUPSEPARATOR, /* state */ 0, &sepRect, &clipRect);
|
||||
}
|
||||
else if (aWidgetType == NS_THEME_MENUARROW)
|
||||
{
|
||||
// We're dpi aware and as such on systems that have dpi > 96 set, the
|
||||
// theme library expects us to do proper positioning and scaling of glyphs.
|
||||
// For NS_THEME_MENUARROW, layout may hand us a widget rect larger than the
|
||||
// glyph rect we request in GetMinimumWidgetSize. To prevent distortion we
|
||||
// have to position and scale what we draw.
|
||||
|
||||
SIZE glyphSize;
|
||||
GetThemePartSize(theme, hdc, part, state, nullptr, TS_TRUE, &glyphSize);
|
||||
|
||||
int32_t widgetHeight = widgetRect.bottom - widgetRect.top;
|
||||
|
||||
RECT renderRect = widgetRect;
|
||||
|
||||
// We request (glyph width * 2, glyph height) in GetMinimumWidgetSize. In
|
||||
// Firefox some menu items provide the full height of the item to us, in
|
||||
// others our widget rect is the exact dims of our arrow glyph. Adjust the
|
||||
// vertical position by the added space, if any exists.
|
||||
renderRect.top += ((widgetHeight - glyphSize.cy) / 2);
|
||||
renderRect.bottom = renderRect.top + glyphSize.cy;
|
||||
// I'm using the width of the arrow glyph for the arrow-side padding.
|
||||
// AFAICT there doesn't appear to be a theme constant we can query
|
||||
// for this value. Generally this looks correct, and has the added
|
||||
// benefit of being a dpi adjusted value.
|
||||
if (!IsFrameRTL(aFrame)) {
|
||||
renderRect.right = widgetRect.right - glyphSize.cx;
|
||||
renderRect.left = renderRect.right - glyphSize.cx;
|
||||
} else {
|
||||
renderRect.left = glyphSize.cx;
|
||||
renderRect.right = renderRect.left + glyphSize.cx;
|
||||
}
|
||||
DrawThemeBGRTLAware(theme, hdc, part, state, &renderRect, &clipRect,
|
||||
IsFrameRTL(aFrame));
|
||||
}
|
||||
// The following widgets need to be RTL-aware
|
||||
else if (aWidgetType == NS_THEME_MENUARROW ||
|
||||
aWidgetType == NS_THEME_RESIZER ||
|
||||
else if (aWidgetType == NS_THEME_RESIZER ||
|
||||
aWidgetType == NS_THEME_DROPDOWN_BUTTON)
|
||||
{
|
||||
DrawThemeBGRTLAware(theme, hdc, part, state,
|
||||
@ -2239,11 +2273,6 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsRenderingContext* aContext, nsIFrame* a
|
||||
case NS_THEME_MENUITEMTEXT:
|
||||
return NS_OK;
|
||||
|
||||
case NS_THEME_MENUARROW:
|
||||
aResult->width = 26;
|
||||
aResult->height = 16;
|
||||
return NS_OK;
|
||||
|
||||
case NS_THEME_PROGRESSBAR:
|
||||
case NS_THEME_PROGRESSBAR_VERTICAL:
|
||||
// Best-fit size for progress meters is too large for most
|
||||
@ -2403,6 +2432,14 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsRenderingContext* aContext, nsIFrame* a
|
||||
aResult->width += gutterSize.cx;
|
||||
break;
|
||||
}
|
||||
|
||||
case NS_THEME_MENUARROW:
|
||||
{
|
||||
// Use the width of the arrow glyph as padding. See the drawing
|
||||
// code for details.
|
||||
aResult->width *= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
::ReleaseDC(nullptr, hdc);
|
||||
|
Loading…
Reference in New Issue
Block a user