CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2015-04-06 18:48:20 -04:00
Родитель 7a668f84df 080b9b2f19
Коммит b79ce1078e
543 изменённых файлов: 2085 добавлений и 884 удалений

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

@ -29,6 +29,7 @@ pref("browser.sessionstore.restore_on_demand", false);
pref("browser.sessionstore.resume_from_crash", false);
// No e10s on mulet
pref("browser.tabs.remote.autostart.1", false);
pref("browser.tabs.remote.autostart.2", false);
#endif
// Bug 945235: Prevent all bars to be considered visible:
@ -1037,6 +1038,7 @@ pref("apz.fling_curve_function_y2", "1.0");
pref("apz.fling_curve_threshold_inches_per_ms", "0.01");
pref("apz.fling_friction", "0.0019");
pref("apz.max_velocity_inches_per_ms", "0.07");
pref("apz.touch_start_tolerance", "0.1");
// Tweak default displayport values to reduce the risk of running out of
// memory when zooming in

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

@ -196,19 +196,20 @@ SettingsListener.observe('devtools.overlay', false, (value) => {
});
#ifdef MOZ_WIDGET_GONK
let LogShake;
SettingsListener.observe('devtools.logshake', false, (value) => {
if (value) {
if (!LogShake) {
(function() {
let scope = {};
Cu.import('resource://gre/modules/LogShake.jsm', scope);
LogShake = scope.LogShake;
}
LogShake.init();
})();
SettingsListener.observe('devtools.logshake', false, value => {
if (value) {
LogShake.enableDeviceMotionListener();
} else {
if (LogShake) {
LogShake.uninit();
}
LogShake.disableDeviceMotionListener();
}
});
#endif

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

@ -56,6 +56,7 @@ function debug(msg) {
const EXCITEMENT_THRESHOLD = 500;
const DEVICE_MOTION_EVENT = "devicemotion";
const SCREEN_CHANGE_EVENT = "screenchange";
const CAPTURE_LOGS_CONTENT_EVENT = "requestSystemLogs";
const CAPTURE_LOGS_START_EVENT = "capture-logs-start";
const CAPTURE_LOGS_ERROR_EVENT = "capture-logs-error";
const CAPTURE_LOGS_SUCCESS_EVENT = "capture-logs-success";
@ -69,6 +70,18 @@ let LogShake = {
*/
deviceMotionEnabled: false,
/**
* We only listen to motion events when the screen is enabled, keep track
* of its state.
*/
screenEnabled: true,
/**
* Flag monitoring if the preference to enable shake to capture is
* enabled in gaia.
*/
listenToDeviceMotion: true,
/**
* If a capture has been requested and is waiting for reads/parsing. Used for
* debouncing.
@ -109,6 +122,7 @@ let LogShake = {
screenEnabled: true
}});
SystemAppProxy.addEventListener(CAPTURE_LOGS_CONTENT_EVENT, this, false);
SystemAppProxy.addEventListener(SCREEN_CHANGE_EVENT, this, false);
Services.obs.addObserver(this, "xpcom-shutdown", false);
@ -129,6 +143,10 @@ let LogShake = {
case SCREEN_CHANGE_EVENT:
this.handleScreenChangeEvent(event);
break;
case CAPTURE_LOGS_CONTENT_EVENT:
this.startCapture();
break;
}
},
@ -141,8 +159,20 @@ let LogShake = {
}
},
enableDeviceMotionListener: function() {
this.listenToDeviceMotion = true;
this.startDeviceMotionListener();
},
disableDeviceMotionListener: function() {
this.listenToDeviceMotion = false;
this.stopDeviceMotionListener();
},
startDeviceMotionListener: function() {
if (!this.deviceMotionEnabled) {
if (!this.deviceMotionEnabled &&
this.listenToDeviceMotion &&
this.screenEnabled) {
SystemAppProxy.addEventListener(DEVICE_MOTION_EVENT, this, false);
this.deviceMotionEnabled = true;
}
@ -169,7 +199,14 @@ let LogShake = {
var excitement = acc.x * acc.x + acc.y * acc.y + acc.z * acc.z;
if (excitement > EXCITEMENT_THRESHOLD) {
if (!this.captureRequested) {
this.startCapture();
}
},
startCapture: function() {
if (this.captureRequested) {
return;
}
this.captureRequested = true;
SystemAppProxy._sendCustomEvent(CAPTURE_LOGS_START_EVENT, {});
this.captureLogs().then(logResults => {
@ -179,18 +216,16 @@ let LogShake = {
logPrefix: logResults.logPrefix
});
this.captureRequested = false;
},
error => {
}, error => {
// On an error send the error event
SystemAppProxy._sendCustomEvent(CAPTURE_LOGS_ERROR_EVENT, {error: error});
this.captureRequested = false;
});
}
}
},
handleScreenChangeEvent: function(event) {
if (event.detail.screenEnabled) {
this.screenEnabled = event.detail.screenEnabled;
if (this.screenEnabled) {
this.startDeviceMotionListener();
} else {
this.stopDeviceMotionListener();

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ef61ebbe5de8c2c9fc2a8f74a12455044c3b82e9"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="834385f4c834238a4306bf87cc4be41615d91ff0"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ef61ebbe5de8c2c9fc2a8f74a12455044c3b82e9"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="834385f4c834238a4306bf87cc4be41615d91ff0"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>

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

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ef61ebbe5de8c2c9fc2a8f74a12455044c3b82e9"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="834385f4c834238a4306bf87cc4be41615d91ff0"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b1d86462d3150dceacff927536ded9fcc168419"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ef61ebbe5de8c2c9fc2a8f74a12455044c3b82e9"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="834385f4c834238a4306bf87cc4be41615d91ff0"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ef61ebbe5de8c2c9fc2a8f74a12455044c3b82e9"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="834385f4c834238a4306bf87cc4be41615d91ff0"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ef61ebbe5de8c2c9fc2a8f74a12455044c3b82e9"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="834385f4c834238a4306bf87cc4be41615d91ff0"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ef61ebbe5de8c2c9fc2a8f74a12455044c3b82e9"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="834385f4c834238a4306bf87cc4be41615d91ff0"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ef61ebbe5de8c2c9fc2a8f74a12455044c3b82e9"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="834385f4c834238a4306bf87cc4be41615d91ff0"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b1d86462d3150dceacff927536ded9fcc168419"/>

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

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "ef61ebbe5de8c2c9fc2a8f74a12455044c3b82e9",
"git_revision": "834385f4c834238a4306bf87cc4be41615d91ff0",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "fceb69a8216d41525d5bec7efe4e97c140cc386d",
"revision": "e7a7a8c4f624820b810b33e098a3e7d941de53a1",
"repo_path": "integration/gaia-central"
}

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

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ef61ebbe5de8c2c9fc2a8f74a12455044c3b82e9"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="834385f4c834238a4306bf87cc4be41615d91ff0"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b1d86462d3150dceacff927536ded9fcc168419"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ef61ebbe5de8c2c9fc2a8f74a12455044c3b82e9"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="834385f4c834238a4306bf87cc4be41615d91ff0"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -17,3 +17,4 @@ pref("devtools.toolbox.sidebar.width", 800);
// nor the system app OOP, but only inner apps
pref("browser.tabs.remote.autostart", false);
pref("browser.tabs.remote.autostart.1", false);
pref("browser.tabs.remote.autostart.2", false);

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

@ -1855,7 +1855,11 @@ pref("privacy.trackingprotection.ui.enabled", false);
#endif
#ifdef NIGHTLY_BUILD
pref("browser.tabs.remote.autostart.1", true);
// At the moment, autostart.2 is used, while autostart.1 is unused.
// We leave it here set to false to reset users' defaults and allow
// us to change everybody to true in the future, when desired.
pref("browser.tabs.remote.autostart.1", false);
pref("browser.tabs.remote.autostart.2", true);
#endif
#ifdef NIGHTLY_BUILD

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

@ -834,7 +834,7 @@
<image id="reader-mode-button"
class="urlbar-icon"
hidden="true"
onclick="ReaderParent.toggleReaderMode(event);"/>
onclick="ReaderParent.buttonClick(event);"/>
</hbox>
<toolbarbutton id="urlbar-go-button"
class="chromeclass-toolbar-additional"

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

@ -2772,7 +2772,12 @@ let E10SUINotification = {
return;
}
// The user has just voluntarily disabled e10s. Subtract one from displayedE10SNotice
// so that the next time e10s is activated (either by the user or forced by us), they
// can see the notice again.
Services.prefs.setIntPref("browser.displayedE10SNotice", this.CURRENT_NOTICE_COUNT - 1);
Services.prefs.clearUserPref("browser.requestE10sFeedback");
let url = Services.urlFormatter.formatURLPref("app.feedback.baseURL");
url += "?utm_source=tab&utm_campaign=e10sfeedback";

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

@ -14,7 +14,7 @@
name="browser.tabs.remote.autostart"
type="bool"/>
<preference id="e10sTempPref"
name="browser.tabs.remote.autostart.1"
name="browser.tabs.remote.autostart.2"
type="bool"/>
#endif

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

@ -21,8 +21,13 @@ if test "$OS_ARCH" = "WINNT"; then
fi
fi
fi
elif test "$OS_ARCH" = "Darwin"; then
MOZ_VERIFY_MAR_SIGNATURE=1
fi
# Enable building ./signmar and running libmar signature tests
MOZ_ENABLE_SIGNMAR=1
MOZ_CHROME_FILE_FORMAT=omni
MOZ_DISABLE_EXPORT_JS=1
MOZ_SAFE_BROWSING=1

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

@ -125,6 +125,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "DevToolsUtils",
XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils",
"resource://gre/modules/ShortcutUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
"@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper");
Object.defineProperty(this, "NetworkHelper", {
get: function() {
return devtools.require("devtools/toolkit/webconsole/network-helper");

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

@ -40,6 +40,8 @@ function SourcesView() {
this._onConditionalPopupShown = this._onConditionalPopupShown.bind(this);
this._onConditionalPopupHiding = this._onConditionalPopupHiding.bind(this);
this._onConditionalTextboxKeyPress = this._onConditionalTextboxKeyPress.bind(this);
this._onCopyUrlCommand = this._onCopyUrlCommand.bind(this);
this._onNewTabCommand = this._onNewTabCommand.bind(this);
}
SourcesView.prototype = Heritage.extend(WidgetMethods, {
@ -50,6 +52,7 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
dumpn("Initializing the SourcesView");
this.widget = new SideMenuWidget(document.getElementById("sources"), {
contextMenu: document.getElementById("debuggerSourcesContextMenu"),
showArrows: true
});
@ -65,6 +68,8 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
this._stopBlackBoxButton = document.getElementById("black-boxed-message-button");
this._prettyPrintButton = document.getElementById("pretty-print");
this._toggleBreakpointsButton = document.getElementById("toggle-breakpoints");
this._newTabMenuItem = document.getElementById("debugger-sources-context-newtab");
this._copyUrlMenuItem = document.getElementById("debugger-sources-context-copyurl");
if (Prefs.prettyPrintEnabled) {
this._prettyPrintButton.removeAttribute("hidden");
@ -78,7 +83,10 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
this._cbPanel.addEventListener("popupshown", this._onConditionalPopupShown, false);
this._cbPanel.addEventListener("popuphiding", this._onConditionalPopupHiding, false);
this._cbTextbox.addEventListener("keypress", this._onConditionalTextboxKeyPress, false);
this._copyUrlMenuItem.addEventListener("command", this._onCopyUrlCommand, false);
this._newTabMenuItem.addEventListener("command", this._onNewTabCommand, false);
this.allowFocusOnRightClick = true;
this.autoFocusOnSelection = false;
// Sort the contents by the displayed label.
@ -112,6 +120,8 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
this._cbPanel.removeEventListener("popupshowing", this._onConditionalPopupShown, false);
this._cbPanel.removeEventListener("popuphiding", this._onConditionalPopupHiding, false);
this._cbTextbox.removeEventListener("keypress", this._onConditionalTextboxKeyPress, false);
this._copyUrlMenuItem.removeEventListener("command", this._onCopyUrlCommand, false);
this._newTabMenuItem.removeEventListener("command", this._onNewTabCommand, false);
},
/**
@ -872,6 +882,26 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
}
},
/**
* Copy the source url from the currently selected item.
*/
_onCopyUrlCommand: function() {
let selected = this.selectedItem && this.selectedItem.attachment;
if (!selected) {
return;
}
clipboardHelper.copyString(selected.source.url, document);
},
/**
* Opens selected item source in a new tab.
*/
_onNewTabCommand: function() {
let win = Services.wm.getMostRecentWindow("navigator:browser");
let selected = this.selectedItem.attachment;
win.openUILinkIn(selected.source.url, "tab", { relatedToCurrent: true });
},
/**
* Function called each time a breakpoint item is removed.
*

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

@ -156,6 +156,17 @@
</menupopup>
</popupset>
<popupset id="debuggerSourcesPopupset">
<menupopup id="debuggerSourcesContextMenu">
<menuitem id="debugger-sources-context-newtab"
label="&debuggerUI.context.newTab;"
accesskey="&debuggerUI.context.newTab.accesskey;"/>
<menuitem id="debugger-sources-context-copyurl"
label="&debuggerUI.context.copyUrl;"
accesskey="&debuggerUI.context.copyUrl.accesskey;"/>
</menupopup>
</popupset>
<keyset id="debuggerKeys">
<key id="nextSourceKey"
keycode="VK_DOWN"
@ -242,6 +253,10 @@
key="&debuggerUI.removeAllWatch.key;"
modifiers="accel alt"
command="removeAllWatchExpressionsCommand"/>
<key id="debuggerSourcesCopyUrl"
key="&debuggerUI.context.copyUrl.key;"
modifiers="accel"
oncommand="DebuggerView.Sources._onCopyUrlCommand()"/>
</keyset>
<vbox id="body"

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

@ -389,10 +389,13 @@ skip-if = e10s && debug
[browser_dbg_source-maps-04.js]
skip-if = e10s # Bug 1093535
[browser_dbg_sources-cache.js]
[browser_dbg_sources-contextmenu-01.js]
[browser_dbg_sources-contextmenu-02.js]
skip-if = e10s && debug
[browser_dbg_sources-eval-01.js]
skip-if = true # non-named eval sources turned off for now, bug 1124106
[browser_dbg_sources-eval-02.js]
[browser_dbg_sources-keybindings.js]
skip-if = e10s && debug
[browser_dbg_sources-labels.js]
skip-if = e10s && debug

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

@ -0,0 +1,52 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests the "Copy URL" functionality of the sources panel context menu
*/
const TAB_URL = EXAMPLE_URL + "doc_function-search.html";
const SCRIPT_URI = EXAMPLE_URL + "code_function-search-01.js";
function test() {
let gTab, gPanel, gDebugger, gSources;
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
gTab = aTab;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gSources = gDebugger.DebuggerView.Sources;
waitForSourceShown(gPanel, "-01.js")
.then(openContextMenu)
.then(testCopyMenuItem)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
function clickCopyURL() {
return new Promise((resolve, reject) => {
let copyURLMenuItem = gDebugger.document.getElementById("debugger-sources-context-copyurl");
if (!copyURLMenuItem) {
reject(new Error("The Copy URL context menu item is not available."));
}
ok(copyURLMenuItem, "The Copy URL context menu item is available.");
EventUtils.synthesizeMouseAtCenter(copyURLMenuItem, {}, gDebugger);
resolve();
});
}
function testCopyMenuItem() {
return waitForClipboardPromise(clickCopyURL, SCRIPT_URI);
}
function openContextMenu() {
let contextMenu = gDebugger.document.getElementById("debuggerSourcesContextMenu");
let contextMenuShown = once(contextMenu, "popupshown");
EventUtils.synthesizeMouseAtCenter(gSources.selectedItem.prebuiltNode, {type: 'contextmenu'}, gDebugger);
return contextMenuShown;
}
}

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

@ -0,0 +1,70 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests the "Open in New Tab" functionality of the sources panel context menu
*/
const TAB_URL = EXAMPLE_URL + "doc_function-search.html";
const SCRIPT_URI = EXAMPLE_URL + "code_function-search-01.js";
function test() {
let gTab, gPanel, gDebugger;
let gSources;
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
gTab = aTab;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gSources = gDebugger.DebuggerView.Sources;
waitForSourceShown(gPanel, "-01.js")
.then(openContextMenu)
.then(testNewTabMenuItem)
.then(testNewTabURI)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
function testNewTabURI(tabUri) {
is(tabUri, SCRIPT_URI, "The tab contains the right script.");
gBrowser.removeCurrentTab();
}
function waitForTabOpen() {
return new Promise(resolve => {
gBrowser.tabContainer.addEventListener("TabOpen", function onOpen(e) {
gBrowser.tabContainer.removeEventListener("TabOpen", onOpen, false);
ok(true, "A new tab loaded");
gBrowser.addEventListener("DOMContentLoaded", function onTabLoad(e){
gBrowser.removeEventListener("DOMContentLoaded", onTabLoad, false);
// Pass along the new tab's URI.
resolve(gBrowser.currentURI.spec);
}, false);
}, false);
});
}
function testNewTabMenuItem() {
return new Promise((resolve, reject) => {
let newTabMenuItem = gDebugger.document.getElementById("debugger-sources-context-newtab");
if (!newTabMenuItem) {
reject(new Error("The Open in New Tab context menu item is not available."));
}
ok(newTabMenuItem, "The Open in New Tab context menu item is available.");
waitForTabOpen().then(resolve);
EventUtils.synthesizeMouseAtCenter(newTabMenuItem, {}, gDebugger);
});
}
function openContextMenu() {
let contextMenu = gDebugger.document.getElementById("debuggerSourcesContextMenu");
let contextMenuShown = once(contextMenu, "popupshown");
EventUtils.synthesizeMouseAtCenter(gSources.selectedItem.prebuiltNode, {type: 'contextmenu'}, gDebugger);
return contextMenuShown;
}
}

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

@ -0,0 +1,35 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests related to source panel keyboard shortcut bindings
*/
const TAB_URL = EXAMPLE_URL + "doc_function-search.html";
const SCRIPT_URI = EXAMPLE_URL + "code_function-search-01.js";
function test() {
let gTab, gPanel, gDebugger, gSources;
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
gTab = aTab;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gSources = gDebugger.DebuggerView.Sources;
waitForSourceShown(gPanel, "-01.js")
.then(testCopyURLShortcut)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
function testCopyURLShortcut() {
return waitForClipboardPromise(sendCopyShortcut, SCRIPT_URI);
}
function sendCopyShortcut() {
EventUtils.synthesizeKey("C", { accelKey: true }, gDebugger);
}
}

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

@ -441,6 +441,12 @@ function waitForClientEvents(aPanel, aEventName, aEventRepeat = 1) {
return deferred.promise;
}
function waitForClipboardPromise(setup, expected) {
return new Promise((resolve, reject) => {
SimpleTest.waitForClipboard(expected, setup, resolve, reject);
});
}
function ensureThreadClientState(aPanel, aState) {
let thread = aPanel.panelWin.gThreadClient;
let state = thread.state;

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

@ -11,6 +11,7 @@ Cu.import("resource://gre/modules/Services.jsm");
let promise = require("resource://gre/modules/Promise.jsm").Promise;
let EventEmitter = require("devtools/toolkit/event-emitter");
let clipboard = require("sdk/clipboard");
let {HostType} = require("devtools/framework/toolbox").Toolbox;
loader.lazyGetter(this, "MarkupView", () => require("devtools/markupview/markup-view").MarkupView);
loader.lazyGetter(this, "HTMLBreadcrumbs", () => require("devtools/inspector/breadcrumbs").HTMLBreadcrumbs);
@ -144,6 +145,9 @@ InspectorPanel.prototype = {
this.breadcrumbs = new HTMLBreadcrumbs(this);
this.onToolboxHostChanged = this.onToolboxHostChanged.bind(this);
this._toolbox.on("host-changed", this.onToolboxHostChanged);
if (this.target.isLocalTab) {
this.browser = this.target.tab.linkedBrowser;
this.scheduleLayoutChange = this.scheduleLayoutChange.bind(this);
@ -350,6 +354,19 @@ InspectorPanel.prototype = {
}
this.sidebar.show();
this.setupSidebarToggle();
},
/**
* Add the expand/collapse behavior for the sidebar panel.
*/
setupSidebarToggle: function() {
this._paneToggleButton = this.panelDoc.getElementById("inspector-pane-toggle");
this.onPaneToggleButtonClicked = this.onPaneToggleButtonClicked.bind(this);
this._paneToggleButton.addEventListener("mousedown",
this.onPaneToggleButtonClicked);
this.updatePaneToggleButton();
},
/**
@ -553,6 +570,7 @@ InspectorPanel.prototype = {
this.target.off("thread-paused", this.updateDebuggerPausedWarning);
this.target.off("thread-resumed", this.updateDebuggerPausedWarning);
this._toolbox.off("select", this.updateDebuggerPausedWarning);
this._toolbox.off("host-changed", this.onToolboxHostChanged);
this.sidebar.off("select", this._setDefaultSidebar);
let sidebarDestroyer = this.sidebar.destroy();
@ -561,6 +579,9 @@ InspectorPanel.prototype = {
this.nodemenu.removeEventListener("popupshowing", this._setupNodeMenu, true);
this.nodemenu.removeEventListener("popuphiding", this._resetNodeMenu, true);
this.breadcrumbs.destroy();
this._paneToggleButton.removeEventListener("mousedown",
this.onPaneToggleButtonClicked);
this._paneToggleButton = null;
this.searchSuggestions.destroy();
this.searchBox = null;
this.selection.off("new-node-front", this.onNewSelection);
@ -784,6 +805,47 @@ InspectorPanel.prototype = {
return destroyPromise;
},
/**
* When the type of toolbox host changes.
*/
onToolboxHostChanged: function() {
this.updatePaneToggleButton();
},
/**
* When the pane toggle button is clicked, toggle the pane, change the button
* state and tooltip.
*/
onPaneToggleButtonClicked: function(e) {
let sidePane = this.panelDoc.querySelector("#inspector-sidebar");
let button = this._paneToggleButton;
let isVisible = !button.hasAttribute("pane-collapsed");
ViewHelpers.togglePane({
visible: !isVisible,
animated: true,
delayed: true
}, sidePane);
if (isVisible) {
button.setAttribute("pane-collapsed", "");
button.setAttribute("tooltiptext",
this.strings.GetStringFromName("inspector.expandPane"));
} else {
button.removeAttribute("pane-collapsed");
button.setAttribute("tooltiptext",
this.strings.GetStringFromName("inspector.collapsePane"));
}
},
/**
* Update the pane toggle button visibility depending on the toolbox host type.
*/
updatePaneToggleButton: function() {
this._paneToggleButton.setAttribute("hidden",
this._toolbox.hostType === HostType.SIDE);
},
/**
* Toggle a pseudo class.
*/

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

@ -121,6 +121,9 @@
timeout="50"
class="devtools-searchinput"
placeholder="&inspectorSearchHTML.label2;"/>
<toolbarbutton id="inspector-pane-toggle"
class="devtools-toolbarbutton"
tabindex="0" />
</toolbar>
<vbox flex="1" id="markup-box">
</vbox>

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

@ -76,6 +76,9 @@ skip-if = e10s # GCLI isn't e10s compatible. See bug 1128988.
[browser_inspector_menu-03-paste-items.js]
[browser_inspector_menu-04-other.js]
[browser_inspector_navigation.js]
[browser_inspector_pane-toggle-01.js]
[browser_inspector_pane-toggle-02.js]
[browser_inspector_pane-toggle-03.js]
[browser_inspector_picker-stop-on-destroy.js]
[browser_inspector_picker-stop-on-tool-change.js]
[browser_inspector_pseudoclass-lock.js]

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

@ -0,0 +1,23 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the inspector panel has a sidebar pane toggle button, and that
// this button is hidden when the toolbox is in SIDE mode.
add_task(function* () {
info("Open the inspector in a bottom toolbox host");
let {toolbox, inspector} = yield openInspectorForURL("about:blank", "bottom");
let button = inspector.panelDoc.getElementById("inspector-pane-toggle");
ok(button, "The toggle button exists in the DOM");
is(button.parentNode.id, "inspector-toolbar", "The toggle button is in the toolbar");
ok(!button.hasAttribute("pane-collapsed"), "The button is in expanded state");
ok(!!button.getClientRects().length, "The button is visible");
info("Switch the host to side type");
yield toolbox.switchHost("side");
ok(!button.getClientRects().length, "The button is hidden");
});

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

@ -0,0 +1,24 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the inspector panel has its toggle pane button hidden by default
// when it is opened in a "side" host, and that the button becomes visible when
// the toolbox is switched to a "bottom" host.
add_task(function* () {
info("Open the inspector in a side toolbox host");
let {toolbox, inspector} = yield openInspectorForURL("about:blank", "side");
let button = inspector.panelDoc.getElementById("inspector-pane-toggle");
ok(button, "The toggle button exists in the DOM");
is(button.parentNode.id, "inspector-toolbar", "The toggle button is in the toolbar");
ok(!button.hasAttribute("pane-collapsed"), "The button is in expanded state");
ok(!button.getClientRects().length, "The button is hidden");
info("Switch the host to bottom type");
yield toolbox.switchHost("bottom");
ok(!!button.getClientRects().length, "The button is visible");
});

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

@ -0,0 +1,37 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the sidebar panel toggle button actually works.
add_task(function* () {
let {inspector} = yield openInspectorForURL("about:blank");
let button = inspector.panelDoc.getElementById("inspector-pane-toggle");
let panel = inspector.panelDoc.querySelector("#inspector-sidebar");
ok(!button.hasAttribute("pane-collapsed"), "The button is in expanded state");
info("Listen to the end of the animation on the sidebar panel");
let onTransitionEnd = once(panel, "transitionend");
info("Click on the toggle button");
EventUtils.synthesizeMouseAtCenter(button, {type: "mousedown"},
inspector.panelDoc.defaultView);
yield onTransitionEnd;
ok(button.hasAttribute("pane-collapsed"), "The button is in collapsed state");
ok(panel.hasAttribute("pane-collapsed"), "The panel is in collapsed state");
info("Listen again to the end of the animation on the sidebar panel");
onTransitionEnd = once(panel, "transitionend");
info("Click on the toggle button again");
EventUtils.synthesizeMouseAtCenter(button, {type: "mousedown"},
inspector.panelDoc.defaultView);
yield onTransitionEnd;
ok(!button.hasAttribute("pane-collapsed"), "The button is in expanded state");
ok(!panel.hasAttribute("pane-collapsed"), "The panel is in expanded state");
});

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

@ -149,12 +149,13 @@ let selectNode = Task.async(function*(selector, inspector, reason="test") {
/**
* Open the inspector in a tab with given URL.
* @param {string} url The URL to open.
* @param {String} hostType Optional hostType, as defined in Toolbox.HostType
* @return A promise that is resolved once the tab and inspector have loaded
* with an object: { tab, toolbox, inspector }.
*/
let openInspectorForURL = Task.async(function* (url) {
let openInspectorForURL = Task.async(function*(url, hostType) {
let tab = yield addTab(url);
let { inspector, toolbox } = yield openInspector();
let { inspector, toolbox } = yield openInspector(null, hostType);
return { tab, inspector, toolbox };
});
@ -162,9 +163,10 @@ let openInspectorForURL = Task.async(function* (url) {
* Open the toolbox, with the inspector tool visible.
* @param {Function} cb Optional callback, if you don't want to use the returned
* promise
* @param {String} hostType Optional hostType, as defined in Toolbox.HostType
* @return a promise that resolves when the inspector is ready
*/
let openInspector = Task.async(function*(cb) {
let openInspector = Task.async(function*(cb, hostType) {
info("Opening the inspector");
let target = TargetFactory.forTab(gBrowser.selectedTab);
@ -190,7 +192,7 @@ let openInspector = Task.async(function*(cb) {
}
info("Opening the toolbox");
toolbox = yield gDevTools.showToolbox(target, "inspector");
toolbox = yield gDevTools.showToolbox(target, "inspector", hostType);
yield waitForToolboxFrameFocus(toolbox);
inspector = toolbox.getPanel("inspector");

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

@ -0,0 +1,113 @@
/* 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";
/**
* This file contains the base line graph that all Performance line graphs use.
*/
const {Cc, Ci, Cu, Cr} = require("chrome");
Cu.import("resource:///modules/devtools/Graphs.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
const { colorUtils: { setAlpha }} = require("devtools/css-color");
const { getColor } = require("devtools/shared/theme");
loader.lazyRequireGetter(this, "ProfilerGlobal",
"devtools/shared/profiler/global");
loader.lazyRequireGetter(this, "TimelineGlobal",
"devtools/shared/timeline/global");
const HEIGHT = 35; // px
const STROKE_WIDTH = 1; // px
const DAMPEN_VALUES = 0.95;
const CLIPHEAD_LINE_COLOR = "#666";
const SELECTION_LINE_COLOR = "#555";
const SELECTION_BACKGROUND_COLOR_NAME = "highlight-blue";
const FRAMERATE_GRAPH_COLOR_NAME = "highlight-green";
const MEMORY_GRAPH_COLOR_NAME = "highlight-blue";
/**
* A base class for performance graphs to inherit from.
*
* @param nsIDOMNode parent
* The parent node holding the overview.
* @param string metric
* The unit of measurement for this graph.
*/
function PerformanceGraph(parent, metric) {
LineGraphWidget.call(this, parent, { metric });
this.setTheme();
}
PerformanceGraph.prototype = Heritage.extend(LineGraphWidget.prototype, {
strokeWidth: STROKE_WIDTH,
dampenValuesFactor: DAMPEN_VALUES,
fixedHeight: HEIGHT,
clipheadLineColor: CLIPHEAD_LINE_COLOR,
selectionLineColor: SELECTION_LINE_COLOR,
withTooltipArrows: false,
withFixedTooltipPositions: true,
/**
* Disables selection and empties this graph.
*/
clearView: function() {
this.selectionEnabled = false;
this.dropSelection();
this.setData([]);
},
/**
* Sets the theme via `theme` to either "light" or "dark",
* and updates the internal styling to match. Requires a redraw
* to see the effects.
*/
setTheme: function (theme) {
theme = theme || "light";
let mainColor = getColor(this.mainColor || "highlight-blue", theme);
this.backgroundColor = getColor("body-background", theme);
this.strokeColor = mainColor;
this.backgroundGradientStart = setAlpha(mainColor, 0.2);
this.backgroundGradientEnd = setAlpha(mainColor, 0.2);
this.selectionBackgroundColor = setAlpha(getColor(SELECTION_BACKGROUND_COLOR_NAME, theme), 0.25);
this.selectionStripesColor = "rgba(255, 255, 255, 0.1)";
this.maximumLineColor = setAlpha(mainColor, 0.4);
this.averageLineColor = setAlpha(mainColor, 0.7);
this.minimumLineColor = setAlpha(mainColor, 0.9);
}
});
/**
* Constructor for the framerate graph. Inherits from PerformanceGraph.
*
* @param nsIDOMNode parent
* The parent node holding the overview.
*/
function FramerateGraph(parent) {
PerformanceGraph.call(this, parent, ProfilerGlobal.L10N.getStr("graphs.fps"));
}
FramerateGraph.prototype = Heritage.extend(PerformanceGraph.prototype, {
mainColor: FRAMERATE_GRAPH_COLOR_NAME
});
exports.FramerateGraph = FramerateGraph;
/**
* Constructor for the memory graph. Inherits from PerformanceGraph.
*
* @param nsIDOMNode parent
* The parent node holding the overview.
*/
function MemoryGraph(parent) {
PerformanceGraph.call(this, parent, TimelineGlobal.L10N.getStr("graphs.memory"));
}
MemoryGraph.prototype = Heritage.extend(PerformanceGraph.prototype, {
mainColor: MEMORY_GRAPH_COLOR_NAME
});
exports.MemoryGraph = MemoryGraph;

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

@ -7,6 +7,7 @@ EXTRA_JS_MODULES.devtools.performance += [
'modules/compatibility.js',
'modules/front.js',
'modules/io.js',
'modules/performance-graphs.js',
'modules/recording-model.js',
'modules/recording-utils.js',
'panel.js'

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

@ -27,10 +27,12 @@ devtools.lazyRequireGetter(this, "RecordingUtils",
"devtools/performance/recording-utils", true);
devtools.lazyRequireGetter(this, "RecordingModel",
"devtools/performance/recording-model", true);
devtools.lazyRequireGetter(this, "FramerateGraph",
"devtools/performance/performance-graphs", true);
devtools.lazyRequireGetter(this, "MemoryGraph",
"devtools/performance/performance-graphs", true);
devtools.lazyRequireGetter(this, "MarkersOverview",
"devtools/shared/timeline/markers-overview", true);
devtools.lazyRequireGetter(this, "MemoryOverview",
"devtools/shared/timeline/memory-overview", true);
devtools.lazyRequireGetter(this, "Waterfall",
"devtools/shared/timeline/waterfall", true);
devtools.lazyRequireGetter(this, "MarkerDetails",
@ -48,14 +50,14 @@ devtools.lazyRequireGetter(this, "OptionsView",
devtools.lazyImporter(this, "CanvasGraphUtils",
"resource:///modules/devtools/Graphs.jsm");
devtools.lazyImporter(this, "LineGraphWidget",
"resource:///modules/devtools/Graphs.jsm");
devtools.lazyImporter(this, "FlameGraphUtils",
"resource:///modules/devtools/FlameGraph.jsm");
devtools.lazyImporter(this, "FlameGraph",
"resource:///modules/devtools/FlameGraph.jsm");
devtools.lazyImporter(this, "SideMenuWidget",
"resource:///modules/devtools/SideMenuWidget.jsm");
devtools.lazyImporter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
const BRANCH_NAME = "devtools.performance.ui.";

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

@ -99,6 +99,7 @@ support-files =
[browser_profiler_tree-model-04.js]
[browser_profiler_tree-model-05.js]
[browser_profiler_tree-model-06.js]
[browser_profiler_tree-model-07.js]
[browser_profiler_tree-view-01.js]
[browser_profiler_tree-view-02.js]
[browser_profiler_tree-view-03.js]
@ -106,5 +107,6 @@ support-files =
[browser_profiler_tree-view-05.js]
[browser_profiler_tree-view-06.js]
[browser_profiler_tree-view-07.js]
[browser_profiler_tree-view-08.js]
[browser_timeline_blueprint.js]
[browser_timeline_filters.js]

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

@ -0,0 +1,91 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that when displaying only content nodes, platform nodes are generalized.
*/
let { CATEGORY_MASK } = devtools.require("devtools/shared/profiler/global");
function test() {
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
let url = (n) => `http://content/${n}`;
// Create a root node from a given samples array.
let root = new ThreadNode(gSamples, { contentOnly: true });
/*
* should have a tree like:
* root
* - (JS)
* - A
* - (GC)
* - B
* - C
* - D
* - E
* - F
* - (JS)
*/
// Test the root node.
is(Object.keys(root.calls).length, 2, "root has 2 children");
ok(root.calls[url("A")], "root has content child");
ok(root.calls["64"], "root has platform generalized child");
is(Object.keys(root.calls["64"].calls).length, 0, "platform generalized child is a leaf.");
ok(root.calls[url("A")].calls["128"], "A has platform generalized child of another type");
is(Object.keys(root.calls[url("A")].calls["128"].calls).length, 0, "second generalized type is a leaf.");
ok(root.calls[url("A")].calls[url("E")].calls[url("F")].calls["64"],
"a second leaf of the first generalized type exists deep in the tree.");
ok(root.calls[url("A")].calls["128"], "A has platform generalized child of another type");
is(root.calls["64"].category, root.calls[url("A")].calls[url("E")].calls[url("F")].calls["64"].category,
"generalized frames of same type are duplicated in top-down view");
finish();
}
let gSamples = [{
time: 5,
frames: [
{ location: "(root)" },
{ location: "http://content/A" },
{ location: "http://content/B" },
{ location: "http://content/C" }
]
}, {
time: 5 + 6,
frames: [
{ location: "(root)" },
{ location: "http://content/A" },
{ location: "http://content/B" },
{ location: "contentY", category: CATEGORY_MASK("css") },
{ location: "http://content/D" }
]
}, {
time: 5 + 6 + 7,
frames: [
{ location: "(root)" },
{ location: "http://content/A" },
{ location: "contentY", category: CATEGORY_MASK("css") },
{ location: "http://content/E" },
{ location: "http://content/F" },
{ location: "contentY", category: CATEGORY_MASK("js") },
]
}, {
time: 5 + 20,
frames: [
{ location: "(root)" },
{ location: "contentX", category: CATEGORY_MASK("js") },
]
}, {
time: 5 + 25,
frames: [
{ location: "(root)" },
{ location: "http://content/A" },
{ location: "contentZ", category: CATEGORY_MASK("gc", 1) },
]
}];

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

@ -0,0 +1,104 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the profiler's tree view renders generalized platform data
* when `contentOnly` is on correctly.
*/
let { CATEGORY_MASK } = devtools.require("devtools/shared/profiler/global");
function test() {
let { ThreadNode } = devtools.require("devtools/shared/profiler/tree-model");
let { CallView } = devtools.require("devtools/shared/profiler/tree-view");
/*
* should have a tree like:
* root
* - A
* - B
* - C
* - D
* - E
* - F
* - (JS)
* - (GC)
* - (JS)
*/
let threadNode = new ThreadNode(gSamples, { contentOnly: true });
let treeRoot = new CallView({ frame: threadNode, autoExpandDepth: 10 });
let container = document.createElement("vbox");
treeRoot.attachTo(container);
let A = treeRoot.getChild(0);
let JS = treeRoot.getChild(1);
let GC = A.getChild(1);
let JS2 = A.getChild(2).getChild().getChild();
is(JS.target.getAttribute("category"), "js",
"Generalized JS node has correct category");
is(JS.target.getAttribute("tooltiptext"), "JIT",
"Generalized JS node has correct category");
is(JS.target.querySelector(".call-tree-name").getAttribute("value"), "JIT",
"Generalized JS node has correct display value as just the category name.");
is(JS2.target.getAttribute("category"), "js",
"Generalized second JS node has correct category");
is(JS2.target.getAttribute("tooltiptext"), "JIT",
"Generalized second JS node has correct category");
is(JS2.target.querySelector(".call-tree-name").getAttribute("value"), "JIT",
"Generalized second JS node has correct display value as just the category name.");
is(GC.target.getAttribute("category"), "gc",
"Generalized GC node has correct category");
is(GC.target.getAttribute("tooltiptext"), "GC",
"Generalized GC node has correct category");
is(GC.target.querySelector(".call-tree-name").getAttribute("value"), "GC",
"Generalized GC node has correct display value as just the category name.");
finish();
}
let gSamples = [{
time: 5,
frames: [
{ location: "(root)" },
{ location: "http://content/A" },
{ location: "http://content/B" },
{ location: "http://content/C" }
]
}, {
time: 5 + 6,
frames: [
{ location: "(root)" },
{ location: "http://content/A" },
{ location: "http://content/B" },
{ location: "contentY", category: CATEGORY_MASK("css") },
{ location: "http://content/D" }
]
}, {
time: 5 + 6 + 7,
frames: [
{ location: "(root)" },
{ location: "http://content/A" },
{ location: "contentY", category: CATEGORY_MASK("css") },
{ location: "http://content/E" },
{ location: "http://content/F" },
{ location: "contentY", category: CATEGORY_MASK("js") },
]
}, {
time: 5 + 20,
frames: [
{ location: "(root)" },
{ location: "contentX", category: CATEGORY_MASK("js") },
]
}, {
time: 5 + 25,
frames: [
{ location: "(root)" },
{ location: "http://content/A" },
{ location: "contentZ", category: CATEGORY_MASK("gc", 1) },
]
}];

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

@ -17,10 +17,8 @@ function spawnTest () {
for (let [key, value] of Iterator(TIMELINE_BLUEPRINT)) {
ok("group" in value,
"Each entry in the timeline blueprint contains a `group` key.");
ok("fill" in value,
"Each entry in the timeline blueprint contains a `fill` key.");
ok("stroke" in value,
"Each entry in the timeline blueprint contains a `stroke` key.");
ok("colorName" in value,
"Each entry in the timeline blueprint contains a `colorName` key.");
ok("label" in value,
"Each entry in the timeline blueprint contains a `label` key.");
}

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

@ -5,7 +5,7 @@
const URL_LABEL_TOOLTIP = L10N.getStr("table.url.tooltiptext");
const OPTIMIZATION_FAILURE = L10N.getStr("jit.optimizationFailure");
const JIT_SAMPLES = L10N.getStr("jit.samples");
const JIT_SAMPLES = L10N.getStr("jit.samples2");
const JIT_EMPTY_TEXT = L10N.getStr("jit.empty");
/**
@ -209,7 +209,8 @@ let JITOptimizationsView = {
node.appendChild(icon);
}
desc.textContent = `${lastStrategy} - (${site.samples} ${JIT_SAMPLES})`;
let sampleString = PluralForm.get(site.samples, JIT_SAMPLES).replace("#1", site.samples);
desc.textContent = `${lastStrategy} – (${sampleString})`;
line.textContent = site.data.line;
line.className = "opt-line";
column.textContent = site.data.column;

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

@ -11,11 +11,9 @@ const OVERVIEW_UPDATE_INTERVAL = 200; // ms
const FRAMERATE_GRAPH_LOW_RES_INTERVAL = 100; // ms
const FRAMERATE_GRAPH_HIGH_RES_INTERVAL = 16; // ms
const FRAMERATE_GRAPH_HEIGHT = 40; // px
const MARKERS_GRAPH_HEADER_HEIGHT = 14; // px
const MARKERS_GRAPH_ROW_HEIGHT = 10; // px
const MARKERS_GROUP_VERTICAL_PADDING = 4; // px
const MEMORY_GRAPH_HEIGHT = 30; // px
/**
* View handler for the overview panel's time view, displaying
@ -101,6 +99,11 @@ let OverviewView = {
setTheme: function (options={}) {
let theme = options.theme || PerformanceController.getTheme();
if (this.framerateGraph) {
this.framerateGraph.setTheme(theme);
this.framerateGraph.refresh({ force: options.redraw });
}
if (this.markersOverview) {
this.markersOverview.setTheme(theme);
this.markersOverview.refresh({ force: options.redraw });
@ -191,8 +194,7 @@ let OverviewView = {
yield this.memoryOverview.ready();
return true;
}
this.memoryOverview = new MemoryOverview($("#memory-overview"));
this.memoryOverview.fixedHeight = MEMORY_GRAPH_HEIGHT;
this.memoryOverview = new MemoryGraph($("#memory-overview"));
yield this.memoryOverview.ready();
this.setTheme();
@ -216,10 +218,9 @@ let OverviewView = {
yield this.framerateGraph.ready();
return true;
}
let metric = L10N.getStr("graphs.fps");
this.framerateGraph = new LineGraphWidget($("#time-framerate"), { metric });
this.framerateGraph.fixedHeight = FRAMERATE_GRAPH_HEIGHT;
this.framerateGraph = new FramerateGraph($("#time-framerate"));
yield this.framerateGraph.ready();
this.setTheme();
CanvasGraphUtils.linkAnimation(this.markersOverview, this.framerateGraph);
CanvasGraphUtils.linkSelection(this.markersOverview, this.framerateGraph);

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

@ -53,14 +53,10 @@ let ToolbarView = {
menuitem.setAttribute("flex", "1");
menuitem.setAttribute("label", markerDetails.label);
menuitem.setAttribute("marker-type", markerName);
menuitem.className = markerDetails.colorName;
menuitem.addEventListener("command", this._onHiddenMarkersChanged);
// Style used by pseudo element ::before in performance.inc.css
let bulletStyle = `--bullet-bg: ${markerDetails.fill};`
bulletStyle += `--bullet-border: ${markerDetails.stroke}`;
menuitem.setAttribute("style", bulletStyle);
$("#performance-filter-menupopup").appendChild(menuitem);
}
},

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

@ -42,7 +42,6 @@ EXTRA_JS_MODULES.devtools.shared.timeline += [
'timeline/global.js',
'timeline/marker-details.js',
'timeline/markers-overview.js',
'timeline/memory-overview.js',
'timeline/waterfall.js',
]

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

@ -4,16 +4,21 @@
"use strict";
const {Cc, Ci, Cu, Cr} = require("chrome");
const {extend} = require("sdk/util/object");
loader.lazyRequireGetter(this, "Services");
loader.lazyRequireGetter(this, "L10N",
"devtools/shared/profiler/global", true);
loader.lazyRequireGetter(this, "CATEGORY_MAPPINGS",
"devtools/shared/profiler/global", true);
loader.lazyRequireGetter(this, "CATEGORIES",
"devtools/shared/profiler/global", true);
loader.lazyRequireGetter(this, "CATEGORY_JIT",
"devtools/shared/profiler/global", true);
loader.lazyRequireGetter(this, "JITOptimizations",
"devtools/shared/profiler/jit", true);
loader.lazyRequireGetter(this, "CATEGORY_OTHER",
"devtools/shared/profiler/global", true);
const CHROME_SCHEMES = ["chrome://", "resource://", "jar:file://"];
const CONTENT_SCHEMES = ["http://", "https://", "file://", "app://"];
@ -97,7 +102,7 @@ ThreadNode.prototype = {
// should be taken into consideration.
if (options.contentOnly) {
// The (root) node is not considered a content function, it'll be removed.
sampleFrames = sampleFrames.filter(isContent);
sampleFrames = filterPlatformData(sampleFrames);
} else {
// Remove the (root) node manually.
sampleFrames = sampleFrames.slice(1);
@ -161,8 +166,11 @@ ThreadNode.prototype = {
* The category type of this function call ("js", "graphics" etc.).
* @param number allocations
* The number of memory allocations performed in this frame.
* @param boolean isMetaCategory
* Whether or not this is a platform node that should appear as a
* generalized meta category or not.
*/
function FrameNode({ location, line, column, category, allocations }) {
function FrameNode({ location, line, column, category, allocations, isMetaCategory }) {
this.location = location;
this.line = line;
this.column = column;
@ -173,6 +181,7 @@ function FrameNode({ location, line, column, category, allocations }) {
this.duration = 0;
this.calls = {};
this._optimizations = null;
this.isMetaCategory = isMetaCategory;
}
FrameNode.prototype = {
@ -202,8 +211,12 @@ FrameNode.prototype = {
if (!frame) {
return;
}
let location = frame.location;
let child = _store[location] || (_store[location] = new FrameNode(frame));
// If we are only displaying content, then platform data will have
// a `isMetaCategory` property. Group by category (GC, Graphics, etc.)
// to group together frames so they're displayed only once, since we don't
// need the location anyway.
let key = frame.isMetaCategory ? frame.category : frame.location;
let child = _store[key] || (_store[key] = new FrameNode(frame));
child.sampleTimes.push({ start: time, end: time + duration });
child.samples++;
child.duration += duration;
@ -273,7 +286,8 @@ FrameNode.prototype = {
line: line,
column: column,
categoryData: categoryData,
isContent: !!isContent(this)
isContent: !!isContent(this),
isMetaCategory: this.isMetaCategory
};
},
@ -332,3 +346,47 @@ function nsIURL(url) {
// The cache used in the `nsIURL` function.
let gNSURLStore = new Map();
/**
* This filters out platform data frames in a sample. With latest performance
* tool in Fx40, when displaying only content, we still filter out all platform data,
* except we generalize platform data that are leaves. We do this because of two
* observations:
*
* 1. The leaf is where time is _actually_ being spent, so we _need_ to show it
* to developers in some way to give them accurate profiling data. We decide to
* split the platform into various category buckets and just show time spent in
* each bucket.
*
* 2. The calls leading to the leaf _aren't_ where we are spending time, but
* _do_ give the developer context for how they got to the leaf where they _are_
* spending time. For non-platform hackers, the non-leaf platform frames don't
* give any meaningful context, and so we can safely filter them out.
*
* Example transformations:
* Before: PlatformA -> PlatformB -> ContentA -> ContentB
* After: ContentA -> ContentB
*
* Before: PlatformA -> ContentA -> PlatformB -> PlatformC
* After: ContentA -> Category(PlatformC)
*/
function filterPlatformData (frames) {
let result = [];
let last = frames.length - 1;
let frame;
for (let i = 0; i < frames.length; i++) {
frame = frames[i];
if (isContent(frame)) {
result.push(frame);
} else if (last === i) {
// Extend here so we're not destructively editing
// the original profiler data. Set isMetaCategory `true`,
// and ensure we have a category set by default, because that's how
// the generalized frame nodes are organized.
result.push(extend({ isMetaCategory: true, category: CATEGORY_OTHER }, frame));
}
}
return result;
}

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

@ -187,7 +187,8 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
targetNode.className = "call-tree-item";
targetNode.setAttribute("origin", frameInfo.isContent ? "content" : "chrome");
targetNode.setAttribute("category", frameInfo.categoryData.abbrev || "");
targetNode.setAttribute("tooltiptext", this.frame.location || "");
targetNode.setAttribute("tooltiptext", frameInfo.isMetaCategory ? frameInfo.categoryData.label :
this.frame.location || "");
if (this.hidden) {
targetNode.style.display = "none";
}
@ -309,9 +310,13 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
nameNode.className = "plain call-tree-name";
nameNode.setAttribute("flex", "1");
nameNode.setAttribute("crop", "end");
nameNode.setAttribute("value", frameInfo.functionName || "");
nameNode.setAttribute("value", frameInfo.isMetaCategory
? frameInfo.categoryData.label
: frameInfo.functionName || "");
cell.appendChild(nameNode);
// Don't render detailed labels for meta category frames
if (!frameInfo.isMetaCategory) {
let urlNode = this.document.createElement("label");
urlNode.className = "plain call-tree-url";
urlNode.setAttribute("flex", "1");
@ -351,6 +356,7 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
categoryNode.style.color = frameInfo.categoryData.color;
categoryNode.setAttribute("value", frameInfo.categoryData.label || "");
cell.appendChild(categoryNode);
}
let hasDescendants = Object.keys(this.frame.calls).length > 0;
if (hasDescendants == false) {

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

@ -18,9 +18,11 @@ const L10N = new ViewHelpers.L10N(STRINGS_URI);
* to marker names, while the values are objects with the following format:
* - group: the row index in the timeline overview graph; multiple markers
* can be added on the same row. @see <overview.js/buildGraphImage>
* - fill: a fill color used when drawing the marker
* - stroke: a stroke color used when drawing the marker
* - label: the label used in the waterfall to identify the marker
* - colorName: the name of the DevTools color used for this marker. If adding
* a new color, be sure to check that there's an entry for
* `.marker-details-bullet.{COLORNAME}` for the equivilent entry.
* https://developer.mozilla.org/en-US/docs/Tools/DevToolsColors
*
* Whenever this is changed, browser_timeline_waterfall-styles.js *must* be
* updated as well.
@ -28,38 +30,32 @@ const L10N = new ViewHelpers.L10N(STRINGS_URI);
const TIMELINE_BLUEPRINT = {
"Styles": {
group: 0,
fill: "hsl(285,50%,68%)",
stroke: "hsl(285,50%,48%)",
colorName: "highlight-pink",
label: L10N.getStr("timeline.label.styles2")
},
"Reflow": {
group: 0,
fill: "hsl(285,50%,68%)",
stroke: "hsl(285,50%,48%)",
colorName: "highlight-pink",
label: L10N.getStr("timeline.label.reflow2")
},
"Paint": {
group: 0,
fill: "hsl(104,57%,71%)",
stroke: "hsl(104,57%,51%)",
colorName: "highlight-green",
label: L10N.getStr("timeline.label.paint")
},
"DOMEvent": {
group: 1,
fill: "hsl(39,82%,69%)",
stroke: "hsl(39,82%,49%)",
colorName: "highlight-lightorange",
label: L10N.getStr("timeline.label.domevent")
},
"Javascript": {
group: 1,
fill: "hsl(39,82%,69%)",
stroke: "hsl(39,82%,49%)",
colorName: "highlight-lightorange",
label: L10N.getStr("timeline.label.javascript2")
},
"ConsoleTime": {
group: 2,
fill: "hsl(0,0%,80%)",
stroke: "hsl(0,0%,60%)",
colorName: "highlight-bluegrey",
label: L10N.getStr("timeline.label.consoleTime")
},
};

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

@ -64,9 +64,7 @@ MarkerDetails.prototype = {
hbox.setAttribute("align", "center");
let bullet = this._document.createElement("hbox");
bullet.className = "marker-details-bullet";
bullet.style.backgroundColor = blueprint.fill;
bullet.style.borderColor = blueprint.stroke;
bullet.className = `marker-details-bullet ${blueprint.colorName}`;
let label = this._document.createElement("label");
label.className = "marker-details-type";

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

@ -169,12 +169,8 @@ MarkersOverview.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
let top = headerHeight + style.group * groupHeight + groupPadding / 2;
let height = groupHeight - groupPadding;
let gradient = ctx.createLinearGradient(0, top, 0, top + height);
gradient.addColorStop(OVERVIEW_MARKERS_COLOR_STOPS[0], style.stroke);
gradient.addColorStop(OVERVIEW_MARKERS_COLOR_STOPS[1], style.fill);
gradient.addColorStop(OVERVIEW_MARKERS_COLOR_STOPS[2], style.fill);
gradient.addColorStop(OVERVIEW_MARKERS_COLOR_STOPS[3], style.stroke);
ctx.fillStyle = gradient;
let color = getColor(style.colorName, this.theme);
ctx.fillStyle = color;
ctx.beginPath();
for (let { start, end } of batch) {
@ -226,7 +222,7 @@ MarkersOverview.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
* to see the effects.
*/
setTheme: function (theme) {
theme = theme || "light";
this.theme = theme = theme || "light";
this.backgroundColor = getColor("body-background", theme);
this.selectionBackgroundColor = setAlpha(getColor("selection-background", theme), 0.25);
this.selectionStripesColor = setAlpha("#fff", 0.1);

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

@ -1,80 +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/. */
"use strict";
/**
* This file contains the "memory overview" graph, a simple representation of
* of all the memory measurements taken while streaming the timeline data.
*/
const {Cc, Ci, Cu, Cr} = require("chrome");
Cu.import("resource:///modules/devtools/Graphs.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
const { colorUtils: { setAlpha }} = require("devtools/css-color");
const { getColor } = require("devtools/shared/theme");
loader.lazyRequireGetter(this, "L10N",
"devtools/shared/timeline/global", true);
const OVERVIEW_DAMPEN_VALUES = 0.95;
const OVERVIEW_HEIGHT = 30; // px
const OVERVIEW_STROKE_WIDTH = 1; // px
const OVERVIEW_MAXIMUM_LINE_COLOR = "rgba(0,136,204,0.4)";
const OVERVIEW_AVERAGE_LINE_COLOR = "rgba(0,136,204,0.7)";
const OVERVIEW_MINIMUM_LINE_COLOR = "rgba(0,136,204,0.9)";
const OVERVIEW_CLIPHEAD_LINE_COLOR = "#666";
const OVERVIEW_SELECTION_LINE_COLOR = "#555";
/**
* An overview for the memory data.
*
* @param nsIDOMNode parent
* The parent node holding the overview.
*/
function MemoryOverview(parent) {
LineGraphWidget.call(this, parent, { metric: L10N.getStr("graphs.memory") });
this.setTheme();
}
MemoryOverview.prototype = Heritage.extend(LineGraphWidget.prototype, {
dampenValuesFactor: OVERVIEW_DAMPEN_VALUES,
fixedHeight: OVERVIEW_HEIGHT,
strokeWidth: OVERVIEW_STROKE_WIDTH,
maximumLineColor: OVERVIEW_MAXIMUM_LINE_COLOR,
averageLineColor: OVERVIEW_AVERAGE_LINE_COLOR,
minimumLineColor: OVERVIEW_MINIMUM_LINE_COLOR,
clipheadLineColor: OVERVIEW_CLIPHEAD_LINE_COLOR,
selectionLineColor: OVERVIEW_SELECTION_LINE_COLOR,
withTooltipArrows: false,
withFixedTooltipPositions: true,
/**
* Disables selection and empties this graph.
*/
clearView: function() {
this.selectionEnabled = false;
this.dropSelection();
this.setData([]);
},
/**
* Sets the theme via `theme` to either "light" or "dark",
* and updates the internal styling to match. Requires a redraw
* to see the effects.
*/
setTheme: function (theme) {
theme = theme || "light";
this.backgroundColor = getColor("body-background", theme);
this.backgroundGradientStart = setAlpha(getColor("highlight-blue", theme), 0.2);
this.backgroundGradientEnd = setAlpha(getColor("highlight-blue", theme), 0.05);
this.strokeColor = getColor("highlight-blue", theme);
this.selectionBackgroundColor = setAlpha(getColor("selection-background", theme), 0.25);
this.selectionStripesColor = "rgba(255, 255, 255, 0.1)";
}
});
exports.MemoryOverview = MemoryOverview;

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

@ -432,9 +432,7 @@ Waterfall.prototype = {
sidebar.setAttribute("align", "center");
let bullet = this._document.createElement("hbox");
bullet.className = "waterfall-marker-bullet";
bullet.style.backgroundColor = blueprint.fill;
bullet.style.borderColor = blueprint.stroke;
bullet.className = `waterfall-marker-bullet ${blueprint.colorName}`;
bullet.setAttribute("type", marker.name);
sidebar.appendChild(bullet);
@ -483,12 +481,8 @@ Waterfall.prototype = {
let offset = this._isRTL ? this._waterfallWidth : 0;
let bar = this._document.createElement("hbox");
bar.className = "waterfall-marker-bar";
bar.style.backgroundColor = blueprint.fill;
bar.style.borderColor = blueprint.stroke;
bar.className = `waterfall-marker-bar ${blueprint.colorName}`;
bar.style.transform = "translateX(" + (start - offset) + "px)";
// Save border color. It will change when marker is selected.
bar.setAttribute("borderColor", blueprint.stroke);
bar.setAttribute("type", marker.name);
bar.setAttribute("width", Math.max(width, WATERFALL_MARKER_BAR_WIDTH_MIN));
waterfall.appendChild(bar);

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

@ -22,6 +22,7 @@ this.EXPORTED_SYMBOLS = ["SideMenuWidget"];
* @param nsIDOMNode aNode
* The element associated with the widget.
* @param Object aOptions
* - contextMenu: optional element or element ID that serves as a context menu.
* - showArrows: specifies if items should display horizontal arrows.
* - showItemCheckboxes: specifies if items should display checkboxes.
* - showGroupCheckboxes: specifies if groups should display checkboxes.
@ -31,7 +32,8 @@ this.SideMenuWidget = function SideMenuWidget(aNode, aOptions={}) {
this.window = this.document.defaultView;
this._parent = aNode;
let { showArrows, showItemCheckboxes, showGroupCheckboxes } = aOptions;
let { contextMenu, showArrows, showItemCheckboxes, showGroupCheckboxes } = aOptions;
this._contextMenu = contextMenu || null;
this._showArrows = showArrows || false;
this._showItemCheckboxes = showItemCheckboxes || false;
this._showGroupCheckboxes = showGroupCheckboxes || false;
@ -45,6 +47,7 @@ this.SideMenuWidget = function SideMenuWidget(aNode, aOptions={}) {
this._list.setAttribute("with-item-checkboxes", this._showItemCheckboxes);
this._list.setAttribute("with-group-checkboxes", this._showGroupCheckboxes);
this._list.setAttribute("tabindex", "0");
this._list.addEventListener("contextmenu", e => this._showContextMenu(e), false);
this._list.addEventListener("keypress", e => this.emit("keyPress", e), false);
this._list.addEventListener("mousedown", e => this.emit("mousePress", e), false);
this._parent.appendChild(this._list);
@ -389,6 +392,17 @@ SideMenuWidget.prototype = {
}
},
/**
* Shows the contextMenu element.
*/
_showContextMenu: function(e) {
if (!this._contextMenu) {
return;
}
this._contextMenu.openPopupAtScreen(e.screenX, e.screenY, true);
},
window: null,
document: null,
_showArrows: false,

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

@ -198,3 +198,17 @@
<!ENTITY debuggerUI.stepping.stepIn2 "VK_SEMICOLON">
<!ENTITY debuggerUI.stepping.stepOut1 "VK_F11">
<!ENTITY debuggerUI.stepping.stepOut2 "VK_SEMICOLON">
<!-- LOCALIZATION NOTE (debuggerUI.context.newTab): This is the label
- for the Open in New Tab menu item displayed in the context menu of the
- debugger sources side menu. This should be the same as
- netmonitorUI.context.newTab -->
<!ENTITY debuggerUI.context.newTab "Open in New Tab">
<!ENTITY debuggerUI.context.newTab.accesskey "O">
<!-- LOCALIZATION NOTE (debuggerUI.context.copyUrl): This is the label displayed
- on the context menu that copies the selected request's url. This should be
- the same as netmonitorUI.context.copyUrl -->
<!ENTITY debuggerUI.context.copyUrl "Copy URL">
<!ENTITY debuggerUI.context.copyUrl.accesskey "C">
<!ENTITY debuggerUI.context.copyUrl.key "C">

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

@ -1529,16 +1529,16 @@ folderInvalidPath=Please enter a valid path
# The argument (%1$S) is the folder path.
folderOpenDirResult=Opened %1$S
# LOCALIZATION NOTE (rulesDesc) A very short description of the
# 'rules' command. See highlightManual for a fuller description of what
# LOCALIZATION NOTE (rulersDesc) A very short description of the
# 'rulers' command. See rulersManual for a fuller description of what
# it does. This string is designed to be shown in a menu alongside the
# command name, which is why it should be as short as possible.
rulersDesc=Toggle rulers for the page
# LOCALIZATION NOTE (rulesManual) A fuller description of the 'rules'
# LOCALIZATION NOTE (rulersManual) A fuller description of the 'rulers'
# command, displayed when the user asks for help on what it does.
rulersManual=Toggle the horizontal and vertical rulers for the current page
# LOCALIZATION NOTE (rulersTooltip) A string displayed as the
# tooltip of button in devtools toolbox which toggles the rulers highligher.
# tooltip of button in devtools toolbox which toggles the rulers.
rulersTooltip=Toggle rulers for the page

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

@ -54,3 +54,13 @@ previewTooltip.image.brokenImage=Could not load the image
#LOCALIZATION NOTE: Used in the image preview tooltip when the image could not be loaded
eventsTooltip.openInDebugger=Open in Debugger
# LOCALIZATION NOTE (inspector.collapsePane): This is the tooltip for the button
# that collapses the right panel (rules, computed, box-model, etc...) in the
# inspector UI.
inspector.collapsePane=Collapse pane
# LOCALIZATION NOTE (inspector.expandPane): This is the tooltip for the button
# that expands the right panel (rules, computed, box-model, etc...) in the
# inspector UI.
inspector.expandPane=Expand pane

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

@ -125,10 +125,13 @@ recordingsList.saveDialogAllFilter=All Files
# This string is displayed in a tooltip when no JIT optimizations were detected.
jit.optimizationFailure=Optimization failed
# LOCALIZATION NOTE (jit.samples):
# This string is displayed for the unit representing thenumber of times a
# LOCALIZATION NOTE (jit.samples2):
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
# This string is displayed for the unit representing the number of times a
# frame is sampled.
jit.samples=samples
# "#1" represents the number of samples
# example: 30 samples
jit.samples2=#1 sample;#1 samples
# LOCALIZATION NOTE (jit.empty):
# This string is displayed when there are no JIT optimizations to display.

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

@ -159,6 +159,13 @@ let ReaderParent = {
}
},
buttonClick: function(event) {
if (event.button != 0) {
return;
}
this.toggleReaderMode(event);
},
toggleReaderMode: function(event) {
let win = event.target.ownerDocument.defaultView;
let browser = win.gBrowser.selectedBrowser;

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

@ -39,6 +39,44 @@
max-width: 200px !important;
}
/* Expand/collapse panel toolbar button */
#inspector-pane-toggle {
background: none;
box-shadow: none;
border: none;
list-style-image: url(debugger-collapse.png);
-moz-image-region: rect(0px,16px,16px,0px);
}
#inspector-pane-toggle > .toolbarbutton-icon {
width: 16px;
height: 16px;
}
#inspector-pane-toggle[pane-collapsed] {
list-style-image: url(debugger-expand.png);
}
#inspector-pane-toggle:active {
-moz-image-region: rect(0px,32px,16px,16px);
}
@media (min-resolution: 2dppx) {
#inspector-pane-toggle {
list-style-image: url(debugger-collapse@2x.png);
-moz-image-region: rect(0px,32px,32px,0px);
}
#inspector-pane-toggle[pane-collapsed] {
list-style-image: url(debugger-expand@2x.png);
}
#inspector-pane-toggle:active {
-moz-image-region: rect(0px,64px,32px,32px);
}
}
/* Tooltip: Events */
#devtools-tooltip-events-container {

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

@ -57,10 +57,7 @@
width: 8px;
height: 8px;
margin: 0 8px;
border: 1px solid;
border-radius: 1px;
background-color: var(--bullet-bg);
border-color: var(--bullet-border);
}
/* Recording Notice */
@ -380,7 +377,6 @@
height: 8px;
-moz-margin-start: 8px;
-moz-margin-end: 6px;
border: 1px solid;
border-radius: 1px;
}
@ -391,9 +387,8 @@
.waterfall-marker-bar {
height: 9px;
border: 1px solid;
border-radius: 1px;
transform-origin: left center;
border-radius: 1px;
}
.waterfall-marker-container.selected > .waterfall-sidebar,
@ -402,11 +397,6 @@
color: var(--theme-selection-color);
}
.waterfall-marker-container.selected .waterfall-marker-bullet,
.waterfall-marker-container.selected .waterfall-marker-bar {
border-color: initial !important;
}
.waterfall-marker-location {
color: -moz-nativehyperlinktext;
}
@ -426,10 +416,34 @@
.marker-details-bullet {
width: 8px;
height: 8px;
border: 1px solid;
border-radius: 1px;
}
#performance-filter-menupopup > menuitem.highlight-pink:before,
.marker-details-bullet.highlight-pink,
.waterfall-marker-bar.highlight-pink,
.waterfall-marker-bullet.highlight-pink {
background-color: var(--theme-highlight-pink);
}
#performance-filter-menupopup > menuitem.highlight-bluegrey:before,
.marker-details-bullet.highlight-bluegrey,
.waterfall-marker-bar.highlight-bluegrey,
.waterfall-marker-bullet.highlight-bluegrey {
background-color: var(--theme-highlight-bluegrey);
}
#performance-filter-menupopup > menuitem.highlight-green:before,
.marker-details-bullet.highlight-green,
.waterfall-marker-bar.highlight-green,
.waterfall-marker-bullet.highlight-green {
background-color: var(--theme-highlight-green);
}
#performance-filter-menupopup > menuitem.highlight-lightorange:before,
.marker-details-bullet.highlight-lightorange,
.waterfall-marker-bar.highlight-lightorange,
.waterfall-marker-bullet.highlight-lightorange {
background-color: var(--theme-highlight-lightorange);
}
#waterfall-details > * {
padding-top: 3px;
}

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

@ -6425,11 +6425,7 @@ MOZ_ARG_ENABLE_BOOL(verify-mar,
MOZ_VERIFY_MAR_SIGNATURE= )
if test -n "$MOZ_VERIFY_MAR_SIGNATURE"; then
if test "$OS_ARCH" = "WINNT"; then
AC_DEFINE(MOZ_VERIFY_MAR_SIGNATURE)
else
AC_MSG_ERROR([Can only build with --enable-verify-mar with a Windows target])
fi
fi
dnl ========================================================

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

@ -503,7 +503,6 @@ this.AppsUtils = {
* Checks if the app role is allowed:
* Only certified apps can be themes.
* Only privileged or certified apps can be addons.
* Langpacks need to be privileged.
* @param aRole : the role assigned to this app.
* @param aStatus : the APP_STATUS_* for this app.
*/
@ -511,13 +510,6 @@ this.AppsUtils = {
if (aRole == "theme" && aStatus !== Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
return false;
}
if (aRole == "langpack" && aStatus !== Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) {
let allow = false;
try {
allow = Services.prefs.getBoolPref("dom.apps.allow_unsigned_langpacks");
} catch(e) {}
return allow;
}
if (!this.allowUnsignedAddons &&
(aRole == "addon" &&
aStatus !== Ci.nsIPrincipal.APP_STATUS_CERTIFIED &&

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

@ -26,6 +26,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "PermissionsInstaller",
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm");
this.EXPORTED_SYMBOLS = ["ImportExport"];
const kAppArchiveMimeType = "application/openwebapp+zip";
@ -225,7 +228,12 @@ this.ImportExport = {
// |file| now points to application.zip, open it.
let appZipReader = Cc["@mozilla.org/libjar/zip-reader;1"]
.createInstance(Ci.nsIZipReader);
try {
appZipReader.open(file);
} catch(e) {
throw "InvalidZip";
}
if (!appZipReader.hasEntry("manifest.webapp")) {
throw "NoManifestFound";
}
@ -233,10 +241,35 @@ this.ImportExport = {
return [readObjectFromZip(appZipReader, "manifest.webapp"), file];
},
// Returns a promise that resolves to the temp file path.
_writeBlobToTempFile: function(aBlob) {
// Save the blob to a temp file.
debug("_writeBlobToTempFile");
let path;
return new Promise((aResolve, aReject) => {
let reader = Cc['@mozilla.org/files/filereader;1']
.createInstance(Ci.nsIDOMFileReader);
reader.onloadend = () => {
path = OS.Path.join(OS.Constants.Path.tmpDir, "app-blob.zip");
debug("onloadend path=" + path);
OS.File.openUnique(path).then(obj => {
path = obj.path;
let file = obj.file;
debug("openUnique path=" + path);
return file.write(new Uint8Array(reader.result))
.then(file.close.bind(file))
})
.then(() => aResolve(path))
.catch(aReject);
}
reader.readAsArrayBuffer(aBlob);
});
},
// Imports a blob, returning a Promise that resolves to
// [manifestURL, manifest]
// Possible errors are:
// NoBlobFound, UnsupportedBlobArchive, MissingMetadataFile, IncorrectVersion,
// NoBlobFound, InvalidZip, MissingMetadataFile, IncorrectVersion,
// AppAlreadyInstalled, DontImportCertifiedApps, InvalidManifest,
// InvalidPrivilegeLevel, InvalidOrigin, DuplicateOrigin
import: Task.async(function*(aBlob) {
@ -246,15 +279,15 @@ this.ImportExport = {
throw "NoBlobFound";
}
let isFile = aBlob instanceof Ci.nsIDOMFile;
if (!isFile) {
// XXX: TODO Store the blob on disk.
throw "UnsupportedBlobArchive";
}
let isFileBlob = aBlob instanceof Ci.nsIDOMFile;
// We can't QI the DOMFile to nsIFile, so we need to create one.
let zipFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
if (!isFileBlob) {
let path = yield this._writeBlobToTempFile(aBlob);
zipFile.initWithPath(path);
} else {
zipFile.initWithPath(aBlob.mozFullPath);
}
debug("Importing from " + zipFile.path);
@ -263,8 +296,13 @@ this.ImportExport = {
let manifest;
let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]
.createInstance(Ci.nsIZipReader);
zipReader.open(zipFile);
try {
try {
zipReader.open(zipFile);
} catch(e) {
throw "InvalidZip";
}
// Do some sanity checks on the metadata.json and manifest.webapp files.
if (!zipReader.hasEntry("metadata.json")) {
throw "MissingMetadataFile";
@ -431,6 +469,9 @@ this.ImportExport = {
throw e;
} finally {
zipReader.close();
if (!isFileBlob) {
zipFile.remove(false);
}
}
return [meta.manifestURL, manifest];
@ -439,31 +480,37 @@ this.ImportExport = {
// Extracts the manifest from a blob, returning a Promise that resolves to
// the manifest
// Possible errors are:
// NoBlobFound, UnsupportedBlobArchive, MissingMetadataFile.
// NoBlobFound, InvalidZip, MissingMetadataFile.
extractManifest: Task.async(function*(aBlob) {
// First, do we even have a blob?
if (!aBlob || !aBlob instanceof Ci.nsIDOMBlob) {
throw "NoBlobFound";
}
let isFile = aBlob instanceof Ci.nsIDOMFile;
if (!isFile) {
// XXX: TODO Store the blob on disk.
throw "UnsupportedBlobArchive";
}
let isFileBlob = aBlob instanceof Ci.nsIDOMFile;
// We can't QI the DOMFile to nsIFile, so we need to create one.
let zipFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
if (!isFileBlob) {
let path = yield this._writeBlobToTempFile(aBlob);
zipFile.initWithPath(path);
} else {
zipFile.initWithPath(aBlob.mozFullPath);
}
debug("extractManifest from " + zipFile.path);
// Do some sanity checks on the metadata.json and manifest.webapp files.
let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]
.createInstance(Ci.nsIZipReader);
zipReader.open(zipFile);
let manifest;
try {
try {
zipReader.open(zipFile);
} catch(e) {
throw "InvalidZip";
}
if (zipReader.hasEntry("manifest.webapp")) {
manifest = readObjectFromZip(zipReader, "manifest.webapp");
if (!manifest) {
@ -484,6 +531,9 @@ this.ImportExport = {
}
} finally {
zipReader.close();
if (!isFileBlob) {
zipFile.remove(false);
}
}
return manifest;

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

@ -3901,8 +3901,16 @@ this.DOMApplicationRegistry = {
? Ci.nsIPrincipal.APP_STATUS_PRIVILEGED
: Ci.nsIPrincipal.APP_STATUS_INSTALLED;
let allowUnsignedLangpack = false;
try {
allowUnsignedLangpack =
Services.prefs.getBoolPref("dom.apps.allow_unsigned_langpacks");
} catch(e) {}
let isLangPack = newManifest.role === "langpack" &&
(aIsSigned || allowUnsignedLangpack);
let status = AppsUtils.getAppManifestStatus(newManifest);
if (status > maxStatus) {
if (status > maxStatus && !isLangPack) {
throw "INVALID_SECURITY_LEVEL";
}

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

@ -299,6 +299,21 @@ function runTest() {
is(request.result, miniManifestURL, "Packaged App uninstalled.");
navigator.mozApps.mgmt.onuninstall = null;
// Check that we support memory backed blobs.
// The blob here is not a valid app, but that's fine for this test.
let blob = new Blob(["This is a test blob."]);
navigator.mozApps.mgmt.import(blob)
.then(() => {
ok(false, "This is not an app!");
continueTest();
})
.catch(aError => {
is(aError.name, "InvalidZip", "Memory blob processed.");
continueTest();
});
yield undefined;
// Check that we restored the app registry.
request = navigator.mozApps.mgmt.getAll();
request.onerror = cbError;

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

@ -223,6 +223,7 @@ class RefTest(object):
#Don't use auto-enabled e10s
prefs['browser.tabs.remote.autostart.1'] = False
prefs['browser.tabs.remote.autostart.2'] = False
if options.e10s:
prefs['browser.tabs.remote.autostart'] = True

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

@ -115,6 +115,10 @@ public final class PrefsHelper {
}
public static void setPref(String pref, Object value) {
setPref(pref, value, false);
}
public static void setPref(String pref, Object value, boolean flush) {
if (pref == null || pref.length() == 0) {
throw new IllegalArgumentException("Pref name must be non-empty");
}
@ -122,6 +126,8 @@ public final class PrefsHelper {
try {
JSONObject jsonPref = new JSONObject();
jsonPref.put("name", pref);
jsonPref.put("flush", flush);
if (value instanceof Boolean) {
jsonPref.put("type", "bool");
jsonPref.put("value", ((Boolean)value).booleanValue());

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

До

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

После

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

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

@ -141,9 +141,11 @@ public class GeckoMenuItem implements MenuItem {
public View getActionView() {
if (mActionProvider != null) {
if (getActionEnum() == MenuItem.SHOW_AS_ACTION_IF_ROOM) {
return mActionProvider.onCreateActionView(SECONDARY_ACTION_BAR_HISTORY_SIZE, false);
return mActionProvider.onCreateActionView(SECONDARY_ACTION_BAR_HISTORY_SIZE,
GeckoActionProvider.ActionViewType.DEFAULT);
} else {
return mActionProvider.onCreateActionView(QUICK_SHARE_ACTION_BAR_HISTORY_SIZE, true);
return mActionProvider.onCreateActionView(QUICK_SHARE_ACTION_BAR_HISTORY_SIZE,
GeckoActionProvider.ActionViewType.QUICK_SHARE_ICON);
}
}

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

@ -165,4 +165,18 @@ public class MenuItemActionView extends LinearLayout
listener.onClick(view);
}
}
/**
* Update the styles if this view is being used in the context menus.
*
* Ideally, we just use different layout files and styles to set this, but
* MenuItemActionView is too integrated into GeckoActionProvider to provide
* an easy separation so instead I provide this hack. I'm sorry.
*/
public void initContextMenuStyles() {
final int defaultContextMenuPadding = getContext().getResources().getDimensionPixelOffset(
R.dimen.context_menu_item_horizontal_padding);
mMenuItem.setPadding(defaultContextMenuPadding, getPaddingTop(),
defaultContextMenuPadding, getPaddingBottom());
}
}

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

@ -5,16 +5,17 @@
package org.mozilla.gecko.overlays.ui;
import android.util.AttributeSet;
import org.mozilla.gecko.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -29,25 +30,17 @@ import android.widget.TextView;
public class OverlayDialogButton extends LinearLayout {
private static final String LOGTAG = "GeckoOverlayDialogButton";
// The views making up this button.
private final ImageView icon;
private final TextView label;
// Label/icon used when enabled.
private String enabledLabel;
private Drawable enabledIcon;
// Label/icon used when disabled.
private String disabledLabel;
private Drawable disabledIcon;
// Click listeners used when enabled/disabled. Currently, disabledOnClickListener is set
// internally to something that causes the icon to pulse.
private OnClickListener enabledOnClickListener;
private OnClickListener disabledOnClickListener;
// We can't use super.isEnabled(), since we want to stay clickable in disabled state.
private boolean isEnabled = true;
private final ImageView iconView;
private final TextView labelView;
private String enabledText = "";
private String disabledText = "";
private OnClickListener enabledOnClickListener;
public OverlayDialogButton(Context context) {
this(context, null);
}
@ -59,71 +52,60 @@ public class OverlayDialogButton extends LinearLayout {
LayoutInflater.from(context).inflate(R.layout.overlay_share_button, this);
icon = (ImageView) findViewById(R.id.overlaybtn_icon);
label = (TextView) findViewById(R.id.overlaybtn_label);
}
iconView = (ImageView) findViewById(R.id.overlaybtn_icon);
labelView = (TextView) findViewById(R.id.overlaybtn_label);
public void setEnabledLabelAndIcon(String s, Drawable d) {
enabledLabel = s;
enabledIcon = d;
super.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (isEnabled) {
updateViews();
}
}
public void setDisabledLabelAndIcon(String s, Drawable d) {
disabledLabel = s;
disabledIcon = d;
if (!isEnabled) {
updateViews();
}
}
/**
* Assign the appropriate label and icon to the views, and update the onClickListener for this
* view to the correct one (based on current enabledness state).
*/
private void updateViews() {
label.setEnabled(isEnabled);
if (isEnabled) {
label.setText(enabledLabel);
icon.setImageDrawable(enabledIcon);
super.setOnClickListener(enabledOnClickListener);
if (enabledOnClickListener != null) {
enabledOnClickListener.onClick(v);
} else {
label.setText(disabledLabel);
icon.setImageDrawable(disabledIcon);
super.setOnClickListener(getPopListener());
Log.e(LOGTAG, "enabledOnClickListener is null.");
}
}
/**
* Helper method to lazily-initialise disabledOnClickListener to a listener that performs the
* "pop" animation on the icon.
* updateViews handles making this the actual onClickListener for this view.
*/
private OnClickListener getPopListener() {
if (disabledOnClickListener == null) {
disabledOnClickListener = new OnClickListener() {
@Override
public void onClick(View view) {
} else {
Animation anim = AnimationUtils.loadAnimation(getContext(), R.anim.overlay_pop);
icon.startAnimation(anim);
iconView.startAnimation(anim);
}
};
}
});
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.OverlayDialogButton);
Drawable drawable = typedArray.getDrawable(R.styleable.OverlayDialogButton_drawable);
if (drawable != null) {
setDrawable(drawable);
}
return disabledOnClickListener;
String disabledText = typedArray.getString(R.styleable.OverlayDialogButton_disabledText);
if (disabledText != null) {
this.disabledText = disabledText;
}
String enabledText = typedArray.getString(R.styleable.OverlayDialogButton_enabledText);
if (enabledText != null) {
this.enabledText = enabledText;
}
typedArray.recycle();
setEnabled(true);
}
public void setDrawable(Drawable drawable) {
iconView.setImageDrawable(drawable);
}
public void setText(String text) {
labelView.setText(text);
}
@Override
public void setOnClickListener(OnClickListener l) {
enabledOnClickListener = l;
if (isEnabled) {
updateViews();
}
public void setOnClickListener(OnClickListener listener) {
enabledOnClickListener = listener;
}
/**
@ -132,11 +114,15 @@ public class OverlayDialogButton extends LinearLayout {
*/
@Override
public void setEnabled(boolean enabled) {
if (enabled == isEnabled) {
return;
isEnabled = enabled;
iconView.setEnabled(enabled);
labelView.setEnabled(enabled);
if (enabled) {
setText(enabledText);
} else {
setText(disabledText);
}
}
isEnabled = enabled;
updateViews();
}
}

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

@ -105,7 +105,8 @@ public class SendTabDeviceListArrayAdapter extends ArrayAdapter<ParcelableClient
if (currentState != State.LIST) {
// If we're in a special "Button-like" state, use the override string and a generic icon.
final Drawable sendTabIcon = context.getResources().getDrawable(R.drawable.overlay_send_tab_icon);
row.setEnabledLabelAndIcon(dummyRecordName, sendTabIcon);
row.setText(dummyRecordName);
row.setDrawable(sendTabIcon);
}
// If we're just a button to launch the dialog, set the listener and abort.
@ -124,7 +125,8 @@ public class SendTabDeviceListArrayAdapter extends ArrayAdapter<ParcelableClient
final ParcelableClientRecord clientRecord = getItem(position);
if (currentState == State.LIST) {
final Drawable clientIcon = context.getResources().getDrawable(getImage(clientRecord));
row.setEnabledLabelAndIcon(clientRecord.name, clientIcon);
row.setText(clientRecord.name);
row.setDrawable(clientIcon);
final String listenerGUID = clientRecord.guid;

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

@ -30,7 +30,6 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcelable;
@ -41,8 +40,6 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
@ -188,15 +185,8 @@ public class ShareDialog extends Locales.LocaleAwareActivity implements SendTabT
readingListButtonDrawable = readingListButton.getBackground();
final Resources resources = getResources();
final String bookmarkEnabledLabel = resources.getString(R.string.overlay_share_bookmark_btn_label);
final Drawable bookmarkEnabledIcon = resources.getDrawable(R.drawable.overlay_bookmark_icon);
bookmarkButton.setEnabledLabelAndIcon(bookmarkEnabledLabel, bookmarkEnabledIcon);
final String bookmarkDisabledLabel = resources.getString(R.string.overlay_share_bookmark_btn_label_already);
final Drawable bookmarkDisabledIcon = resources.getDrawable(R.drawable.overlay_bookmarked_already_icon);
bookmarkButton.setDisabledLabelAndIcon(bookmarkDisabledLabel, bookmarkDisabledIcon);
// Bookmark button
bookmarkButton = (OverlayDialogButton) findViewById(R.id.overlay_share_bookmark_btn);
bookmarkButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
@ -204,14 +194,8 @@ public class ShareDialog extends Locales.LocaleAwareActivity implements SendTabT
}
});
final String readingListEnabledLabel = resources.getString(R.string.overlay_share_reading_list_btn_label);
final Drawable readingListEnabledIcon = resources.getDrawable(R.drawable.overlay_readinglist_icon);
readingListButton.setEnabledLabelAndIcon(readingListEnabledLabel, readingListEnabledIcon);
final String readingListDisabledLabel = resources.getString(R.string.overlay_share_reading_list_btn_label_already);
final Drawable readingListDisabledIcon = resources.getDrawable(R.drawable.overlay_readinglist_already_icon);
readingListButton.setDisabledLabelAndIcon(readingListDisabledLabel, readingListDisabledIcon);
// Reading List button
readingListButton = (OverlayDialogButton) findViewById(R.id.overlay_share_reading_list_btn);
readingListButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

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

@ -1088,7 +1088,7 @@ OnSharedPreferenceChangeListener
// Send Gecko-side pref changes to Gecko
if (isGeckoPref(prefName)) {
PrefsHelper.setPref(prefName, newValue);
PrefsHelper.setPref(prefName, newValue, true /* flush */);
}
if (preference instanceof ListPreference) {
@ -1191,6 +1191,7 @@ OnSharedPreferenceChangeListener
JSONObject jsonPref = new JSONObject();
try {
jsonPref.put("name", PREFS_MP_ENABLED);
jsonPref.put("flush", true);
jsonPref.put("type", "string");
jsonPref.put("value", input1.getText().toString());

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

@ -179,7 +179,8 @@ public class PromptListAdapter extends ArrayAdapter<PromptListItem> {
final GeckoActionProvider provider = GeckoActionProvider.getForType(item.getIntent().getType(), getContext());
provider.setIntent(item.getIntent());
final MenuItemActionView view = (MenuItemActionView) provider.onCreateActionView();
final MenuItemActionView view = (MenuItemActionView) provider.onCreateActionView(
GeckoActionProvider.ActionViewType.CONTEXT_MENU);
// If a quickshare button is clicked, we need to close the dialog.
view.addActionButtonClickListener(new View.OnClickListener() {
@Override

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

@ -260,6 +260,11 @@ public class ReadingListSyncAdapter extends AbstractThreadedSyncAdapter {
}
}
if (result == null) {
// The poll timed out. Let's call this an error.
result = Result.Error;
}
switch (result) {
case Success:
requestPeriodicSync(account, ReadingListSyncAdapter.AFTER_SUCCESS_SYNC_DELAY_SECONDS);

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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

До

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

После

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

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