merge fx-team to mozilla-central

This commit is contained in:
Carsten "Tomcat" Book 2014-01-31 12:52:17 +01:00
Родитель c2edd2f424 e1b5ca4be3
Коммит f1a2c94d74
246 изменённых файлов: 2057 добавлений и 1498 удалений

Просмотреть файл

@ -1236,9 +1236,11 @@ pref("devtools.hud.loglimit.console", 200);
// - tabsize: how many spaces to use when a Tab character is displayed.
// - expandtab: expand Tab characters to spaces.
// - keymap: which keymap to use (can be 'default', 'emacs' or 'vim')
// - autoclosebrackets: whether to permit automatic bracket/quote closing.
pref("devtools.editor.tabsize", 4);
pref("devtools.editor.expandtab", true);
pref("devtools.editor.keymap", "default");
pref("devtools.editor.autoclosebrackets", true);
// Enable the Font Inspector
pref("devtools.fontinspector.enabled", true);

Просмотреть файл

@ -9,7 +9,8 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/FxAccounts.jsm");
const PREF_LAST_FXA_USER = "identity.fxaccounts.lastSignedInUser";
const PREF_LAST_FXA_USER = "identity.fxaccounts.lastSignedInUserHash";
const PREF_SYNC_SHOW_CUSTOMIZATION = "services.sync.ui.showCustomizationDialog";
function log(msg) {
//dump("FXA: " + msg + "\n");
@ -19,7 +20,7 @@ function error(msg) {
console.log("Firefox Account Error: " + msg + "\n");
};
function getPreviousAccountName() {
function getPreviousAccountNameHash() {
try {
return Services.prefs.getComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString).data;
} catch (_) {
@ -27,24 +28,39 @@ function getPreviousAccountName() {
}
}
function setPreviousAccountName(acctName) {
function setPreviousAccountNameHash(acctName) {
let string = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
string.data = acctName;
string.data = sha256(acctName);
Services.prefs.setComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString, string);
}
function needRelinkWarning(accountData) {
let prevAcct = getPreviousAccountName();
return prevAcct && prevAcct != accountData.email;
function needRelinkWarning(acctName) {
let prevAcctHash = getPreviousAccountNameHash();
return prevAcctHash && prevAcctHash != sha256(acctName);
}
function promptForRelink() {
// Given a string, returns the SHA265 hash in base64
function sha256(str) {
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
// Data is an array of bytes.
let data = converter.convertToByteArray(str, {});
let hasher = Cc["@mozilla.org/security/hash;1"]
.createInstance(Ci.nsICryptoHash);
hasher.init(hasher.SHA256);
hasher.update(data, data.length);
return hasher.finish(true);
}
function promptForRelink(acctName) {
let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
let continueLabel = sb.GetStringFromName("continue.label");
let title = sb.GetStringFromName("relink.verify.title");
let description = sb.formatStringFromName("relink.verify.description",
[Services.prefs.getCharPref(PREF_LAST_FXA_USER)], 1);
[acctName], 1);
let body = sb.GetStringFromName("relink.verify.heading") +
"\n\n" + description;
let ps = Services.prompt;
@ -104,7 +120,7 @@ let wrapper = {
log("Received: 'login'. Data:" + JSON.stringify(accountData));
if (accountData.customizeSync) {
Services.prefs.setBoolPref("services.sync.needsCustomization", true);
Services.prefs.setBoolPref(PREF_SYNC_SHOW_CUSTOMIZATION, true);
delete accountData.customizeSync;
}
@ -113,7 +129,8 @@ let wrapper = {
// (This is sync-specific, so ideally would be in sync's identity module,
// but it's a little more seamless to do here, and sync is currently the
// only fxa consumer, so...
if (needRelinkWarning(accountData) && !promptForRelink()) {
let newAccountEmail = accountData.email;
if (needRelinkWarning(newAccountEmail) && !promptForRelink(newAccountEmail)) {
// we need to tell the page we successfully received the message, but
// then bail without telling fxAccounts
this.injectData("message", { status: "login" });
@ -123,7 +140,7 @@ let wrapper = {
}
// Remember who it was so we can log out next time.
setPreviousAccountName(accountData.email);
setPreviousAccountNameHash(newAccountEmail);
fxAccounts.setSignedInUser(accountData).then(
() => {

Просмотреть файл

@ -61,14 +61,14 @@
<section>
<div class="graphic graphic-sync-intro"> </div>
<div class="description">&aboutAccountsSetup.description;</div>
<div class="description">&aboutAccountsConfig.description;</div>
<div class="button-row">
<a class="button" href="#" onclick="getStarted()">&aboutAccountsSetup.startButton.label;</a>
<a class="button" href="#" onclick="getStarted()">&aboutAccountsConfig.startButton.label;</a>
</div>
<div class="links">
<a id="oldsync" href="#" onclick="handleOldSync();">&aboutAccountsSetup.useOldSync.label;</a>
<a id="oldsync" href="#" onclick="handleOldSync();">&aboutAccountsConfig.useOldSync.label;</a>
</div>
</section>
</div>

Просмотреть файл

@ -310,6 +310,11 @@ var FullZoom = {
if (token.isCurrent) {
ZoomManager.setZoomForBrowser(browser, value === undefined ? 1 : value);
this._ignorePendingZoomAccesses(browser);
this._executeSoon(function () {
// _getGlobalValue may be either sync or async, so notify asyncly so
// observers are guaranteed consistent behavior.
Services.obs.notifyObservers(null, "browser-fullZoom:reset", "");
});
}
});
this._removePref(browser);

Просмотреть файл

@ -6,10 +6,11 @@ XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () {
return Cu.import("resource://gre/modules/FxAccountsCommon.js", {});
});
const PREF_SYNC_START_DOORHANGER = "services.sync.ui.showSyncStartDoorhanger";
let gFxAccounts = {
_initialized: false,
_originalLabel: null,
_inCustomizationMode: false,
get weave() {
@ -20,29 +21,46 @@ let gFxAccounts = {
},
get topics() {
// Do all this dance to lazy-load FxAccountsCommon.
delete this.topics;
return this.topics = [
"weave:service:sync:start",
"weave:service:login:error",
FxAccountsCommon.ONLOGIN_NOTIFICATION,
FxAccountsCommon.ONVERIFIED_NOTIFICATION,
FxAccountsCommon.ONLOGOUT_NOTIFICATION
];
},
// The set of topics that only the active window should handle.
get activeWindowTopics() {
// Do all this dance to lazy-load FxAccountsCommon.
delete this.activeWindowTopics;
return this.activeWindowTopics = new Set([
"weave:service:sync:start",
FxAccountsCommon.ONVERIFIED_NOTIFICATION
]);
},
get button() {
delete this.button;
return this.button = document.getElementById("PanelUI-fxa-status");
},
get syncNeedsCustomization() {
try {
return Services.prefs.getBoolPref("services.sync.needsCustomization");
} catch (e) {
return false;
}
get loginFailed() {
return Weave.Service.identity.readyToAuthenticate &&
Weave.Status.login != Weave.LOGIN_SUCCEEDED;
},
get isActiveWindow() {
let mostRecentNonPopupWindow =
RecentWindow.getMostRecentBrowserWindow({allowPopups: false});
return window == mostRecentNonPopupWindow;
},
init: function () {
if (this._initialized) {
// Bail out if we're already initialized and for pop-up windows.
if (this._initialized || !window.toolbar.visible) {
return;
}
@ -53,9 +71,6 @@ let gFxAccounts = {
gNavToolbox.addEventListener("customizationstarting", this);
gNavToolbox.addEventListener("customizationending", this);
// Save the button's original label so that
// we can restore it if overridden later.
this._originalLabel = this.button.getAttribute("label");
this._initialized = true;
this.updateUI();
@ -74,9 +89,33 @@ let gFxAccounts = {
},
observe: function (subject, topic) {
if (topic != FxAccountsCommon.ONVERIFIED_NOTIFICATION) {
this.updateUI();
} else if (!this.syncNeedsCustomization) {
// Ignore certain topics if we're not the active window.
if (this.activeWindowTopics.has(topic) && !this.isActiveWindow) {
return;
}
switch (topic) {
case FxAccountsCommon.ONVERIFIED_NOTIFICATION:
Services.prefs.setBoolPref(PREF_SYNC_START_DOORHANGER, true);
break;
case "weave:service:sync:start":
this.onSyncStart();
break;
default:
this.updateUI();
break;
}
},
onSyncStart: function () {
let showDoorhanger = false;
try {
showDoorhanger = Services.prefs.getBoolPref(PREF_SYNC_START_DOORHANGER);
} catch (e) { /* The pref might not exist. */ }
if (showDoorhanger) {
Services.prefs.clearUserPref(PREF_SYNC_START_DOORHANGER);
this.showSyncStartedDoorhanger();
}
},
@ -122,17 +161,27 @@ let gFxAccounts = {
this.button.removeAttribute("disabled");
}
let defaultLabel = this.button.getAttribute("defaultlabel");
let errorLabel = this.button.getAttribute("errorlabel");
// If the user is signed into their Firefox account and we are not
// currently in customization mode, show their email address.
fxAccounts.getSignedInUser().then(userData => {
if (userData && !this._inCustomizationMode) {
this.button.setAttribute("signedin", "true");
this.button.setAttribute("label", userData.email);
this.button.setAttribute("tooltiptext", userData.email);
} else {
this.button.removeAttribute("signedin");
this.button.setAttribute("label", this._originalLabel);
this.button.removeAttribute("tooltiptext");
// Reset the button to its original state.
this.button.setAttribute("label", defaultLabel);
this.button.removeAttribute("tooltiptext");
this.button.removeAttribute("signedin");
this.button.removeAttribute("failed");
if (!this._inCustomizationMode) {
if (this.loginFailed) {
this.button.setAttribute("failed", "true");
this.button.setAttribute("label", errorLabel);
} else if (userData) {
this.button.setAttribute("signedin", "true");
this.button.setAttribute("label", userData.email);
this.button.setAttribute("tooltiptext", userData.email);
}
}
});
},

Просмотреть файл

@ -15,6 +15,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
"resource://gre/modules/CharsetMenu.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils",
"resource://gre/modules/ShortcutUtils.jsm");
const nsIWebNavigation = Ci.nsIWebNavigation;
@ -3731,6 +3733,22 @@ var XULBrowserWindow = {
setTimeout(function () { XULBrowserWindow.asyncUpdateUI(); }, 0);
else
this.asyncUpdateUI();
#ifdef MOZ_CRASHREPORTER
if (aLocationURI) {
let uri = aLocationURI.clone();
try {
// If the current URI contains a username/password, remove it.
uri.userPass = "";
} catch (ex) { /* Ignore failures on about: URIs. */ }
try {
gCrashReporter.annotateCrashReport("URL", uri.spec);
} catch (ex if ex.result == Components.results.NS_ERROR_NOT_INITIALIZED) {
// Don't make noise when the crash reporter is built but not enabled.
}
}
#endif
},
asyncUpdateUI: function () {
@ -3990,15 +4008,6 @@ var CombinedStopReload = {
var TabsProgressListener = {
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
#ifdef MOZ_CRASHREPORTER
if (aRequest instanceof Ci.nsIChannel &&
aStateFlags & Ci.nsIWebProgressListener.STATE_START &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT &&
gCrashReporter.enabled) {
gCrashReporter.annotateCrashReport("URL", aRequest.URI.spec);
}
#endif
// Collect telemetry data about tab load times.
if (aWebProgress.isTopLevel) {
if (aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
@ -4820,6 +4829,44 @@ var gHomeButton = {
},
};
const nodeToTooltipMap = {
"bookmarks-menu-button": "bookmarksMenuButton.tooltip",
#ifdef XP_MACOSX
"print-button": "printButton.tooltip",
#endif
"new-window-button": "newWindowButton.tooltip",
"fullscreen-button": "fullscreenButton.tooltip",
"tabview-button": "tabviewButton.tooltip",
};
const nodeToShortcutMap = {
"bookmarks-menu-button": "manBookmarkKb",
#ifdef XP_MACOSX
"print-button": "printKb",
#endif
"new-window-button": "key_newNavigator",
"fullscreen-button": "key_fullScreen",
"tabview-button": "key_tabview",
};
const gDynamicTooltipCache = new Map();
function UpdateDynamicShortcutTooltipText(popupTriggerNode) {
let label = document.getElementById("dynamic-shortcut-tooltip-label");
let nodeId = popupTriggerNode.id;
if (!gDynamicTooltipCache.has(nodeId) && nodeId in nodeToTooltipMap) {
let strId = nodeToTooltipMap[nodeId];
let args = [];
if (nodeId in nodeToShortcutMap) {
let shortcutId = nodeToShortcutMap[nodeId];
let shortcut = document.getElementById(shortcutId);
if (shortcut) {
args.push(ShortcutUtils.prettifyShortcut(shortcut));
}
}
gDynamicTooltipCache.set(nodeId, gNavigatorBundle.getFormattedString(strId, args));
}
let desiredLabel = gDynamicTooltipCache.get(nodeId);
label.setAttribute("value", desiredLabel);
}
/**
* Gets the selected text in the active browser. Leading and trailing
* whitespace is removed, and consecutive whitespace is replaced by a single

Просмотреть файл

@ -210,7 +210,11 @@
<vbox flex="1">
<label id="UITourTooltipTitle" flex="1"/>
<description id="UITourTooltipDescription" flex="1"/>
<hbox id="UITourTooltipButtons" flex="1" align="end"/>
<hbox id="UITourTooltipButtons" flex="1" align="center"/>
</vbox>
<vbox align="start">
<toolbarbutton id="UITourTooltipClose" class="close-icon"
tooltiptext="&uiTour.infoPanel.close;"/>
</vbox>
</hbox>
</panel>
@ -463,6 +467,11 @@
<vbox id="downloads-indicator-notification"/>
</vbox>
</hbox>
<tooltip id="dynamic-shortcut-tooltip"
onpopupshowing="UpdateDynamicShortcutTooltipText(this.triggerNode)">
<label id="dynamic-shortcut-tooltip-label"/>
</tooltip>
</popupset>
#ifdef CAN_DRAW_IN_TITLEBAR
@ -744,7 +753,7 @@
removable="true"
type="menu-button"
label="&bookmarksMenuButton.label;"
tooltiptext="&bookmarksMenuButton.tooltip;"
tooltip="dynamic-shortcut-tooltip"
anchor="dropmarker"
ondragenter="PlacesMenuDNDHandler.onDragEnter(event);"
ondragover="PlacesMenuDNDHandler.onDragOver(event);"
@ -964,17 +973,17 @@
<toolbarbutton id="print-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
#ifdef XP_MACOSX
command="cmd_print"
command="cmd_print" tooltip="dynamic-shortcut-tooltip"
#else
command="cmd_printPreview"
command="cmd_printPreview" tooltiptext="&printButton.tooltip;"
#endif
label="&printButton.label;" tooltiptext="&printButton.tooltip;"/>
label="&printButton.label;"/>
<toolbarbutton id="new-window-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
label="&newNavigatorCmd.label;"
command="key_newNavigator"
tooltiptext="&newWindowButton.tooltip;"
tooltip="dynamic-shortcut-tooltip"
ondrop="newWindowButtonObserver.onDrop(event)"
ondragover="newWindowButtonObserver.onDragOver(event)"
ondragenter="newWindowButtonObserver.onDragOver(event)"
@ -984,7 +993,7 @@
observes="View:FullScreen"
type="checkbox"
label="&fullScreenCmd.label;"
tooltiptext="&fullScreenButton.tooltip;"/>
tooltip="dynamic-shortcut-tooltip"/>
#ifdef MOZ_SERVICES_SYNC
<toolbarbutton id="sync-button"

Просмотреть файл

@ -1708,11 +1708,13 @@
// solve the problem of windows "obscuring" the prompt.
// see bug #350299 for more details
window.focus();
var warningMessage =
PluralForm.get(tabsToClose, bundle.getString("tabs.closeWarningMultiple"))
.replace("#1", tabsToClose);
var buttonPressed =
ps.confirmEx(window,
bundle.getString("tabs.closeWarningTitle"),
bundle.getFormattedString("tabs.closeWarningMultipleTabs",
[tabsToClose]),
warningMessage,
(ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_0)
+ (ps.BUTTON_TITLE_CANCEL * ps.BUTTON_POS_1),
bundle.getString("tabs.closeButtonMultiple"),

Просмотреть файл

@ -15,7 +15,9 @@
</vbox>
<footer id="PanelUI-footer">
<toolbarbutton id="PanelUI-fxa-status" label="&fxaSignIn.label;"
<toolbarbutton id="PanelUI-fxa-status"
defaultlabel="&fxaSignIn.label;"
errorlabel="&fxaSignInError.label;"
oncommand="gFxAccounts.toggle(event);"
hidden="true"/>

Просмотреть файл

@ -1,50 +1,125 @@
/* 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";
let Preferences = Cu.import("resource://gre/modules/Preferences.jsm", {}).Preferences;
Cu.import("resource://gre/modules/Promise.jsm");
add_task(function() {
yield PanelUI.show({type: "command"});
let historyButton = document.getElementById("history-panelmenu");
let historySubview = document.getElementById("PanelUI-history");
let subviewShownPromise = subviewShown(historySubview);
EventUtils.synthesizeMouseAtCenter(historyButton, {});
yield subviewShownPromise;
let tabsFromOtherComputers = document.getElementById("sync-tabs-menuitem2");
is(tabsFromOtherComputers.hidden, true, "The Tabs From Other Computers menuitem should be hidden when sync isn't enabled.");
let hiddenPanelPromise = promisePanelHidden(window);
PanelUI.hide();
yield hiddenPanelPromise;
// Part 2 - When Sync is enabled the menuitem should be shown.
Weave.Service.createAccount("john@doe.com", "mysecretpw",
"challenge", "response");
Weave.Service.identity.account = "john@doe.com";
Weave.Service.identity.basicPassword = "mysecretpw";
Weave.Service.identity.syncKey = Weave.Utils.generatePassphrase();
Weave.Svc.Prefs.set("firstSync", "newAccount");
Weave.Service.persistLogin();
yield PanelUI.show({type: "command"});
subviewShownPromise = subviewShown(historySubview);
EventUtils.synthesizeMouseAtCenter(historyButton, {});
yield subviewShownPromise;
is(tabsFromOtherComputers.hidden, false, "The Tabs From Other Computers menuitem should be shown when sync is enabled.");
let syncPrefBranch = new Preferences("services.sync.");
syncPrefBranch.resetBranch("");
Services.logins.removeAllLogins();
hiddenPanelPromise = promisePanelHidden(window);
PanelUI.toggle({type: "command"});
yield hiddenPanelPromise;
});
/* 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";
let Preferences = Cu.import("resource://gre/modules/Preferences.jsm", {}).Preferences;
Cu.import("resource://gre/modules/Promise.jsm");
let tmp = {};
Cu.import("resource://gre/modules/FxAccounts.jsm", tmp);
Cu.import("resource://gre/modules/FxAccountsCommon.js", tmp);
Cu.import("resource://services-sync/browserid_identity.js", tmp);
let {FxAccounts, BrowserIDManager, DATA_FORMAT_VERSION, CERT_LIFETIME} = tmp;
let fxaSyncIsEnabled = Weave.Service.identity instanceof BrowserIDManager;
add_task(function() {
yield PanelUI.show({type: "command"});
let historyButton = document.getElementById("history-panelmenu");
let historySubview = document.getElementById("PanelUI-history");
let subviewShownPromise = subviewShown(historySubview);
EventUtils.synthesizeMouseAtCenter(historyButton, {});
yield subviewShownPromise;
let tabsFromOtherComputers = document.getElementById("sync-tabs-menuitem2");
is(tabsFromOtherComputers.hidden, true, "The Tabs From Other Computers menuitem should be hidden when sync isn't enabled.");
let hiddenPanelPromise = promisePanelHidden(window);
PanelUI.hide();
yield hiddenPanelPromise;
// Part 2 - When Sync is enabled the menuitem should be shown.
yield configureIdentity();
yield PanelUI.show({type: "command"});
subviewShownPromise = subviewShown(historySubview);
EventUtils.synthesizeMouseAtCenter(historyButton, {});
yield subviewShownPromise;
is(tabsFromOtherComputers.hidden, false, "The Tabs From Other Computers menuitem should be shown when sync is enabled.");
let syncPrefBranch = new Preferences("services.sync.");
syncPrefBranch.resetBranch("");
Services.logins.removeAllLogins();
hiddenPanelPromise = promisePanelHidden(window);
PanelUI.toggle({type: "command"});
yield hiddenPanelPromise;
if (fxaSyncIsEnabled) {
yield fxAccounts.signOut();
}
});
function configureIdentity() {
// do the FxAccounts thang...
configureFxAccountIdentity();
if (fxaSyncIsEnabled) {
return Weave.Service.identity.initializeWithCurrentIdentity().then(() => {
// need to wait until this identity manager is readyToAuthenticate.
return Weave.Service.identity.whenReadyToAuthenticate.promise;
});
}
Weave.Service.createAccount("john@doe.com", "mysecretpw",
"challenge", "response");
Weave.Service.identity.account = "john@doe.com";
Weave.Service.identity.basicPassword = "mysecretpw";
Weave.Service.identity.syncKey = Weave.Utils.generatePassphrase();
Weave.Svc.Prefs.set("firstSync", "newAccount");
Weave.Service.persistLogin();
return Promise.resolve();
}
// Configure an instance of an FxAccount identity provider with the specified
// config (or the default config if not specified).
function configureFxAccountIdentity() {
let user = {
assertion: "assertion",
email: "email",
kA: "kA",
kB: "kB",
sessionToken: "sessionToken",
uid: "user_uid",
verified: true,
};
let token = {
endpoint: Weave.Svc.Prefs.get("tokenServerURI"),
duration: 300,
id: "id",
key: "key",
// uid will be set to the username.
};
let MockInternal = {
signedInUser: {
version: DATA_FORMAT_VERSION,
accountData: user
},
getCertificate: function(data, keyPair, mustBeValidUntil) {
this.cert = {
validUntil: Date.now() + CERT_LIFETIME,
cert: "certificate",
};
return Promise.resolve(this.cert.cert);
},
};
let mockTSC = { // TokenServerClient
getTokenFromBrowserIDAssertion: function(uri, assertion, cb) {
token.uid = "username";
cb(null, token);
},
};
let authService = Weave.Service.identity;
authService._fxaService = new FxAccounts(MockInternal);
authService._tokenServerClient = mockTSC;
// Set the "account" of the browserId manager to be the "email" of the
// logged in user of the mockFXA service.
authService._account = user.email;
}

Просмотреть файл

@ -5,6 +5,10 @@
Components.utils.import("resource://services-sync/main.js");
Components.utils.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () {
return Components.utils.import("resource://gre/modules/FxAccountsCommon.js", {});
});
const PAGE_NO_ACCOUNT = 0;
const PAGE_HAS_ACCOUNT = 1;
const PAGE_NEEDS_UPDATE = 2;
@ -83,7 +87,8 @@ let gSyncPane = {
"weave:service:login:finish",
"weave:service:start-over",
"weave:service:setup-complete",
"weave:service:logout:finish"];
"weave:service:logout:finish",
FxAccountsCommon.ONVERIFIED_NOTIFICATION];
// Add the observers now and remove them on unload
//XXXzpao This should use Services.obs.* but Weave's Obs does nice handling
@ -127,7 +132,10 @@ let gSyncPane = {
fxaLoginStatus.selectedIndex = FXA_LOGIN_UNVERIFIED;
enginesListDisabled = true;
// So we think we are logged in, so login problems are next.
} else if (Weave.Status.login != Weave.LOGIN_SUCCEEDED) {
// (Although if the Sync identity manager is still initializing, we
// ignore login errors and assume all will eventually be good.)
} else if (Weave.Service.identity.readyToAuthenticate &&
Weave.Status.login != Weave.LOGIN_SUCCEEDED) {
fxaLoginStatus.selectedIndex = FXA_LOGIN_FAILED;
enginesListDisabled = true;
// Else we must be golden!

Просмотреть файл

@ -226,7 +226,7 @@
<spacer flex="1"/>
<vbox align="end">
<button onclick="gSyncPane.verifyFirefoxAccount();"
caption="&verify.label;"/>
label="&verify.label;"/>
<label class="text-link"
onclick="/* no warning as account can't have previously synced */ gSyncPane.unlinkFirefoxAccount(false);"
value="&forget.label;"/>
@ -253,9 +253,8 @@
</groupbox>
<groupbox id="syncOptions">
<caption label="&syncBrand.fullName.label;"/>
<caption label="&syncBrand.shortName.label;"/>
<vbox>
<label value="&syncMy.label;" />
<richlistbox id="fxaSyncEnginesList"
orient="vertical"
onselect="if (this.selectedCount) this.clearSelection();">

Просмотреть файл

@ -87,16 +87,15 @@ let EventListener = {
// If we're in the process of restoring, this load may signal
// the end of the restoration.
let epoch = gContentRestore.getRestoreEpoch();
if (epoch) {
// Restore the form data and scroll position.
gContentRestore.restoreDocument();
// Ask SessionStore.jsm to trigger SSTabRestored.
sendAsyncMessage("SessionStore:restoreDocumentComplete", {epoch: epoch});
if (!epoch) {
return;
}
// Send a load message for all loads.
sendAsyncMessage("SessionStore:load");
// Restore the form data and scroll position.
gContentRestore.restoreDocument();
// Ask SessionStore.jsm to trigger SSTabRestored.
sendAsyncMessage("SessionStore:restoreDocumentComplete", {epoch: epoch});
}
};

Просмотреть файл

@ -105,6 +105,21 @@ let SessionHistoryInternal = {
return data;
},
/**
* Determines whether a given session history entry has been added dynamically.
*
* @param shEntry
* The session history entry.
* @return bool
*/
isDynamic: function (shEntry) {
// shEntry.isDynamicallyAdded() is true for dynamically added
// <iframe> and <frameset>, but also for <html> (the root of the
// document) so we use shEntry.parent to ensure that we're not looking
// at the root of the document
return shEntry.parent && shEntry.isDynamicallyAdded();
},
/**
* Get an object that is a serialized representation of a History entry.
*
@ -183,7 +198,7 @@ let SessionHistoryInternal = {
for (let i = 0; i < shEntry.childCount; i++) {
let child = shEntry.GetChildAt(i);
if (child) {
if (child && !this.isDynamic(child)) {
// Don't try to restore framesets containing wyciwyg URLs.
// (cf. bug 424689 and bug 450595)
if (child.URI.schemeIs("wyciwyg")) {

Просмотреть файл

@ -57,9 +57,6 @@ const MESSAGES = [
// be saved to disk.
"SessionStore:update",
// A "load" event happened.
"SessionStore:load",
// The restoreHistory code has run. This is a good time to run SSTabRestoring.
"SessionStore:restoreHistoryComplete",
@ -131,11 +128,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "TabStateCache",
XPCOMUtils.defineLazyModuleGetter(this, "Utils",
"resource:///modules/sessionstore/Utils.jsm");
#ifdef MOZ_CRASHREPORTER
XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
"@mozilla.org/xre/app-info;1", "nsICrashReporter");
#endif
/**
* |true| if we are in debug mode, |false| otherwise.
* Debug mode is controlled by preference browser.sessionstore.debug
@ -598,9 +590,6 @@ let SessionStoreInternal = {
TabState.update(browser, aMessage.data);
this.saveStateDelayed(win);
break;
case "SessionStore:load":
this.onTabLoad(win, browser);
break;
case "SessionStore:restoreHistoryComplete":
if (this.isCurrentEpoch(browser, aMessage.data.epoch)) {
// Notify the tabbrowser that the tab chrome has been restored.
@ -1300,8 +1289,6 @@ let SessionStoreInternal = {
if (!aNoNotification) {
this.saveStateDelayed(aWindow);
}
this._updateCrashReportURL(aWindow);
},
/**
@ -1385,29 +1372,6 @@ let SessionStoreInternal = {
}
},
/**
* When a tab loads, invalidate its cached state, trigger async save.
*
* @param aWindow
* Window reference
* @param aBrowser
* Browser reference
*/
onTabLoad: function ssi_onTabLoad(aWindow, aBrowser) {
// It's possible to get a load event after calling stop on a browser (when
// overwriting tabs). We want to return early if the tab hasn't been restored yet.
if (aBrowser.__SS_restoreState &&
aBrowser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
return;
}
delete aBrowser.__SS_data;
this.saveStateDelayed(aWindow);
// attempt to update the current URL we send in a crash report
this._updateCrashReportURL(aWindow);
},
/**
* When a tab is selected, save session data
* @param aWindow
@ -1424,9 +1388,6 @@ let SessionStoreInternal = {
if (tab.linkedBrowser.__SS_restoreState &&
tab.linkedBrowser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE)
this.restoreTabContent(tab);
// attempt to update the current URL we send in a crash report
this._updateCrashReportURL(aWindow);
}
},
@ -3066,29 +3027,6 @@ let SessionStoreInternal = {
return Services.io.newURI(aString, null, null);
},
/**
* Annotate a breakpad crash report with the currently selected tab's URL.
*/
_updateCrashReportURL: function ssi_updateCrashReportURL(aWindow) {
#ifdef MOZ_CRASHREPORTER
try {
var currentURI = aWindow.gBrowser.currentURI.clone();
// if the current URI contains a username/password, remove it
try {
currentURI.userPass = "";
}
catch (ex) { } // ignore failures on about: URIs
CrashReporter.annotateCrashReport("URL", currentURI.spec);
}
catch (ex) {
// don't make noise when crashreporter is built but not enabled
if (ex.result != Components.results.NS_ERROR_NOT_INITIALIZED)
debug(ex);
}
#endif
},
/**
* @param aState is a session state
* @param aRecentCrashes is the number of consecutive crashes

Просмотреть файл

@ -16,6 +16,14 @@ support-files =
browser_formdata_xpath_sample.html
browser_frametree_sample.html
browser_frametree_sample_frameset.html
browser_frame_history_index.html
browser_frame_history_index2.html
browser_frame_history_index_blank.html
browser_frame_history_a.html
browser_frame_history_b.html
browser_frame_history_c.html
browser_frame_history_c1.html
browser_frame_history_c2.html
browser_form_restore_events_sample.html
browser_formdata_format_sample.html
browser_pageStyle_sample.html
@ -33,12 +41,6 @@ support-files =
browser_463206_sample.html
browser_466937_sample.html
browser_485482_sample.html
browser_597315_index.html
browser_597315_a.html
browser_597315_b.html
browser_597315_c.html
browser_597315_c1.html
browser_597315_c2.html
browser_662743_sample.html
browser_739531_sample.html
browser_911547_sample.html
@ -58,11 +60,13 @@ support-files =
[browser_broadcast.js]
[browser_capabilities.js]
[browser_dying_cache.js]
[browser_dynamic_frames.js]
[browser_form_restore_events.js]
[browser_formdata.js]
[browser_formdata_format.js]
[browser_formdata_xpath.js]
[browser_frametree.js]
[browser_frame_history.js]
[browser_global_store.js]
[browser_label_and_icon.js]
[browser_merge_closed_tabs.js]
@ -141,7 +145,6 @@ skip-if = true
[browser_590268.js]
[browser_590563.js]
[browser_595601-restore_hidden.js]
[browser_597315.js]
[browser_599909.js]
[browser_600545.js]
[browser_601955.js]

Просмотреть файл

@ -1,58 +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() {
/** Test for Bug 597315 - Frameset history does not work properly when restoring a tab **/
waitForExplicitFinish();
let testURL = getRootDirectory(gTestPath) + "browser_597315_index.html";
let tab = gBrowser.addTab(testURL);
gBrowser.selectedTab = tab;
waitForLoadsInBrowser(tab.linkedBrowser, 4, function() {
let browser_b = tab.linkedBrowser.contentDocument.getElementsByTagName("frame")[1];
let document_b = browser_b.contentDocument;
let links = document_b.getElementsByTagName("a");
// We're going to click on the first link, so listen for another load event
waitForLoadsInBrowser(tab.linkedBrowser, 1, function() {
waitForLoadsInBrowser(tab.linkedBrowser, 1, function() {
gBrowser.removeTab(tab);
// wait for 4 loads again...
let newTab = ss.undoCloseTab(window, 0);
waitForLoadsInBrowser(newTab.linkedBrowser, 4, function() {
gBrowser.goBack();
waitForLoadsInBrowser(newTab.linkedBrowser, 1, function() {
let expectedURLEnds = ["a.html", "b.html", "c1.html"];
let frames = newTab.linkedBrowser.contentDocument.getElementsByTagName("frame");
for (let i = 0; i < frames.length; i++) {
is(frames[i].contentDocument.location,
getRootDirectory(gTestPath) + "browser_597315_" + expectedURLEnds[i],
"frame " + i + " has the right url");
}
gBrowser.removeTab(newTab);
executeSoon(finish);
});
});
});
EventUtils.sendMouseEvent({type:"click"}, links[1], browser_b.contentWindow);
});
EventUtils.sendMouseEvent({type:"click"}, links[0], browser_b.contentWindow);
});
}
// helper function
function waitForLoadsInBrowser(aBrowser, aLoadCount, aCallback) {
let loadCount = 0;
aBrowser.addEventListener("load", function(aEvent) {
if (++loadCount < aLoadCount)
return;
aBrowser.removeEventListener("load", arguments.callee, true);
aCallback();
}, true);
}

Просмотреть файл

@ -1,10 +0,0 @@
<html>
<body>
I'm B!<br/>
<a target="c" href="browser_597315_c1.html">click me first</a><br/>
<a target="c" href="browser_597315_c2.html">then click me</a><br/>
Close this tab.<br/>
Restore this tab.<br/>
Click back.<br/>
</body>
</html>

Просмотреть файл

@ -1,10 +0,0 @@
<html>
<frameset cols="20%,80%">
<frameset rows="30%,70%">
<frame src="browser_597315_a.html"/>
<frame src="browser_597315_b.html"/>
</frameset>
<frame src="browser_597315_c.html" name="c"/>
</frameset>
</html>

Просмотреть файл

@ -178,6 +178,10 @@ function testOnWindow(aIsPrivate, aCallback) {
}
function waitForTabLoad(aWin, aURL, aCallback) {
whenBrowserLoaded(aWin.gBrowser.selectedBrowser, aCallback);
aWin.gBrowser.selectedBrowser.loadURI(aURL);
let browser = aWin.gBrowser.selectedBrowser;
whenBrowserLoaded(browser, function () {
SyncHandlers.get(browser).flush();
executeSoon(aCallback);
});
browser.loadURI(aURL);
}

Просмотреть файл

@ -0,0 +1,95 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Ensure that static frames of framesets are serialized but dynamically
* inserted iframes are ignored.
*/
add_task(function () {
// This URL has the following frames:
// + about:mozilla (static)
// + about:robots (static)
// + about:rights (dynamic iframe)
const URL = "data:text/html;charset=utf-8," +
"<frameset cols=50%25,50%25><frame src=about%3Amozilla>" +
"<frame src=about%3Arobots></frameset>" +
"<script>var i=document.createElement('iframe');" +
"i.setAttribute('src', 'about%3Arights');" +
"document.body.appendChild(i);</script>";
// Add a new tab with two "static" and one "dynamic" frame.
let tab = gBrowser.addTab(URL);
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
SyncHandlers.get(browser).flush();
let {entries} = JSON.parse(ss.getTabState(tab));
// Check URLs.
ok(entries[0].url.startsWith("data:text/html"), "correct root url");
is(entries[0].children[0].url, "about:mozilla", "correct url for 1st frame");
is(entries[0].children[1].url, "about:robots", "correct url for 2nd frame");
// Check the number of children.
is(entries.length, 1, "there is one root entry ...");
is(entries[0].children.length, 2, "... with two child entries");
// Cleanup.
gBrowser.removeTab(tab);
});
/**
* Ensure that iframes created by the network parser are serialized but
* dynamically inserted iframes are ignored. Navigating a subframe should
* create a second root entry that doesn't contain any dynamic children either.
*/
add_task(function () {
// This URL has the following frames:
// + about:mozilla (static iframe)
// + about:rights (dynamic iframe)
const URL = "data:text/html;charset=utf-8," +
"<iframe name=t src=about%3Amozilla></iframe>" +
"<a id=lnk href=about%3Arobots target=t>clickme</a>" +
"<script>var i=document.createElement('iframe');" +
"i.setAttribute('src', 'about%3Arights');" +
"document.body.appendChild(i);</script>";
// Add a new tab with one "static" and one "dynamic" frame.
let tab = gBrowser.addTab(URL);
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
SyncHandlers.get(browser).flush();
let {entries} = JSON.parse(ss.getTabState(tab));
// Check URLs.
ok(entries[0].url.startsWith("data:text/html"), "correct root url");
is(entries[0].children[0].url, "about:mozilla", "correct url for static frame");
// Check the number of children.
is(entries.length, 1, "there is one root entry ...");
is(entries[0].children.length, 1, "... with a single child entry");
// Navigate the subframe.
browser.messageManager.sendAsyncMessage("ss-test:click", {id: "lnk"});
yield promiseBrowserLoaded(browser, false /* don't ignore subframes */);
SyncHandlers.get(browser).flush();
let {entries} = JSON.parse(ss.getTabState(tab));
// Check URLs.
ok(entries[0].url.startsWith("data:text/html"), "correct 1st root url");
ok(entries[1].url.startsWith("data:text/html"), "correct 2nd root url");
is(entries[0].children[0].url, "about:mozilla", "correct url for 1st static frame");
is(entries[1].children[0].url, "about:robots", "correct url for 2ns static frame");
// Check the number of children.
is(entries.length, 2, "there are two root entries ...");
is(entries[0].children.length, 1, "... with a single child entry ...");
is(entries[1].children.length, 1, "... each");
// Cleanup.
gBrowser.removeTab(tab);
});

Просмотреть файл

@ -0,0 +1,170 @@
/* 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/. */
/**
Ensure that frameset history works properly when restoring a tab,
provided that the frameset is static.
*/
// Loading a toplevel frameset
add_task(function() {
let testURL = getRootDirectory(gTestPath) + "browser_frame_history_index.html";
let tab = gBrowser.addTab(testURL);
gBrowser.selectedTab = tab;
info("Opening a page with three frames, 4 loads should take place");
yield waitForLoadsInBrowser(tab.linkedBrowser, 4);
let browser_b = tab.linkedBrowser.contentDocument.getElementsByTagName("frame")[1];
let document_b = browser_b.contentDocument;
let links = document_b.getElementsByTagName("a");
// We're going to click on the first link, so listen for another load event
info("Clicking on link 1, 1 load should take place");
let promise = waitForLoadsInBrowser(tab.linkedBrowser, 1);
EventUtils.sendMouseEvent({type:"click"}, links[0], browser_b.contentWindow);
yield promise;
info("Clicking on link 2, 1 load should take place");
promise = waitForLoadsInBrowser(tab.linkedBrowser, 1);
EventUtils.sendMouseEvent({type:"click"}, links[1], browser_b.contentWindow);
yield promise;
info("Close then un-close page, 4 loads should take place");
gBrowser.removeTab(tab);
let newTab = ss.undoCloseTab(window, 0);
yield waitForLoadsInBrowser(newTab.linkedBrowser, 4);
info("Go back in time, 1 load should take place");
gBrowser.goBack();
yield waitForLoadsInBrowser(newTab.linkedBrowser, 1);
let expectedURLEnds = ["a.html", "b.html", "c1.html"];
let frames = newTab.linkedBrowser.contentDocument.getElementsByTagName("frame");
for (let i = 0; i < frames.length; i++) {
is(frames[i].contentDocument.location,
getRootDirectory(gTestPath) + "browser_frame_history_" + expectedURLEnds[i],
"frame " + i + " has the right url");
}
gBrowser.removeTab(newTab);
});
// Loading the frameset inside an iframe
add_task(function() {
let testURL = getRootDirectory(gTestPath) + "browser_frame_history_index2.html";
let tab = gBrowser.addTab(testURL);
gBrowser.selectedTab = tab;
info("iframe: Opening a page with an iframe containing three frames, 5 loads should take place");
yield waitForLoadsInBrowser(tab.linkedBrowser, 5);
let browser_b = tab.linkedBrowser.contentDocument.
getElementById("iframe").contentDocument.
getElementsByTagName("frame")[1];
let document_b = browser_b.contentDocument;
let links = document_b.getElementsByTagName("a");
// We're going to click on the first link, so listen for another load event
info("iframe: Clicking on link 1, 1 load should take place");
let promise = waitForLoadsInBrowser(tab.linkedBrowser, 1);
EventUtils.sendMouseEvent({type:"click"}, links[0], browser_b.contentWindow);
yield promise;
info("iframe: Clicking on link 2, 1 load should take place");
promise = waitForLoadsInBrowser(tab.linkedBrowser, 1);
EventUtils.sendMouseEvent({type:"click"}, links[1], browser_b.contentWindow);
yield promise;
info("iframe: Close then un-close page, 5 loads should take place");
gBrowser.removeTab(tab);
let newTab = ss.undoCloseTab(window, 0);
yield waitForLoadsInBrowser(newTab.linkedBrowser, 5);
info("iframe: Go back in time, 1 load should take place");
gBrowser.goBack();
yield waitForLoadsInBrowser(newTab.linkedBrowser, 1);
let expectedURLEnds = ["a.html", "b.html", "c1.html"];
let frames = newTab.linkedBrowser.contentDocument.
getElementById("iframe").contentDocument.
getElementsByTagName("frame");
for (let i = 0; i < frames.length; i++) {
is(frames[i].contentDocument.location,
getRootDirectory(gTestPath) + "browser_frame_history_" + expectedURLEnds[i],
"frame " + i + " has the right url");
}
gBrowser.removeTab(newTab);
});
// Now, test that we don't record history if the iframe is added dynamically
add_task(function() {
// Start with an empty history
let blankState = JSON.stringify({
windows: [{
tabs: [{ entries: [{ url: "about:blank" }] }],
_closedTabs: []
}],
_closedWindows: []
});
ss.setBrowserState(blankState);
let testURL = getRootDirectory(gTestPath) + "browser_frame_history_index_blank.html";
let tab = gBrowser.addTab(testURL);
gBrowser.selectedTab = tab;
yield waitForLoadsInBrowser(tab.linkedBrowser, 1);
info("dynamic: Opening a page with an iframe containing three frames, 4 dynamic loads should take place");
let doc = tab.linkedBrowser.contentDocument;
let iframe = doc.createElement("iframe");
iframe.id = "iframe";
iframe.src="browser_frame_history_index.html";
doc.body.appendChild(iframe);
yield waitForLoadsInBrowser(tab.linkedBrowser, 4);
let browser_b = tab.linkedBrowser.contentDocument.
getElementById("iframe").contentDocument.
getElementsByTagName("frame")[1];
let document_b = browser_b.contentDocument;
let links = document_b.getElementsByTagName("a");
// We're going to click on the first link, so listen for another load event
info("dynamic: Clicking on link 1, 1 load should take place");
let promise = waitForLoadsInBrowser(tab.linkedBrowser, 1);
EventUtils.sendMouseEvent({type:"click"}, links[0], browser_b.contentWindow);
yield promise;
info("dynamic: Clicking on link 2, 1 load should take place");
promise = waitForLoadsInBrowser(tab.linkedBrowser, 1);
EventUtils.sendMouseEvent({type:"click"}, links[1], browser_b.contentWindow);
yield promise;
info("Check in the state that we have not stored this history");
let state = ss.getBrowserState();
info(JSON.stringify(JSON.parse(state), null, "\t"));
is(state.indexOf("c1.html"), -1, "History entry was not stored in the session state");;
gBrowser.removeTab(tab);
});
// helper functions
function waitForLoadsInBrowser(aBrowser, aLoadCount) {
let deferred = Promise.defer();
let loadCount = 0;
aBrowser.addEventListener("load", function(aEvent) {
if (++loadCount < aLoadCount) {
info("Got " + loadCount + " loads, waiting until we have " + aLoadCount);
return;
}
aBrowser.removeEventListener("load", arguments.callee, true);
deferred.resolve();
}, true);
return deferred.promise;
}
function timeout(delay, task) {
let deferred = Promise.defer();
setTimeout(() => deferred.resolve(true), delay);
task.then(() => deferred.resolve(false), deferred.reject);
return deferred.promise;
}

Просмотреть файл

@ -0,0 +1,10 @@
<html>
<body>
I'm B!<br/>
<a target="c" href="browser_frame_history_c1.html">click me first</a><br/>
<a target="c" href="browser_frame_history_c2.html">then click me</a><br/>
Close this tab.<br/>
Restore this tab.<br/>
Click back.<br/>
</body>
</html>

Просмотреть файл

@ -0,0 +1,10 @@
<html>
<frameset cols="20%,80%">
<frameset rows="30%,70%">
<frame src="browser_frame_history_a.html"/>
<frame src="browser_frame_history_b.html"/>
</frameset>
<frame src="browser_frame_history_c.html" name="c"/>
</frameset>
</html>

Просмотреть файл

@ -0,0 +1,4 @@
<html>
<iframe src="browser_frame_history_index.html" id="iframe" />
</html>

Просмотреть файл

@ -0,0 +1,5 @@
<html>
<body>
</body>
</html>

Просмотреть файл

@ -13,6 +13,7 @@ const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const {require} = devtools;
const {ConnectionManager, Connection} = require("devtools/client/connection-manager");
const {getDeviceFront} = require("devtools/server/actors/device");
const ConnectionStore = require("devtools/app-manager/connection-store");
const DeviceStore = require("devtools/app-manager/device-store");
const simulatorsStore = require("devtools/app-manager/simulators-store");
@ -187,4 +188,22 @@ let UI = {
this.connect();
});
},
screenshot: function() {
this.connection.client.listTabs(
response => {
let front = getDeviceFront(this.connection.client, response);
front.screenshotToBlob().then(blob => {
let topWindow = Services.wm.getMostRecentWindow("navigator:browser");
let gBrowser = topWindow.gBrowser;
let url = topWindow.URL.createObjectURL(blob);
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
tab.addEventListener("TabClose", function onTabClose() {
tab.removeEventListener("TabClose", onTabClose, false);
topWindow.URL.revokeObjectURL(url);
}, false);
}).then(null, console.error);
}
);
},
}

Просмотреть файл

@ -26,6 +26,7 @@
<div class="banner-content">
<span template='{"type":"localizedContent","property":"connection.connectedToDevice","paths":["device.description.name"]}'></span>
<button class="action-cancel" onclick="UI.disconnect()" title="&connection.disconnectTooltip;">&connection.disconnect;</button>
<button class="action-primary" onclick="UI.screenshot()" title="&device.screenshotTooltip;">&device.screenshot;</button>
</div>
</div>
</div>

Просмотреть файл

@ -141,23 +141,6 @@ let UI = {
if (panel) panel.classList.add("selected");
},
screenshot: function() {
if (!this.connected) {
return;
}
let front = getDeviceFront(this.connection.client, this.listTabsResponse);
front.screenshotToBlob().then(blob => {
let topWindow = Services.wm.getMostRecentWindow("navigator:browser");
let gBrowser = topWindow.gBrowser;
let url = topWindow.URL.createObjectURL(blob);
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
tab.addEventListener("TabClose", function onTabClose() {
tab.removeEventListener("TabClose", onTabClose, false);
topWindow.URL.revokeObjectURL(url);
}, false);
}).then(null, console.error);
},
openToolbox: function(manifest) {
if (!this.connected) {
return;

Просмотреть файл

@ -36,7 +36,6 @@
</h3>
<p template='{"type":"localizedContent","property":"device.deviceSize", "paths":["device.description.width","device.description.height","device.description.dpi"]}'></p>
</header>
<button onclick="UI.screenshot()" title="&device.screenshotTooltip;">&device.screenshot;</button>
<div id="tabs-headers">
<div onclick="UI.setTab('apps')" class="tab sidebar-item apps" title="&device.installedAppsTooltip;">&device.installedApps;</div>
<div onclick="UI.setTab('permissions')" class="tab sidebar-item permissions" title="&device.permissionsTooltip;">

Просмотреть файл

@ -410,7 +410,7 @@
<button id="black-boxed-message-button"
class="devtools-toolbarbutton"
label="&debuggerUI.blackBoxMessage.unBlackBoxButton;"
image="chrome://browser/skin/devtools/debugger-blackboxMessageEye.png"
image="chrome://browser/skin/devtools/debugger-blackbox-eye.png"
command="unBlackBoxCommand"/>
</vbox>
<vbox id="source-progress-container"
@ -432,7 +432,7 @@
<tabpanels flex="1">
<tabpanel id="variables-tabpanel">
<vbox id="expressions"/>
<splitter class="devtools-horizontal-splitter"/>
<splitter class="devtools-horizontal-splitter devtools-invisible splitter"/>
<vbox id="variables" flex="1"/>
</tabpanel>
<tabpanel id="events-tabpanel">

Просмотреть файл

@ -16,7 +16,7 @@
<link rel="stylesheet" href="chrome://browser/skin/devtools/font-inspector.css" type="text/css"/>
<script type="application/javascript;version=1.8" src="chrome://browser/content/devtools/theme-switching.js"/>
</head>
<body class="theme-body devtools-monospace" role="application">
<body class="theme-sidebar devtools-monospace" role="application">
<script type="application/javascript;version=1.8" src="font-inspector.js"></script>
<div id="root">
<ul id="all-fonts"></ul>

Просмотреть файл

@ -12,6 +12,9 @@ const ENSURE_SELECTION_VISIBLE_DELAY = 50; // ms
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/devtools/DOMHelpers.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
const ELLIPSIS = Services.prefs.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data;
const MAX_LABEL_LENGTH = 40;
let promise = require("sdk/core/promise");
@ -72,6 +75,17 @@ HTMLBreadcrumbs.prototype = {
_init: function BC__init()
{
this.container = this.chromeDoc.getElementById("inspector-breadcrumbs");
// These separators are used for CSS purposes only, and are positioned
// off screen, but displayed with -moz-element.
this.separators = this.chromeDoc.createElement("box");
this.separators.className = "breadcrumb-separator-container";
this.separators.innerHTML =
"<box id='breadcrumb-separator-before'></box>" +
"<box id='breadcrumb-separator-after'></box>" +
"<box id='breadcrumb-separator-normal'></box>";
this.container.parentNode.appendChild(this.separators);
this.container.addEventListener("mousedown", this, true);
this.container.addEventListener("keypress", this, true);
@ -184,16 +198,15 @@ HTMLBreadcrumbs.prototype = {
let pseudosLabel = this.chromeDoc.createElement("label");
pseudosLabel.className = "breadcrumbs-widget-item-pseudo-classes plain";
tagLabel.textContent = aNode.tagName.toLowerCase();
idLabel.textContent = aNode.id ? ("#" + aNode.id) : "";
let tagText = aNode.tagName.toLowerCase();
let idText = aNode.id ? ("#" + aNode.id) : "";
let classesText = "";
if (aNode.className) {
let classesText = "";
let classList = aNode.className.split(/\s+/);
for (let i = 0; i < classList.length; i++) {
classesText += "." + classList[i];
}
classesLabel.textContent = classesText;
}
// XXX: Until we have pseudoclass lock in the node.
@ -201,6 +214,26 @@ HTMLBreadcrumbs.prototype = {
}
// Figure out which element (if any) needs ellipsing.
// Substring for that element, then clear out any extras
// (except for pseudo elements).
let maxTagLength = MAX_LABEL_LENGTH;
let maxIdLength = MAX_LABEL_LENGTH - tagText.length;
let maxClassLength = MAX_LABEL_LENGTH - tagText.length - idText.length;
if (tagText.length > maxTagLength) {
tagText = tagText.substr(0, maxTagLength) + ELLIPSIS;
idText = classesText = "";
} else if (idText.length > maxIdLength) {
idText = idText.substr(0, maxIdLength) + ELLIPSIS;
classesText = "";
} else if (classesText.length > maxClassLength) {
classesText = classesText.substr(0, maxClassLength) + ELLIPSIS;
}
tagLabel.textContent = tagText;
idLabel.textContent = idText;
classesLabel.textContent = classesText;
pseudosLabel.textContent = aNode.pseudoClassLocks.join("");
fragment.appendChild(tagLabel);
@ -360,6 +393,10 @@ HTMLBreadcrumbs.prototype = {
this.container.removeEventListener("mousedown", this, true);
this.container.removeEventListener("keypress", this, true);
this.container = null;
this.separators.remove();
this.separators = null;
this.nodeHierarchy = null;
},

Просмотреть файл

@ -53,6 +53,7 @@ function SelectorSearch(aInspector, aContentDocument, aInputNode) {
autoSelect: true,
position: "before_start",
direction: "ltr",
theme: "auto",
onClick: this._onListBoxKeypress,
onKeypress: this._onListBoxKeypress,
};

Просмотреть файл

@ -35,7 +35,7 @@
</popupset>
<box id="body"
class="devtools-responsive-container theme-body"
class="devtools-responsive-container theme-sidebar"
flex="1">
<vbox id="network-table" flex="1">
<toolbar id="requests-menu-toolbar"
@ -119,6 +119,7 @@
tabindex="0"/>
</toolbar>
<label id="requests-menu-empty-notice"
class="side-menu-widget-empty-text"
value="&netmonitorUI.emptyNotice2;"/>
<vbox id="requests-menu-contents" flex="1" context="network-request-popup">
<hbox id="requests-menu-item-template" hidden="true">

Просмотреть файл

@ -22,7 +22,7 @@
<script type="text/javascript" src="sidebar.js"/>
<box flex="1" id="profiler-chrome"
class="devtools-responsive-container theme-body">
<vbox class="profiler-sidebar">
<vbox class="profiler-sidebar theme-sidebar">
<toolbar class="devtools-toolbar">
<hbox id="profiler-controls">
<toolbarbutton id="profiler-start"
@ -40,7 +40,7 @@
</vbox>
</vbox>
<splitter class="devtools-side-splitter"/>
<splitter class="devtools-side-splitter devtools-invisible-splitter"/>
<vbox flex="1" id="profiler-report">
<!-- Example:

Просмотреть файл

@ -19,7 +19,7 @@
<script type="application/javascript" src="shadereditor.js"/>
<vbox id="body" flex="1">
<vbox class="theme-body" flex="1">
<hbox id="reload-notice"
class="notice-container"
align="center"
@ -44,8 +44,10 @@
value="&shaderEditorUI.emptyNotice;"/>
</hbox>
<box id="content" flex="1" hidden="true"
class="devtools-responsive-container theme-body">
<box id="content"
class="devtools-responsive-container"
flex="1"
hidden="true">
<vbox id="shaders-pane"/>
<splitter class="devtools-side-splitter"/>
<box id="shaders-editors" class="devtools-responsive-container" flex="1">

Просмотреть файл

@ -46,6 +46,17 @@ this.BreadcrumbsWidget = function BreadcrumbsWidget(aNode) {
this._list.addEventListener("underflow", this._onUnderflow.bind(this), false);
this._list.addEventListener("overflow", this._onOverflow.bind(this), false);
// These separators are used for CSS purposes only, and are positioned
// off screen, but displayed with -moz-element.
this._separators = this.document.createElement("box");
this._separators.className = "breadcrumb-separator-container";
this._separators.innerHTML =
"<box id='breadcrumb-separator-before'></box>" +
"<box id='breadcrumb-separator-after'></box>" +
"<box id='breadcrumb-separator-normal'></box>";
this._parent.appendChild(this._separators);
// This widget emits events that can be handled in a MenuContainer.
EventEmitter.decorate(this);

Просмотреть файл

@ -38,7 +38,7 @@ this.SideMenuWidget = function SideMenuWidget(aNode, aOptions={}) {
// Create an internal scrollbox container.
this._list = this.document.createElement("scrollbox");
this._list.className = "side-menu-widget-container theme-body";
this._list.className = "side-menu-widget-container theme-sidebar";
this._list.setAttribute("flex", "1");
this._list.setAttribute("orient", "vertical");
this._list.setAttribute("with-arrows", this._showArrows);

Просмотреть файл

@ -10,6 +10,7 @@ const { Cu, Cc, Ci, components } = require("chrome");
const TAB_SIZE = "devtools.editor.tabsize";
const EXPAND_TAB = "devtools.editor.expandtab";
const KEYMAP = "devtools.editor.keymap";
const AUTO_CLOSE = "devtools.editor.autoclosebrackets";
const L10N_BUNDLE = "chrome://browser/locale/devtools/sourceeditor.properties";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@ -132,6 +133,7 @@ function Editor(config) {
const tabSize = Services.prefs.getIntPref(TAB_SIZE);
const useTabs = !Services.prefs.getBoolPref(EXPAND_TAB);
const keyMap = Services.prefs.getCharPref(KEYMAP);
const useAutoClose = Services.prefs.getBoolPref(AUTO_CLOSE);
this.version = null;
this.config = {
@ -144,7 +146,8 @@ function Editor(config) {
extraKeys: {},
indentWithTabs: useTabs,
styleActiveLine: true,
autoCloseBrackets: true,
autoCloseBrackets: "()[]{}''\"\"",
autoCloseEnabled: useAutoClose,
theme: "mozilla"
};
@ -187,6 +190,10 @@ function Editor(config) {
}
}
// Configure automatic bracket closing.
if (!this.config.autoCloseEnabled)
this.config.autoCloseBrackets = false;
// Overwrite default tab behavior. If something is selected,
// indent those lines. If nothing is selected and we're
// indenting with tabs, insert one tab. Otherwise insert N

Просмотреть файл

@ -72,7 +72,7 @@
<xul:keyset id="sourceEditorKeys"/>
<xul:box id="style-editor-chrome" class="splitview-root loading"
<xul:box id="style-editor-chrome" class="theme-body splitview-root loading"
context="sidebar-context">
<xul:box class="splitview-controller">
<xul:box class="splitview-main">
@ -87,7 +87,7 @@
label="&importButton.label;"/>
</xul:toolbar>
</xul:box>
<xul:box id="splitview-resizer-target" class="splitview-nav-container"
<xul:box id="splitview-resizer-target" class="theme-sidebar splitview-nav-container"
persist="height">
<ol class="splitview-nav" tabindex="0"></ol>
<div class="splitview-nav placeholder empty">
@ -99,7 +99,7 @@
</div>
</xul:box> <!-- .splitview-nav-container -->
</xul:box> <!-- .splitview-controller -->
<xul:splitter class="devtools-side-splitter splitview-landscape-splitter"/>
<xul:splitter class="devtools-side-splitter splitview-landscape-splitter devtools-invisible-splitter"/>
<xul:box class="splitview-side-details"/>
<div id="splitview-templates" hidden="true">

Просмотреть файл

@ -21,7 +21,7 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
class="theme-body">
class="theme-sidebar">
<head>

Просмотреть файл

@ -11,7 +11,7 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
class="theme-body">
class="theme-sidebar">
<head>
<title>&ruleViewTitle;</title>

Просмотреть файл

@ -4,6 +4,6 @@
<!ENTITY aboutAccounts.pageTitle "Welcome to Sync">
<!ENTITY aboutAccountsSetup.description "Sign in to sync your tabs, bookmarks, passwords &amp; more.">
<!ENTITY aboutAccountsSetup.startButton.label "Get started">
<!ENTITY aboutAccountsSetup.useOldSync.label "Using an older version of Sync?">
<!ENTITY aboutAccountsConfig.description "Sign in to sync your tabs, bookmarks, passwords &amp; more.">
<!ENTITY aboutAccountsConfig.startButton.label "Get started">
<!ENTITY aboutAccountsConfig.useOldSync.label "Using an older version of Sync?">

Просмотреть файл

@ -97,6 +97,7 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY showAllTabsCmd.accesskey "A">
<!ENTITY fxaSignIn.label "Sign in to &syncBrand.shortName.label;">
<!ENTITY fxaSignInError.label "Reconnect to &syncBrand.shortName.label;">
<!ENTITY syncStartPanel.title "&brandShortName; is now syncing.">
<!ENTITY syncStartPanel.subTitle "You can manage &syncBrand.shortName.label; in Options.">
<!ENTITY syncStartPanel.subTitleUnix "You can manage &syncBrand.shortName.label; in Preferences.">
@ -183,7 +184,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY bookmarksCmd.commandkey "b">
<!ENTITY bookmarksMenuButton.label "Bookmarks">
<!ENTITY bookmarksMenuButton.tooltip "Display your bookmarks">
<!ENTITY bookmarksMenuButton.unsorted.label "Unsorted Bookmarks">
<!ENTITY viewBookmarksSidebar2.label "View Bookmarks Sidebar">
<!ENTITY viewBookmarksToolbar.label "View Bookmarks Toolbar">
@ -737,6 +737,8 @@ just addresses the organization to follow, e.g. "This site is run by " -->
<!ENTITY tabCrashed.checkSendReport "Tell &vendorShortName; about this crash so they can fix it.">
<!ENTITY tabCrashed.tryAgain "Try Again">
<!ENTITY uiTour.infoPanel.close "Close">
<!-- LOCALIZATION NOTE: the following strings are unused in Australis, they're
kept here to avoid warnings from l10n tools like compare-locales on
l10n-central. They will be definitely removed when Australis is ready

Просмотреть файл

@ -232,11 +232,27 @@ refreshBlocked.goButton.accesskey=A
refreshBlocked.refreshLabel=%S prevented this page from automatically reloading.
refreshBlocked.redirectLabel=%S prevented this page from automatically redirecting to another page.
# General bookmarks button
# LOCALIZATION NOTE (bookmarksMenuButton.tooltip):
# %S is the keyboard shortcut for "Show All Bookmarks"
bookmarksMenuButton.tooltip=Show your bookmarks (%S)
# Star button
starButtonOn.tooltip=Edit this bookmark
starButtonOff.tooltip=Bookmark this page
starButtonOverflowed.label=Bookmark This Page
# Print button tooltip on OS X
# LOCALIZATION NOTE (printButton.tooltip):
# Use the unicode ellipsis char, \u2026,
# or use "..." if \u2026 doesn't suit traditions in your locale.
# %S is the keyboard shortcut for "Print"
printButton.tooltip=Print this page… (%S)
# New Window button tooltip
# LOCALIZATION NOTE (newWindowButton.tooltip):
# %S is the keyboard shortcut for "New Window"
newWindowButton.tooltip=Open a new window (%S)
# Offline web applications
offlineApps.available=This website (%S) is asking to store data on your computer for offline use.
offlineApps.allow=Allow
@ -358,6 +374,9 @@ tabview.title=%S - Group Your Tabs
# #2 is the number of remaining tabs.
tabview.moveToUnnamedGroup.label=#1 and 1 more;#1 and #2 more
# LOCALIZATION NOTE (tabviewButton.tooltip): %S is the keyboard shortcut for tab groups
tabviewButton.tooltip=Group your tabs (%S)
extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.name=Default
extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description=The default theme.
@ -414,6 +433,9 @@ fullscreen.entered=%S is now fullscreen.
# LOCALIZATION NOTE (fullscreen.rememberDecision): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
fullscreen.rememberDecision=Remember decision for %S
# LOCALIZATION NOTE (fullscreenButton.tooltip): %S is the keyboard shortcut for full screen
fullscreenButton.tooltip=Display the window in full screen (%S)
service.toolbarbutton.label=Services
service.toolbarbutton.tooltiptext=Services

Просмотреть файл

@ -58,7 +58,7 @@
<!ENTITY notSignedIn.label "You are not signed in.">
<!ENTITY signIn.label "Sign in">
<!ENTITY manage.label "Manage">
<!ENTITY unlink.label "Unlink This Browser…">
<!ENTITY unlink.label "Unlink this Browser…">
<!ENTITY verify.label "Verify Email">
<!ENTITY forget.label "Forget this Email">

Просмотреть файл

@ -21,6 +21,11 @@ tabs.emptyTabTitle=New Tab
tabs.closeTab=Close Tab
tabs.close=Close
tabs.closeWarningTitle=Confirm close
tabs.closeWarningMultipleTabs=You are about to close %S tabs. Are you sure you want to continue?
# LOCALIZATION NOTE (tabs.closeWarningMultiple):
# Semicolon-separated list of plural forms. See:
# http://developer.mozilla.org/en/docs/Localization_and_Plurals
# The singular form is not considered since this string is used only for
# multiple tabs.
tabs.closeWarningMultiple=;You are about to close #1 tabs. Are you sure you want to continue?
tabs.closeButtonMultiple=Close tabs
tabs.closeWarningPromptMe=Warn me when I attempt to close multiple tabs

Просмотреть файл

@ -500,11 +500,11 @@
</binding>
<binding id="urlbar-autocomplete">
<content class="meta-section-container">
<xul:vbox class="meta-section" anonid="results-container" flex="1">
<content class="meta-section-container" pack="end">
<xul:vbox class="meta-section" anonid="results-container" flex="2">
<xul:label class="meta-section-title"
value="&autocompleteResultsHeader.label;"/>
<richgrid anonid="results" rows="3" flex="1" minSlots="1"
<richgrid anonid="results" rows="3" minSlots="8"
seltype="single" nocontext="true" deferlayout="true"/>
</xul:vbox>
@ -600,6 +600,17 @@
this.clearSelection();
this.invalidate();
let viewstate = this.getAttribute("viewstate");
switch (viewstate) {
case "portrait":
case "snapped":
this._results.setAttribute("vertical", true);
break;
default:
this._results.removeAttribute("vertical");
break;
}
this._results.arrangeItemsNow();
this._searches.arrangeItemsNow();
@ -658,8 +669,8 @@
if (!this.popupOpen)
return;
this.updateResults();
this.updateSearchEngineHeader();
this.updateResults();
]]>
</body>
</method>
@ -676,22 +687,27 @@
return;
let haveNoResults = (this.matchCount == 0);
this._resultsContainer.hidden = haveNoResults;
if (haveNoResults) {
this._results.clearAll();
this.setAttribute("nomatch", true);
this._resultsContainer.removeAttribute("flex");
return;
}
this.removeAttribute("nomatch");
this._resultsContainer.setAttribute("flex", 1);
let controller = this.input.controller;
let lastMatch = this.matchCount - 1;
let iterCount = Math.max(this._results.itemCount, this.matchCount);
// Swap out existing items for new search hit results
for (let i = 0; i < iterCount; i++) {
let item = this._results._slotAt(i);
if (i > lastMatch) {
let lastItem = this._results.itemCount - 1;
this._results.removeItemAt(lastItem, true);
item.removeAttribute("value");
item.removeAttribute("autocomplete");
continue;
}
@ -699,15 +715,9 @@
let label = controller.getCommentAt(i) || value;
let iconURI = controller.getImageAt(i);
let item = this._results.getItemAtIndex(i);
if (item == null) {
item = this._results.appendItem(label, value, true);
item.setAttribute("autocomplete", "true");
} else {
item.setAttribute("label", label);
item.setAttribute("value", value);
}
item.setAttribute("autocomplete", true);
item.setAttribute("label", label);
item.setAttribute("value", value);
item.setAttribute("iconURI", iconURI);
}

Просмотреть файл

@ -747,7 +747,7 @@ var Browser = {
Services.metro.pinTileAsync(this._currentPageTileID,
Browser.selectedBrowser.contentTitle, // short name
Browser.selectedBrowser.contentTitle, // display name
"metrobrowser -url " + Browser.selectedBrowser.currentURI.spec,
"-url " + Browser.selectedBrowser.currentURI.spec,
uriSpec, uriSpec);
},

Просмотреть файл

@ -227,7 +227,7 @@ Desktop browser's sync prefs.
<vbox id="toolbar-overlay" flex="1">
<!-- Autocomplete -->
<scrollbox flex="1">
<scrollbox flex="1" id="urlbar-autocomplete-scroll" observes="bcast_urlbarState">
<hbox id="urlbar-autocomplete" observes="bcast_windowState"/>
</scrollbox>

Просмотреть файл

@ -102,6 +102,11 @@ gTests.push({
edit.select();
let editCoords = logicalCoordsForElement(edit);
// wait for popup animation to complete, it interferes with edit selection testing
let autocompletePopup = document.getElementById("urlbar-autocomplete-scroll");
yield waitForEvent(autocompletePopup, "transitionend");
SelectionHelperUI.attachEditSession(ChromeSelectionHandler, editCoords.x, editCoords.y);
ok(SelectionHelperUI.isSelectionUIVisible, "selection enabled");

Просмотреть файл

@ -325,15 +325,16 @@ gTests.push({
let opened = yield waitForCondition(() => gEdit.popup.popupOpen);
yield waitForCondition(() => gEdit.popup._results.itemCount > 0);
ok(!gEdit.popup._resultsContainer.hidden, "'Your results' are visible");
ok(!gEdit.popup.hasAttribute("nomatch"), "'Popup doesnt have nomatch attribute when there are results");
ok(gEdit.popup._resultsContainer.getBoundingClientRect().width, "'Your results' are visible");
ok(gEdit.popup._results.itemCount > 0, "'Your results' are populated");
// Append a string to make sure it doesn't match anything in 'your results'
EventUtils.sendString("zzzzzzzzzzzzzzzzzz", window);
yield waitForCondition(() => gEdit.popup._resultsContainer.hidden);
yield waitForCondition(() => gEdit.popup.hasAttribute("nomatch"));
ok(gEdit.popup._resultsContainer.hidden, "'Your results' are hidden");
is(gEdit.popup._resultsContainer.getBoundingClientRect().width, 0, "'Your results' are hidden");
ok(gEdit.popup._results.itemCount === 0, "'Your results' are empty");
EventUtils.synthesizeKey("VK_DOWN", {}, window);

Просмотреть файл

@ -728,6 +728,45 @@ tabmodalprompt:not([promptType="promptUserAndPass"]) .infoContainer {
transition-property: none;
}
/* Autocomplete ----------------------------------------------------------------- */
#urlbar-autocomplete-scroll:not([autocomplete]) {
transform: translateY(calc(3 * @grid_row_height@ + 64px));
visibility: collapse;
}
#urlbar-autocomplete-scroll[autocomplete] {
height: calc(3 * @grid_row_height@ + 64px);
max-height: calc(3 * @grid_row_height@ + 64px);
transform: translateY(0);
transition-timing-function: @metro_animation_easing@;
transition-property: transform;
transition-duration: @metro_animation_duration@;
transition-delay: 0s;
visibility: visible;
}
#urlbar-autocomplete-scroll:not([autocomplete]) > .meta-section-container > .meta-section {
opacity: 0;
}
#urlbar-autocomplete > .meta-section {
opacity: 1;
transition-property: opacity;
transition-timing-function: @metro_animation_easing@;
transition-duration: @metro_animation_duration@;
transition-delay: 0s;
visibility: visible;
}
#urlbar-autocomplete[nomatch] > .meta-section[anonid="results-container"] {
opacity: 0;
visibility: collapse;
}
#urlbar-autocomplete richgriditem:not([value]) {
visibility: collapse;
}
/* App bars ----------------------------------------------------------------- */

Просмотреть файл

@ -33,6 +33,15 @@ this.UITour = {
highlightEffects: ["random", "wobble", "zoom", "color"],
targets: new Map([
["accountStatus", {
query: (aDocument) => {
let statusButton = aDocument.getElementById("PanelUI-fxa-status");
return aDocument.getAnonymousElementByAttribute(statusButton,
"class",
"toolbarbutton-icon");
},
widgetName: "PanelUI-fxa-status",
}],
["addons", {query: "#add-ons-button"}],
["appMenu", {query: "#PanelUI-menu-button"}],
["backForward", {
@ -157,6 +166,9 @@ this.UITour = {
if (typeof buttonData.icon == "string")
button.iconURL = this.resolveURL(contentDocument, buttonData.icon);
if (typeof buttonData.style == "string")
button.style = buttonData.style;
buttons.push(button);
if (buttons.length == MAX_BUTTONS)
@ -298,6 +310,14 @@ this.UITour = {
}
break;
}
case "command": {
if (aEvent.target.id == "UITourTooltipClose") {
let window = aEvent.target.ownerDocument.defaultView;
this.hideInfo(window);
}
break;
}
}
},
@ -628,6 +648,9 @@ this.UITour = {
if (button.iconURL)
el.setAttribute("image", button.iconURL);
if (button.style == "link")
el.setAttribute("class", "button-link");
let callbackID = button.callbackID;
el.addEventListener("command", event => {
tooltip.hidePopup();
@ -639,6 +662,9 @@ this.UITour = {
tooltipButtons.hidden = !aButtons.length;
let tooltipClose = document.getElementById("UITourTooltipClose");
tooltipClose.addEventListener("command", this);
tooltip.hidden = false;
let alignment = "bottomcenter topright";
tooltip.openPopup(aAnchorEl, alignment);

Просмотреть файл

@ -78,6 +78,7 @@ if (typeof Mozilla == 'undefined') {
buttonData.push({
label: buttons[i].label,
icon: buttons[i].icon,
style: buttons[i].style,
callbackID: _waitForCallback(buttons[i].callback)
});
}

Двоичные данные
browser/themes/linux/Toolbar-inverted.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 8.7 KiB

После

Ширина:  |  Высота:  |  Размер: 8.8 KiB

Двоичные данные
browser/themes/linux/Toolbar.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 14 KiB

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Просмотреть файл

@ -1958,3 +1958,20 @@ chatbox {
}
%include ../shared/UITour.inc.css
#UITourTooltipDescription {
font-size: 1.05rem;
}
#UITourTooltipClose {
-moz-appearance: toolbarbutton;
list-style-image: url("moz-icon://stock/gtk-close?size=menu");
}
#UITourTooltipClose > .toolbarbutton-icon {
margin: -4px;
}
#UITourTooltipButtons {
margin-bottom: 0;
}

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 545 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 869 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 879 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 879 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 610 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1012 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.0 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 982 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 640 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 855 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 838 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 858 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 646 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 872 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 871 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 871 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 600 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1004 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1007 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 957 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 624 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 846 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 840 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 854 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 637 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1005 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 836 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 693 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 669 B

Двоичные данные
browser/themes/linux/devtools/debugger-pause.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 496 B

Двоичные данные
browser/themes/linux/devtools/debugger-play.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 686 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 451 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 473 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 599 B

Двоичные данные
browser/themes/linux/devtools/itemToggle.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Просмотреть файл

@ -1,131 +0,0 @@
/* 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/. */
#style-editor-chrome {
background-color: hsl(208,11%,27%);
}
.stylesheet-title,
.stylesheet-name {
text-decoration: none;
color: hsl(207,17%,88%);
}
.stylesheet-name {
font-size: 13px;
}
.stylesheet-rule-count,
.stylesheet-saveButton {
color: hsl(211,12%,60%);
}
.stylesheet-saveButton {
text-decoration: underline;
cursor: pointer;
}
.splitview-active .stylesheet-title,
.splitview-active .stylesheet-name {
color: hsl(0,0%,100%);
}
.splitview-active .stylesheet-rule-count,
.splitview-active .stylesheet-saveButton {
color: hsl(200,66%,70%);
}
.splitview-nav:focus {
outline: 0; /* focus ring is on the stylesheet name */
}
.splitview-nav > li.unsaved > hgroup .stylesheet-name {
font-style: italic;
}
.splitview-nav:-moz-locale-dir(ltr) > li.unsaved > hgroup .stylesheet-name:before,
.splitview-nav:-moz-locale-dir(rtl) > li.unsaved > hgroup .stylesheet-name:after {
font-style: italic;
}
.splitview-nav.empty > p {
padding: 0 10px;
}
.stylesheet-enabled {
padding: 8px 0;
margin: 0 8px;
background-image: url(itemToggle.png);
background-repeat: no-repeat;
background-clip: content-box;
background-position: 0 8px;
width: 24px;
height: 40px;
}
.disabled > .stylesheet-enabled {
background-position: -24px 8px;
}
.splitview-nav > li > .stylesheet-enabled:focus,
.splitview-nav > li:hover > .stylesheet-enabled {
outline: 0;
}
.stylesheet-error-message {
color: red;
}
.stylesheet-more > h3 {
font-size: 11px;
-moz-margin-end: 2px;
}
.devtools-searchinput {
max-width: 25ex;
font-size: 11px;
}
.placeholder {
color: white;
}
.placeholder a {
text-decoration: underline;
}
h1,
h2,
h3 {
font-size: inherit;
font-weight: normal;
margin: 0;
padding: 0;
}
/* portrait mode */
@media (max-width: 550px) {
.splitview-nav {
box-shadow: none;
}
.splitview-nav > li.splitview-active {
background-size: 0 0, 0 0, auto;
}
.stylesheet-enabled {
padding: 0;
background-position: 0 0;
height: 24px;
}
.disabled > .stylesheet-enabled {
background-position: -24px 0;
}
.splitview-nav > li > hgroup.stylesheet-info {
-moz-box-align: baseline;
}
}

Просмотреть файл

@ -153,6 +153,7 @@ browser.jar:
* skin/classic/browser/devtools/common.css (../shared/devtools/common.css)
* skin/classic/browser/devtools/dark-theme.css (../shared/devtools/dark-theme.css)
* skin/classic/browser/devtools/light-theme.css (../shared/devtools/light-theme.css)
skin/classic/browser/devtools/filters.svg (../shared/devtools/filters.svg)
skin/classic/browser/devtools/controls.png (../shared/devtools/controls.png)
* skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/commandline-icon.png (devtools/commandline-icon.png)
@ -178,61 +179,40 @@ browser.jar:
skin/classic/browser/devtools/editor-error.png (devtools/editor-error.png)
skin/classic/browser/devtools/editor-breakpoint.png (devtools/editor-breakpoint.png)
skin/classic/browser/devtools/editor-debug-location.png (devtools/editor-debug-location.png)
skin/classic/browser/devtools/breadcrumbs-scrollbutton.png (devtools/breadcrumbs-scrollbutton.png)
skin/classic/browser/devtools/breadcrumbs/ltr-end-pressed.png (devtools/breadcrumbs/ltr-end-pressed.png)
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png (devtools/breadcrumbs/ltr-end-selected-pressed.png)
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected.png (devtools/breadcrumbs/ltr-end-selected.png)
skin/classic/browser/devtools/breadcrumbs/ltr-end.png (devtools/breadcrumbs/ltr-end.png)
skin/classic/browser/devtools/breadcrumbs/ltr-middle-pressed.png (devtools/breadcrumbs/ltr-middle-pressed.png)
skin/classic/browser/devtools/breadcrumbs/ltr-middle-selected-pressed.png (devtools/breadcrumbs/ltr-middle-selected-pressed.png)
skin/classic/browser/devtools/breadcrumbs/ltr-middle-selected.png (devtools/breadcrumbs/ltr-middle-selected.png)
skin/classic/browser/devtools/breadcrumbs/ltr-middle.png (devtools/breadcrumbs/ltr-middle.png)
skin/classic/browser/devtools/breadcrumbs/ltr-start-pressed.png (devtools/breadcrumbs/ltr-start-pressed.png)
skin/classic/browser/devtools/breadcrumbs/ltr-start-selected-pressed.png (devtools/breadcrumbs/ltr-start-selected-pressed.png)
skin/classic/browser/devtools/breadcrumbs/ltr-start.png (devtools/breadcrumbs/ltr-start.png)
skin/classic/browser/devtools/breadcrumbs/ltr-start-selected.png (devtools/breadcrumbs/ltr-start-selected.png)
skin/classic/browser/devtools/breadcrumbs/rtl-end-pressed.png (devtools/breadcrumbs/rtl-end-pressed.png)
skin/classic/browser/devtools/breadcrumbs/rtl-end-selected-pressed.png (devtools/breadcrumbs/rtl-end-selected-pressed.png)
skin/classic/browser/devtools/breadcrumbs/rtl-end-selected.png (devtools/breadcrumbs/rtl-end-selected.png)
skin/classic/browser/devtools/breadcrumbs/rtl-end.png (devtools/breadcrumbs/rtl-end.png)
skin/classic/browser/devtools/breadcrumbs/rtl-middle-pressed.png (devtools/breadcrumbs/rtl-middle-pressed.png)
skin/classic/browser/devtools/breadcrumbs/rtl-middle-selected-pressed.png (devtools/breadcrumbs/rtl-middle-selected-pressed.png)
skin/classic/browser/devtools/breadcrumbs/rtl-middle-selected.png (devtools/breadcrumbs/rtl-middle-selected.png)
skin/classic/browser/devtools/breadcrumbs/rtl-middle.png (devtools/breadcrumbs/rtl-middle.png)
skin/classic/browser/devtools/breadcrumbs/rtl-start-pressed.png (devtools/breadcrumbs/rtl-start-pressed.png)
skin/classic/browser/devtools/breadcrumbs/rtl-start-selected-pressed.png (devtools/breadcrumbs/rtl-start-selected-pressed.png)
skin/classic/browser/devtools/breadcrumbs/rtl-start.png (devtools/breadcrumbs/rtl-start.png)
skin/classic/browser/devtools/breadcrumbs/rtl-start-selected.png (devtools/breadcrumbs/rtl-start-selected.png)
skin/classic/browser/devtools/splitview.css (devtools/splitview.css)
skin/classic/browser/devtools/styleeditor.css (devtools/styleeditor.css)
skin/classic/browser/devtools/breadcrumbs-divider@2x.png (../shared/devtools/images/breadcrumbs-divider@2x.png)
skin/classic/browser/devtools/breadcrumbs-scrollbutton.png (../shared/devtools/images/breadcrumbs-scrollbutton.png)
skin/classic/browser/devtools/breadcrumbs-scrollbutton@2x.png (../shared/devtools/images/breadcrumbs-scrollbutton@2x.png)
skin/classic/browser/devtools/splitview.css (../shared/devtools/splitview.css)
skin/classic/browser/devtools/styleeditor.css (../shared/devtools/styleeditor.css)
* skin/classic/browser/devtools/shadereditor.css (devtools/shadereditor.css)
* skin/classic/browser/devtools/debugger.css (devtools/debugger.css)
* skin/classic/browser/devtools/profiler.css (devtools/profiler.css)
* skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
* skin/classic/browser/devtools/scratchpad.css (devtools/scratchpad.css)
skin/classic/browser/devtools/magnifying-glass.png (devtools/magnifying-glass.png)
skin/classic/browser/devtools/option-icon.png (devtools/option-icon.png)
skin/classic/browser/devtools/itemToggle.png (devtools/itemToggle.png)
skin/classic/browser/devtools/option-icon.png (../shared/devtools/images/option-icon.png)
skin/classic/browser/devtools/itemToggle.png (../shared/devtools/images/itemToggle.png)
skin/classic/browser/devtools/itemToggle-light.png (../shared/devtools/images/itemToggle-light.png)
skin/classic/browser/devtools/itemArrow-dark-rtl.png (../shared/devtools/images/itemArrow-dark-rtl.png)
skin/classic/browser/devtools/itemArrow-dark-ltr.png (../shared/devtools/images/itemArrow-dark-ltr.png)
skin/classic/browser/devtools/itemArrow-rtl.png (../shared/devtools/images/itemArrow-rtl.png)
skin/classic/browser/devtools/itemArrow-ltr.png (../shared/devtools/images/itemArrow-ltr.png)
skin/classic/browser/devtools/itemArrow-rtl.svg (../shared/devtools/images/itemArrow-rtl.svg)
skin/classic/browser/devtools/itemArrow-ltr.svg (../shared/devtools/images/itemArrow-ltr.svg)
skin/classic/browser/devtools/background-noise-toolbar.png (devtools/background-noise-toolbar.png)
skin/classic/browser/devtools/noise.png (devtools/noise.png)
skin/classic/browser/devtools/inspect-button.png (devtools/inspect-button.png)
skin/classic/browser/devtools/dropmarker.png (devtools/dropmarker.png)
skin/classic/browser/devtools/layout-background-grid.png (devtools/layout-background-grid.png)
skin/classic/browser/devtools/layoutview.css (devtools/layoutview.css)
skin/classic/browser/devtools/debugger-collapse.png (devtools/debugger-collapse.png)
skin/classic/browser/devtools/debugger-expand.png (devtools/debugger-expand.png)
skin/classic/browser/devtools/debugger-pause.png (devtools/debugger-pause.png)
skin/classic/browser/devtools/debugger-play.png (devtools/debugger-play.png)
skin/classic/browser/devtools/debugger-step-in.png (devtools/debugger-step-in.png)
skin/classic/browser/devtools/debugger-step-out.png (devtools/debugger-step-out.png)
skin/classic/browser/devtools/debugger-step-over.png (devtools/debugger-step-over.png)
skin/classic/browser/devtools/debugger-blackbox.png (devtools/debugger-blackbox.png)
skin/classic/browser/devtools/debugger-blackboxMessageEye.png (devtools/debugger-blackboxMessageEye.png)
skin/classic/browser/devtools/debugger-toggleBreakpoints.png (devtools/debugger-toggleBreakpoints.png)
skin/classic/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png)
skin/classic/browser/devtools/debugger-expand.png (../shared/devtools/images/debugger-expand.png)
skin/classic/browser/devtools/debugger-pause.png (../shared/devtools/images/debugger-pause.png)
skin/classic/browser/devtools/debugger-play.png (../shared/devtools/images/debugger-play.png)
skin/classic/browser/devtools/debugger-step-in.png (../shared/devtools/images/debugger-step-in.png)
skin/classic/browser/devtools/debugger-step-out.png (../shared/devtools/images/debugger-step-out.png)
skin/classic/browser/devtools/debugger-step-over.png (../shared/devtools/images/debugger-step-over.png)
skin/classic/browser/devtools/debugger-blackbox-eye.png (../shared/devtools/images/debugger-blackbox-eye.png)
skin/classic/browser/devtools/debugger-blackbox.png (../shared/devtools/images/debugger-blackbox.png)
skin/classic/browser/devtools/debugger-toggleBreakpoints.png (../shared/devtools/images/debugger-toggleBreakpoints.png)
skin/classic/browser/devtools/tracer-icon.png (devtools/tracer-icon.png)
skin/classic/browser/devtools/tracer-icon@2x.png (devtools/tracer-icon@2x.png)
skin/classic/browser/devtools/responsive-se-resizer.png (devtools/responsive-se-resizer.png)
@ -245,7 +225,7 @@ browser.jar:
skin/classic/browser/devtools/floating-scrollbars.css (devtools/floating-scrollbars.css)
skin/classic/browser/devtools/floating-scrollbars-light.css (devtools/floating-scrollbars-light.css)
skin/classic/browser/devtools/inspector.css (devtools/inspector.css)
skin/classic/browser/devtools/profiler-stopwatch.png (devtools/profiler-stopwatch.png)
skin/classic/browser/devtools/profiler-stopwatch.png (../shared/devtools/images/profiler-stopwatch.png)
skin/classic/browser/devtools/tool-options.svg (../shared/devtools/images/tool-options.svg)
skin/classic/browser/devtools/tool-webconsole.svg (../shared/devtools/images/tool-webconsole.svg)
skin/classic/browser/devtools/tool-debugger.svg (../shared/devtools/images/tool-debugger.svg)

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше