merge fx-team to mozilla-central
|
@ -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 & 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 & 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;
|
||||
}
|
||||
|
|
Двоичные данные
browser/themes/linux/devtools/breadcrumbs-scrollbutton.png
До Ширина: | Высота: | Размер: 545 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/ltr-end-pressed.png
До Ширина: | Высота: | Размер: 869 B |
До Ширина: | Высота: | Размер: 879 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/ltr-end-selected.png
До Ширина: | Высота: | Размер: 879 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/ltr-end.png
До Ширина: | Высота: | Размер: 610 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/ltr-middle-pressed.png
До Ширина: | Высота: | Размер: 1012 B |
До Ширина: | Высота: | Размер: 1.0 KiB |
До Ширина: | Высота: | Размер: 982 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/ltr-middle.png
До Ширина: | Высота: | Размер: 640 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/ltr-start-pressed.png
До Ширина: | Высота: | Размер: 855 B |
До Ширина: | Высота: | Размер: 838 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/ltr-start-selected.png
До Ширина: | Высота: | Размер: 858 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/ltr-start.png
До Ширина: | Высота: | Размер: 646 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/rtl-end-pressed.png
До Ширина: | Высота: | Размер: 872 B |
До Ширина: | Высота: | Размер: 871 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/rtl-end-selected.png
До Ширина: | Высота: | Размер: 871 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/rtl-end.png
До Ширина: | Высота: | Размер: 600 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/rtl-middle-pressed.png
До Ширина: | Высота: | Размер: 1004 B |
До Ширина: | Высота: | Размер: 1007 B |
До Ширина: | Высота: | Размер: 957 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/rtl-middle.png
До Ширина: | Высота: | Размер: 624 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/rtl-start-pressed.png
До Ширина: | Высота: | Размер: 846 B |
До Ширина: | Высота: | Размер: 840 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/rtl-start-selected.png
До Ширина: | Высота: | Размер: 854 B |
Двоичные данные
browser/themes/linux/devtools/breadcrumbs/rtl-start.png
До Ширина: | Высота: | Размер: 637 B |
Двоичные данные
browser/themes/linux/devtools/debugger-blackbox.png
До Ширина: | Высота: | Размер: 1005 B |
Двоичные данные
browser/themes/linux/devtools/debugger-blackboxMessageEye.png
До Ширина: | Высота: | Размер: 836 B |
Двоичные данные
browser/themes/linux/devtools/debugger-collapse.png
До Ширина: | Высота: | Размер: 693 B |
Двоичные данные
browser/themes/linux/devtools/debugger-expand.png
До Ширина: | Высота: | Размер: 669 B |
Двоичные данные
browser/themes/linux/devtools/debugger-pause.png
До Ширина: | Высота: | Размер: 496 B |
Двоичные данные
browser/themes/linux/devtools/debugger-play.png
До Ширина: | Высота: | Размер: 686 B |
Двоичные данные
browser/themes/linux/devtools/debugger-step-in.png
До Ширина: | Высота: | Размер: 451 B |
Двоичные данные
browser/themes/linux/devtools/debugger-step-out.png
До Ширина: | Высота: | Размер: 473 B |
Двоичные данные
browser/themes/linux/devtools/debugger-step-over.png
До Ширина: | Высота: | Размер: 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)
|
||||
|
|