зеркало из https://github.com/mozilla/gecko-dev.git
Merge fx-team to m-c a=merge
This commit is contained in:
Коммит
865c827ac1
|
@ -99,16 +99,12 @@ devtools/client/promisedebugger/**
|
|||
devtools/client/responsivedesign/**
|
||||
devtools/client/scratchpad/**
|
||||
devtools/client/shadereditor/**
|
||||
devtools/client/shared/*.js
|
||||
devtools/client/shared/*.jsm
|
||||
!devtools/client/shared/css-angle.js
|
||||
!devtools/client/shared/css-color.js
|
||||
!devtools/client/shared/css-color-db.js
|
||||
!devtools/client/shared/css-parsing-utils.js
|
||||
devtools/client/shared/developer-toolbar.js
|
||||
devtools/client/shared/components/test/**
|
||||
devtools/client/shared/redux/middleware/test/**
|
||||
devtools/client/shared/test/**
|
||||
devtools/client/shared/widgets/**
|
||||
devtools/client/shared/widgets/*.jsm
|
||||
devtools/client/sourceeditor/**
|
||||
devtools/client/webaudioeditor/**
|
||||
devtools/client/webconsole/**
|
||||
|
|
|
@ -166,14 +166,6 @@
|
|||
label="&mediaHideControls.label;"
|
||||
accesskey="&mediaHideControls.accesskey;"
|
||||
oncommand="gContextMenu.mediaCommand('hidecontrols');"/>
|
||||
<menuitem id="context-video-showstats"
|
||||
accesskey="&videoShowStats.accesskey;"
|
||||
label="&videoShowStats.label;"
|
||||
oncommand="gContextMenu.mediaCommand('showstats');"/>
|
||||
<menuitem id="context-video-hidestats"
|
||||
accesskey="&videoHideStats.accesskey;"
|
||||
label="&videoHideStats.label;"
|
||||
oncommand="gContextMenu.mediaCommand('hidestats');"/>
|
||||
<menuitem id="context-video-fullscreen"
|
||||
accesskey="&videoFullScreen.accesskey;"
|
||||
label="&videoFullScreen.label;"
|
||||
|
|
|
@ -755,13 +755,6 @@ addMessageListener("ContextMenu:MediaCommand", (message) => {
|
|||
case "showcontrols":
|
||||
media.setAttribute("controls", "true");
|
||||
break;
|
||||
case "hidestats":
|
||||
case "showstats":
|
||||
let event = media.ownerDocument.createEvent("CustomEvent");
|
||||
event.initCustomEvent("media-showStatistics", false, true,
|
||||
message.data.command == "showstats");
|
||||
media.dispatchEvent(event);
|
||||
break;
|
||||
case "fullscreen":
|
||||
if (content.document.fullscreenEnabled)
|
||||
media.requestFullscreen();
|
||||
|
|
|
@ -474,9 +474,6 @@ nsContextMenu.prototype = {
|
|||
this.showItem("context-media-showcontrols", onMedia && !this.target.controls);
|
||||
this.showItem("context-media-hidecontrols", this.target.controls && (this.onVideo || (this.onAudio && !this.inSyntheticDoc)));
|
||||
this.showItem("context-video-fullscreen", this.onVideo && this.target.ownerDocument.fullscreenElement == null);
|
||||
var statsShowing = this.onVideo && this.target.mozMediaStatisticsShowing;
|
||||
this.showItem("context-video-showstats", this.onVideo && this.target.controls && !statsShowing);
|
||||
this.showItem("context-video-hidestats", this.onVideo && this.target.controls && statsShowing);
|
||||
this.showItem("context-media-eme-learnmore", this.onDRMMedia);
|
||||
this.showItem("context-media-eme-separator", this.onDRMMedia);
|
||||
|
||||
|
@ -506,8 +503,6 @@ nsContextMenu.prototype = {
|
|||
let canSaveSnapshot = !this.onDRMMedia && this.target.readyState >= this.target.HAVE_CURRENT_DATA;
|
||||
this.setItemAttr("context-video-saveimage", "disabled", !canSaveSnapshot);
|
||||
this.setItemAttr("context-video-fullscreen", "disabled", hasError);
|
||||
this.setItemAttr("context-video-showstats", "disabled", hasError);
|
||||
this.setItemAttr("context-video-hidestats", "disabled", hasError);
|
||||
}
|
||||
}
|
||||
this.showItem("context-media-sep-commands", onMedia);
|
||||
|
|
|
@ -63,17 +63,10 @@
|
|||
Components.classes["@mozilla.org/docshell/urifixup;1"]
|
||||
.getService(Components.interfaces.nsIURIFixup);
|
||||
</field>
|
||||
<field name="mFaviconService" readonly="true">
|
||||
Components.classes["@mozilla.org/browser/favicon-service;1"]
|
||||
.getService(Components.interfaces.nsIFaviconService);
|
||||
</field>
|
||||
<field name="_unifiedComplete" readonly="true">
|
||||
Components.classes["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"]
|
||||
.getService(Components.interfaces.mozIPlacesAutoComplete);
|
||||
</field>
|
||||
<field name="PlacesUtils" readonly="true">
|
||||
(Components.utils.import("resource://gre/modules/PlacesUtils.jsm", {})).PlacesUtils;
|
||||
</field>
|
||||
<field name="AppConstants" readonly="true">
|
||||
(Components.utils.import("resource://gre/modules/AppConstants.jsm", {})).AppConstants;
|
||||
</field>
|
||||
|
@ -862,7 +855,7 @@
|
|||
let browser = this.getBrowserForTab(aTab);
|
||||
browser.mIconURL = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
|
||||
|
||||
if (aURI && this.mFaviconService) {
|
||||
if (aURI) {
|
||||
if (!(aURI instanceof Ci.nsIURI)) {
|
||||
aURI = makeURI(aURI);
|
||||
}
|
||||
|
@ -872,12 +865,7 @@
|
|||
let loadingPrincipal = aLoadingPrincipal
|
||||
? aLoadingPrincipal
|
||||
: Services.scriptSecurityManager.getSystemPrincipal();
|
||||
let loadType = PrivateBrowsingUtils.isWindowPrivate(window)
|
||||
? this.mFaviconService.FAVICON_LOAD_PRIVATE
|
||||
: this.mFaviconService.FAVICON_LOAD_NON_PRIVATE;
|
||||
|
||||
this.mFaviconService.setAndFetchFaviconForPage(
|
||||
browser.currentURI, aURI, false, loadType, null, loadingPrincipal);
|
||||
PlacesUIUtils.loadFavicon(browser, loadingPrincipal, aURI);
|
||||
}
|
||||
|
||||
let sizedIconUrl = browser.mIconURL || "";
|
||||
|
@ -950,12 +938,9 @@
|
|||
<parameter name="aURI"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this.mFaviconService) {
|
||||
if (!(aURI instanceof Ci.nsIURI))
|
||||
aURI = makeURI(aURI);
|
||||
return this.mFaviconService.isFailedFavicon(aURI);
|
||||
}
|
||||
return null;
|
||||
if (!(aURI instanceof Ci.nsIURI))
|
||||
aURI = makeURI(aURI);
|
||||
return PlacesUtils.favicons.isFailedFavicon(aURI);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
|
|
@ -117,7 +117,6 @@ add_task(function* test_video_ok() {
|
|||
"context-media-playbackrate-200x", true], null,
|
||||
"context-media-loop", true,
|
||||
"context-media-hidecontrols", true,
|
||||
"context-video-showstats", true,
|
||||
"context-video-fullscreen", true,
|
||||
"---", null,
|
||||
"context-viewvideo", true,
|
||||
|
@ -165,7 +164,6 @@ add_task(function* test_video_bad() {
|
|||
"context-media-playbackrate-200x", false], null,
|
||||
"context-media-loop", true,
|
||||
"context-media-hidecontrols", false,
|
||||
"context-video-showstats", false,
|
||||
"context-video-fullscreen", false,
|
||||
"---", null,
|
||||
"context-viewvideo", true,
|
||||
|
@ -192,7 +190,6 @@ add_task(function* test_video_bad2() {
|
|||
"context-media-playbackrate-200x", false], null,
|
||||
"context-media-loop", true,
|
||||
"context-media-hidecontrols", false,
|
||||
"context-video-showstats", false,
|
||||
"context-video-fullscreen", false,
|
||||
"---", null,
|
||||
"context-viewvideo", false,
|
||||
|
@ -253,7 +250,6 @@ add_task(function* test_video_in_iframe() {
|
|||
"context-media-playbackrate-200x", true], null,
|
||||
"context-media-loop", true,
|
||||
"context-media-hidecontrols", true,
|
||||
"context-video-showstats", true,
|
||||
"context-video-fullscreen", true,
|
||||
"---", null,
|
||||
"context-viewvideo", true,
|
||||
|
|
|
@ -214,15 +214,6 @@ FeedWriter.prototype = {
|
|||
element.setAttribute(attribute, uri);
|
||||
},
|
||||
|
||||
__faviconService: null,
|
||||
get _faviconService() {
|
||||
if (!this.__faviconService)
|
||||
this.__faviconService = Cc["@mozilla.org/browser/favicon-service;1"].
|
||||
getService(Ci.nsIFaviconService);
|
||||
|
||||
return this.__faviconService;
|
||||
},
|
||||
|
||||
__bundle: null,
|
||||
get _bundle() {
|
||||
if (!this.__bundle) {
|
||||
|
@ -1027,7 +1018,6 @@ FeedWriter.prototype = {
|
|||
prefs.removeObserver(PREF_AUDIO_SELECTED_APP, this);
|
||||
|
||||
this._removeFeedFromCache();
|
||||
this.__faviconService = null;
|
||||
this.__bundle = null;
|
||||
this._feedURI = null;
|
||||
|
||||
|
@ -1168,52 +1158,6 @@ FeedWriter.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the icon for the given web-reader item in the readers menu.
|
||||
* The icon is fetched and stored through the favicon service.
|
||||
*
|
||||
* @param aReaderUrl
|
||||
* the reader url.
|
||||
* @param aMenuItem
|
||||
* the reader item in the readers menulist.
|
||||
*
|
||||
* @note For privacy reasons we cannot set the image attribute directly
|
||||
* to the icon url. See Bug 358878 for details.
|
||||
*/
|
||||
_setFaviconForWebReader:
|
||||
function FW__setFaviconForWebReader(aReaderUrl, aMenuItem) {
|
||||
let readerURI = makeURI(aReaderUrl);
|
||||
if (!/^https?$/.test(readerURI.scheme)) {
|
||||
// Don't try to get a favicon for non http(s) URIs.
|
||||
return;
|
||||
}
|
||||
let faviconURI = makeURI(readerURI.prePath + "/favicon.ico");
|
||||
let self = this;
|
||||
|
||||
let docShell = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
let usePrivateBrowsing = docShell.QueryInterface(Ci.nsILoadContext)
|
||||
.usePrivateBrowsing;
|
||||
|
||||
// We probably need to call InheritFromDocShellToDoc for this, but right now
|
||||
// we can't call it from JS.
|
||||
let attrs = docShell.getOriginAttributes();
|
||||
let ssm = Services.scriptSecurityManager;
|
||||
let nullPrincipal = ssm.createNullPrincipal(attrs);
|
||||
|
||||
this._faviconService.setAndFetchFaviconForPage(readerURI, faviconURI, false,
|
||||
usePrivateBrowsing ? this._faviconService.FAVICON_LOAD_PRIVATE
|
||||
: this._faviconService.FAVICON_LOAD_NON_PRIVATE,
|
||||
function (aURI, aDataLen, aData, aMimeType) {
|
||||
if (aDataLen > 0) {
|
||||
let dataURL = "data:" + aMimeType + ";base64," +
|
||||
btoa(String.fromCharCode.apply(null, aData));
|
||||
aMenuItem.setAttribute('image', dataURL);
|
||||
}
|
||||
}, nullPrincipal);
|
||||
},
|
||||
|
||||
get _mm() {
|
||||
let mm = this._window.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDocShell).
|
||||
|
|
|
@ -12,6 +12,7 @@ var Cu = Components.utils;
|
|||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||
|
@ -37,6 +38,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "CloudSync",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "Weave",
|
||||
"resource://services-sync/main.js");
|
||||
|
||||
const gInContentProcess = Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
|
||||
const FAVICON_REQUEST_TIMEOUT = 60 * 1000;
|
||||
// Map from windows to arrays of data about pending favicon loads.
|
||||
let gFaviconLoadDataMap = new Map();
|
||||
|
||||
// copied from utilityOverlay.js
|
||||
const TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab";
|
||||
|
||||
|
@ -77,6 +83,149 @@ function IsLivemark(aItemId) {
|
|||
return self.ids.has(aItemId);
|
||||
}
|
||||
|
||||
let InternalFaviconLoader = {
|
||||
/**
|
||||
* This gets called for every inner window that is destroyed.
|
||||
* In the parent process, we process the destruction ourselves. In the child process,
|
||||
* we notify the parent which will then process it based on that message.
|
||||
*/
|
||||
observe(subject, topic, data) {
|
||||
let innerWindowID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
this.onInnerDestroyed(innerWindowID);
|
||||
},
|
||||
|
||||
/**
|
||||
* Actually cancel the request, and clear the timeout for cancelling it.
|
||||
*/
|
||||
_cancelRequest({uri, innerWindowID, timerID, callback}, reason) {
|
||||
// Break cycle
|
||||
let request = callback.request;
|
||||
delete callback.request;
|
||||
// Ensure we don't time out.
|
||||
clearTimeout(timerID);
|
||||
try {
|
||||
request.cancel();
|
||||
} catch (ex) {
|
||||
Cu.reportError("When cancelling a request for " + uri.spec + " because " + reason + ", it was already canceled!");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called for every inner that gets destroyed, only in the parent process.
|
||||
*/
|
||||
onInnerDestroyed(innerID) {
|
||||
for (let [window, loadDataForWindow] of gFaviconLoadDataMap) {
|
||||
let newLoadDataForWindow = loadDataForWindow.filter(loadData => {
|
||||
let innerWasDestroyed = loadData.innerWindowID == innerID;
|
||||
if (innerWasDestroyed) {
|
||||
this._cancelRequest(loadData, "the inner window was destroyed");
|
||||
}
|
||||
// Keep the items whose inner is still alive.
|
||||
return !innerWasDestroyed;
|
||||
});
|
||||
// Map iteration with for...of is safe against modification, so
|
||||
// now just replace the old value:
|
||||
gFaviconLoadDataMap.set(window, newLoadDataForWindow);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a toplevel chrome window unloads. We use this to tidy up after ourselves,
|
||||
* avoid leaks, and cancel any remaining requests. The last part should in theory be
|
||||
* handled by the inner-window-destroyed handlers. We clean up just to be on the safe side.
|
||||
*/
|
||||
onUnload(win) {
|
||||
let loadDataForWindow = gFaviconLoadDataMap.get(win);
|
||||
if (loadDataForWindow) {
|
||||
for (let loadData of loadDataForWindow) {
|
||||
this._cancelRequest(loadData, "the chrome window went away");
|
||||
}
|
||||
}
|
||||
gFaviconLoadDataMap.delete(win);
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a function to use as a nsIFaviconDataCallback, so we can remove cancelling
|
||||
* information when the request succeeds. Note that right now there are some edge-cases,
|
||||
* such as about: URIs with chrome:// favicons where the success callback is not invoked.
|
||||
* This is OK: we will 'cancel' the request after the timeout (or when the window goes
|
||||
* away) but that will be a no-op in such cases.
|
||||
*/
|
||||
_makeCompletionCallback(win, id) {
|
||||
return {
|
||||
onComplete(uri) {
|
||||
let loadDataForWindow = gFaviconLoadDataMap.get(win);
|
||||
if (loadDataForWindow) {
|
||||
let itemIndex = loadDataForWindow.findIndex(loadData => {
|
||||
return loadData.innerWindowID == id &&
|
||||
loadData.uri.equals(uri) &&
|
||||
loadData.callback.request == this.request;
|
||||
});
|
||||
if (itemIndex != -1) {
|
||||
let loadData = loadDataForWindow[itemIndex];
|
||||
clearTimeout(loadData.timerID);
|
||||
loadDataForWindow.splice(itemIndex, 1);
|
||||
}
|
||||
}
|
||||
delete this.request;
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
ensureInitialized() {
|
||||
if (this._initialized) {
|
||||
return;
|
||||
}
|
||||
this._initialized = true;
|
||||
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||
Services.ppmm.addMessageListener("Toolkit:inner-window-destroyed", msg => {
|
||||
this.onInnerDestroyed(msg.data);
|
||||
});
|
||||
},
|
||||
|
||||
loadFavicon(browser, principal, uri) {
|
||||
this.ensureInitialized();
|
||||
let win = browser.ownerDocument.defaultView;
|
||||
if (!gFaviconLoadDataMap.has(win)) {
|
||||
gFaviconLoadDataMap.set(win, []);
|
||||
let unloadHandler = event => {
|
||||
let doc = event.target;
|
||||
let eventWin = doc.defaultview;
|
||||
if (win == win.top && doc.documentURI != "about:blank") {
|
||||
win.removeEventListener("unload", unloadHandler);
|
||||
this.onUnload(win);
|
||||
}
|
||||
};
|
||||
win.addEventListener("unload", unloadHandler, true);
|
||||
}
|
||||
|
||||
// First we do the actual setAndFetch call:
|
||||
let {innerWindowID, currentURI} = browser;
|
||||
let loadType = PrivateBrowsingUtils.isWindowPrivate(win)
|
||||
? PlacesUtils.favicons.FAVICON_LOAD_PRIVATE
|
||||
: PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE;
|
||||
let callback = this._makeCompletionCallback(win, innerWindowID);
|
||||
let request = PlacesUtils.favicons.setAndFetchFaviconForPage(currentURI, uri, false,
|
||||
loadType, callback, principal);
|
||||
|
||||
// Now register the result so we can cancel it if/when necessary.
|
||||
if (!request) {
|
||||
// The favicon service can return with success but no-op (and leave request
|
||||
// as null) if the icon is the same as the page (e.g. for images) or if it is
|
||||
// the favicon for an error page. In this case, we do not need to do anything else.
|
||||
return;
|
||||
}
|
||||
callback.request = request;
|
||||
let loadData = {innerWindowID, uri, callback};
|
||||
loadData.timerID = setTimeout(() => {
|
||||
this._cancelRequest(loadData, "it timed out");
|
||||
}, FAVICON_REQUEST_TIMEOUT);
|
||||
let loadDataForWindow = gFaviconLoadDataMap.get(win);
|
||||
loadDataForWindow.push(loadData);
|
||||
},
|
||||
};
|
||||
|
||||
this.PlacesUIUtils = {
|
||||
ORGANIZER_LEFTPANE_VERSION: 7,
|
||||
ORGANIZER_FOLDER_ANNO: "PlacesOrganizer/OrganizerFolder",
|
||||
|
@ -481,6 +630,19 @@ this.PlacesUIUtils = {
|
|||
return RecentWindow.getMostRecentBrowserWindow();
|
||||
},
|
||||
|
||||
/**
|
||||
* set and fetch a favicon. Can only be used from the parent process.
|
||||
* @param browser {Browser} The XUL browser element for which we're fetching a favicon.
|
||||
* @param principal {Principal} The loading principal to use for the fetch.
|
||||
* @param uri {URI} The URI to fetch.
|
||||
*/
|
||||
loadFavicon(browser, principal, uri) {
|
||||
if (gInContentProcess) {
|
||||
throw new Error("Can't track loads from within the child process!");
|
||||
}
|
||||
InternalFaviconLoader.loadFavicon(browser, principal, uri);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the closet ancestor places view for the given DOM node
|
||||
* @param aNode
|
||||
|
|
|
@ -107,6 +107,7 @@ Var DownloadedBytes
|
|||
Var DownloadRetryCount
|
||||
Var OpenedDownloadPage
|
||||
Var DownloadServerIP
|
||||
Var PostSigningData
|
||||
|
||||
Var ControlHeightPX
|
||||
Var ControlRightPX
|
||||
|
@ -115,7 +116,7 @@ Var ControlRightPX
|
|||
; the stub installer
|
||||
;!define STUB_DEBUG
|
||||
|
||||
!define StubURLVersion "v6"
|
||||
!define StubURLVersion "v7"
|
||||
|
||||
; Successful install exit code
|
||||
!define ERR_SUCCESS 0
|
||||
|
@ -220,11 +221,13 @@ Var ControlRightPX
|
|||
!include "nsDialogs.nsh"
|
||||
!include "LogicLib.nsh"
|
||||
!include "FileFunc.nsh"
|
||||
!include "TextFunc.nsh"
|
||||
!include "WinVer.nsh"
|
||||
!include "WordFunc.nsh"
|
||||
|
||||
!insertmacro GetParameters
|
||||
!insertmacro GetOptions
|
||||
!insertmacro LineFind
|
||||
!insertmacro StrFilter
|
||||
|
||||
!include "locales.nsi"
|
||||
|
@ -745,14 +748,15 @@ Function SendPing
|
|||
$\nHas Admin = $R8 \
|
||||
$\nDefault Status = $R2 \
|
||||
$\nSet As Sefault Status = $R3 \
|
||||
$\nDownload Server IP = $DownloadServerIP"
|
||||
$\nDownload Server IP = $DownloadServerIP \
|
||||
$\nPost-Signing Data = $PostSigningData"
|
||||
; The following will exit the installer
|
||||
SetAutoClose true
|
||||
StrCpy $R9 "2"
|
||||
Call RelativeGotoPage
|
||||
!else
|
||||
${NSD_CreateTimer} OnPing ${DownloadIntervalMS}
|
||||
InetBgDL::Get "${BaseURLStubPing}/${StubURLVersion}${StubURLVersionAppend}/${Channel}/${UpdateChannel}/${AB_CD}/$R0/$R1/$5/$6/$7/$8/$9/$ExitCode/$FirefoxLaunchCode/$DownloadRetryCount/$DownloadedBytes/$DownloadSizeBytes/$IntroPhaseSeconds/$OptionsPhaseSeconds/$0/$1/$DownloadFirstTransferSeconds/$2/$3/$4/$InitialInstallRequirementsCode/$OpenedDownloadPage/$ExistingProfile/$ExistingVersion/$ExistingBuildID/$R5/$R6/$R7/$R8/$R2/$R3/$DownloadServerIP" \
|
||||
InetBgDL::Get "${BaseURLStubPing}/${StubURLVersion}${StubURLVersionAppend}/${Channel}/${UpdateChannel}/${AB_CD}/$R0/$R1/$5/$6/$7/$8/$9/$ExitCode/$FirefoxLaunchCode/$DownloadRetryCount/$DownloadedBytes/$DownloadSizeBytes/$IntroPhaseSeconds/$OptionsPhaseSeconds/$0/$1/$DownloadFirstTransferSeconds/$2/$3/$4/$InitialInstallRequirementsCode/$OpenedDownloadPage/$ExistingProfile/$ExistingVersion/$ExistingBuildID/$R5/$R6/$R7/$R8/$R2/$R3/$DownloadServerIP/$PostSigningData" \
|
||||
"$PLUGINSDIR\_temp" /END
|
||||
!endif
|
||||
${Else}
|
||||
|
@ -1045,7 +1049,7 @@ Function createOptions
|
|||
; We can only install the maintenance service if the user is an admin.
|
||||
Call IsUserAdmin
|
||||
Pop $0
|
||||
|
||||
|
||||
; Only show the maintenance service checkbox if we're on XP SP3 or higher;
|
||||
; we don't ever want to install it on XP without at least SP3 installed.
|
||||
${If} $0 == "true"
|
||||
|
@ -1053,7 +1057,7 @@ Function createOptions
|
|||
${AndIf} ${AtMostServicePack} 2
|
||||
StrCpy $0 "false"
|
||||
${EndIf}
|
||||
|
||||
|
||||
; Only show the maintenance service checkbox if we have write access to HKLM
|
||||
ClearErrors
|
||||
WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" \
|
||||
|
@ -1767,8 +1771,8 @@ Function FinishProgressBar
|
|||
|
||||
${NSD_KillTimer} FinishProgressBar
|
||||
|
||||
Call CopyPostSigningData
|
||||
Call LaunchApp
|
||||
|
||||
Call SendPing
|
||||
FunctionEnd
|
||||
|
||||
|
@ -1997,6 +2001,17 @@ Function LaunchAppFromElevatedProcess
|
|||
Exec "$\"$0$\""
|
||||
FunctionEnd
|
||||
|
||||
Function CopyPostSigningData
|
||||
${LineRead} "$EXEDIR\postSigningData" "1" $PostSigningData
|
||||
${If} ${Errors}
|
||||
ClearErrors
|
||||
StrCpy $PostSigningData "0"
|
||||
${Else}
|
||||
CreateDirectory "$LOCALAPPDATA\Mozilla\Firefox"
|
||||
CopyFiles /SILENT "$EXEDIR\postSigningData" "$LOCALAPPDATA\Mozilla\Firefox"
|
||||
${Endif}
|
||||
FunctionEnd
|
||||
|
||||
Function DisplayDownloadError
|
||||
${NSD_KillTimer} DisplayDownloadError
|
||||
; To better display the error state on the taskbar set the progress completed
|
||||
|
|
|
@ -699,8 +699,8 @@ this.BrowserUITelemetry = {
|
|||
"media-mute", "media-unmute", "media-playbackrate",
|
||||
"media-playbackrate-050x", "media-playbackrate-100x",
|
||||
"media-playbackrate-125x", "media-playbackrate-150x", "media-playbackrate-200x",
|
||||
"media-showcontrols", "media-hidecontrols", "video-showstats",
|
||||
"video-hidestats", "video-fullscreen", "leave-dom-fullscreen",
|
||||
"media-showcontrols", "media-hidecontrols",
|
||||
"video-fullscreen", "leave-dom-fullscreen",
|
||||
"reloadimage", "viewimage", "viewvideo", "copyimage-contents", "copyimage",
|
||||
"copyvideourl", "copyaudiourl", "saveimage", "shareimage", "sendimage",
|
||||
"setDesktopBackground", "viewimageinfo", "viewimagedesc", "savevideo",
|
||||
|
|
|
@ -1156,6 +1156,12 @@ html|span.ac-tag {
|
|||
color: Highlight;
|
||||
}
|
||||
|
||||
html|span.ac-emphasize-text-title,
|
||||
html|span.ac-emphasize-text-tag,
|
||||
html|span.ac-emphasize-text-url {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ac-type-icon[type=bookmark] {
|
||||
list-style-image: url("chrome://browser/skin/urlbar-star.svg#star");
|
||||
}
|
||||
|
|
|
@ -1750,10 +1750,6 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
|||
color: hsl(0, 0%, 0%);
|
||||
}
|
||||
|
||||
html|span.ac-emphasize-text-title {
|
||||
color: hsl(0, 0%, 50%);
|
||||
}
|
||||
|
||||
.ac-tags {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
@ -1766,10 +1762,6 @@ html|span.ac-tag {
|
|||
padding: 0 1px;
|
||||
}
|
||||
|
||||
html|span.ac-emphasize-text-tag {
|
||||
color: hsl(0, 0%, 50%);
|
||||
}
|
||||
|
||||
.ac-separator,
|
||||
.ac-url,
|
||||
.ac-action {
|
||||
|
@ -1784,10 +1776,6 @@ html|span.ac-emphasize-text-tag {
|
|||
color: hsl(210, 77%, 47%);
|
||||
}
|
||||
|
||||
html|span.ac-emphasize-text-url {
|
||||
color: hsl(210, 86%, 64%);
|
||||
}
|
||||
|
||||
.ac-action {
|
||||
color: hsl(178, 100%, 28%);
|
||||
}
|
||||
|
@ -1795,10 +1783,7 @@ html|span.ac-emphasize-text-url {
|
|||
.ac-title[selected],
|
||||
.ac-separator[selected],
|
||||
.ac-url[selected],
|
||||
.ac-action[selected],
|
||||
.ac-title-text[selected] > html|span.ac-emphasize-text,
|
||||
.ac-url-text[selected] > html|span.ac-emphasize-text,
|
||||
.ac-action-text[selected] > html|span.ac-emphasize-text {
|
||||
.ac-action[selected] {
|
||||
color: hsl(0, 0%, 100%);
|
||||
}
|
||||
|
||||
|
@ -1807,8 +1792,10 @@ html|span.ac-emphasize-text-url {
|
|||
color: hsl(210, 80%, 40%);
|
||||
}
|
||||
|
||||
.ac-tags-text[selected] > html|span.ac-tag > html|span.ac-emphasize-text-tag {
|
||||
color: hsl(210, 80%, 52%);
|
||||
html|span.ac-emphasize-text-title,
|
||||
html|span.ac-emphasize-text-tag,
|
||||
html|span.ac-emphasize-text-url {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ac-type-icon[type=bookmark] {
|
||||
|
|
|
@ -1424,10 +1424,6 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
|
|||
color: hsl(0, 0%, 0%);
|
||||
}
|
||||
|
||||
html|span.ac-emphasize-text-title {
|
||||
color: hsl(0, 0%, 50%);
|
||||
}
|
||||
|
||||
.ac-tags {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
@ -1440,10 +1436,6 @@ html|span.ac-tag {
|
|||
padding: 0 1px;
|
||||
}
|
||||
|
||||
html|span.ac-emphasize-text-tag {
|
||||
color: hsl(0, 0%, 50%);
|
||||
}
|
||||
|
||||
.ac-separator,
|
||||
.ac-url,
|
||||
.ac-action {
|
||||
|
@ -1458,10 +1450,6 @@ html|span.ac-emphasize-text-tag {
|
|||
color: hsl(210, 77%, 47%);
|
||||
}
|
||||
|
||||
html|span.ac-emphasize-text-url {
|
||||
color: hsl(210, 86%, 64%);
|
||||
}
|
||||
|
||||
.ac-action {
|
||||
color: hsl(178, 100%, 28%);
|
||||
}
|
||||
|
@ -1469,10 +1457,7 @@ html|span.ac-emphasize-text-url {
|
|||
.ac-title[selected=true],
|
||||
.ac-separator[selected],
|
||||
.ac-url[selected=true],
|
||||
.ac-action[selected=true],
|
||||
.ac-title-text[selected=true] > html|span.ac-emphasize-text,
|
||||
.ac-url-text[selected=true] > html|span.ac-emphasize-text,
|
||||
.ac-action-text[selected=true] > html|span.ac-emphasize-text {
|
||||
.ac-action[selected=true] {
|
||||
color: hsl(0, 0%, 100%);
|
||||
}
|
||||
|
||||
|
@ -1481,8 +1466,10 @@ html|span.ac-emphasize-text-url {
|
|||
color: hsl(210, 80%, 40%);
|
||||
}
|
||||
|
||||
.ac-tags-text[selected] > html|span.ac-tag > html|span.ac-emphasize-text-tag {
|
||||
color: hsl(210, 80%, 52%);
|
||||
html|span.ac-emphasize-text-title,
|
||||
html|span.ac-emphasize-text-tag,
|
||||
html|span.ac-emphasize-text-url {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@media not all and (-moz-windows-default-theme) {
|
||||
|
@ -1490,26 +1477,22 @@ html|span.ac-emphasize-text-url {
|
|||
background-color: Highlight;
|
||||
}
|
||||
|
||||
.ac-title,
|
||||
html|span.ac-emphasize-text-title {
|
||||
.ac-title {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
html|span.ac-tag,
|
||||
html|span.ac-emphasize-text-tag {
|
||||
html|span.ac-tag {
|
||||
background-color: -moz-FieldText;
|
||||
color: -moz-Field;
|
||||
}
|
||||
|
||||
.ac-separator,
|
||||
.ac-url,
|
||||
.ac-action,
|
||||
html|span.ac-emphasize-text-url {
|
||||
.ac-action {
|
||||
color: -moz-nativehyperlinktext;
|
||||
}
|
||||
|
||||
.ac-tags-text[selected] > html|span.ac-tag,
|
||||
.ac-tags-text[selected] > html|span.ac-tag > html|span.ac-emphasize-text-tag {
|
||||
.ac-tags-text[selected] > html|span.ac-tag {
|
||||
background-color: HighlightText;
|
||||
color: Highlight;
|
||||
}
|
||||
|
|
|
@ -68,9 +68,9 @@ function testEventListeners(aThreadClient) {
|
|||
return;
|
||||
}
|
||||
|
||||
// There are 4 event listeners in the page: button.onclick, window.onload
|
||||
// and two more from the video element controls.
|
||||
is(aPacket.listeners.length, 4, "Found all event listeners.");
|
||||
// There are 3 event listeners in the page: button.onclick, window.onload
|
||||
// and one more from the video element controls.
|
||||
is(aPacket.listeners.length, 3, "Found all event listeners.");
|
||||
aThreadClient.resume(deferred.resolve);
|
||||
});
|
||||
|
||||
|
|
|
@ -20,6 +20,9 @@ const TEST_URI = `
|
|||
<p>Empty<p>
|
||||
<h1 class="asd@@@@a!!!!:::@asd">Invalid characters in class</h1>
|
||||
<h2 id="asd@@@a!!2a">Invalid characters in id</h2>
|
||||
<svg viewBox="0 0 10 10">
|
||||
<circle cx="5" cy="5" r="5" fill="blue"></circle>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
const TEST_DATA = [
|
||||
|
@ -29,7 +32,8 @@ const TEST_DATA = [
|
|||
{ node: ".class3.class4", expected: ".class3.class4" },
|
||||
{ node: "p", expected: "p" },
|
||||
{ node: "h1", expected: ".asd\\@\\@\\@\\@a\\!\\!\\!\\!\\:\\:\\:\\@asd" },
|
||||
{ node: "h2", expected: "#asd\\@\\@\\@a\\!\\!2a" }
|
||||
{ node: "h2", expected: "#asd\\@\\@\\@a\\!\\!2a" },
|
||||
{ node: "circle", expected: "circle" }
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
|
|
|
@ -147,8 +147,7 @@ function BrowserLoaderBuilder({ baseURI, window, useOnlyShared }) {
|
|||
const proxy = createProxy(exports);
|
||||
componentProxies.set(uri, proxy);
|
||||
module.exports = proxy.get();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
const proxy = componentProxies.get(uri);
|
||||
const instances = proxy.update(exports);
|
||||
instances.forEach(getForceUpdate(React));
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { Ci, Cc } = require("chrome");
|
||||
const { getJSON } = require("devtools/client/shared/getjson");
|
||||
const Services = require("Services");
|
||||
const promise = require("promise");
|
||||
|
|
|
@ -28,9 +28,8 @@ function findSourceDir(path) {
|
|||
).then(exists => {
|
||||
if (exists) {
|
||||
return path;
|
||||
} else {
|
||||
return findSourceDir(OS.Path.dirname(path));
|
||||
}
|
||||
return findSourceDir(OS.Path.dirname(path));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -56,7 +55,8 @@ const onPrefChange = function () {
|
|||
const searchPoint = OS.Path.dirname(OS.Path.dirname(devtoolsPath));
|
||||
findSourceDir(searchPoint)
|
||||
.then(srcPath => {
|
||||
const rootPath = srcPath ? OS.Path.join(srcPath, "devtools") : devtoolsPath;
|
||||
const rootPath = srcPath ? OS.Path.join(srcPath, "devtools")
|
||||
: devtoolsPath;
|
||||
const watchPath = OS.Path.join(rootPath, "client");
|
||||
const { watchFiles } = require("devtools/client/shared/file-watcher");
|
||||
worker = watchFiles(watchPath, path => {
|
||||
|
@ -69,6 +69,7 @@ const onPrefChange = function () {
|
|||
worker = null;
|
||||
}
|
||||
};
|
||||
|
||||
Services.prefs.addObserver(HOTRELOAD_PREF, {
|
||||
observe: onPrefChange
|
||||
}, false);
|
||||
|
|
|
@ -37,7 +37,9 @@ var TYPES = {
|
|||
// in Beta releases. Only displayed once per profile.
|
||||
deveditionpromo: {
|
||||
predicate: shouldDevEditionPromoShow,
|
||||
success: () => Services.prefs.setBoolPref(DEV_EDITION_PROMO_SHOWN_PREF, true),
|
||||
success: () => {
|
||||
return Services.prefs.setBoolPref(DEV_EDITION_PROMO_SHOWN_PREF, true);
|
||||
},
|
||||
action: () => {
|
||||
let url = Services.prefs.getCharPref(DEV_EDITION_PROMO_URL_PREF);
|
||||
getGBrowser().selectedTab = getGBrowser().addTab(url);
|
||||
|
@ -63,10 +65,11 @@ var panelAttrs = {
|
|||
* @param {XULWindow} window
|
||||
* The window that should house the doorhanger.
|
||||
* @param {String} type
|
||||
* The type of doorhanger to be displayed is, using the `TYPES` definition.
|
||||
* The type of doorhanger to be displayed is, using the `TYPES`
|
||||
* definition.
|
||||
* @param {String} selector
|
||||
* The selector that the doorhanger should be appended to within `window`.
|
||||
* Defaults to a XUL Document's `window` element.
|
||||
* The selector that the doorhanger should be appended to within
|
||||
* `window`. Defaults to a XUL Document's `window` element.
|
||||
*/
|
||||
exports.showDoorhanger = Task.async(function* ({ window, type, anchor }) {
|
||||
let { predicate, success, url, action } = TYPES[type];
|
||||
|
@ -118,7 +121,9 @@ exports.showDoorhanger = Task.async(function* ({ window, type, anchor }) {
|
|||
});
|
||||
|
||||
function setDoorhangerStyle(panel, frame) {
|
||||
Object.keys(panelAttrs).forEach(prop => panel.setAttribute(prop, panelAttrs[prop]));
|
||||
Object.keys(panelAttrs).forEach(prop => {
|
||||
return panel.setAttribute(prop, panelAttrs[prop]);
|
||||
});
|
||||
panel.style.margin = "20px";
|
||||
panel.style.borderRadius = "5px";
|
||||
panel.style.border = "none";
|
||||
|
|
|
@ -79,4 +79,3 @@ onmessage = function (event) {
|
|||
});
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { Ci, ChromeWorker } = require("chrome");
|
||||
const Services = require("Services");
|
||||
const { ChromeWorker } = require("chrome");
|
||||
|
||||
function watchFiles(path, onFileChanged) {
|
||||
const watchWorker = new ChromeWorker(
|
||||
|
@ -16,8 +15,8 @@ function watchFiles(path, onFileChanged) {
|
|||
// chrome). This means that this system will only work when built
|
||||
// files are symlinked, so that these URIs actually read from
|
||||
// local sources. There might be a better way to do this.
|
||||
const { path } = event.data;
|
||||
onFileChanged(path);
|
||||
const { newPath } = event.data;
|
||||
onFileChanged(newPath);
|
||||
};
|
||||
|
||||
watchWorker.postMessage({
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* 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/. */
|
||||
|
||||
/* eslint-env browser */
|
||||
/* global addMessageListener, sendAsyncMessage, content */
|
||||
"use strict";
|
||||
var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
const {require, loader} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
|
@ -25,7 +27,8 @@ addMessageListener("devtools:test:reload", function ({ data }) {
|
|||
content.location.reload(data.forceget);
|
||||
});
|
||||
|
||||
addMessageListener("devtools:test:console", function ({ data: { method, args, id } }) {
|
||||
addMessageListener("devtools:test:console", function ({ data }) {
|
||||
let { method, args, id } = data;
|
||||
content.console[method].apply(content.console, args);
|
||||
sendAsyncMessage("devtools:test:console:response", { id });
|
||||
});
|
||||
|
@ -79,8 +82,9 @@ function promiseXHR(data) {
|
|||
|
||||
/**
|
||||
* Performs XMLHttpRequest request(s) in the context of the page. The data
|
||||
* parameter can be either a single object or an array of objects described below.
|
||||
* The requests will be performed one at a time in the order they appear in the data.
|
||||
* parameter can be either a single object or an array of objects described
|
||||
* below. The requests will be performed one at a time in the order they appear
|
||||
* in the data.
|
||||
*
|
||||
* The objects should have following form (any of them can be omitted; defaults
|
||||
* shown below):
|
||||
|
@ -115,7 +119,8 @@ addMessageListener("devtools:test:xhr", Task.async(function* ({ data }) {
|
|||
sendAsyncMessage("devtools:test:xhr", responses);
|
||||
}));
|
||||
|
||||
addMessageListener("devtools:test:profiler", function ({ data: { method, args, id }}) {
|
||||
addMessageListener("devtools:test:profiler", function ({ data }) {
|
||||
let { method, args, id } = data;
|
||||
let result = nsIProfilerModule[method](...args);
|
||||
sendAsyncMessage("devtools:test:profiler:response", {
|
||||
data: result,
|
||||
|
@ -123,7 +128,6 @@ addMessageListener("devtools:test:profiler", function ({ data: { method, args, i
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
// To eval in content, look at `evalInDebuggee` in the shared-head.js.
|
||||
addMessageListener("devtools:test:eval", function ({ data }) {
|
||||
sendAsyncMessage("devtools:test:eval:response", {
|
||||
|
@ -190,14 +194,13 @@ function superQuerySelector(superSelector, root = content.document) {
|
|||
let frameIndex = superSelector.indexOf("||");
|
||||
if (frameIndex === -1) {
|
||||
return root.querySelector(superSelector);
|
||||
} else {
|
||||
let rootSelector = superSelector.substring(0, frameIndex).trim();
|
||||
let childSelector = superSelector.substring(frameIndex + 2).trim();
|
||||
root = root.querySelector(rootSelector);
|
||||
if (!root || !root.contentWindow) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return superQuerySelector(childSelector, root.contentWindow.document);
|
||||
}
|
||||
let rootSelector = superSelector.substring(0, frameIndex).trim();
|
||||
let childSelector = superSelector.substring(frameIndex + 2).trim();
|
||||
root = root.querySelector(rootSelector);
|
||||
if (!root || !root.contentWindow) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return superQuerySelector(childSelector, root.contentWindow.document);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const {Cu, CC} = require("chrome");
|
||||
"use strict";
|
||||
|
||||
const {CC} = require("chrome");
|
||||
const promise = require("promise");
|
||||
const Services = require("Services");
|
||||
|
||||
|
@ -15,7 +17,9 @@ exports.getJSON = function (prefName, bypassCache) {
|
|||
let str = Services.prefs.getCharPref(prefName + "_cache");
|
||||
let json = JSON.parse(str);
|
||||
return promise.resolve(json);
|
||||
} catch (e) {/* no pref or invalid json. Let's continue */}
|
||||
} catch (e) {
|
||||
// no pref or invalid json. Let's continue
|
||||
}
|
||||
}
|
||||
|
||||
let deferred = promise.defer();
|
||||
|
@ -29,7 +33,7 @@ exports.getJSON = function (prefName, bypassCache) {
|
|||
return deferred.reject("Invalid JSON");
|
||||
}
|
||||
Services.prefs.setCharPref(prefName + "_cache", xhr.responseText);
|
||||
deferred.resolve(json);
|
||||
return deferred.resolve(json);
|
||||
};
|
||||
|
||||
xhr.onerror = (e) => {
|
||||
|
|
|
@ -43,7 +43,7 @@ const FOCUS_FORWARD = Ci.nsIFocusManager.MOVEFOCUS_FORWARD;
|
|||
const FOCUS_BACKWARD = Ci.nsIFocusManager.MOVEFOCUS_BACKWARD;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://devtools/shared/event-emitter.js");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { findMostRelevantCssPropertyIndex } = require("./suggestion-picker");
|
||||
|
||||
/**
|
||||
|
@ -628,7 +628,9 @@ InplaceEditor.prototype = {
|
|||
* 'type'.
|
||||
*/
|
||||
_parseCSSValue: function (value, offset) {
|
||||
/* eslint-disable max-len */
|
||||
const reSplitCSS = /(url\("?[^"\)]+"?\)?)|(rgba?\([^)]*\)?)|(hsla?\([^)]*\)?)|(#[\dA-Fa-f]+)|(-?\d*\.?\d+(%|[a-z]{1,4})?)|"([^"]*)"?|'([^']*)'?|([^,\s\/!\(\)]+)|(!(.*)?)/;
|
||||
/* eslint-enable */
|
||||
let start = 0;
|
||||
let m;
|
||||
|
||||
|
|
|
@ -174,7 +174,8 @@ KeyShortcuts.prototype = {
|
|||
|
||||
on(key, listener) {
|
||||
if (typeof listener !== "function") {
|
||||
throw new Error("KeyShortcuts.on() expects a function as second argument");
|
||||
throw new Error("KeyShortcuts.on() expects a function as " +
|
||||
"second argument");
|
||||
}
|
||||
if (!this.keys.has(key)) {
|
||||
let shortcut = KeyShortcuts.parseElectronKey(this.window, key);
|
||||
|
|
|
@ -16,7 +16,8 @@ function LocalizationHelper(stringBundleName) {
|
|||
loader.lazyGetter(this, "stringBundle", () =>
|
||||
Services.strings.createBundle(stringBundleName));
|
||||
loader.lazyGetter(this, "ellipsis", () =>
|
||||
Services.prefs.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data);
|
||||
Services.prefs.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString)
|
||||
.data);
|
||||
}
|
||||
|
||||
LocalizationHelper.prototype = {
|
||||
|
@ -51,8 +52,12 @@ LocalizationHelper.prototype = {
|
|||
* @return string
|
||||
*/
|
||||
getFormatStrWithNumbers: function (name, ...args) {
|
||||
let newArgs = args.map(x => typeof x == "number" ? this.numberWithDecimals(x, 2) : x);
|
||||
return this.stringBundle.formatStringFromName(name, newArgs, newArgs.length);
|
||||
let newArgs = args.map(x => {
|
||||
return typeof x == "number" ? this.numberWithDecimals(x, 2) : x;
|
||||
});
|
||||
return this.stringBundle.formatStringFromName(name,
|
||||
newArgs,
|
||||
newArgs.length);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -92,19 +97,22 @@ LocalizationHelper.prototype = {
|
|||
};
|
||||
|
||||
/**
|
||||
* A helper for having the same interface as LocalizationHelper, but for more than
|
||||
* one file. Useful for abstracting l10n string locations.
|
||||
* A helper for having the same interface as LocalizationHelper, but for more
|
||||
* than one file. Useful for abstracting l10n string locations.
|
||||
*/
|
||||
function MultiLocalizationHelper(...stringBundleNames) {
|
||||
let instances = stringBundleNames.map(bundle => new LocalizationHelper(bundle));
|
||||
let instances = stringBundleNames.map(bundle => {
|
||||
return new LocalizationHelper(bundle);
|
||||
});
|
||||
|
||||
// Get all function members of the LocalizationHelper class, making sure we're not
|
||||
// executing any potential getters while doing so, and wrap all the
|
||||
// Get all function members of the LocalizationHelper class, making sure we're
|
||||
// not executing any potential getters while doing so, and wrap all the
|
||||
// methods we've found to work on all given string bundles.
|
||||
Object.getOwnPropertyNames(LocalizationHelper.prototype)
|
||||
.map(name => ({
|
||||
name: name,
|
||||
descriptor: Object.getOwnPropertyDescriptor(LocalizationHelper.prototype, name)
|
||||
descriptor: Object.getOwnPropertyDescriptor(LocalizationHelper.prototype,
|
||||
name)
|
||||
}))
|
||||
.filter(({ descriptor }) => descriptor.value instanceof Function)
|
||||
.forEach(method => {
|
||||
|
@ -112,8 +120,11 @@ function MultiLocalizationHelper(...stringBundleNames) {
|
|||
for (let l10n of instances) {
|
||||
try {
|
||||
return method.descriptor.value.apply(l10n, args);
|
||||
} catch (e) {}
|
||||
} catch (e) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -34,10 +34,10 @@ const TYPE_IDREF_LIST = "idrefList";
|
|||
const TYPE_JS_RESOURCE_URI = "jsresource";
|
||||
const TYPE_CSS_RESOURCE_URI = "cssresource";
|
||||
|
||||
const SVG_NS = "http://www.w3.org/2000/svg";
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
/* eslint-disable max-len */
|
||||
const ATTRIBUTE_TYPES = [
|
||||
{namespaceURI: HTML_NS, attributeName: "action", tagName: "form", type: TYPE_URI},
|
||||
{namespaceURI: HTML_NS, attributeName: "background", tagName: "body", type: TYPE_URI},
|
||||
|
@ -69,9 +69,11 @@ const ATTRIBUTE_TYPES = [
|
|||
{namespaceURI: HTML_NS, attributeName: "href", tagName: "a", type: TYPE_URI},
|
||||
{namespaceURI: HTML_NS, attributeName: "href", tagName: "area", type: TYPE_URI},
|
||||
{namespaceURI: "*", attributeName: "href", tagName: "link", type: TYPE_CSS_RESOURCE_URI,
|
||||
isValid: (namespaceURI, tagName, attributes) => {
|
||||
return getAttribute(attributes, "rel") === "stylesheet";
|
||||
}},
|
||||
/* eslint-enable */
|
||||
isValid: (namespaceURI, tagName, attributes) => {
|
||||
return getAttribute(attributes, "rel") === "stylesheet";
|
||||
}},
|
||||
/* eslint-disable max-len */
|
||||
{namespaceURI: "*", attributeName: "href", tagName: "link", type: TYPE_URI},
|
||||
{namespaceURI: HTML_NS, attributeName: "href", tagName: "base", type: TYPE_URI},
|
||||
{namespaceURI: HTML_NS, attributeName: "icon", tagName: "menuitem", type: TYPE_URI},
|
||||
|
@ -115,6 +117,7 @@ const ATTRIBUTE_TYPES = [
|
|||
{namespaceURI: XUL_NS, attributeName: "src", tagName: "stringbundle", type: TYPE_URI},
|
||||
{namespaceURI: XUL_NS, attributeName: "template", tagName: "*", type: TYPE_IDREF},
|
||||
{namespaceURI: XUL_NS, attributeName: "tooltip", tagName: "*", type: TYPE_IDREF},
|
||||
/* eslint-enable */
|
||||
// SVG links aren't handled yet, see bug 1158831.
|
||||
// {namespaceURI: SVG_NS, attributeName: "fill", tagName: "*", type: },
|
||||
// {namespaceURI: SVG_NS, attributeName: "stroke", tagName: "*", type: },
|
||||
|
@ -188,7 +191,8 @@ var parsers = {
|
|||
*/
|
||||
function parseAttribute(namespaceURI, tagName, attributes, attributeName) {
|
||||
if (!hasAttribute(attributes, attributeName)) {
|
||||
throw new Error(`Attribute ${attributeName} isn't part of the provided attributes`);
|
||||
throw new Error(`Attribute ${attributeName} isn't part of the ` +
|
||||
"provided attributes");
|
||||
}
|
||||
|
||||
let type = getType(namespaceURI, tagName, attributes, attributeName);
|
||||
|
@ -214,17 +218,20 @@ function parseAttribute(namespaceURI, tagName, attributes, attributeName) {
|
|||
*/
|
||||
function getType(namespaceURI, tagName, attributes, attributeName) {
|
||||
for (let typeData of ATTRIBUTE_TYPES) {
|
||||
let hasAttribute = attributeName === typeData.attributeName ||
|
||||
typeData.attributeName === "*";
|
||||
let containsAttribute = attributeName === typeData.attributeName ||
|
||||
typeData.attributeName === "*";
|
||||
let hasNamespace = namespaceURI === typeData.namespaceURI ||
|
||||
typeData.namespaceURI === "*";
|
||||
let hasTagName = tagName.toLowerCase() === typeData.tagName ||
|
||||
typeData.tagName === "*";
|
||||
let isValid = typeData.isValid
|
||||
? typeData.isValid(namespaceURI, tagName, attributes, attributeName)
|
||||
? typeData.isValid(namespaceURI,
|
||||
tagName,
|
||||
attributes,
|
||||
attributeName)
|
||||
: true;
|
||||
|
||||
if (hasAttribute && hasNamespace && hasTagName && isValid) {
|
||||
if (containsAttribute && hasNamespace && hasTagName && isValid) {
|
||||
return typeData.type;
|
||||
}
|
||||
}
|
||||
|
@ -242,7 +249,7 @@ function getAttribute(attributes, attributeName) {
|
|||
}
|
||||
|
||||
function hasAttribute(attributes, attributeName) {
|
||||
for (let {name, value} of attributes) {
|
||||
for (let {name} of attributes) {
|
||||
if (name === attributeName) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const Services = require("Services");
|
||||
const { Preferences } = require("resource://gre/modules/Preferences.jsm");
|
||||
|
@ -10,9 +12,10 @@ const PREF_CHANGE_EVENT = "pref-changed";
|
|||
* - branchName: The name of the prefs branch, like "devtools.debugger."
|
||||
* - menupopup: The XUL `menupopup` item that contains the pref buttons.
|
||||
*
|
||||
* Fires an event, PREF_CHANGE_EVENT, with the preference name that changed as the second
|
||||
* argument. Fires events on opening/closing the XUL panel (OPTIONS_SHOW_EVENT, OPTIONS_HIDDEN_EVENT)
|
||||
* as the second argument in the listener, used for tests mostly.
|
||||
* Fires an event, PREF_CHANGE_EVENT, with the preference name that changed as
|
||||
* the second argument. Fires events on opening/closing the XUL panel
|
||||
* (OPTIONS_SHOW_EVENT, OPTIONS_HIDDEN_EVENT) as the second argument in the
|
||||
* listener, used for tests mostly.
|
||||
*/
|
||||
const OptionsView = function (options = {}) {
|
||||
this.branchName = options.branchName;
|
||||
|
@ -43,8 +46,8 @@ OptionsView.prototype = {
|
|||
this._onPopupHidden = this._onPopupHidden.bind(this);
|
||||
|
||||
// We use a mutation observer instead of a click handler
|
||||
// because the click handler is fired before the XUL menuitem updates
|
||||
// it's checked status, which cascades incorrectly with the Preference observer.
|
||||
// because the click handler is fired before the XUL menuitem updates its
|
||||
// checked status, which cascades incorrectly with the Preference observer.
|
||||
this.mutationObserver = new MutationObserver(this._onOptionChange);
|
||||
let observerConfig = { attributes: true, attributeFilter: ["checked"]};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {Cc, Ci, Cu} = require("chrome");
|
||||
const {Cc, Ci} = require("chrome");
|
||||
const {angleUtils} = require("devtools/client/shared/css-angle");
|
||||
const {colorUtils} = require("devtools/client/shared/css-color");
|
||||
const {getCSSLexer} = require("devtools/shared/css-lexer");
|
||||
|
@ -398,7 +398,8 @@ OutputParser.prototype = {
|
|||
style: "background-color:" + color
|
||||
});
|
||||
this.colorSwatches.set(swatch, colorObj);
|
||||
swatch.addEventListener("mousedown", this._onColorSwatchMouseDown, false);
|
||||
swatch.addEventListener("mousedown", this._onColorSwatchMouseDown,
|
||||
false);
|
||||
EventEmitter.decorate(swatch);
|
||||
container.appendChild(swatch);
|
||||
}
|
||||
|
|
|
@ -81,7 +81,8 @@ Poller.prototype.off = function pollerOff() {
|
|||
|
||||
/**
|
||||
* Turns off polling and removes the reference to the poller function.
|
||||
* Resolves when the last outstanding `fn` call finishes if it's an async function.
|
||||
* Resolves when the last outstanding `fn` call finishes if it's an async
|
||||
* function.
|
||||
*/
|
||||
Poller.prototype.destroy = function pollerDestroy() {
|
||||
return this.off().then(() => {
|
||||
|
|
|
@ -61,7 +61,9 @@ function get(cache, prefType, prefsRoot, prefName) {
|
|||
if (cachedPref !== undefined) {
|
||||
return cachedPref;
|
||||
}
|
||||
let value = Services.prefs["get" + prefType + "Pref"]([prefsRoot, prefName].join("."));
|
||||
let value = Services.prefs["get" + prefType + "Pref"](
|
||||
[prefsRoot, prefName].join(".")
|
||||
);
|
||||
cache.set(prefName, value);
|
||||
return value;
|
||||
}
|
||||
|
@ -76,7 +78,10 @@ function get(cache, prefType, prefsRoot, prefName) {
|
|||
* @param any value
|
||||
*/
|
||||
function set(cache, prefType, prefsRoot, prefName, value) {
|
||||
Services.prefs["set" + prefType + "Pref"]([prefsRoot, prefName].join("."), value);
|
||||
Services.prefs["set" + prefType + "Pref"](
|
||||
[prefsRoot, prefName].join("."),
|
||||
value
|
||||
);
|
||||
cache.set(prefName, value);
|
||||
}
|
||||
|
||||
|
@ -94,16 +99,24 @@ function set(cache, prefType, prefsRoot, prefName, value) {
|
|||
* @param string prefName
|
||||
* @param array serializer [optional]
|
||||
*/
|
||||
function map(self, cache, accessorName, prefType, prefsRoot, prefName, serializer = { in: e => e, out: e => e }) {
|
||||
function map(self, cache, accessorName, prefType, prefsRoot, prefName,
|
||||
serializer = { in: e => e, out: e => e }) {
|
||||
if (prefName in self) {
|
||||
throw new Error(`Can't use ${prefName} because it overrides a property on the instance.`);
|
||||
throw new Error(`Can't use ${prefName} because it overrides a property` +
|
||||
"on the instance.");
|
||||
}
|
||||
if (prefType == "Json") {
|
||||
map(self, cache, accessorName, "Char", prefsRoot, prefName, { in: JSON.parse, out: JSON.stringify });
|
||||
map(self, cache, accessorName, "Char", prefsRoot, prefName, {
|
||||
in: JSON.parse,
|
||||
out: JSON.stringify
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (prefType == "Float") {
|
||||
map(self, cache, accessorName, "Char", prefsRoot, prefName, { in: Number.parseFloat, out: (n) => n + ""});
|
||||
map(self, cache, accessorName, "Char", prefsRoot, prefName, {
|
||||
in: Number.parseFloat,
|
||||
out: (n) => n + ""
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,21 +64,24 @@ function parseURL(location) {
|
|||
// `host`: "foo.com:8888"
|
||||
//
|
||||
// sdk/url does not match several definitions.: both `host` and `hostname`
|
||||
// are actually the `hostname` (even though this is the `host` property on the
|
||||
// original nsIURL, with `hostPort` representing the actual `host` name, AH!!!)
|
||||
// So normalize all that garbage here.
|
||||
// are actually the `hostname` (even though this is the `host` property on
|
||||
// the original nsIURL, with `hostPort` representing the actual `host` name,
|
||||
// AH!!!). So normalize all that garbage here.
|
||||
let isChrome = isChromeScheme(location);
|
||||
let fileName = url.fileName || "/";
|
||||
let hostname = isChrome ? null : url.hostname;
|
||||
let host = isChrome ? null :
|
||||
url.port ? `${url.host}:${url.port}` :
|
||||
url.host;
|
||||
let hostname, host;
|
||||
if (isChrome) {
|
||||
hostname = null;
|
||||
host = null;
|
||||
} else {
|
||||
hostname = url.hostname;
|
||||
host = url.port ? `${url.host}:${url.port}` : url.host;
|
||||
}
|
||||
|
||||
let parsed = Object.assign({}, url, { host, fileName, hostname });
|
||||
gURLStore.set(location, parsed);
|
||||
return parsed;
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
gURLStore.set(location, null);
|
||||
return null;
|
||||
}
|
||||
|
@ -88,12 +91,14 @@ function parseURL(location) {
|
|||
* Parse a source into a short and long name as well as a host name.
|
||||
*
|
||||
* @param {String} source
|
||||
* The source to parse. Can be a URI or names like "(eval)" or "self-hosted".
|
||||
* The source to parse. Can be a URI or names like "(eval)" or
|
||||
* "self-hosted".
|
||||
* @return {Object}
|
||||
* An object with the following properties:
|
||||
* - {String} short: A short name for the source.
|
||||
* - "http://page.com/test.js#go?q=query" -> "test.js"
|
||||
* - {String} long: The full, long name for the source, with hash/query stripped.
|
||||
* - {String} long: The full, long name for the source, with
|
||||
hash/query stripped.
|
||||
* - "http://page.com/test.js#go?q=query" -> "http://page.com/test.js"
|
||||
* - {String?} host: If available, the host name for the source.
|
||||
* - "http://page.com/test.js#go?q=query" -> "page.com"
|
||||
|
@ -114,7 +119,7 @@ function getSourceNames(source) {
|
|||
if (commaIndex > -1) {
|
||||
// The `short` name for a data URI becomes `data:` followed by the actual
|
||||
// encoded content, omitting the MIME type, and charset.
|
||||
let short = `data:${sourceStr.substring(commaIndex + 1)}`.slice(0, 100);
|
||||
short = `data:${sourceStr.substring(commaIndex + 1)}`.slice(0, 100);
|
||||
let result = { short, long: sourceStr };
|
||||
gSourceNamesStore.set(source, result);
|
||||
return result;
|
||||
|
@ -208,10 +213,11 @@ function isContentScheme(location, i = 0) {
|
|||
let firstChar = location.charCodeAt(i);
|
||||
|
||||
switch (firstChar) {
|
||||
case CHAR_CODE_H: // "http://" or "https://"
|
||||
// "http://" or "https://"
|
||||
case CHAR_CODE_H:
|
||||
if (location.charCodeAt(++i) === CHAR_CODE_T &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_T &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_P) {
|
||||
location.charCodeAt(++i) === CHAR_CODE_T &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_P) {
|
||||
if (location.charCodeAt(i + 1) === CHAR_CODE_S) {
|
||||
++i;
|
||||
}
|
||||
|
@ -219,17 +225,19 @@ function isContentScheme(location, i = 0) {
|
|||
}
|
||||
return false;
|
||||
|
||||
case CHAR_CODE_F: // "file://"
|
||||
// "file://"
|
||||
case CHAR_CODE_F:
|
||||
if (location.charCodeAt(++i) === CHAR_CODE_I &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_L &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_E) {
|
||||
location.charCodeAt(++i) === CHAR_CODE_L &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_E) {
|
||||
return isColonSlashSlash(location, i);
|
||||
}
|
||||
return false;
|
||||
|
||||
case CHAR_CODE_A: // "app://"
|
||||
// "app://"
|
||||
case CHAR_CODE_A:
|
||||
if (location.charCodeAt(++i) == CHAR_CODE_P &&
|
||||
location.charCodeAt(++i) == CHAR_CODE_P) {
|
||||
location.charCodeAt(++i) == CHAR_CODE_P) {
|
||||
return isColonSlashSlash(location, i);
|
||||
}
|
||||
return false;
|
||||
|
@ -243,36 +251,39 @@ function isChromeScheme(location, i = 0) {
|
|||
let firstChar = location.charCodeAt(i);
|
||||
|
||||
switch (firstChar) {
|
||||
case CHAR_CODE_C: // "chrome://"
|
||||
// "chrome://"
|
||||
case CHAR_CODE_C:
|
||||
if (location.charCodeAt(++i) === CHAR_CODE_H &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_R &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_O &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_M &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_E) {
|
||||
location.charCodeAt(++i) === CHAR_CODE_R &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_O &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_M &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_E) {
|
||||
return isColonSlashSlash(location, i);
|
||||
}
|
||||
return false;
|
||||
|
||||
case CHAR_CODE_R: // "resource://"
|
||||
// "resource://"
|
||||
case CHAR_CODE_R:
|
||||
if (location.charCodeAt(++i) === CHAR_CODE_E &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_S &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_O &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_U &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_R &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_C &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_E) {
|
||||
location.charCodeAt(++i) === CHAR_CODE_S &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_O &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_U &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_R &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_C &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_E) {
|
||||
return isColonSlashSlash(location, i);
|
||||
}
|
||||
return false;
|
||||
|
||||
case CHAR_CODE_J: // "jar:file://"
|
||||
// "jar:file://"
|
||||
case CHAR_CODE_J:
|
||||
if (location.charCodeAt(++i) === CHAR_CODE_A &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_R &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_COLON &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_F &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_I &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_L &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_E) {
|
||||
location.charCodeAt(++i) === CHAR_CODE_R &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_COLON &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_F &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_I &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_L &&
|
||||
location.charCodeAt(++i) === CHAR_CODE_E) {
|
||||
return isColonSlashSlash(location, i);
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
* telemetry.mozilla.org.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const TOOLS_OPENED_PREF = "devtools.telemetry.tools.opened.version";
|
||||
|
||||
this.Telemetry = function () {
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* 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/. */
|
||||
|
||||
/* eslint-env browser */
|
||||
"use strict";
|
||||
(function () {
|
||||
const SCROLLBARS_URL = "chrome://devtools/skin/floating-scrollbars-dark-theme.css";
|
||||
let documentElement = document.documentElement;
|
||||
|
@ -33,10 +35,13 @@
|
|||
// required then as scrollbars would be in their state without flushing.
|
||||
return;
|
||||
}
|
||||
let display = computedStyle.display; // Save display value
|
||||
// Save display value
|
||||
let display = computedStyle.display;
|
||||
documentElement.style.display = "none";
|
||||
window.getComputedStyle(documentElement).display; // Flush
|
||||
documentElement.style.display = display; // Restore
|
||||
// Flush
|
||||
window.getComputedStyle(documentElement).display;
|
||||
// Restore
|
||||
documentElement.style.display = display;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
* https://developer.mozilla.org/en-US/docs/Tools/DevToolsColors
|
||||
*/
|
||||
|
||||
const { Ci, Cu } = require("chrome");
|
||||
const { Cu } = require("chrome");
|
||||
const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
|
||||
const Services = require("Services");
|
||||
const { gDevTools } = require("devtools/client/framework/devtools");
|
||||
|
@ -32,7 +32,9 @@ function readURI(uri) {
|
|||
).open();
|
||||
|
||||
let count = stream.available();
|
||||
let data = NetUtil.readInputStreamToString(stream, count, { charset: "UTF-8" });
|
||||
let data = NetUtil.readInputStreamToString(stream, count, {
|
||||
charset: "UTF-8"
|
||||
});
|
||||
stream.close();
|
||||
return data;
|
||||
}
|
||||
|
@ -48,7 +50,7 @@ function getThemeFile(name) {
|
|||
|
||||
// If there's no theme expected for this name, use `light` as default.
|
||||
let selector = THEME_SELECTOR_STRINGS[name] ||
|
||||
THEME_SELECTOR_STRINGS["light"];
|
||||
THEME_SELECTOR_STRINGS.light;
|
||||
|
||||
// This is a pretty naive way to find the contents between:
|
||||
// selector {
|
||||
|
@ -67,14 +69,17 @@ function getThemeFile(name) {
|
|||
* Returns the string value of the current theme,
|
||||
* like "dark" or "light".
|
||||
*/
|
||||
const getTheme = exports.getTheme = () => Services.prefs.getCharPref("devtools.theme");
|
||||
const getTheme = exports.getTheme = () => {
|
||||
return Services.prefs.getCharPref("devtools.theme");
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a color indicated by `type` (like "toolbar-background", or "highlight-red"),
|
||||
* with the ability to specify a theme, or use whatever the current theme is
|
||||
* if left unset. If theme not found, falls back to "light" theme. Returns null
|
||||
* if the type cannot be found for the theme given.
|
||||
* Returns a color indicated by `type` (like "toolbar-background", or
|
||||
* "highlight-red"), with the ability to specify a theme, or use whatever the
|
||||
* current theme is if left unset. If theme not found, falls back to "light"
|
||||
* theme. Returns null if the type cannot be found for the theme given.
|
||||
*/
|
||||
/* eslint-disable no-unused-vars */
|
||||
const getColor = exports.getColor = (type, theme) => {
|
||||
let themeName = theme || getTheme();
|
||||
let themeFile = getThemeFile(themeName);
|
||||
|
@ -99,3 +104,4 @@ const setTheme = exports.setTheme = (newTheme) => {
|
|||
oldValue: oldTheme
|
||||
});
|
||||
};
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -4,21 +4,19 @@
|
|||
* 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";
|
||||
|
||||
/**
|
||||
* A simple undo stack manager.
|
||||
*
|
||||
* Actions are added along with the necessary code to
|
||||
* reverse the action.
|
||||
*
|
||||
* @param function aChange Called whenever the size or position
|
||||
* of the undo stack changes, to use for updating undo-related
|
||||
* UI.
|
||||
* @param integer aMaxUndo Maximum number of undo steps.
|
||||
* @param integer maxUndo Maximum number of undo steps.
|
||||
* defaults to 50.
|
||||
*/
|
||||
function UndoStack(aMaxUndo)
|
||||
{
|
||||
this.maxUndo = aMaxUndo || 50;
|
||||
function UndoStack(maxUndo) {
|
||||
this.maxUndo = maxUndo || 50;
|
||||
this._stack = [];
|
||||
}
|
||||
|
||||
|
@ -32,8 +30,7 @@ UndoStack.prototype = {
|
|||
// The current batch depth (see startBatch() for details)
|
||||
_batchDepth: 0,
|
||||
|
||||
destroy: function Undo_destroy()
|
||||
{
|
||||
destroy: function () {
|
||||
this.uninstallController();
|
||||
delete this._stack;
|
||||
},
|
||||
|
@ -47,8 +44,7 @@ UndoStack.prototype = {
|
|||
* actions made up of a collection of smaller actions to be
|
||||
* undone as a single action.
|
||||
*/
|
||||
startBatch: function Undo_startBatch()
|
||||
{
|
||||
startBatch: function () {
|
||||
if (this._batchDepth++ === 0) {
|
||||
this._batch = [];
|
||||
}
|
||||
|
@ -58,8 +54,7 @@ UndoStack.prototype = {
|
|||
* End a batch of related changes, performing its action and adding
|
||||
* it to the undo stack.
|
||||
*/
|
||||
endBatch: function Undo_endBatch()
|
||||
{
|
||||
endBatch: function () {
|
||||
if (--this._batchDepth > 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -92,20 +87,19 @@ UndoStack.prototype = {
|
|||
/**
|
||||
* Perform an action, adding it to the undo stack.
|
||||
*
|
||||
* @param function aDo Called to perform the action.
|
||||
* @param function aUndo Called to reverse the action.
|
||||
* @param function toDo Called to perform the action.
|
||||
* @param function undo Called to reverse the action.
|
||||
*/
|
||||
do: function Undo_do(aDo, aUndo) {
|
||||
do: function (toDo, undo) {
|
||||
this.startBatch();
|
||||
this._batch.push({ do: aDo, undo: aUndo });
|
||||
this._batch.push({ do: toDo, undo });
|
||||
this.endBatch();
|
||||
},
|
||||
|
||||
/*
|
||||
* Returns true if undo() will do anything.
|
||||
*/
|
||||
canUndo: function Undo_canUndo()
|
||||
{
|
||||
canUndo: function () {
|
||||
return this._index > 0;
|
||||
},
|
||||
|
||||
|
@ -114,8 +108,7 @@ UndoStack.prototype = {
|
|||
*
|
||||
* @return true if an action was undone.
|
||||
*/
|
||||
undo: function Undo_canUndo()
|
||||
{
|
||||
undo: function () {
|
||||
if (!this.canUndo()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -127,8 +120,7 @@ UndoStack.prototype = {
|
|||
/**
|
||||
* Returns true if redo() will do anything.
|
||||
*/
|
||||
canRedo: function Undo_canRedo()
|
||||
{
|
||||
canRedo: function () {
|
||||
return this._stack.length > this._index;
|
||||
},
|
||||
|
||||
|
@ -137,8 +129,7 @@ UndoStack.prototype = {
|
|||
*
|
||||
* @return true if an action was redone.
|
||||
*/
|
||||
redo: function Undo_canRedo()
|
||||
{
|
||||
redo: function () {
|
||||
if (!this.canRedo()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -147,8 +138,7 @@ UndoStack.prototype = {
|
|||
return true;
|
||||
},
|
||||
|
||||
_change: function Undo__change()
|
||||
{
|
||||
_change: function () {
|
||||
if (this._controllerWindow) {
|
||||
this._controllerWindow.goUpdateCommand("cmd_undo");
|
||||
this._controllerWindow.goUpdateCommand("cmd_redo");
|
||||
|
@ -162,45 +152,41 @@ UndoStack.prototype = {
|
|||
/**
|
||||
* Install this object as a command controller.
|
||||
*/
|
||||
installController: function Undo_installController(aControllerWindow)
|
||||
{
|
||||
this._controllerWindow = aControllerWindow;
|
||||
aControllerWindow.controllers.appendController(this);
|
||||
installController: function (controllerWindow) {
|
||||
this._controllerWindow = controllerWindow;
|
||||
controllerWindow.controllers.appendController(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Uninstall this object from the command controller.
|
||||
*/
|
||||
uninstallController: function Undo_uninstallController()
|
||||
{
|
||||
uninstallController: function () {
|
||||
if (!this._controllerWindow) {
|
||||
return;
|
||||
}
|
||||
this._controllerWindow.controllers.removeController(this);
|
||||
},
|
||||
|
||||
supportsCommand: function Undo_supportsCommand(aCommand)
|
||||
{
|
||||
return (aCommand == "cmd_undo" ||
|
||||
aCommand == "cmd_redo");
|
||||
supportsCommand: function (command) {
|
||||
return (command == "cmd_undo" ||
|
||||
command == "cmd_redo");
|
||||
},
|
||||
|
||||
isCommandEnabled: function Undo_isCommandEnabled(aCommand)
|
||||
{
|
||||
switch (aCommand) {
|
||||
isCommandEnabled: function (command) {
|
||||
switch (command) {
|
||||
case "cmd_undo": return this.canUndo();
|
||||
case "cmd_redo": return this.canRedo();
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
doCommand: function Undo_doCommand(aCommand)
|
||||
{
|
||||
switch (aCommand) {
|
||||
doCommand: function (command) {
|
||||
switch (command) {
|
||||
case "cmd_undo": return this.undo();
|
||||
case "cmd_redo": return this.redo();
|
||||
default: return null;
|
||||
}
|
||||
},
|
||||
|
||||
onEvent: function Undo_onEvent(aEvent) {},
|
||||
onEvent: function (event) {},
|
||||
};
|
||||
|
|
|
@ -8,14 +8,13 @@ var { Task } = require("devtools/shared/task");
|
|||
|
||||
var Services = require("Services");
|
||||
var {gDevTools} = require("devtools/client/framework/devtools");
|
||||
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
|
||||
/**
|
||||
* Tries to open a Stylesheet file in the Style Editor. If the file is not found,
|
||||
* it is opened in source view instead.
|
||||
* Tries to open a Stylesheet file in the Style Editor. If the file is not
|
||||
* found, it is opened in source view instead.
|
||||
* Returns a promise resolving to a boolean indicating whether or not
|
||||
* the source was able to be displayed in the StyleEditor, as the built-in Firefox
|
||||
* View Source is the fallback.
|
||||
* the source was able to be displayed in the StyleEditor, as the built-in
|
||||
* Firefox View Source is the fallback.
|
||||
*
|
||||
* @param {Toolbox} toolbox
|
||||
* @param {string} sourceURL
|
||||
|
@ -23,7 +22,8 @@ var DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
|||
*
|
||||
* @return {Promise<boolean>}
|
||||
*/
|
||||
exports.viewSourceInStyleEditor = Task.async(function* (toolbox, sourceURL, sourceLine) {
|
||||
exports.viewSourceInStyleEditor = Task.async(function* (toolbox, sourceURL,
|
||||
sourceLine) {
|
||||
let panel = yield toolbox.loadTool("styleeditor");
|
||||
|
||||
try {
|
||||
|
@ -49,7 +49,8 @@ exports.viewSourceInStyleEditor = Task.async(function* (toolbox, sourceURL, sour
|
|||
*
|
||||
* @return {Promise<boolean>}
|
||||
*/
|
||||
exports.viewSourceInDebugger = Task.async(function* (toolbox, sourceURL, sourceLine) {
|
||||
exports.viewSourceInDebugger = Task.async(function* (toolbox, sourceURL,
|
||||
sourceLine) {
|
||||
// If the Debugger was already open, switch to it and try to show the
|
||||
// source immediately. Otherwise, initialize it and wait for the sources
|
||||
// to be added first.
|
||||
|
@ -66,8 +67,11 @@ exports.viewSourceInDebugger = Task.async(function* (toolbox, sourceURL, sourceL
|
|||
let item = Sources.getItemForAttachment(a => a.source.url === sourceURL);
|
||||
if (item) {
|
||||
yield toolbox.selectTool("jsdebugger");
|
||||
const isLoading = dbg.DebuggerController.getState().sources.selectedSource !== item.attachment.source.actor;
|
||||
DebuggerView.setEditorLocation(item.attachment.source.actor, sourceLine, { noDebug: true });
|
||||
const isLoading = dbg.DebuggerController.getState().sources.selectedSource
|
||||
!== item.attachment.source.actor;
|
||||
DebuggerView.setEditorLocation(item.attachment.source.actor, sourceLine, {
|
||||
noDebug: true
|
||||
});
|
||||
if (isLoading) {
|
||||
yield dbg.DebuggerController.waitForSourceShown(sourceURL);
|
||||
}
|
||||
|
@ -138,4 +142,5 @@ exports.viewSource = Task.async(function* (toolbox, sourceURL, sourceLine) {
|
|||
}
|
||||
let utils = toolbox.gViewSourceUtils;
|
||||
utils.viewSource(sourceURL, null, toolbox.doc, sourceLine || 0);
|
||||
return null;
|
||||
});
|
||||
|
|
|
@ -8,13 +8,11 @@ const Services = require("Services");
|
|||
|
||||
const WEBGL_CONTEXT_NAME = "experimental-webgl";
|
||||
|
||||
function isWebGLForceEnabled()
|
||||
{
|
||||
function isWebGLForceEnabled() {
|
||||
return Services.prefs.getBoolPref("webgl.force-enabled");
|
||||
}
|
||||
|
||||
function isWebGLSupportedByGFX()
|
||||
{
|
||||
function isWebGLSupportedByGFX() {
|
||||
let supported = false;
|
||||
|
||||
try {
|
||||
|
@ -31,12 +29,11 @@ function isWebGLSupportedByGFX()
|
|||
return supported;
|
||||
}
|
||||
|
||||
function create3DContext(aCanvas)
|
||||
{
|
||||
function create3DContext(canvas) {
|
||||
// try to get a valid context from an existing canvas
|
||||
let context = null;
|
||||
try {
|
||||
context = aCanvas.getContext(WEBGL_CONTEXT_NAME, aFlags);
|
||||
context = canvas.getContext(WEBGL_CONTEXT_NAME, {});
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu, Cr } = require("chrome");
|
||||
|
||||
const { Heritage, setNamedTimeout, clearNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
|
||||
const { AbstractCanvasGraph, CanvasGraphUtils } = require("devtools/client/shared/widgets/Graphs");
|
||||
|
||||
|
@ -10,10 +8,12 @@ const HTML_NS = "http://www.w3.org/1999/xhtml";
|
|||
// Bar graph constants.
|
||||
|
||||
const GRAPH_DAMPEN_VALUES_FACTOR = 0.75;
|
||||
const GRAPH_BARS_MARGIN_TOP = 1; // px
|
||||
const GRAPH_BARS_MARGIN_END = 1; // px
|
||||
const GRAPH_MIN_BARS_WIDTH = 5; // px
|
||||
const GRAPH_MIN_BLOCKS_HEIGHT = 1; // px
|
||||
|
||||
// The following are in pixels
|
||||
const GRAPH_BARS_MARGIN_TOP = 1;
|
||||
const GRAPH_BARS_MARGIN_END = 1;
|
||||
const GRAPH_MIN_BARS_WIDTH = 5;
|
||||
const GRAPH_MIN_BLOCKS_HEIGHT = 1;
|
||||
|
||||
const GRAPH_BACKGROUND_GRADIENT_START = "rgba(0,136,204,0.0)";
|
||||
const GRAPH_BACKGROUND_GRADIENT_END = "rgba(255,255,255,0.25)";
|
||||
|
@ -28,7 +28,8 @@ const GRAPH_REGION_STRIPES_COLOR = "rgba(237,38,85,0.2)";
|
|||
const GRAPH_HIGHLIGHTS_MASK_BACKGROUND = "rgba(255,255,255,0.75)";
|
||||
const GRAPH_HIGHLIGHTS_MASK_STRIPES = "rgba(255,255,255,0.5)";
|
||||
|
||||
const GRAPH_LEGEND_MOUSEOVER_DEBOUNCE = 50; // ms
|
||||
// in ms
|
||||
const GRAPH_LEGEND_MOUSEOVER_DEBOUNCE = 50;
|
||||
|
||||
/**
|
||||
* A bar graph, plotting tuples of values as rectangles.
|
||||
|
@ -144,7 +145,8 @@ BarGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
*/
|
||||
buildGraphImage: function () {
|
||||
if (!this.format || !this.format.length) {
|
||||
throw "The graph format traits are mandatory to style the data source.";
|
||||
throw new Error("The graph format traits are mandatory to style " +
|
||||
"the data source.");
|
||||
}
|
||||
let { canvas, ctx } = this._getNamedCanvas("bar-graph-data");
|
||||
let width = this._width;
|
||||
|
@ -260,7 +262,8 @@ BarGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
* @param function unpack [optional]
|
||||
* @see AbstractCanvasGraph.prototype.getMappedSelection
|
||||
*/
|
||||
buildMaskImage: function (highlights, inPixels = false, unpack = e => e.delta) {
|
||||
buildMaskImage: function (highlights, inPixels = false,
|
||||
unpack = e => e.delta) {
|
||||
// A null `highlights` array is used to clear the mask. An empty array
|
||||
// will mask the entire graph.
|
||||
if (!highlights) {
|
||||
|
@ -295,11 +298,19 @@ BarGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
start = CanvasGraphUtils.map(start, firstTick, lastTick, 0, width);
|
||||
end = CanvasGraphUtils.map(end, firstTick, lastTick, 0, width);
|
||||
}
|
||||
let firstSnap = findFirst(this._blocksBoundingRects, e => e.start >= start);
|
||||
let lastSnap = findLast(this._blocksBoundingRects, e => e.start >= start && e.end <= end);
|
||||
let firstSnap = findFirst(this._blocksBoundingRects,
|
||||
e => e.start >= start);
|
||||
let lastSnap = findLast(this._blocksBoundingRects,
|
||||
e => e.start >= start && e.end <= end);
|
||||
|
||||
let x1 = firstSnap ? firstSnap.start : start;
|
||||
let x2 = lastSnap ? lastSnap.end : firstSnap ? firstSnap.end : end;
|
||||
let x2;
|
||||
if (lastSnap) {
|
||||
x2 = lastSnap.end;
|
||||
} else {
|
||||
x2 = firstSnap ? firstSnap.end : end;
|
||||
}
|
||||
|
||||
let y1 = top || 0;
|
||||
let y2 = bottom || height;
|
||||
ctx.clearRect(x1, y1, x2 - x1, y2 - y1);
|
||||
|
@ -357,7 +368,8 @@ BarGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
* Creates the legend container when constructing this graph.
|
||||
*/
|
||||
_createLegend: function () {
|
||||
let legendNode = this._legendNode = this._document.createElementNS(HTML_NS, "div");
|
||||
let legendNode = this._legendNode = this._document.createElementNS(HTML_NS,
|
||||
"div");
|
||||
legendNode.className = "bar-graph-widget-legend";
|
||||
this._container.appendChild(legendNode);
|
||||
},
|
||||
|
@ -390,17 +402,21 @@ BarGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
/**
|
||||
* Invoked whenever a color node in the legend is hovered.
|
||||
*/
|
||||
_onLegendMouseOver: function (e) {
|
||||
setNamedTimeout("bar-graph-debounce", GRAPH_LEGEND_MOUSEOVER_DEBOUNCE, () => {
|
||||
let type = e.target.dataset.index;
|
||||
let rects = this._blocksBoundingRects.filter(e => e.type == type);
|
||||
_onLegendMouseOver: function (ev) {
|
||||
setNamedTimeout(
|
||||
"bar-graph-debounce",
|
||||
GRAPH_LEGEND_MOUSEOVER_DEBOUNCE,
|
||||
() => {
|
||||
let type = ev.target.dataset.index;
|
||||
let rects = this._blocksBoundingRects.filter(e => e.type == type);
|
||||
|
||||
this._originalHighlights = this._mask;
|
||||
this._hasCustomHighlights = true;
|
||||
this.setMask(rects, true);
|
||||
this._originalHighlights = this._mask;
|
||||
this._hasCustomHighlights = true;
|
||||
this.setMask(rects, true);
|
||||
|
||||
this.emit("legend-hover", [type, rects]);
|
||||
});
|
||||
this.emit("legend-hover", [type, rects]);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -421,11 +437,11 @@ BarGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
/**
|
||||
* Invoked whenever a color node in the legend is pressed.
|
||||
*/
|
||||
_onLegendMouseDown: function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
_onLegendMouseDown: function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
let type = e.target.dataset.index;
|
||||
let type = ev.target.dataset.index;
|
||||
let rects = this._blocksBoundingRects.filter(e => e.type == type);
|
||||
let leftmost = rects[0];
|
||||
let rightmost = rects[rects.length - 1];
|
||||
|
@ -456,8 +472,11 @@ BarGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
function findFirst(array, predicate) {
|
||||
for (let i = 0, len = array.length; i < len; i++) {
|
||||
let element = array[i];
|
||||
if (predicate(element)) return element;
|
||||
if (predicate(element)) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -469,8 +488,11 @@ function findFirst(array, predicate) {
|
|||
function findLast(array, predicate) {
|
||||
for (let i = array.length - 1; i >= 0; i--) {
|
||||
let element = array[i];
|
||||
if (predicate(element)) return element;
|
||||
if (predicate(element)) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
module.exports = BarGraphWidget;
|
||||
|
|
|
@ -32,7 +32,6 @@ const {
|
|||
DEFAULT_PRESET_CATEGORY
|
||||
} = require("devtools/client/shared/widgets/CubicBezierPresets");
|
||||
const {getCSSLexer} = require("devtools/shared/css-lexer");
|
||||
const {Cc, Ci} = require("chrome");
|
||||
|
||||
/**
|
||||
* CubicBezier data structure helper
|
||||
|
@ -114,10 +113,12 @@ BezierCanvas.prototype = {
|
|||
|
||||
return [{
|
||||
left: w * (this.bezier.coordinates[0] * (1 - p[3] - p[1]) - p[3]) + "px",
|
||||
top: h * (1 - this.bezier.coordinates[1] * (1 - p[0] - p[2]) - p[0]) + "px"
|
||||
top: h * (1 - this.bezier.coordinates[1] * (1 - p[0] - p[2]) - p[0])
|
||||
+ "px"
|
||||
}, {
|
||||
left: w * (this.bezier.coordinates[2] * (1 - p[3] - p[1]) - p[3]) + "px",
|
||||
top: h * (1 - this.bezier.coordinates[3] * (1 - p[0] - p[2]) - p[0]) + "px"
|
||||
top: h * (1 - this.bezier.coordinates[3] * (1 - p[0] - p[2]) - p[0])
|
||||
+ "px"
|
||||
}];
|
||||
},
|
||||
|
||||
|
@ -400,7 +401,9 @@ CubicBezierWidget.prototype = {
|
|||
_updateFromPoints: function () {
|
||||
// Get the new coordinates from the point's offsets
|
||||
let coordinates = this.bezierCanvas.offsetsToCoordinates(this.p1);
|
||||
coordinates = coordinates.concat(this.bezierCanvas.offsetsToCoordinates(this.p2));
|
||||
coordinates = coordinates.concat(
|
||||
this.bezierCanvas.offsetsToCoordinates(this.p2)
|
||||
);
|
||||
|
||||
this.presets.refreshMenu(coordinates);
|
||||
this._redraw(coordinates);
|
||||
|
@ -602,7 +605,8 @@ CubicBezierPresetWidget.prototype = {
|
|||
|
||||
// Create preset label
|
||||
let presetLabelElem = doc.createElement("p");
|
||||
let presetDisplayLabel = this._normalizePresetLabel(categoryLabel, presetLabel);
|
||||
let presetDisplayLabel = this._normalizePresetLabel(categoryLabel,
|
||||
presetLabel);
|
||||
presetLabelElem.textContent = presetDisplayLabel;
|
||||
preset.appendChild(presetLabelElem);
|
||||
preset.setAttribute("title", presetDisplayLabel);
|
||||
|
@ -759,7 +763,7 @@ TimingFunctionPreviewWidget.prototype = {
|
|||
preview: function (value) {
|
||||
// Don't restart the preview animation if the value is the same
|
||||
if (value === this.previousValue) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
clearTimeout(this.autoRestartAnimation);
|
||||
|
@ -781,7 +785,6 @@ TimingFunctionPreviewWidget.prototype = {
|
|||
|
||||
// Just toggling the class won't do it unless there's a sync reflow
|
||||
this.dot.classList.remove("animate");
|
||||
let w = this.dot.offsetWidth;
|
||||
this.dot.classList.add("animate");
|
||||
|
||||
// Restart it again after a while
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
"use strict";
|
||||
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { Cu, Ci } = require("chrome");
|
||||
const { ViewHelpers } = require("devtools/client/shared/widgets/view-helpers");
|
||||
|
||||
/**
|
||||
|
@ -18,10 +17,10 @@ const { ViewHelpers } = require("devtools/client/shared/widgets/view-helpers");
|
|||
* @param nsIDOMNode aNode
|
||||
* The element associated with the widget.
|
||||
*/
|
||||
const FastListWidget = module.exports = function FastListWidget(aNode) {
|
||||
this.document = aNode.ownerDocument;
|
||||
const FastListWidget = module.exports = function FastListWidget(node) {
|
||||
this.document = node.ownerDocument;
|
||||
this.window = this.document.defaultView;
|
||||
this._parent = aNode;
|
||||
this._parent = node;
|
||||
this._fragment = this.document.createDocumentFragment();
|
||||
|
||||
// This is a prototype element that each item added to the list clones.
|
||||
|
@ -34,7 +33,8 @@ const FastListWidget = module.exports = function FastListWidget(aNode) {
|
|||
this._list.setAttribute("orient", "vertical");
|
||||
this._list.setAttribute("tabindex", "0");
|
||||
this._list.addEventListener("keypress", e => this.emit("keyPress", e), false);
|
||||
this._list.addEventListener("mousedown", e => this.emit("mousePress", e), false);
|
||||
this._list.addEventListener("mousedown", e => this.emit("mousePress", e),
|
||||
false);
|
||||
this._parent.appendChild(this._list);
|
||||
|
||||
this._orderedMenuElementsArray = [];
|
||||
|
@ -45,8 +45,8 @@ const FastListWidget = module.exports = function FastListWidget(aNode) {
|
|||
|
||||
// Delegate some of the associated node's methods to satisfy the interface
|
||||
// required by MenuContainer instances.
|
||||
ViewHelpers.delegateWidgetAttributeMethods(this, aNode);
|
||||
ViewHelpers.delegateWidgetEventMethods(this, aNode);
|
||||
ViewHelpers.delegateWidgetAttributeMethods(this, node);
|
||||
ViewHelpers.delegateWidgetEventMethods(this, node);
|
||||
};
|
||||
|
||||
FastListWidget.prototype = {
|
||||
|
@ -63,11 +63,11 @@ FastListWidget.prototype = {
|
|||
* @return nsIDOMNode
|
||||
* The element associated with the displayed item.
|
||||
*/
|
||||
insertItemAt: function (aIndex, aContents, aAttachment = {}) {
|
||||
insertItemAt: function (index, contents, attachment = {}) {
|
||||
let element = this._templateElement.cloneNode();
|
||||
element.appendChild(aContents);
|
||||
element.appendChild(contents);
|
||||
|
||||
if (aIndex >= 0) {
|
||||
if (index >= 0) {
|
||||
throw new Error("FastListWidget only supports appending items.");
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,6 @@ FastListWidget.prototype = {
|
|||
* Removes all of the child nodes from this container.
|
||||
*/
|
||||
removeAllItems: function () {
|
||||
let parent = this._parent;
|
||||
let list = this._list;
|
||||
|
||||
while (list.hasChildNodes()) {
|
||||
|
@ -204,11 +203,11 @@ FastListWidget.prototype = {
|
|||
* Sets the text displayed in this container when empty.
|
||||
* @param string aValue
|
||||
*/
|
||||
set _textWhenEmpty(aValue) {
|
||||
set _textWhenEmpty(value) {
|
||||
if (this._emptyTextNode) {
|
||||
this._emptyTextNode.setAttribute("value", aValue);
|
||||
this._emptyTextNode.setAttribute("value", value);
|
||||
}
|
||||
this._emptyTextValue = aValue;
|
||||
this._emptyTextValue = value;
|
||||
this._showEmptyText();
|
||||
},
|
||||
|
||||
|
|
|
@ -10,8 +10,7 @@
|
|||
*/
|
||||
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { Cu, Cc, Ci } = require("chrome");
|
||||
const { ViewHelpers } = require("devtools/client/shared/widgets/view-helpers");
|
||||
const { Cc, Ci } = require("chrome");
|
||||
|
||||
const { LocalizationHelper } = require("devtools/client/shared/l10n");
|
||||
const STRINGS_URI = "chrome://devtools/locale/filterwidget.properties";
|
||||
|
@ -539,7 +538,8 @@ CSSFilterEditorWidget.prototype = {
|
|||
if (el.classList.contains("remove-button")) {
|
||||
// If the click happened on the remove button.
|
||||
presets.splice(id, 1);
|
||||
this.setPresets(presets).then(this.renderPresets, e => console.error(e));
|
||||
this.setPresets(presets).then(this.renderPresets,
|
||||
ex => console.error(ex));
|
||||
} else {
|
||||
// Or if the click happened on a preset.
|
||||
let p = presets[id];
|
||||
|
@ -547,7 +547,7 @@ CSSFilterEditorWidget.prototype = {
|
|||
this.setCssValue(p.value);
|
||||
this.addPresetInput.value = p.name;
|
||||
}
|
||||
}, e => console.error(e));
|
||||
}, ex => console.error(ex));
|
||||
},
|
||||
|
||||
_togglePresets: function () {
|
||||
|
@ -575,8 +575,9 @@ CSSFilterEditorWidget.prototype = {
|
|||
presets.push({name, value});
|
||||
}
|
||||
|
||||
this.setPresets(presets).then(this.renderPresets, e => console.error(e));
|
||||
}, e => console.error(e));
|
||||
this.setPresets(presets).then(this.renderPresets,
|
||||
ex => console.error(ex));
|
||||
}, ex => console.error(ex));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -840,7 +841,7 @@ CSSFilterEditorWidget.prototype = {
|
|||
|
||||
removeAt: function (index) {
|
||||
if (!this.filters[index]) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.filters.splice(index, 1);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"use strict";
|
||||
|
||||
const { Task } = require("devtools/shared/task");
|
||||
const { ViewHelpers, setNamedTimeout, clearNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
|
||||
const { ViewHelpers, setNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
|
||||
const { LocalizationHelper } = require("devtools/client/shared/l10n");
|
||||
|
||||
loader.lazyRequireGetter(this, "promise");
|
||||
|
@ -28,12 +28,12 @@ loader.lazyRequireGetter(this, "GraphArea",
|
|||
loader.lazyRequireGetter(this, "GraphAreaDragger",
|
||||
"devtools/client/shared/widgets/Graphs", true);
|
||||
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const GRAPH_SRC = "chrome://devtools/content/shared/widgets/graphs-frame.xhtml";
|
||||
|
||||
const L10N = new LocalizationHelper();
|
||||
|
||||
const GRAPH_RESIZE_EVENTS_DRAIN = 100; // ms
|
||||
// ms
|
||||
const GRAPH_RESIZE_EVENTS_DRAIN = 100;
|
||||
|
||||
const GRAPH_WHEEL_ZOOM_SENSITIVITY = 0.00035;
|
||||
const GRAPH_WHEEL_SCROLL_SENSITIVITY = 0.5;
|
||||
|
@ -41,31 +41,43 @@ const GRAPH_KEYBOARD_ZOOM_SENSITIVITY = 20;
|
|||
const GRAPH_KEYBOARD_PAN_SENSITIVITY = 20;
|
||||
const GRAPH_KEYBOARD_ACCELERATION = 1.05;
|
||||
const GRAPH_KEYBOARD_TRANSLATION_MAX = 150;
|
||||
const GRAPH_MIN_SELECTION_WIDTH = 0.001; // ms
|
||||
|
||||
const GRAPH_HORIZONTAL_PAN_THRESHOLD = 10; // px
|
||||
const GRAPH_VERTICAL_PAN_THRESHOLD = 30; // px
|
||||
// ms
|
||||
const GRAPH_MIN_SELECTION_WIDTH = 0.001;
|
||||
|
||||
// px
|
||||
const GRAPH_HORIZONTAL_PAN_THRESHOLD = 10;
|
||||
const GRAPH_VERTICAL_PAN_THRESHOLD = 30;
|
||||
|
||||
const FIND_OPTIMAL_TICK_INTERVAL_MAX_ITERS = 100;
|
||||
const TIMELINE_TICKS_MULTIPLE = 5; // ms
|
||||
const TIMELINE_TICKS_SPACING_MIN = 75; // px
|
||||
|
||||
const OVERVIEW_HEADER_HEIGHT = 16; // px
|
||||
const OVERVIEW_HEADER_TEXT_FONT_SIZE = 9; // px
|
||||
// ms
|
||||
const TIMELINE_TICKS_MULTIPLE = 5;
|
||||
// px
|
||||
const TIMELINE_TICKS_SPACING_MIN = 75;
|
||||
|
||||
// px
|
||||
const OVERVIEW_HEADER_HEIGHT = 16;
|
||||
const OVERVIEW_HEADER_TEXT_FONT_SIZE = 9;
|
||||
const OVERVIEW_HEADER_TEXT_FONT_FAMILY = "sans-serif";
|
||||
const OVERVIEW_HEADER_TEXT_PADDING_LEFT = 6; // px
|
||||
const OVERVIEW_HEADER_TEXT_PADDING_TOP = 5; // px
|
||||
// px
|
||||
const OVERVIEW_HEADER_TEXT_PADDING_LEFT = 6;
|
||||
const OVERVIEW_HEADER_TEXT_PADDING_TOP = 5;
|
||||
const OVERVIEW_HEADER_TIMELINE_STROKE_COLOR = "rgba(128, 128, 128, 0.5)";
|
||||
|
||||
const FLAME_GRAPH_BLOCK_HEIGHT = 15; // px
|
||||
const FLAME_GRAPH_BLOCK_BORDER = 1; // px
|
||||
const FLAME_GRAPH_BLOCK_TEXT_FONT_SIZE = 10; // px
|
||||
const FLAME_GRAPH_BLOCK_TEXT_FONT_FAMILY = "message-box, Helvetica Neue, Helvetica, sans-serif";
|
||||
const FLAME_GRAPH_BLOCK_TEXT_PADDING_TOP = 0; // px
|
||||
const FLAME_GRAPH_BLOCK_TEXT_PADDING_LEFT = 3; // px
|
||||
const FLAME_GRAPH_BLOCK_TEXT_PADDING_RIGHT = 3; // px
|
||||
// px
|
||||
const FLAME_GRAPH_BLOCK_HEIGHT = 15;
|
||||
const FLAME_GRAPH_BLOCK_BORDER = 1;
|
||||
const FLAME_GRAPH_BLOCK_TEXT_FONT_SIZE = 10;
|
||||
const FLAME_GRAPH_BLOCK_TEXT_FONT_FAMILY = "message-box, Helvetica Neue," +
|
||||
"Helvetica, sans-serif";
|
||||
// px
|
||||
const FLAME_GRAPH_BLOCK_TEXT_PADDING_TOP = 0;
|
||||
const FLAME_GRAPH_BLOCK_TEXT_PADDING_LEFT = 3;
|
||||
const FLAME_GRAPH_BLOCK_TEXT_PADDING_RIGHT = 3;
|
||||
|
||||
const PALLETTE_SIZE = 20; // Large enough number for a diverse pallette.
|
||||
// Large enough number for a diverse pallette.
|
||||
const PALLETTE_SIZE = 20;
|
||||
const PALLETTE_HUE_OFFSET = Math.random() * 90;
|
||||
const PALLETTE_HUE_RANGE = 270;
|
||||
const PALLETTE_SATURATION = 100;
|
||||
|
@ -73,7 +85,8 @@ const PALLETTE_BRIGHTNESS = 55;
|
|||
const PALLETTE_OPACITY = 0.35;
|
||||
|
||||
const COLOR_PALLETTE = Array.from(Array(PALLETTE_SIZE)).map((_, i) => "hsla" +
|
||||
"(" + ((PALLETTE_HUE_OFFSET + (i / PALLETTE_SIZE * PALLETTE_HUE_RANGE)) | 0 % 360) +
|
||||
"(" +
|
||||
((PALLETTE_HUE_OFFSET + (i / PALLETTE_SIZE * PALLETTE_HUE_RANGE)) | 0 % 360) +
|
||||
"," + PALLETTE_SATURATION + "%" +
|
||||
"," + PALLETTE_BRIGHTNESS + "%" +
|
||||
"," + PALLETTE_OPACITY +
|
||||
|
@ -141,7 +154,8 @@ function FlameGraph(parent, sharpness) {
|
|||
this._document = iframe.contentDocument;
|
||||
this._pixelRatio = sharpness || this._window.devicePixelRatio;
|
||||
|
||||
let container = this._container = this._document.getElementById("graph-container");
|
||||
let container =
|
||||
this._container = this._document.getElementById("graph-container");
|
||||
container.className = "flame-graph-widget-container graph-widget-container";
|
||||
|
||||
let canvas = this._canvas = this._document.getElementById("graph-canvas");
|
||||
|
@ -201,7 +215,8 @@ function FlameGraph(parent, sharpness) {
|
|||
let ownerWindow = this._parent.ownerDocument.defaultView;
|
||||
ownerWindow.addEventListener("resize", this._onResize);
|
||||
|
||||
this._animationId = this._window.requestAnimationFrame(this._onAnimationFrame);
|
||||
this._animationId =
|
||||
this._window.requestAnimationFrame(this._onAnimationFrame);
|
||||
|
||||
this._ready.resolve(this);
|
||||
this.emit("ready", this);
|
||||
|
@ -415,8 +430,10 @@ FlameGraph.prototype = {
|
|||
theme = theme || "light";
|
||||
this.overviewHeaderBackgroundColor = getColor("body-background", theme);
|
||||
this.overviewHeaderTextColor = getColor("body-color", theme);
|
||||
// Hard to get a color that is readable across both themes for the text on the flames
|
||||
this.blockTextColor = getColor(theme === "dark" ? "selection-color" : "body-color", theme);
|
||||
// Hard to get a color that is readable across both themes for the text
|
||||
// on the flames
|
||||
this.blockTextColor = getColor(theme === "dark" ? "selection-color"
|
||||
: "body-color", theme);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -430,7 +447,8 @@ FlameGraph.prototype = {
|
|||
* Animation frame callback, invoked on each tick of the refresh driver.
|
||||
*/
|
||||
_onAnimationFrame: function () {
|
||||
this._animationId = this._window.requestAnimationFrame(this._onAnimationFrame);
|
||||
this._animationId =
|
||||
this._window.requestAnimationFrame(this._onAnimationFrame);
|
||||
this._drawWidget();
|
||||
},
|
||||
|
||||
|
@ -459,7 +477,8 @@ FlameGraph.prototype = {
|
|||
let selectionWidth = selection.end - selection.start;
|
||||
let selectionScale = canvasWidth / selectionWidth;
|
||||
this._drawTicks(selection.start, selectionScale);
|
||||
this._drawPyramid(this._data, this._verticalOffset, selection.start, selectionScale);
|
||||
this._drawPyramid(this._data, this._verticalOffset,
|
||||
selection.start, selectionScale);
|
||||
this._drawHeader(selection.start, selectionScale);
|
||||
|
||||
// If the user isn't doing anything anymore, it's safe to stop drawing.
|
||||
|
@ -467,7 +486,8 @@ FlameGraph.prototype = {
|
|||
// if any input stops (e.g. smooth panning transitions after the user
|
||||
// finishes input). We don't care about that right now.
|
||||
if (this._userInputStack == 0) {
|
||||
return void (this._shouldRedraw = false);
|
||||
this._shouldRedraw = false;
|
||||
return;
|
||||
}
|
||||
if (this._userInputStack < 0) {
|
||||
throw new Error("The user went back in time from a pyramid.");
|
||||
|
@ -489,7 +509,6 @@ FlameGraph.prototype = {
|
|||
const KEY_CODE_D = 68;
|
||||
|
||||
let canvasWidth = this._width;
|
||||
let canvasHeight = this._height;
|
||||
let pressed = this._keysPressed;
|
||||
|
||||
let selection = this._selection;
|
||||
|
@ -573,7 +592,11 @@ FlameGraph.prototype = {
|
|||
ctx.fillStyle = this.overviewHeaderBackgroundColor;
|
||||
ctx.fillRect(0, 0, canvasWidth, headerHeight);
|
||||
|
||||
this._drawTicks(dataOffset, dataScale, { from: 0, to: headerHeight, renderText: true });
|
||||
this._drawTicks(dataOffset, dataScale, {
|
||||
from: 0,
|
||||
to: headerHeight,
|
||||
renderText: true
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -604,7 +627,8 @@ FlameGraph.prototype = {
|
|||
ctx.strokeStyle = OVERVIEW_HEADER_TIMELINE_STROKE_COLOR;
|
||||
ctx.beginPath();
|
||||
|
||||
for (let x = -scaledOffset % tickInterval; x < canvasWidth; x += tickInterval) {
|
||||
for (let x = -scaledOffset % tickInterval; x < canvasWidth;
|
||||
x += tickInterval) {
|
||||
let lineLeft = x;
|
||||
let textLeft = lineLeft + textPaddingLeft;
|
||||
let time = Math.round((x / dataScale + dataOffset) / this._pixelRatio);
|
||||
|
@ -635,20 +659,23 @@ FlameGraph.prototype = {
|
|||
|
||||
let fontSize = FLAME_GRAPH_BLOCK_TEXT_FONT_SIZE * this._pixelRatio;
|
||||
let fontFamily = FLAME_GRAPH_BLOCK_TEXT_FONT_FAMILY;
|
||||
let visibleBlocksInfo = this._drawPyramidFill(dataSource, verticalOffset, dataOffset, dataScale);
|
||||
let visibleBlocksInfo = this._drawPyramidFill(dataSource, verticalOffset,
|
||||
dataOffset, dataScale);
|
||||
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.font = fontSize + "px " + fontFamily;
|
||||
ctx.fillStyle = this.blockTextColor;
|
||||
|
||||
this._drawPyramidText(visibleBlocksInfo, verticalOffset, dataOffset, dataScale);
|
||||
this._drawPyramidText(visibleBlocksInfo, verticalOffset,
|
||||
dataOffset, dataScale);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fills all block inside this graph's pyramid.
|
||||
* @see FlameGraph.prototype._drawPyramid
|
||||
*/
|
||||
_drawPyramidFill: function (dataSource, verticalOffset, dataOffset, dataScale) {
|
||||
_drawPyramidFill: function (dataSource, verticalOffset, dataOffset,
|
||||
dataScale) {
|
||||
let visibleBlocksInfoStore = [];
|
||||
let minVisibleBlockWidth = this._overflowCharWidth;
|
||||
|
||||
|
@ -665,7 +692,8 @@ FlameGraph.prototype = {
|
|||
* Adds the text for all block inside this graph's pyramid.
|
||||
* @see FlameGraph.prototype._drawPyramid
|
||||
*/
|
||||
_drawPyramidText: function (blocksInfo, verticalOffset, dataOffset, dataScale) {
|
||||
_drawPyramidText: function (blocksInfo, verticalOffset, dataOffset,
|
||||
dataScale) {
|
||||
for (let { block, rect } of blocksInfo) {
|
||||
this._drawBlockText(block, rect, verticalOffset, dataOffset, dataScale);
|
||||
}
|
||||
|
@ -694,8 +722,7 @@ FlameGraph.prototype = {
|
|||
*/
|
||||
_drawBlocksFill: function (
|
||||
color, blocks, verticalOffset, dataOffset, dataScale,
|
||||
visibleBlocksInfoStore, minVisibleBlockWidth)
|
||||
{
|
||||
visibleBlocksInfoStore, minVisibleBlockWidth) {
|
||||
let ctx = this._ctx;
|
||||
let canvasWidth = this._width;
|
||||
let canvasHeight = this._height;
|
||||
|
@ -707,14 +734,16 @@ FlameGraph.prototype = {
|
|||
for (let block of blocks) {
|
||||
let { x, y, width, height } = block;
|
||||
let rectLeft = x * this._pixelRatio * dataScale - scaledOffset;
|
||||
let rectTop = (y - verticalOffset + OVERVIEW_HEADER_HEIGHT) * this._pixelRatio;
|
||||
let rectTop = (y - verticalOffset + OVERVIEW_HEADER_HEIGHT)
|
||||
* this._pixelRatio;
|
||||
let rectWidth = width * this._pixelRatio * dataScale;
|
||||
let rectHeight = height * this._pixelRatio;
|
||||
|
||||
if (rectLeft > canvasWidth || // Too far right.
|
||||
rectLeft < -rectWidth || // Too far left.
|
||||
rectTop > canvasHeight || // Too far bottom.
|
||||
rectTop < -rectHeight) { // Too far top.
|
||||
// Too far respectively right/left/bottom/top
|
||||
if (rectLeft > canvasWidth ||
|
||||
rectLeft < -rectWidth ||
|
||||
rectTop > canvasHeight ||
|
||||
rectTop < -rectHeight) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -766,11 +795,11 @@ FlameGraph.prototype = {
|
|||
* Offsets and scales the data source by the specified amount.
|
||||
* This is used for scrolling the visualization.
|
||||
*/
|
||||
_drawBlockText: function (block, rect, verticalOffset, dataOffset, dataScale) {
|
||||
_drawBlockText: function (block, rect, verticalOffset, dataOffset,
|
||||
dataScale) {
|
||||
let ctx = this._ctx;
|
||||
let scaledOffset = dataOffset * dataScale;
|
||||
|
||||
let { x, y, width, height, text } = block;
|
||||
let { text } = block;
|
||||
let { rectLeft, rectTop, rectWidth, rectHeight } = rect;
|
||||
|
||||
let paddingTop = FLAME_GRAPH_BLOCK_TEXT_PADDING_TOP * this._pixelRatio;
|
||||
|
@ -849,8 +878,10 @@ FlameGraph.prototype = {
|
|||
*/
|
||||
_calcAverageCharWidth: function () {
|
||||
let letterWidthsSum = 0;
|
||||
let start = 32; // space
|
||||
let end = 123; // "z"
|
||||
// space
|
||||
let start = 32;
|
||||
// "z"
|
||||
let end = 123;
|
||||
|
||||
for (let i = start; i < end; i++) {
|
||||
let char = String.fromCharCode(i);
|
||||
|
@ -881,7 +912,8 @@ FlameGraph.prototype = {
|
|||
}
|
||||
for (let i = 1, len = text.length; i <= len; i++) {
|
||||
let trimmedText = text.substring(0, len - i);
|
||||
let trimmedWidth = this._getTextWidthApprox(trimmedText) + this._overflowCharWidth;
|
||||
let trimmedWidth = this._getTextWidthApprox(trimmedText)
|
||||
+ this._overflowCharWidth;
|
||||
if (trimmedWidth < maxWidth) {
|
||||
return trimmedText + this.overflowChar;
|
||||
}
|
||||
|
@ -929,7 +961,6 @@ FlameGraph.prototype = {
|
|||
let {mouseX, mouseY} = this._getRelativeEventCoordinates(e);
|
||||
|
||||
let canvasWidth = this._width;
|
||||
let canvasHeight = this._height;
|
||||
|
||||
let selection = this._selection;
|
||||
let selectionWidth = selection.end - selection.start;
|
||||
|
@ -955,17 +986,22 @@ FlameGraph.prototype = {
|
|||
}
|
||||
|
||||
if (horizDrag.origin != null && this._horizontalDragEnabled) {
|
||||
let relativeX = mouseX + this._horizontalDragDirection * this.horizontalPanThreshold;
|
||||
selection.start = horizDrag.anchor.start + (horizDrag.origin - relativeX) / selectionScale;
|
||||
selection.end = horizDrag.anchor.end + (horizDrag.origin - relativeX) / selectionScale;
|
||||
let relativeX = mouseX + this._horizontalDragDirection *
|
||||
this.horizontalPanThreshold;
|
||||
selection.start = horizDrag.anchor.start +
|
||||
(horizDrag.origin - relativeX) / selectionScale;
|
||||
selection.end = horizDrag.anchor.end +
|
||||
(horizDrag.origin - relativeX) / selectionScale;
|
||||
this._normalizeSelectionBounds();
|
||||
this._shouldRedraw = true;
|
||||
this.emit("selecting");
|
||||
}
|
||||
|
||||
if (vertDrag.origin != null && this._verticalDragEnabled) {
|
||||
let relativeY = mouseY + this._verticalDragDirection * this.verticalPanThreshold;
|
||||
this._verticalOffset = vertDrag.anchor + (vertDrag.origin - relativeY) / this._pixelRatio;
|
||||
let relativeY = mouseY +
|
||||
this._verticalDragDirection * this.verticalPanThreshold;
|
||||
this._verticalOffset = vertDrag.anchor +
|
||||
(vertDrag.origin - relativeY) / this._pixelRatio;
|
||||
this._normalizeVerticalOffset();
|
||||
this._shouldRedraw = true;
|
||||
this.emit("panning-vertically");
|
||||
|
@ -1011,7 +1047,6 @@ FlameGraph.prototype = {
|
|||
let {mouseX} = this._getRelativeEventCoordinates(e);
|
||||
|
||||
let canvasWidth = this._width;
|
||||
let canvasHeight = this._height;
|
||||
|
||||
let selection = this._selection;
|
||||
let selectionWidth = selection.end - selection.start;
|
||||
|
@ -1226,7 +1261,8 @@ var FlameGraphUtils = {
|
|||
// Take the timestamp of the first sample as prevTime. 0 is incorrect due
|
||||
// to circular buffer wraparound. If wraparound happens, then the first
|
||||
// sample will have an incorrect, large duration.
|
||||
let prevTime = samplesData.length > 0 ? samplesData[0][SAMPLE_TIME_SLOT] : 0;
|
||||
let prevTime = samplesData.length > 0 ? samplesData[0][SAMPLE_TIME_SLOT]
|
||||
: 0;
|
||||
let prevFrames = [];
|
||||
let sampleFrames = [];
|
||||
let sampleFrameKeys = [];
|
||||
|
@ -1263,8 +1299,9 @@ var FlameGraphUtils = {
|
|||
stackIndex = stackEntry[STACK_PREFIX_SLOT];
|
||||
|
||||
// Inflate the frame.
|
||||
let inflatedFrame = getOrAddInflatedFrame(inflatedFrameCache, frameIndex,
|
||||
frameTable, stringTable);
|
||||
let inflatedFrame = getOrAddInflatedFrame(inflatedFrameCache,
|
||||
frameIndex, frameTable,
|
||||
stringTable);
|
||||
|
||||
mutableFrameKeyOptions.isRoot = stackIndex === null;
|
||||
mutableFrameKeyOptions.isLeaf = stackDepth === 0;
|
||||
|
@ -1317,10 +1354,9 @@ var FlameGraphUtils = {
|
|||
// If there is a block already created, change its width.
|
||||
if (prevFrame && prevFrame.frameKey === key) {
|
||||
prevFrame.width = (time - prevFrame.startTime);
|
||||
}
|
||||
// Otherwise, create a new block for this frame at this depth,
|
||||
// using a simple location based salt for picking a color.
|
||||
else {
|
||||
} else {
|
||||
// Otherwise, create a new block for this frame at this depth,
|
||||
// using a simple location based salt for picking a color.
|
||||
let hash = this._getStringHash(key);
|
||||
let bucket = buckets[hash % PALLETTE_SIZE];
|
||||
|
||||
|
@ -1330,7 +1366,8 @@ var FlameGraphUtils = {
|
|||
} else {
|
||||
label = labelCache[key];
|
||||
if (!label) {
|
||||
label = labelCache[key] = this._formatLabel(key, sampleFrames[frameIndex]);
|
||||
label = labelCache[key] =
|
||||
this._formatLabel(key, sampleFrames[frameIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1404,8 +1441,10 @@ var FlameGraphUtils = {
|
|||
* @return string
|
||||
*/
|
||||
_formatLabel: function (key, frame) {
|
||||
let { functionName, fileName, line } = FrameUtils.parseLocation(key, frame.line);
|
||||
let label = FrameUtils.shouldDemangle(functionName) ? demangle(functionName) : functionName;
|
||||
let { functionName, fileName, line } =
|
||||
FrameUtils.parseLocation(key, frame.line);
|
||||
let label = FrameUtils.shouldDemangle(functionName) ? demangle(functionName)
|
||||
: functionName;
|
||||
|
||||
if (fileName) {
|
||||
label += ` (${fileName}${line != null ? (":" + line) : ""})`;
|
||||
|
|
|
@ -3,10 +3,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu, Cr } = require("chrome");
|
||||
|
||||
const { Task } = require("devtools/shared/task");
|
||||
const { Heritage, setNamedTimeout, clearNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
|
||||
const { setNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
|
||||
const { getCurrentZoom } = require("devtools/shared/layout/utils");
|
||||
|
||||
loader.lazyRequireGetter(this, "promise");
|
||||
|
@ -23,23 +21,28 @@ const WORKER_URL =
|
|||
|
||||
// Generic constants.
|
||||
|
||||
const GRAPH_RESIZE_EVENTS_DRAIN = 100; // ms
|
||||
// ms
|
||||
const GRAPH_RESIZE_EVENTS_DRAIN = 100;
|
||||
const GRAPH_WHEEL_ZOOM_SENSITIVITY = 0.00075;
|
||||
const GRAPH_WHEEL_SCROLL_SENSITIVITY = 0.1;
|
||||
const GRAPH_WHEEL_MIN_SELECTION_WIDTH = 10; // px
|
||||
// px
|
||||
const GRAPH_WHEEL_MIN_SELECTION_WIDTH = 10;
|
||||
|
||||
const GRAPH_SELECTION_BOUNDARY_HOVER_LINE_WIDTH = 4; // px
|
||||
const GRAPH_SELECTION_BOUNDARY_HOVER_THRESHOLD = 10; // px
|
||||
// px
|
||||
const GRAPH_SELECTION_BOUNDARY_HOVER_LINE_WIDTH = 4;
|
||||
const GRAPH_SELECTION_BOUNDARY_HOVER_THRESHOLD = 10;
|
||||
const GRAPH_MAX_SELECTION_LEFT_PADDING = 1;
|
||||
const GRAPH_MAX_SELECTION_RIGHT_PADDING = 1;
|
||||
|
||||
const GRAPH_REGION_LINE_WIDTH = 1; // px
|
||||
// px
|
||||
const GRAPH_REGION_LINE_WIDTH = 1;
|
||||
const GRAPH_REGION_LINE_COLOR = "rgba(237,38,85,0.8)";
|
||||
|
||||
const GRAPH_STRIPE_PATTERN_WIDTH = 16; // px
|
||||
const GRAPH_STRIPE_PATTERN_HEIGHT = 16; // px
|
||||
const GRAPH_STRIPE_PATTERN_LINE_WIDTH = 2; // px
|
||||
const GRAPH_STRIPE_PATTERN_LINE_SPACING = 4; // px
|
||||
// px
|
||||
const GRAPH_STRIPE_PATTERN_WIDTH = 16;
|
||||
const GRAPH_STRIPE_PATTERN_HEIGHT = 16;
|
||||
const GRAPH_STRIPE_PATTERN_LINE_WIDTH = 2;
|
||||
const GRAPH_STRIPE_PATTERN_LINE_SPACING = 4;
|
||||
|
||||
/**
|
||||
* Small data primitives for all graphs.
|
||||
|
@ -109,7 +112,8 @@ this.AbstractCanvasGraph = function (parent, name, sharpness) {
|
|||
this._document = iframe.contentDocument;
|
||||
this._pixelRatio = sharpness || this._window.devicePixelRatio;
|
||||
|
||||
let container = this._container = this._document.getElementById("graph-container");
|
||||
let container =
|
||||
this._container = this._document.getElementById("graph-container");
|
||||
container.className = name + "-widget-container graph-widget-container";
|
||||
|
||||
let canvas = this._canvas = this._document.getElementById("graph-canvas");
|
||||
|
@ -149,7 +153,8 @@ this.AbstractCanvasGraph = function (parent, name, sharpness) {
|
|||
let ownerWindow = this._parent.ownerDocument.defaultView;
|
||||
ownerWindow.addEventListener("resize", this._onResize);
|
||||
|
||||
this._animationId = this._window.requestAnimationFrame(this._onAnimationFrame);
|
||||
this._animationId =
|
||||
this._window.requestAnimationFrame(this._onAnimationFrame);
|
||||
|
||||
this._ready.resolve(this);
|
||||
this.emit("ready", this);
|
||||
|
@ -256,7 +261,8 @@ AbstractCanvasGraph.prototype = {
|
|||
* only when the data source changes.
|
||||
*/
|
||||
buildGraphImage: function () {
|
||||
throw "This method needs to be implemented by inheriting classes.";
|
||||
let error = "This method needs to be implemented by inheriting classes.";
|
||||
throw new Error(error);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -325,10 +331,11 @@ AbstractCanvasGraph.prototype = {
|
|||
*/
|
||||
setRegions: function (regions) {
|
||||
if (!this._cachedGraphImage) {
|
||||
throw "Can't highlight regions on a graph with no data displayed.";
|
||||
throw new Error("Can't highlight regions on a graph with " +
|
||||
"no data displayed.");
|
||||
}
|
||||
if (this._regions) {
|
||||
throw "Regions were already highlighted on the graph.";
|
||||
throw new Error("Regions were already highlighted on the graph.");
|
||||
}
|
||||
this._regions = regions.map(e => ({
|
||||
start: e.start * this.dataScaleX,
|
||||
|
@ -376,7 +383,7 @@ AbstractCanvasGraph.prototype = {
|
|||
*/
|
||||
setSelection: function (selection) {
|
||||
if (!selection || selection.start == null || selection.end == null) {
|
||||
throw "Invalid selection coordinates";
|
||||
throw new Error("Invalid selection coordinates");
|
||||
}
|
||||
if (!this.isSelectionDifferent(selection)) {
|
||||
return;
|
||||
|
@ -416,10 +423,11 @@ AbstractCanvasGraph.prototype = {
|
|||
*/
|
||||
setMappedSelection: function (selection, mapping = {}) {
|
||||
if (!this.hasData()) {
|
||||
throw "A data source is necessary for retrieving a mapped selection.";
|
||||
throw new Error("A data source is necessary for retrieving " +
|
||||
"a mapped selection.");
|
||||
}
|
||||
if (!selection || selection.start == null || selection.end == null) {
|
||||
throw "Invalid selection coordinates";
|
||||
throw new Error("Invalid selection coordinates");
|
||||
}
|
||||
|
||||
let { mapStart, mapEnd } = mapping;
|
||||
|
@ -448,7 +456,8 @@ AbstractCanvasGraph.prototype = {
|
|||
*/
|
||||
getMappedSelection: function (mapping = {}) {
|
||||
if (!this.hasData()) {
|
||||
throw "A data source is necessary for retrieving a mapped selection.";
|
||||
throw new Error("A data source is necessary for retrieving a " +
|
||||
"mapped selection.");
|
||||
}
|
||||
if (!this.hasSelection() && !this.hasSelectionInProgress()) {
|
||||
return { min: null, max: null };
|
||||
|
@ -517,7 +526,7 @@ AbstractCanvasGraph.prototype = {
|
|||
*/
|
||||
setCursor: function (cursor) {
|
||||
if (!cursor || cursor.x == null || cursor.y == null) {
|
||||
throw "Invalid cursor coordinates";
|
||||
throw new Error("Invalid cursor coordinates");
|
||||
}
|
||||
if (!this.isCursorDifferent(cursor)) {
|
||||
return;
|
||||
|
@ -565,7 +574,9 @@ AbstractCanvasGraph.prototype = {
|
|||
* The other graph's selection, as { start, end } values.
|
||||
*/
|
||||
isSelectionDifferent: function (other) {
|
||||
if (!other) return true;
|
||||
if (!other) {
|
||||
return true;
|
||||
}
|
||||
let current = this.getSelection();
|
||||
return current.start != other.start || current.end != other.end;
|
||||
},
|
||||
|
@ -577,7 +588,9 @@ AbstractCanvasGraph.prototype = {
|
|||
* The other graph's position, as { x, y } values.
|
||||
*/
|
||||
isCursorDifferent: function (other) {
|
||||
if (!other) return true;
|
||||
if (!other) {
|
||||
return true;
|
||||
}
|
||||
let current = this.getCursor();
|
||||
return current.x != other.x || current.y != other.y;
|
||||
},
|
||||
|
@ -703,7 +716,8 @@ AbstractCanvasGraph.prototype = {
|
|||
* Animation frame callback, invoked on each tick of the refresh driver.
|
||||
*/
|
||||
_onAnimationFrame: function () {
|
||||
this._animationId = this._window.requestAnimationFrame(this._onAnimationFrame);
|
||||
this._animationId =
|
||||
this._window.requestAnimationFrame(this._onAnimationFrame);
|
||||
this._drawWidget();
|
||||
},
|
||||
|
||||
|
@ -727,7 +741,8 @@ AbstractCanvasGraph.prototype = {
|
|||
}
|
||||
if (this._cachedBackgroundImage) {
|
||||
ctx.globalCompositeOperation = "destination-over";
|
||||
ctx.drawImage(this._cachedBackgroundImage, 0, 0, this._width, this._height);
|
||||
ctx.drawImage(this._cachedBackgroundImage, 0, 0,
|
||||
this._width, this._height);
|
||||
}
|
||||
|
||||
// Revert to the original global composition operation.
|
||||
|
@ -749,7 +764,8 @@ AbstractCanvasGraph.prototype = {
|
|||
* Draws the cliphead, if available and necessary.
|
||||
*/
|
||||
_drawCliphead: function () {
|
||||
if (this._isHoveringSelectionContentsOrBoundaries() || this._isHoveringRegion()) {
|
||||
if (this._isHoveringSelectionContentsOrBoundaries() ||
|
||||
this._isHoveringRegion()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -842,7 +858,7 @@ AbstractCanvasGraph.prototype = {
|
|||
*/
|
||||
_isHoveringStartBoundary: function () {
|
||||
if (!this.hasSelection() || !this.hasCursor()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
let { x } = this._cursor;
|
||||
let { start } = this._selection;
|
||||
|
@ -856,7 +872,7 @@ AbstractCanvasGraph.prototype = {
|
|||
*/
|
||||
_isHoveringEndBoundary: function () {
|
||||
if (!this.hasSelection() || !this.hasCursor()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
let { x } = this._cursor;
|
||||
let { end } = this._selection;
|
||||
|
@ -870,7 +886,7 @@ AbstractCanvasGraph.prototype = {
|
|||
*/
|
||||
_isHoveringSelectionContents: function () {
|
||||
if (!this.hasSelection() || !this.hasCursor()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
let { x } = this._cursor;
|
||||
let { start, end } = this._selection;
|
||||
|
@ -938,7 +954,7 @@ AbstractCanvasGraph.prototype = {
|
|||
let maxX = bb.p2.x - bb.p1.x;
|
||||
let maxY = bb.p3.y - bb.p1.y;
|
||||
let mouseX = Math.max(0, Math.min(x, maxX)) * this._pixelRatio;
|
||||
let mouseY = Math.max(0, Math.min(x, maxY)) * this._pixelRatio;
|
||||
let mouseY = Math.max(0, Math.min(y, maxY)) * this._pixelRatio;
|
||||
|
||||
// The coordinates need to be modified with the current zoom level
|
||||
// to prevent them from being wrong.
|
||||
|
@ -969,7 +985,8 @@ AbstractCanvasGraph.prototype = {
|
|||
if (e.buttons == 0 && (this.hasSelectionInProgress() ||
|
||||
resizer.margin != null ||
|
||||
dragger.origin != null)) {
|
||||
return this._onMouseUp();
|
||||
this._onMouseUp();
|
||||
return;
|
||||
}
|
||||
|
||||
let {mouseX, mouseY} = this._getRelativeEventCoordinates(e);
|
||||
|
@ -1137,9 +1154,8 @@ AbstractCanvasGraph.prototype = {
|
|||
vector = e.detail * GRAPH_WHEEL_ZOOM_SENSITIVITY;
|
||||
selection.start = selection.start + distStart * vector;
|
||||
selection.end = selection.end + distEnd * vector;
|
||||
}
|
||||
// Otherwise, simply pan the selection towards the left or right.
|
||||
else {
|
||||
} else {
|
||||
// Otherwise, simply pan the selection towards the left or right.
|
||||
let direction = 0;
|
||||
if (focusX > selection.end) {
|
||||
direction = Math.sign(focusX - selection.end);
|
||||
|
@ -1389,8 +1405,12 @@ function map(value, istart, istop, ostart, ostop) {
|
|||
* @return number
|
||||
*/
|
||||
function clamp(value, min, max) {
|
||||
if (value < min) return min;
|
||||
if (value > max) return max;
|
||||
if (value < min) {
|
||||
return min;
|
||||
}
|
||||
if (value > max) {
|
||||
return max;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
/* eslint-env worker */
|
||||
|
||||
/**
|
||||
* Import `createTask` to communicate with `devtools/shared/worker`.
|
||||
*/
|
||||
|
@ -16,14 +18,14 @@ const { createTask } = require("resource://devtools/shared/worker/helper.js");
|
|||
* @param number interval
|
||||
* @param number duration
|
||||
*/
|
||||
createTask(self, "plotTimestampsGraph", function ({ timestamps, interval, duration }) {
|
||||
createTask(self, "plotTimestampsGraph", function ({ timestamps,
|
||||
interval, duration }) {
|
||||
let plottedData = plotTimestamps(timestamps, interval);
|
||||
let plottedMinMaxSum = getMinMaxAvg(plottedData, timestamps, duration);
|
||||
|
||||
return { plottedData, plottedMinMaxSum };
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Gets the min, max and average of the values in an array.
|
||||
* @param array source
|
||||
|
@ -32,14 +34,13 @@ createTask(self, "plotTimestampsGraph", function ({ timestamps, interval, durati
|
|||
* @return object
|
||||
*/
|
||||
function getMinMaxAvg(source, timestamps, duration) {
|
||||
let totalTicks = source.length;
|
||||
let totalFrames = timestamps.length;
|
||||
let maxValue = Number.MIN_SAFE_INTEGER;
|
||||
let minValue = Number.MAX_SAFE_INTEGER;
|
||||
// Calculate the average by counting how many frames occurred
|
||||
// in the duration of the recording, rather than average the frame points
|
||||
// we have, as that weights higher FPS, as there'll be more timestamps for those
|
||||
// values
|
||||
// we have, as that weights higher FPS, as there'll be more timestamps for
|
||||
// those values
|
||||
let avgValue = totalFrames / (duration / 1000);
|
||||
|
||||
for (let { value } of source) {
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu, Cr } = require("chrome");
|
||||
|
||||
const { Task } = require("devtools/shared/task");
|
||||
const { ViewHelpers, Heritage } = require("devtools/client/shared/widgets/view-helpers");
|
||||
const { Heritage } = require("devtools/client/shared/widgets/view-helpers");
|
||||
const { AbstractCanvasGraph, CanvasGraphUtils } = require("devtools/client/shared/widgets/Graphs");
|
||||
const { LocalizationHelper } = require("devtools/client/shared/l10n");
|
||||
|
||||
|
@ -13,14 +11,17 @@ const L10N = new LocalizationHelper("chrome://devtools/locale/graphs.properties"
|
|||
// Line graph constants.
|
||||
|
||||
const GRAPH_DAMPEN_VALUES_FACTOR = 0.85;
|
||||
const GRAPH_TOOLTIP_SAFE_BOUNDS = 8; // px
|
||||
const GRAPH_MIN_MAX_TOOLTIP_DISTANCE = 14; // px
|
||||
// px
|
||||
const GRAPH_TOOLTIP_SAFE_BOUNDS = 8;
|
||||
const GRAPH_MIN_MAX_TOOLTIP_DISTANCE = 14;
|
||||
|
||||
const GRAPH_BACKGROUND_COLOR = "#0088cc";
|
||||
const GRAPH_STROKE_WIDTH = 1; // px
|
||||
// px
|
||||
const GRAPH_STROKE_WIDTH = 1;
|
||||
const GRAPH_STROKE_COLOR = "rgba(255,255,255,0.9)";
|
||||
const GRAPH_HELPER_LINES_DASH = [5]; // px
|
||||
const GRAPH_HELPER_LINES_WIDTH = 1; // px
|
||||
// px
|
||||
const GRAPH_HELPER_LINES_DASH = [5];
|
||||
const GRAPH_HELPER_LINES_WIDTH = 1;
|
||||
const GRAPH_MAXIMUM_LINE_COLOR = "rgba(255,255,255,0.4)";
|
||||
const GRAPH_AVERAGE_LINE_COLOR = "rgba(255,255,255,0.7)";
|
||||
const GRAPH_MINIMUM_LINE_COLOR = "rgba(255,255,255,0.9)";
|
||||
|
@ -58,10 +59,10 @@ const GRAPH_REGION_STRIPES_COLOR = "rgba(237,38,85,0.2)";
|
|||
* @param nsIDOMNode parent
|
||||
* The parent node holding the graph.
|
||||
* @param object options [optional]
|
||||
* `metric`: The metric displayed in the graph, e.g. "fps" or "bananas".
|
||||
* `min`: Boolean whether to show the min tooltip/gutter/line (default: true)
|
||||
* `max`: Boolean whether to show the max tooltip/gutter/line (default: true)
|
||||
* `avg`: Boolean whether to show the avg tooltip/gutter/line (default: true)
|
||||
* `metric`: The metric displayed in the graph, e.g. "fps" or "bananas".
|
||||
* `min`: Boolean whether to show the min tooltip/gutter/line (default: true)
|
||||
* `max`: Boolean whether to show the max tooltip/gutter/line (default: true)
|
||||
* `avg`: Boolean whether to show the avg tooltip/gutter/line (default: true)
|
||||
*/
|
||||
this.LineGraphWidget = function (parent, options = {}, ...args) {
|
||||
let { metric, min, max, avg } = options;
|
||||
|
@ -77,11 +78,17 @@ this.LineGraphWidget = function (parent, options = {}, ...args) {
|
|||
// are changed later
|
||||
this._gutter = this._createGutter();
|
||||
this._maxGutterLine = this._createGutterLine("maximum");
|
||||
this._maxTooltip = this._createTooltip("maximum", "start", L10N.getStr("graphs.label.maximum"), metric);
|
||||
this._maxTooltip = this._createTooltip(
|
||||
"maximum", "start", L10N.getStr("graphs.label.maximum"), metric
|
||||
);
|
||||
this._minGutterLine = this._createGutterLine("minimum");
|
||||
this._minTooltip = this._createTooltip("minimum", "start", L10N.getStr("graphs.label.minimum"), metric);
|
||||
this._minTooltip = this._createTooltip(
|
||||
"minimum", "start", L10N.getStr("graphs.label.minimum"), metric
|
||||
);
|
||||
this._avgGutterLine = this._createGutterLine("average");
|
||||
this._avgTooltip = this._createTooltip("average", "end", L10N.getStr("graphs.label.average"), metric);
|
||||
this._avgTooltip = this._createTooltip(
|
||||
"average", "end", L10N.getStr("graphs.label.average"), metric
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -176,7 +183,7 @@ LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
avgValue = this._tempMinMaxSum.avgValue;
|
||||
} else {
|
||||
let sumValues = 0;
|
||||
for (let { delta, value } of this._data) {
|
||||
for (let { value } of this._data) {
|
||||
maxValue = Math.max(value, maxValue);
|
||||
minValue = Math.min(value, minValue);
|
||||
sumValues += value;
|
||||
|
@ -186,7 +193,8 @@ LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
|
||||
let duration = this.dataDuration || lastTick;
|
||||
let dataScaleX = this.dataScaleX = width / (duration - this.dataOffsetX);
|
||||
let dataScaleY = this.dataScaleY = height / maxValue * this.dampenValuesFactor;
|
||||
let dataScaleY =
|
||||
this.dataScaleY = height / maxValue * this.dampenValuesFactor;
|
||||
|
||||
// Draw the background.
|
||||
|
||||
|
@ -289,9 +297,12 @@ LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
L10N.numberWithDecimals(minValue, 2);
|
||||
|
||||
let bottom = height / this._pixelRatio;
|
||||
let maxPosY = CanvasGraphUtils.map(maxValue * this.dampenValuesFactor, 0, maxValue, bottom, 0);
|
||||
let avgPosY = CanvasGraphUtils.map(avgValue * this.dampenValuesFactor, 0, maxValue, bottom, 0);
|
||||
let minPosY = CanvasGraphUtils.map(minValue * this.dampenValuesFactor, 0, maxValue, bottom, 0);
|
||||
let maxPosY = CanvasGraphUtils.map(maxValue * this.dampenValuesFactor, 0,
|
||||
maxValue, bottom, 0);
|
||||
let avgPosY = CanvasGraphUtils.map(avgValue * this.dampenValuesFactor, 0,
|
||||
maxValue, bottom, 0);
|
||||
let minPosY = CanvasGraphUtils.map(minValue * this.dampenValuesFactor, 0,
|
||||
maxValue, bottom, 0);
|
||||
|
||||
let safeTop = GRAPH_TOOLTIP_SAFE_BOUNDS;
|
||||
let safeBottom = bottom - GRAPH_TOOLTIP_SAFE_BOUNDS;
|
||||
|
@ -316,10 +327,14 @@ LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
this._minTooltip.setAttribute("with-arrows", this.withTooltipArrows);
|
||||
|
||||
let distanceMinMax = Math.abs(maxTooltipTop - minTooltipTop);
|
||||
this._maxTooltip.hidden = this._showMax === false || !totalTicks || distanceMinMax < GRAPH_MIN_MAX_TOOLTIP_DISTANCE;
|
||||
this._maxTooltip.hidden = this._showMax === false
|
||||
|| !totalTicks
|
||||
|| distanceMinMax < GRAPH_MIN_MAX_TOOLTIP_DISTANCE;
|
||||
this._avgTooltip.hidden = this._showAvg === false || !totalTicks;
|
||||
this._minTooltip.hidden = this._showMin === false || !totalTicks;
|
||||
this._gutter.hidden = (this._showMin === false && this._showAvg === false && this._showMax === false) || !totalTicks;
|
||||
this._gutter.hidden = (this._showMin === false &&
|
||||
this._showAvg === false &&
|
||||
this._showMax === false) || !totalTicks;
|
||||
|
||||
this._maxGutterLine.hidden = this._showMax === false;
|
||||
this._avgGutterLine.hidden = this._showAvg === false;
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {Cc, Cu, Ci} = require("chrome");
|
||||
const Services = require("Services");
|
||||
const Promise = require("promise");
|
||||
const {getCSSLexer} = require("devtools/shared/css-lexer");
|
||||
|
@ -37,7 +36,8 @@ var XHR_CSS_URL = "https://developer.mozilla.org/en-US/docs/Web/CSS/";
|
|||
|
||||
// Parameters for the link to MDN in the tooltip, so
|
||||
// so we know which MDN visits come from this feature
|
||||
const PAGE_LINK_PARAMS = "?utm_source=mozilla&utm_medium=firefox-inspector&utm_campaign=default";
|
||||
const PAGE_LINK_PARAMS =
|
||||
"?utm_source=mozilla&utm_medium=firefox-inspector&utm_campaign=default";
|
||||
// URL for the page link omits locale, so a locale-specific page will be loaded
|
||||
var PAGE_LINK_URL = "https://developer.mozilla.org/docs/Web/CSS/";
|
||||
exports.PAGE_LINK_URL = PAGE_LINK_URL;
|
||||
|
@ -104,11 +104,8 @@ function appendSyntaxHighlightedCSS(cssText, parentElement) {
|
|||
function updateIdentClass(tokenText) {
|
||||
if (tokenText === ":") {
|
||||
identClass = PROPERTY_VALUE_COLOR;
|
||||
}
|
||||
else {
|
||||
if (tokenText === ";") {
|
||||
identClass = PROPERTY_NAME_COLOR;
|
||||
}
|
||||
} else if (tokenText === ";") {
|
||||
identClass = PROPERTY_NAME_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,8 +169,7 @@ function getMdnPage(pageUrl) {
|
|||
function onLoaded(e) {
|
||||
if (xhr.status != 200) {
|
||||
deferred.reject({page: pageUrl, status: xhr.status});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
deferred.resolve(xhr.responseXML);
|
||||
}
|
||||
}
|
||||
|
@ -202,7 +198,6 @@ function getMdnPage(pageUrl) {
|
|||
* we could not load the page.
|
||||
*/
|
||||
function getCssDocs(cssProperty) {
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let pageUrl = XHR_CSS_URL + cssProperty + XHR_PARAMS;
|
||||
|
||||
|
@ -214,8 +209,7 @@ function getCssDocs(cssProperty) {
|
|||
theDocs.syntax = getSyntax(responseDocument);
|
||||
if (theDocs.summary || theDocs.syntax) {
|
||||
deferred.resolve(theDocs);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
deferred.reject("Couldn't find the docs in the page.");
|
||||
}
|
||||
}
|
||||
|
@ -246,7 +240,6 @@ exports.getCssDocs = getCssDocs;
|
|||
* structure.
|
||||
*/
|
||||
function MdnDocsWidget(tooltipDocument) {
|
||||
|
||||
// fetch all the bits of the document that we will manipulate later
|
||||
this.elements = {
|
||||
heading: tooltipDocument.getElementById("property-name"),
|
||||
|
@ -296,20 +289,18 @@ MdnDocsWidget.prototype = {
|
|||
* The name of the CSS property for which we need to display help.
|
||||
*/
|
||||
loadCssDocs: function (propertyName) {
|
||||
|
||||
/**
|
||||
* Do all the setup we can do synchronously, and get the document in
|
||||
* a state where it can be displayed while we are waiting for the
|
||||
* MDN docs content to be retrieved.
|
||||
*/
|
||||
function initializeDocument(propertyName) {
|
||||
|
||||
function initializeDocument(propName) {
|
||||
// set property name heading
|
||||
elements.heading.textContent = propertyName;
|
||||
elements.heading.textContent = propName;
|
||||
|
||||
// set link target
|
||||
elements.linkToMdn.setAttribute("href",
|
||||
PAGE_LINK_URL + propertyName + PAGE_LINK_PARAMS);
|
||||
PAGE_LINK_URL + propName + PAGE_LINK_PARAMS);
|
||||
|
||||
// clear docs summary and syntax
|
||||
elements.summary.textContent = "";
|
||||
|
@ -346,7 +337,8 @@ MdnDocsWidget.prototype = {
|
|||
*/
|
||||
function gotError(error) {
|
||||
// show error message
|
||||
elements.summary.textContent = l10n.strings.GetStringFromName("docsTooltip.loadDocsError");
|
||||
elements.summary.textContent =
|
||||
l10n.strings.GetStringFromName("docsTooltip.loadDocsError");
|
||||
|
||||
// hide the throbber
|
||||
elements.info.classList.remove("devtools-throbber");
|
||||
|
@ -358,7 +350,6 @@ MdnDocsWidget.prototype = {
|
|||
|
||||
let deferred = Promise.defer();
|
||||
let elements = this.elements;
|
||||
let doc = this.doc;
|
||||
|
||||
initializeDocument(propertyName);
|
||||
getCssDocs(propertyName).then(finalizeDocument, gotError);
|
||||
|
@ -402,8 +393,9 @@ function isAllWhitespace(node) {
|
|||
* True if the node is a comment node or is all whitespace, otherwise false.
|
||||
*/
|
||||
function isIgnorable(node) {
|
||||
return (node.nodeType == 8) || // A comment node
|
||||
((node.nodeType == 3) && isAllWhitespace(node)); // text node, all ws
|
||||
// Comment nodes (8), text nodes (3) or whitespace
|
||||
return (node.nodeType == 8) ||
|
||||
((node.nodeType == 3) && isAllWhitespace(node));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -415,7 +407,9 @@ function isIgnorable(node) {
|
|||
*/
|
||||
function nodeAfter(sib) {
|
||||
while ((sib = sib.nextSibling)) {
|
||||
if (!isIgnorable(sib)) return sib;
|
||||
if (!isIgnorable(sib)) {
|
||||
return sib;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -487,7 +481,6 @@ function getSummary(mdnDocument) {
|
|||
* The syntax section as a string, or null if it could not be found.
|
||||
*/
|
||||
function getSyntax(mdnDocument) {
|
||||
|
||||
let syntax = mdnDocument.getElementById("Syntax");
|
||||
if (!hasTagName(syntax, "H2")) {
|
||||
return null;
|
||||
|
@ -502,9 +495,7 @@ function getSyntax(mdnDocument) {
|
|||
if (hasTagName(secondParagraph, "PRE")) {
|
||||
return secondParagraph.textContent;
|
||||
}
|
||||
else {
|
||||
return firstParagraph.textContent;
|
||||
}
|
||||
return firstParagraph.textContent;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu, Cr } = require("chrome");
|
||||
|
||||
const { Heritage } = require("devtools/client/shared/widgets/view-helpers");
|
||||
const { AbstractCanvasGraph, CanvasGraphUtils } = require("devtools/client/shared/widgets/Graphs");
|
||||
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const { AbstractCanvasGraph } = require("devtools/client/shared/widgets/Graphs");
|
||||
|
||||
// Bar graph constants.
|
||||
|
||||
const GRAPH_DAMPEN_VALUES_FACTOR = 0.9;
|
||||
|
||||
const GRAPH_BACKGROUND_COLOR = "#ddd";
|
||||
const GRAPH_STROKE_WIDTH = 1; // px
|
||||
// px
|
||||
const GRAPH_STROKE_WIDTH = 1;
|
||||
const GRAPH_STROKE_COLOR = "rgba(255,255,255,0.9)";
|
||||
const GRAPH_HELPER_LINES_DASH = [5]; // px
|
||||
const GRAPH_HELPER_LINES_WIDTH = 1; // px
|
||||
// px
|
||||
const GRAPH_HELPER_LINES_DASH = [5];
|
||||
const GRAPH_HELPER_LINES_WIDTH = 1;
|
||||
|
||||
const GRAPH_CLIPHEAD_LINE_COLOR = "#fff";
|
||||
const GRAPH_SELECTION_LINE_COLOR = "#fff";
|
||||
|
@ -117,7 +115,8 @@ MountainGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
|
|||
*/
|
||||
buildGraphImage: function () {
|
||||
if (!this.format || !this.format.length) {
|
||||
throw "The graph format traits are mandatory to style the data source.";
|
||||
throw new Error("The graph format traits are mandatory to style " +
|
||||
"the data source.");
|
||||
}
|
||||
let { canvas, ctx } = this._getNamedCanvas("mountain-graph-data");
|
||||
let width = this._width;
|
||||
|
|
|
@ -166,7 +166,8 @@ Spectrum.draggable = function (element, onmove, onstart, onstop) {
|
|||
if (dragging) {
|
||||
if (e.buttons === 0) {
|
||||
// The button is no longer pressed but we did not get a mouseup event.
|
||||
return stop();
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
let pageX = e.pageX;
|
||||
let pageY = e.pageY;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const {Ci, Cu} = require("chrome");
|
||||
const {Ci} = require("chrome");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
loader.lazyRequireGetter(this, "setNamedTimeout",
|
||||
"devtools/client/shared/widgets/view-helpers", true);
|
||||
|
|
|
@ -493,7 +493,9 @@ Tooltip.prototype = {
|
|||
// Analyzing state history isn't useful with transient object inspectors.
|
||||
widget.commitHierarchy = () => {};
|
||||
|
||||
for (let e in relayEvents) widget.on(e, relayEvents[e]);
|
||||
for (let e in relayEvents) {
|
||||
widget.on(e, relayEvents[e]);
|
||||
}
|
||||
VariablesViewController.attach(widget, controllerOptions);
|
||||
|
||||
// Some of the view options are allowed to change between uses.
|
||||
|
@ -517,7 +519,7 @@ Tooltip.prototype = {
|
|||
* resolves when the broken image tooltip content is ready, but never rejects.
|
||||
*/
|
||||
setRelativeImageContent: Task.async(function* (imageUrl, inspectorFront,
|
||||
maxDim) {
|
||||
maxDim) {
|
||||
if (imageUrl.startsWith("data:")) {
|
||||
// If the imageUrl already is a data-url, save ourselves a round-trip
|
||||
this.setImageContent(imageUrl, {maxDim: maxDim});
|
||||
|
@ -539,7 +541,9 @@ Tooltip.prototype = {
|
|||
*/
|
||||
setBrokenImageContent: function () {
|
||||
this.setTextContent({
|
||||
messages: [l10n.strings.GetStringFromName("previewTooltip.image.brokenImage")]
|
||||
messages: [
|
||||
l10n.strings.GetStringFromName("previewTooltip.image.brokenImage")
|
||||
]
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -738,7 +742,6 @@ Tooltip.prototype = {
|
|||
|
||||
function onLoaded(iframe) {
|
||||
let win = iframe.contentWindow.wrappedJSObject;
|
||||
let doc = win.document.documentElement;
|
||||
let def = promise.defer();
|
||||
let container = win.document.getElementById("container");
|
||||
let widget = new CSSFilterEditorWidget(container, filter);
|
||||
|
@ -1008,7 +1011,8 @@ function SwatchColorPickerTooltip(doc) {
|
|||
|
||||
module.exports.SwatchColorPickerTooltip = SwatchColorPickerTooltip;
|
||||
|
||||
SwatchColorPickerTooltip.prototype = Heritage.extend(SwatchBasedEditorTooltip.prototype, {
|
||||
SwatchColorPickerTooltip.prototype =
|
||||
Heritage.extend(SwatchBasedEditorTooltip.prototype, {
|
||||
/**
|
||||
* Overriding the SwatchBasedEditorTooltip.show function to set spectrum's
|
||||
* color.
|
||||
|
@ -1287,8 +1291,9 @@ EventTooltip.prototype = {
|
|||
iframe.setAttribute("style", "width:100%;");
|
||||
|
||||
editor.appendTo(content, iframe).then(() => {
|
||||
/* eslint-disable camelcase */
|
||||
let tidied = beautify.js(handler, { indent_size: 2 });
|
||||
|
||||
/* eslint-enable */
|
||||
editor.setText(tidied);
|
||||
|
||||
eventEditors.appended = true;
|
||||
|
@ -1335,7 +1340,9 @@ EventTooltip.prototype = {
|
|||
);
|
||||
if (item) {
|
||||
let actor = item.attachment.source.actor;
|
||||
DebuggerView.setEditorLocation(actor, line, {noDebug: true}).then(() => {
|
||||
DebuggerView.setEditorLocation(
|
||||
actor, line, {noDebug: true}
|
||||
).then(() => {
|
||||
if (dom0) {
|
||||
let text = DebuggerView.editor.getText();
|
||||
let index = text.indexOf(searchString);
|
||||
|
@ -1420,7 +1427,8 @@ function SwatchCubicBezierTooltip(doc) {
|
|||
|
||||
module.exports.SwatchCubicBezierTooltip = SwatchCubicBezierTooltip;
|
||||
|
||||
SwatchCubicBezierTooltip.prototype = Heritage.extend(SwatchBasedEditorTooltip.prototype, {
|
||||
SwatchCubicBezierTooltip.prototype =
|
||||
Heritage.extend(SwatchBasedEditorTooltip.prototype, {
|
||||
/**
|
||||
* Overriding the SwatchBasedEditorTooltip.show function to set the cubic
|
||||
* bezier curve in the widget
|
||||
|
@ -1517,7 +1525,8 @@ function SwatchFilterTooltip(doc) {
|
|||
|
||||
exports.SwatchFilterTooltip = SwatchFilterTooltip;
|
||||
|
||||
SwatchFilterTooltip.prototype = Heritage.extend(SwatchBasedEditorTooltip.prototype, {
|
||||
SwatchFilterTooltip.prototype =
|
||||
Heritage.extend(SwatchBasedEditorTooltip.prototype, {
|
||||
show: function () {
|
||||
// Call the parent class' show function
|
||||
SwatchBasedEditorTooltip.prototype.show.call(this);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -3,11 +3,13 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Check that Dead Objects do not break the Web/Browser Consoles. See bug 883649.
|
||||
// Check that Dead Objects do not break the Web/Browser Consoles.
|
||||
// See bug 883649.
|
||||
// This test does:
|
||||
// - opens a new tab,
|
||||
// - opens the Browser Console,
|
||||
// - stores a reference to the content document of the tab on the chrome window object,
|
||||
// - stores a reference to the content document of the tab on the chrome
|
||||
// window object,
|
||||
// - closes the tab,
|
||||
// - tries to use the object that was pointing to the now-defunct content
|
||||
// document. This is the dead object.
|
||||
|
|
|
@ -53,7 +53,8 @@ add_task(function* () {
|
|||
|
||||
info("try ctrl-l to clear output");
|
||||
executeSoon(() => {
|
||||
let clearKey = hud.ui.window.document.querySelector("key[command=consoleCmd_clearOutput]:not([disabled])");
|
||||
let selector = "key[command=consoleCmd_clearOutput]:not([disabled])";
|
||||
let clearKey = hud.ui.window.document.querySelector(selector);
|
||||
synthesizeKeyFromKeyTag(clearKey);
|
||||
});
|
||||
yield hud.jsterm.once("messages-cleared");
|
||||
|
|
|
@ -39,7 +39,11 @@ function consoleOpened() {
|
|||
ok(hud, "Web Console opened");
|
||||
|
||||
hud.jsterm.clearOutput();
|
||||
content.console.log("foobarz1");
|
||||
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
|
||||
content.console.log("foobarz1");
|
||||
});
|
||||
|
||||
return waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
|
@ -51,7 +55,9 @@ function consoleOpened() {
|
|||
}
|
||||
|
||||
function onReload() {
|
||||
content.console.log("foobarz2");
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
|
||||
content.console.log("foobarz2");
|
||||
});
|
||||
|
||||
return waitForMessages({
|
||||
webconsole: hud,
|
||||
|
|
|
@ -38,7 +38,9 @@ function test() {
|
|||
ConsoleAPIStorage.clearEvents();
|
||||
|
||||
// Add a non-private message to the browser console.
|
||||
content.console.log("bug874061-not-private");
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
|
||||
content.console.log("bug874061-not-private");
|
||||
});
|
||||
|
||||
nonPrivateMessage = {
|
||||
name: "console message from a non-private window",
|
||||
|
@ -49,7 +51,7 @@ function test() {
|
|||
|
||||
privateWindow = OpenBrowserWindow({ private: true });
|
||||
ok(privateWindow, "new private window");
|
||||
ok(PrivateBrowsingUtils.isWindowPrivate(privateWindow), "window is private");
|
||||
ok(PrivateBrowsingUtils.isWindowPrivate(privateWindow), "window's private");
|
||||
|
||||
whenDelayedStartupFinished(privateWindow, onPrivateWindowReady);
|
||||
}
|
||||
|
@ -75,8 +77,8 @@ function test() {
|
|||
EventUtils.synthesizeMouse(button, 2, 2, {}, privateContent);
|
||||
}
|
||||
|
||||
function consoleOpened(aHud) {
|
||||
hud = aHud;
|
||||
function consoleOpened(injectedHud) {
|
||||
hud = injectedHud;
|
||||
ok(hud, "web console opened");
|
||||
|
||||
addMessages();
|
||||
|
@ -111,8 +113,8 @@ function test() {
|
|||
});
|
||||
}
|
||||
|
||||
function consoleReopened(aHud) {
|
||||
hud = aHud;
|
||||
function consoleReopened(injectedHud) {
|
||||
hud = injectedHud;
|
||||
ok(hud, "web console reopened");
|
||||
|
||||
// Make sure that cached messages are displayed in the web console, even
|
||||
|
@ -139,8 +141,8 @@ function test() {
|
|||
is(text.indexOf("bug 874061"), -1, "no console message displayed");
|
||||
}
|
||||
|
||||
function onBrowserConsoleOpen(aHud) {
|
||||
hud = aHud;
|
||||
function onBrowserConsoleOpen(injectedHud) {
|
||||
hud = injectedHud;
|
||||
ok(hud, "browser console opened");
|
||||
|
||||
checkNoPrivateMessages();
|
||||
|
@ -156,7 +158,7 @@ function test() {
|
|||
}
|
||||
|
||||
function testPrivateWindowClose() {
|
||||
info("close the private window and check if the private messages are removed");
|
||||
info("close the private window and check if private messages are removed");
|
||||
hud.jsterm.once("private-messages-cleared", () => {
|
||||
isnot(hud.outputNode.textContent.indexOf("bug874061-not-private"), -1,
|
||||
"non-private messages are still shown after private window closed");
|
||||
|
@ -172,8 +174,8 @@ function test() {
|
|||
privateWindow.BrowserTryToCloseWindow();
|
||||
}
|
||||
|
||||
function onBrowserConsoleReopen(aHud) {
|
||||
hud = aHud;
|
||||
function onBrowserConsoleReopen(injectedHud) {
|
||||
hud = injectedHud;
|
||||
ok(hud, "browser console reopened");
|
||||
|
||||
// Make sure that the non-private message is still shown after reopen.
|
||||
|
|
|
@ -35,21 +35,24 @@ add_task(function* () {
|
|||
let variablesView = view._variablesView;
|
||||
let searchbox = variablesView._searchboxNode;
|
||||
|
||||
assertAttrs(view, "foo,__proto__", "To start with, we just see the top level foo attr");
|
||||
assertAttrs(view, "foo,__proto__",
|
||||
"To start with, we just see the top level foo attr");
|
||||
|
||||
fetched = jsterm.once("variablesview-fetched");
|
||||
searchbox.value = "bar";
|
||||
searchbox.doCommand();
|
||||
view = yield fetched;
|
||||
|
||||
assertAttrs(view, "", "If we don't manually expand nested attr, we don't see them in search");
|
||||
assertAttrs(view, "",
|
||||
"If we don't manually expand nested attr, we don't see them");
|
||||
|
||||
fetched = jsterm.once("variablesview-fetched");
|
||||
searchbox.value = "";
|
||||
searchbox.doCommand();
|
||||
view = yield fetched;
|
||||
|
||||
assertAttrs(view, "foo", "If we reset the search, we get back to original state");
|
||||
assertAttrs(view, "foo",
|
||||
"If we reset the search, we get back to original state");
|
||||
|
||||
yield [...view][0][1].expand();
|
||||
|
||||
|
@ -72,5 +75,6 @@ add_task(function* () {
|
|||
searchbox.doCommand();
|
||||
view = yield fetched;
|
||||
|
||||
assertAttrs(view, "foo", "If we reset again, we get back to original state again");
|
||||
assertAttrs(view, "foo",
|
||||
"If we reset again, we get back to original state again");
|
||||
});
|
||||
|
|
|
@ -57,10 +57,12 @@ add_task(function* () {
|
|||
|
||||
function pushPrefEnv() {
|
||||
let deferred = promise.defer();
|
||||
let options = {"set": [
|
||||
["security.mixed_content.block_active_content", true],
|
||||
["security.mixed_content.block_display_content", true]
|
||||
]};
|
||||
let options = {
|
||||
"set": [
|
||||
["security.mixed_content.block_active_content", true],
|
||||
["security.mixed_content.block_display_content", true]
|
||||
]
|
||||
};
|
||||
SpecialPowers.pushPrefEnv(options, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/* eslint-disable no-unused-vars */
|
||||
|
||||
"use strict";
|
||||
|
||||
function counterExternalFile() {
|
||||
console.count("console.count() testcounter");
|
||||
}
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
"use strict";
|
||||
console.log("running network console logging tests");
|
||||
|
|
|
@ -884,12 +884,13 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
|
|||
let sheet = style.sheet;
|
||||
let cssRules = sheet.cssRules;
|
||||
let rawNode = node.rawNode;
|
||||
let classes = [...rawNode.classList];
|
||||
|
||||
let selector;
|
||||
if (rawNode.id) {
|
||||
selector = "#" + CSS.escape(rawNode.id);
|
||||
} else if (rawNode.className) {
|
||||
selector = "." + [...rawNode.classList].map(c => CSS.escape(c)).join(".");
|
||||
} else if (classes.length > 0) {
|
||||
selector = "." + classes.map(c => CSS.escape(c)).join(".");
|
||||
} else {
|
||||
selector = rawNode.localName;
|
||||
}
|
||||
|
|
|
@ -580,16 +580,6 @@ public:
|
|||
SetHTMLBoolAttr(nsGkAtoms::muted, aMuted, aRv);
|
||||
}
|
||||
|
||||
bool MozMediaStatisticsShowing() const
|
||||
{
|
||||
return mStatsShowing;
|
||||
}
|
||||
|
||||
void SetMozMediaStatisticsShowing(bool aShow)
|
||||
{
|
||||
mStatsShowing = aShow;
|
||||
}
|
||||
|
||||
bool MozAllowCasting() const
|
||||
{
|
||||
return mAllowCasting;
|
||||
|
|
|
@ -118,7 +118,6 @@ partial interface HTMLMediaElement {
|
|||
readonly attribute boolean mozAutoplayEnabled;
|
||||
|
||||
// NB: for internal use with the video controls:
|
||||
[Func="IsChromeOrXBL"] attribute boolean mozMediaStatisticsShowing;
|
||||
[Func="IsChromeOrXBL"] attribute boolean mozAllowCasting;
|
||||
[Func="IsChromeOrXBL"] attribute boolean mozIsCasting;
|
||||
|
||||
|
|
|
@ -1076,7 +1076,7 @@ void
|
|||
CountHistogram::Accumulate(Sample value, Count count, size_t index)
|
||||
{
|
||||
size_t zero_index = BucketIndex(0);
|
||||
LinearHistogram::Accumulate(1, 1, zero_index);
|
||||
LinearHistogram::Accumulate(value, 1, zero_index);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -179,6 +179,8 @@ public class GeckoNetworkManager extends BroadcastReceiver implements NativeEven
|
|||
return ManagerState.OffNoListeners;
|
||||
case enableNotifications:
|
||||
return ManagerState.OnWithListeners;
|
||||
case receivedUpdate:
|
||||
return ManagerState.OnNoListeners;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -224,16 +226,24 @@ public class GeckoNetworkManager extends BroadcastReceiver implements NativeEven
|
|||
case OffNoListeners:
|
||||
if (event == ManagerEvent.start) {
|
||||
updateNetworkStateAndConnectionType();
|
||||
registerBroadcastReceiver();
|
||||
}
|
||||
if (event == ManagerEvent.enableNotifications) {
|
||||
updateNetworkStateAndConnectionType();
|
||||
}
|
||||
break;
|
||||
case OnNoListeners:
|
||||
if (event == ManagerEvent.receivedUpdate) {
|
||||
updateNetworkStateAndConnectionType();
|
||||
sendNetworkStateToListeners();
|
||||
}
|
||||
if (event == ManagerEvent.enableNotifications) {
|
||||
updateNetworkStateAndConnectionType();
|
||||
registerBroadcastReceiver();
|
||||
}
|
||||
if (event == ManagerEvent.stop) {
|
||||
unregisterBroadcastReceiver();
|
||||
}
|
||||
break;
|
||||
case OnWithListeners:
|
||||
if (event == ManagerEvent.receivedUpdate) {
|
||||
|
@ -243,14 +253,13 @@ public class GeckoNetworkManager extends BroadcastReceiver implements NativeEven
|
|||
if (event == ManagerEvent.stop) {
|
||||
unregisterBroadcastReceiver();
|
||||
}
|
||||
if (event == ManagerEvent.disableNotifications) {
|
||||
unregisterBroadcastReceiver();
|
||||
}
|
||||
/* no-op event: ManagerEvent.disableNotifications */
|
||||
break;
|
||||
case OffWithListeners:
|
||||
if (event == ManagerEvent.start) {
|
||||
registerBroadcastReceiver();
|
||||
}
|
||||
/* no-op event: ManagerEvent.disableNotifications */
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown current state: " + currentState.name());
|
||||
|
|
|
@ -13,21 +13,24 @@ import com.adjust.sdk.AdjustConfig;
|
|||
import com.adjust.sdk.AdjustReferrerReceiver;
|
||||
import com.adjust.sdk.LogLevel;
|
||||
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
|
||||
public class AdjustHelper implements AdjustHelperInterface {
|
||||
public void onCreate(final Context context, final String maybeAppToken) {
|
||||
final String environment;
|
||||
final String appToken;
|
||||
final LogLevel logLevel;
|
||||
if (maybeAppToken != null) {
|
||||
if (AppConstants.MOZILLA_OFFICIAL) {
|
||||
environment = AdjustConfig.ENVIRONMENT_PRODUCTION;
|
||||
appToken = maybeAppToken;
|
||||
logLevel = LogLevel.WARN;
|
||||
} else {
|
||||
environment = AdjustConfig.ENVIRONMENT_SANDBOX;
|
||||
appToken = "ABCDEFGHIJKL";
|
||||
logLevel = LogLevel.VERBOSE;
|
||||
}
|
||||
AdjustConfig config = new AdjustConfig(context, appToken, environment);
|
||||
if (maybeAppToken == null) {
|
||||
// We've got install tracking turned on -- we better have a token!
|
||||
throw new IllegalArgumentException("maybeAppToken must not be null");
|
||||
}
|
||||
AdjustConfig config = new AdjustConfig(context, maybeAppToken, environment);
|
||||
config.setLogLevel(logLevel);
|
||||
Adjust.onCreate(config);
|
||||
}
|
||||
|
|
|
@ -832,7 +832,9 @@ public class LocalBrowserDB implements BrowserDB {
|
|||
// bookmarks exist, so that the user can still access non-mobile bookmarks.
|
||||
addDesktopFolder = desktopBookmarksExist(cr);
|
||||
addScreenshotsFolder = AppConstants.SCREENSHOTS_IN_BOOKMARKS_ENABLED;
|
||||
addReadingListFolder = true;
|
||||
|
||||
final int readingListItemCount = getBookmarkCountForFolder(cr, Bookmarks.FAKE_READINGLIST_SMARTFOLDER_ID);
|
||||
addReadingListFolder = (readingListItemCount > 0);
|
||||
} else {
|
||||
addDesktopFolder = false;
|
||||
addScreenshotsFolder = false;
|
||||
|
|
|
@ -39,7 +39,7 @@ public class DownloadAction extends BaseAction {
|
|||
|
||||
private static final String CACHE_DIRECTORY = "downloadContent";
|
||||
|
||||
private static final String CDN_BASE_URL = "https://mobile.cdn.mozilla.net/";
|
||||
private static final String CDN_BASE_URL = "https://fennec-catalog.cdn.mozilla.net/";
|
||||
|
||||
public interface Callback {
|
||||
void onContentDownloaded(DownloadContent content);
|
||||
|
|
|
@ -44,7 +44,7 @@ public class SyncAction extends BaseAction {
|
|||
* Dev instance:
|
||||
* https://kinto-ota.dev.mozaws.net/v1/buckets/dlc/collections/catalog/records
|
||||
*/
|
||||
private static final String CATALOG_ENDPOINT = "https://firefox.settings.services.mozilla.com/v1/buckets/fennec-dlc/collections/catalog/records";
|
||||
private static final String CATALOG_ENDPOINT = "https://firefox.settings.services.mozilla.com/v1/buckets/fennec/collections/catalog/records";
|
||||
|
||||
@Override
|
||||
public void perform(Context context, DownloadContentCatalog catalog) {
|
||||
|
|
|
@ -22,10 +22,10 @@ import java.util.List;
|
|||
List<DownloadContent> initialList = Arrays.asList(
|
||||
new DownloadContentBuilder()
|
||||
.setId("c40929cf-7f4c-fa72-3dc9-12cadf56905d")
|
||||
.setLocation("fonts/ff7ecae7669a51d5fa6a5f8e703278ebda3a68f51bc49c4321bde4438020d639.gz")
|
||||
.setLocation("fennec/catalog/f63e5f92-793c-4574-a2d7-fbc50242b8cb.gz")
|
||||
.setFilename("CharisSILCompact-B.ttf")
|
||||
.setChecksum("699d958b492eda0cc2823535f8567d0393090e3842f6df3c36dbe7239cb80b6d")
|
||||
.setDownloadChecksum("ff7ecae7669a51d5fa6a5f8e703278ebda3a68f51bc49c4321bde4438020d639")
|
||||
.setDownloadChecksum("a9f9b34fed353169a88cc159b8f298cb285cce0b8b0f979c22a7d85de46f0532")
|
||||
.setSize(1676072)
|
||||
.setKind("font")
|
||||
.setType("asset-archive")
|
||||
|
@ -33,10 +33,10 @@ import java.util.List;
|
|||
|
||||
new DownloadContentBuilder()
|
||||
.setId("6d265876-85ed-0917-fdc8-baf583ca2cba")
|
||||
.setLocation("fonts/dfb6d583edd27d5e6d91d479e6c8a5706275662c940c65b70911493bb279904a.gz")
|
||||
.setLocation("fennec/catalog/19af6c88-09d9-4d6c-805e-cfebb8699a6c.gz")
|
||||
.setFilename("CharisSILCompact-BI.ttf")
|
||||
.setChecksum("82465e747b4f41471dbfd942842b2ee810749217d44b55dbc43623b89f9c7d9b")
|
||||
.setDownloadChecksum("dfb6d583edd27d5e6d91d479e6c8a5706275662c940c65b70911493bb279904a")
|
||||
.setDownloadChecksum("2be26671039a5e2e4d0360a948b4fa42048171133076a3bb6173d93d4b9cd55b")
|
||||
.setSize(1667812)
|
||||
.setKind("font")
|
||||
.setType("asset-archive")
|
||||
|
@ -44,10 +44,10 @@ import java.util.List;
|
|||
|
||||
new DownloadContentBuilder()
|
||||
.setId("8460dc6d-d129-fd1a-24b6-343dbf6531dd")
|
||||
.setLocation("fonts/5a257ec3c5226e7be0be65e463f5b22eff108da853b9ff7bc47f1733b1ddacf2.gz")
|
||||
.setLocation("fennec/catalog/f35a384a-90ea-41c6-a957-bb1845de97eb.gz")
|
||||
.setFilename("CharisSILCompact-I.ttf")
|
||||
.setChecksum("ab3ed6f2a4d4c2095b78227bd33155d7ccd05a879c107a291912640d4d64f767")
|
||||
.setDownloadChecksum("5a257ec3c5226e7be0be65e463f5b22eff108da853b9ff7bc47f1733b1ddacf2")
|
||||
.setDownloadChecksum("38a6469041c02624d43dfd41d2dd745e3e3211655e616188f65789a90952a1e9")
|
||||
.setSize(1693988)
|
||||
.setKind("font")
|
||||
.setType("asset-archive")
|
||||
|
@ -55,10 +55,10 @@ import java.util.List;
|
|||
|
||||
new DownloadContentBuilder()
|
||||
.setId("c906275c-3747-fe27-426f-6187526a6f06")
|
||||
.setLocation("fonts/cab284228b8dfe8ef46c3f1af70b5b6f9e92878f05e741ecc611e5e750a4a3b3.gz")
|
||||
.setLocation("fennec/catalog/8c3bec92-d2df-4789-8c4a-0f523f026d96.gz")
|
||||
.setFilename("CharisSILCompact-R.ttf")
|
||||
.setChecksum("4ed509317f1bb441b185ea13bf1c9d19d1a0b396962efa3b5dc3190ad88f2067")
|
||||
.setDownloadChecksum("cab284228b8dfe8ef46c3f1af70b5b6f9e92878f05e741ecc611e5e750a4a3b3")
|
||||
.setDownloadChecksum("7c2ec1f550c2005b75383b878f737266b5f0b1c82679dd886c8bbe30c82e340e")
|
||||
.setSize(1727656)
|
||||
.setKind("font")
|
||||
.setType("asset-archive")
|
||||
|
@ -66,10 +66,10 @@ import java.util.List;
|
|||
|
||||
new DownloadContentBuilder()
|
||||
.setId("ff5deecc-6ecc-d816-bb51-65face460119")
|
||||
.setLocation("fonts/d95168996dc932e6504cb5448fcb759e0ee6e66c5c8603293b046d28ab589cce.gz")
|
||||
.setLocation("fennec/catalog/ea115d71-e2ac-4609-853e-c978780776b1.gz")
|
||||
.setFilename("ClearSans-Bold.ttf")
|
||||
.setChecksum("385d0a293c1714770e198f7c762ab32f7905a0ed9d2993f69d640bd7232b4b70")
|
||||
.setDownloadChecksum("d95168996dc932e6504cb5448fcb759e0ee6e66c5c8603293b046d28ab589cce")
|
||||
.setDownloadChecksum("0d3c22bef90e7096f75b331bb7391de3aa43017e10d61041cd3085816db4919a")
|
||||
.setSize(140136)
|
||||
.setKind("font")
|
||||
.setType("asset-archive")
|
||||
|
@ -77,10 +77,10 @@ import java.util.List;
|
|||
|
||||
new DownloadContentBuilder()
|
||||
.setId("a173d1db-373b-ce42-1335-6b3285cfdebd")
|
||||
.setLocation("fonts/f5e18f4acc4ceaeca9e081b1be79cd6034e0dc7ad683fa240195fd6c838452e0.gz")
|
||||
.setLocation("fennec/catalog/0838e513-2d99-4e53-b58f-6b970f6548c6.gz")
|
||||
.setFilename("ClearSans-BoldItalic.ttf")
|
||||
.setChecksum("7bce66864e38eecd7c94b6657b9b38c35ebfacf8046bfb1247e08f07fe933198")
|
||||
.setDownloadChecksum("f5e18f4acc4ceaeca9e081b1be79cd6034e0dc7ad683fa240195fd6c838452e0")
|
||||
.setDownloadChecksum("de0903164dde1ad3768d0bd6dec949871d6ab7be08f573d9d70f38c138a22e37")
|
||||
.setSize(156124)
|
||||
.setKind("font")
|
||||
.setType("asset-archive")
|
||||
|
@ -88,10 +88,10 @@ import java.util.List;
|
|||
|
||||
new DownloadContentBuilder()
|
||||
.setId("e65c66df-0088-940d-ca5c-207c22118c0e")
|
||||
.setLocation("fonts/56d12114ac15d913d7d9876c698889cd25f26e14966a8bd7424aeb0f61ffaf87.gz")
|
||||
.setLocation("fennec/catalog/7550fa42-0947-478c-a5f0-5ea1bbb6ba27.gz")
|
||||
.setFilename("ClearSans-Italic.ttf")
|
||||
.setChecksum("87c13c5fbae832e4f85c3bd46fcbc175978234f39be5fe51c4937be4cbff3b68")
|
||||
.setDownloadChecksum("56d12114ac15d913d7d9876c698889cd25f26e14966a8bd7424aeb0f61ffaf87")
|
||||
.setDownloadChecksum("6e323db3115005dd0e96d2422db87a520f9ae426de28a342cd6cc87b55601d87")
|
||||
.setSize(155672)
|
||||
.setKind("font")
|
||||
.setType("asset-archive")
|
||||
|
@ -99,10 +99,10 @@ import java.util.List;
|
|||
|
||||
new DownloadContentBuilder()
|
||||
.setId("25610abb-5dc8-fd75-40e7-990507f010c4")
|
||||
.setLocation("fonts/1fc716662866b9c01e32dda3fc9c54ca3e57de8c6ac523f46305d8ae6c0a9cf4.gz")
|
||||
.setLocation("fennec/catalog/dd9bee7d-d784-476b-a3dd-69af8e516487.gz")
|
||||
.setFilename("ClearSans-Light.ttf")
|
||||
.setChecksum("e4885f6188e7a8587f5621c077c6c1f5e8d3739dffc8f4d055c2ba87568c750a")
|
||||
.setDownloadChecksum("1fc716662866b9c01e32dda3fc9c54ca3e57de8c6ac523f46305d8ae6c0a9cf4")
|
||||
.setDownloadChecksum("19d4f7c67176e9e254c61420da9c7363d9fe5e6b4bb9d61afa4b3b574280714f")
|
||||
.setSize(145976)
|
||||
.setKind("font")
|
||||
.setType("asset-archive")
|
||||
|
@ -110,10 +110,10 @@ import java.util.List;
|
|||
|
||||
new DownloadContentBuilder()
|
||||
.setId("ffe40339-a096-2262-c3f8-54af75c81fe6")
|
||||
.setLocation("fonts/a29184ec6621dbd3bc6ae1e30bba70c479d1001bca647ea4a205ecb64d5a00a0.gz")
|
||||
.setLocation("fennec/catalog/bc5ada8c-8cfc-443d-93d7-dc5f98138a07.gz")
|
||||
.setFilename("ClearSans-Medium.ttf")
|
||||
.setChecksum("5d0e0115f3a3ed4be3eda6d7eabb899bb9a361292802e763d53c72e00f629da1")
|
||||
.setDownloadChecksum("a29184ec6621dbd3bc6ae1e30bba70c479d1001bca647ea4a205ecb64d5a00a0")
|
||||
.setDownloadChecksum("edec86dab3ad2a97561cb41b584670262a48bed008c57bb587ee05ca47fb067f")
|
||||
.setSize(148892)
|
||||
.setKind("font")
|
||||
.setType("asset-archive")
|
||||
|
@ -121,10 +121,10 @@ import java.util.List;
|
|||
|
||||
new DownloadContentBuilder()
|
||||
.setId("139a94be-ac69-0264-c9cc-8f2d071fd29d")
|
||||
.setLocation("fonts/a381a3d4060e993af440a7b72fed29fa3a488536cc451d7c435d5fae1256318b.gz")
|
||||
.setLocation("fennec/catalog/0490c768-6178-49c2-af88-9f8769ff3167.gz")
|
||||
.setFilename("ClearSans-MediumItalic.ttf")
|
||||
.setChecksum("937dda88b26469306258527d38e42c95e27e7ebb9f05bd1d7c5d706a3c9541d7")
|
||||
.setDownloadChecksum("a381a3d4060e993af440a7b72fed29fa3a488536cc451d7c435d5fae1256318b")
|
||||
.setDownloadChecksum("34edbd1b325dbffe7791fba8dd2d19852eb3c2fe00cff517ea2161ddc424ee22")
|
||||
.setSize(155228)
|
||||
.setKind("font")
|
||||
.setType("asset-archive")
|
||||
|
@ -132,10 +132,10 @@ import java.util.List;
|
|||
|
||||
new DownloadContentBuilder()
|
||||
.setId("b887012a-01e1-7c94-fdcb-ca44d5b974a2")
|
||||
.setLocation("fonts/87dec7f0331e19b293fc510f2764b9bd1b94595ac279cf9414f8d03c5bf34dca.gz")
|
||||
.setLocation("fennec/catalog/78205bf8-c668-41b1-b68f-afd54f98713b.gz")
|
||||
.setFilename("ClearSans-Regular.ttf")
|
||||
.setChecksum("9b91bbdb95ffa6663da24fdaa8ee06060cd0a4d2dceaf1ffbdda00e04915ee5b")
|
||||
.setDownloadChecksum("87dec7f0331e19b293fc510f2764b9bd1b94595ac279cf9414f8d03c5bf34dca")
|
||||
.setDownloadChecksum("a72f1420b4da1ba9e6797adac34f08e72f94128a85e56542d5e6a8080af5f08a")
|
||||
.setSize(142572)
|
||||
.setKind("font")
|
||||
.setType("asset-archive")
|
||||
|
@ -143,10 +143,10 @@ import java.util.List;
|
|||
|
||||
new DownloadContentBuilder()
|
||||
.setId("c8703652-d317-0356-0bf8-95441a5b2c9b")
|
||||
.setLocation("fonts/64300b48b2867e5642212690f0ff9ea3988f47790311c444a81d25213b4102aa.gz")
|
||||
.setLocation("fennec/catalog/3570f44f-9440-4aa0-abd0-642eaf2a1aa0.gz")
|
||||
.setFilename("ClearSans-Thin.ttf")
|
||||
.setChecksum("07b0db85a3ad99afeb803f0f35631436a7b4c67ac66d0c7f77d26a47357c592a")
|
||||
.setDownloadChecksum("64300b48b2867e5642212690f0ff9ea3988f47790311c444a81d25213b4102aa")
|
||||
.setDownloadChecksum("d9f23fd8687d6743f5c281c33539fb16f163304795039959b8caf159e6d62822")
|
||||
.setSize(147004)
|
||||
.setKind("font")
|
||||
.setType("asset-archive")
|
||||
|
|
|
@ -104,8 +104,6 @@ public class FloatingToolbarTextSelection implements TextSelection, GeckoEventLi
|
|||
|
||||
@Override
|
||||
public void handleMessage(final String event, final JSONObject message) {
|
||||
Log.w("SKDBG", "Received event " + event + " with message: " + message.toString());
|
||||
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
|
|
@ -268,11 +268,12 @@ public class ToolbarDisplayLayout extends ThemedLinearLayout {
|
|||
return;
|
||||
}
|
||||
|
||||
final boolean isHttpOrHttps = StringUtils.isHttpOrHttps(url);
|
||||
final String baseDomain = tab.getBaseDomain();
|
||||
|
||||
String strippedURL = stripAboutReaderURL(url);
|
||||
|
||||
final boolean isHttpOrHttps = StringUtils.isHttpOrHttps(strippedURL);
|
||||
|
||||
if (mPrefs.shouldTrimUrls()) {
|
||||
strippedURL = StringUtils.stripCommonSubdomains(StringUtils.stripScheme(strippedURL));
|
||||
}
|
||||
|
@ -290,12 +291,9 @@ public class ToolbarDisplayLayout extends ThemedLinearLayout {
|
|||
&& SwitchBoard.isInExperiment(mActivity, Experiments.URLBAR_SHOW_ORIGIN_ONLY)) {
|
||||
// Show just the base domain as title
|
||||
setTitle(baseDomain);
|
||||
} else if (isHttpOrHttps) {
|
||||
} else {
|
||||
// Display full URL with base domain highlighted as title
|
||||
updateAndColorTitleFromFullURL(strippedURL, baseDomain, tab.isPrivate());
|
||||
} else {
|
||||
// Not http(s): Just show the full URL as title
|
||||
setTitle(url);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
До Ширина: | Высота: | Размер: 494 B После Ширина: | Высота: | Размер: 494 B |
|
@ -1,3 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<inset xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:drawable="@drawable/ic_menu_share_icon"/>
|
До Ширина: | Высота: | Размер: 713 B После Ширина: | Высота: | Размер: 713 B |
До Ширина: | Высота: | Размер: 832 B После Ширина: | Высота: | Размер: 832 B |
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<inset xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:drawable="@drawable/ic_menu_share_icon"
|
||||
android:insetTop="3dp"
|
||||
android:insetRight="3dp"
|
||||
android:insetBottom="3dp"
|
||||
android:insetLeft="3dp"/>
|
|
@ -30,9 +30,9 @@ public class GeckoNetworkManagerTest {
|
|||
testingState = ManagerState.OnNoListeners;
|
||||
assertNull(GeckoNetworkManager.getNextState(testingState, ManagerEvent.start));
|
||||
assertNull(GeckoNetworkManager.getNextState(testingState, ManagerEvent.disableNotifications));
|
||||
assertNull(GeckoNetworkManager.getNextState(testingState, ManagerEvent.receivedUpdate));
|
||||
assertEquals(ManagerState.OnWithListeners, GeckoNetworkManager.getNextState(testingState, ManagerEvent.enableNotifications));
|
||||
assertEquals(ManagerState.OffNoListeners, GeckoNetworkManager.getNextState(testingState, ManagerEvent.stop));
|
||||
assertEquals(ManagerState.OnNoListeners, GeckoNetworkManager.getNextState(testingState, ManagerEvent.receivedUpdate));
|
||||
|
||||
testingState = ManagerState.OnWithListeners;
|
||||
assertNull(GeckoNetworkManager.getNextState(testingState, ManagerEvent.start));
|
||||
|
|
|
@ -3481,7 +3481,9 @@ dnl ========================================================
|
|||
dnl = Include install tracking on Android
|
||||
dnl ========================================================
|
||||
if test -n "$MOZ_INSTALL_TRACKING"; then
|
||||
AC_DEFINE(MOZ_INSTALL_TRACKING)
|
||||
if test -z "$MOZ_INSTALL_TRACKING_ADJUST_SDK_APP_TOKEN"; then
|
||||
AC_MSG_ERROR([Must specify --with-adjust-sdk-keyfile when MOZ_INSTALL_TRACKING is defined!])
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
|
|
Двоичные данные
other-licenses/7zstub/firefox/7zSD.sfx
Двоичные данные
other-licenses/7zstub/firefox/7zSD.sfx
Двоичный файл не отображается.
|
@ -35,6 +35,101 @@ static LPCTSTR kTempDirPrefix = TEXT("7zS");
|
|||
|
||||
#define _SHELL_EXECUTE
|
||||
|
||||
/* BEGIN Mozilla customizations */
|
||||
|
||||
static char const *
|
||||
FindStrInBuf(char const * buf, size_t bufLen, char const * str)
|
||||
{
|
||||
size_t index = 0;
|
||||
while (index < bufLen) {
|
||||
char const * result = strstr(buf + index, str);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
while ((buf[index] != '\0') && (index < bufLen)) {
|
||||
index++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
ReadPostSigningDataFromView(char const * view, DWORD size, AString& data)
|
||||
{
|
||||
// Find the offset and length of the certificate table,
|
||||
// so we know the valid range to look for the token.
|
||||
if (size < (0x3c + sizeof(UInt32))) {
|
||||
return false;
|
||||
}
|
||||
UInt32 PEHeaderOffset = *(UInt32*)(view + 0x3c);
|
||||
UInt32 optionalHeaderOffset = PEHeaderOffset + 24;
|
||||
UInt32 certDirEntryOffset = 0;
|
||||
if (size < (optionalHeaderOffset + sizeof(UInt16))) {
|
||||
return false;
|
||||
}
|
||||
UInt16 magic = *(UInt16*)(view + optionalHeaderOffset);
|
||||
if (magic == 0x010b) {
|
||||
// 32-bit executable
|
||||
certDirEntryOffset = optionalHeaderOffset + 128;
|
||||
} else if (magic == 0x020b) {
|
||||
// 64-bit executable; certain header fields are wider
|
||||
certDirEntryOffset = optionalHeaderOffset + 144;
|
||||
} else {
|
||||
// Unknown executable
|
||||
return false;
|
||||
}
|
||||
if (size < certDirEntryOffset + 8) {
|
||||
return false;
|
||||
}
|
||||
UInt32 certTableOffset = *(UInt32*)(view + certDirEntryOffset);
|
||||
UInt32 certTableLen = *(UInt32*)(view + certDirEntryOffset + sizeof(UInt32));
|
||||
if (certTableOffset == 0 || certTableLen == 0 ||
|
||||
size < (certTableOffset + certTableLen)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char const token[] = "__MOZCUSTOM__:";
|
||||
// We're searching for a string inside a binary blob,
|
||||
// so a normal strstr that bails on the first NUL won't work.
|
||||
char const * tokenPos = FindStrInBuf(view + certTableOffset,
|
||||
certTableLen, token);
|
||||
if (tokenPos) {
|
||||
size_t tokenLen = (sizeof(token) / sizeof(token[0])) - 1;
|
||||
data = AString(tokenPos + tokenLen);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
ReadPostSigningData(UString exePath, AString& data)
|
||||
{
|
||||
bool retval = false;
|
||||
HANDLE exeFile = CreateFileW(exePath, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (exeFile != INVALID_HANDLE_VALUE) {
|
||||
HANDLE mapping = CreateFileMapping(exeFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (mapping != INVALID_HANDLE_VALUE) {
|
||||
// MSDN claims the return value on failure is NULL,
|
||||
// but I've also seen it returned on success, so double-check.
|
||||
if (mapping || GetLastError() == ERROR_SUCCESS) {
|
||||
char * view = (char*)MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
|
||||
if (view) {
|
||||
DWORD fileSize = GetFileSize(exeFile, NULL);
|
||||
retval = ReadPostSigningDataFromView(view, fileSize, data);
|
||||
}
|
||||
CloseHandle(mapping);
|
||||
}
|
||||
}
|
||||
CloseHandle(exeFile);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* END Mozilla customizations */
|
||||
|
||||
|
||||
static bool ReadDataString(LPCWSTR fileName, LPCSTR startID,
|
||||
LPCSTR endID, AString &stringResult)
|
||||
{
|
||||
|
@ -331,7 +426,22 @@ int APIENTRY WinMain(
|
|||
}
|
||||
|
||||
/* BEGIN Mozilla customizations */
|
||||
// The code immediately above handles the error case for extraction.
|
||||
// Retrieve and store any data added to this file after signing.
|
||||
{
|
||||
AString postSigningData;
|
||||
if (ReadPostSigningData(fullPath, postSigningData)) {
|
||||
NFile::NName::CParsedPath postSigningDataFilePath;
|
||||
postSigningDataFilePath.ParsePath(tempDirPath);
|
||||
postSigningDataFilePath.PathParts.Add(L"postSigningData");
|
||||
|
||||
NFile::NIO::COutFile postSigningDataFile;
|
||||
postSigningDataFile.Create(postSigningDataFilePath.MergePath(), true);
|
||||
|
||||
UInt32 written = 0;
|
||||
postSigningDataFile.Write(postSigningData, postSigningData.Length(), written);
|
||||
}
|
||||
}
|
||||
|
||||
if (extractOnly) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -511,7 +511,9 @@ AsyncFetchAndSetIconForPage::AsyncOnChannelRedirect(
|
|||
, nsIAsyncVerifyRedirectCallback *cb
|
||||
)
|
||||
{
|
||||
(void)cb->OnRedirectVerifyCallback(NS_OK);
|
||||
// If we've been canceled, stop the redirect with NS_BINDING_ABORTED, and
|
||||
// handle the cancel on the original channel.
|
||||
(void)cb->OnRedirectVerifyCallback(mCanceled ? NS_BINDING_ABORTED : NS_OK);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -996,9 +996,12 @@ JSHistogram_Add(JSContext *cx, unsigned argc, JS::Value *vp)
|
|||
MOZ_ASSERT(h);
|
||||
Histogram::ClassType type = h->histogram_type();
|
||||
|
||||
JS::CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// If we don't have an argument for the count histogram, assume an increment of 1.
|
||||
// Otherwise, make sure to run some sanity checks on the argument.
|
||||
int32_t value = 1;
|
||||
if (type != base::CountHistogram::COUNT_HISTOGRAM) {
|
||||
JS::CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if ((type != base::CountHistogram::COUNT_HISTOGRAM) || args.length()) {
|
||||
if (!args.length()) {
|
||||
JS_ReportError(cx, "Expected one argument");
|
||||
return false;
|
||||
|
@ -1222,9 +1225,11 @@ JSKeyedHistogram_Add(JSContext *cx, unsigned argc, JS::Value *vp)
|
|||
}
|
||||
|
||||
const uint32_t type = keyed->GetHistogramType();
|
||||
int32_t value = 1;
|
||||
|
||||
if (type != base::CountHistogram::COUNT_HISTOGRAM) {
|
||||
// If we don't have an argument for the count histogram, assume an increment of 1.
|
||||
// Otherwise, make sure to run some sanity checks on the argument.
|
||||
int32_t value = 1;
|
||||
if ((type != base::CountHistogram::COUNT_HISTOGRAM) || (args.length() == 2)) {
|
||||
if (args.length() < 2) {
|
||||
JS_ReportError(cx, "Expected two arguments for this histogram type");
|
||||
return false;
|
||||
|
|
|
@ -126,12 +126,6 @@ function savePing(aPing) {
|
|||
}
|
||||
}
|
||||
|
||||
function tomorrow(date) {
|
||||
let d = new Date(date);
|
||||
d.setDate(d.getDate() + 1);
|
||||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {String} This returns a string with the gzip compressed data.
|
||||
*/
|
||||
|
|
|
@ -105,12 +105,6 @@ var gLastMemoryPoll = null;
|
|||
|
||||
var gWasDebuggerAttached = false;
|
||||
|
||||
function getLocale() {
|
||||
return Cc["@mozilla.org/chrome/chrome-registry;1"].
|
||||
getService(Ci.nsIXULChromeRegistry).
|
||||
getSelectedLocale('global');
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "Telemetry",
|
||||
"@mozilla.org/base/telemetry;1",
|
||||
"nsITelemetry");
|
||||
|
@ -189,35 +183,6 @@ function getPingType(aPayload) {
|
|||
return PING_TYPE_MAIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Date.toISOString() gives us UTC times, this gives us local times in the ISO date format.
|
||||
* http://www.w3.org/TR/NOTE-datetime
|
||||
*/
|
||||
function toLocalTimeISOString(date) {
|
||||
function padNumber(number, places) {
|
||||
number = number.toString();
|
||||
while (number.length < places) {
|
||||
number = "0" + number;
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
let sign = (n) => n >= 0 ? "+" : "-";
|
||||
// getTimezoneOffset counter-intuitively returns -60 for UTC+1.
|
||||
let tzOffset = - date.getTimezoneOffset();
|
||||
|
||||
// YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
|
||||
return padNumber(date.getFullYear(), 4)
|
||||
+ "-" + padNumber(date.getMonth() + 1, 2)
|
||||
+ "-" + padNumber(date.getDate(), 2)
|
||||
+ "T" + padNumber(date.getHours(), 2)
|
||||
+ ":" + padNumber(date.getMinutes(), 2)
|
||||
+ ":" + padNumber(date.getSeconds(), 2)
|
||||
+ "." + date.getMilliseconds()
|
||||
+ sign(tzOffset) + padNumber(Math.floor(Math.abs(tzOffset / 60)), 2)
|
||||
+ ":" + padNumber(Math.abs(tzOffset % 60), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Annotate the current session ID with the crash reporter to map potential
|
||||
* crash pings with the related main ping.
|
||||
|
@ -1022,8 +987,8 @@ var Impl = {
|
|||
getMetadata: function getMetadata(reason) {
|
||||
this._log.trace("getMetadata - Reason " + reason);
|
||||
|
||||
const sessionStartDate = toLocalTimeISOString(Utils.truncateToDays(this._sessionStartDate));
|
||||
const subsessionStartDate = toLocalTimeISOString(Utils.truncateToDays(this._subsessionStartDate));
|
||||
const sessionStartDate = Utils.toLocalTimeISOString(Utils.truncateToDays(this._sessionStartDate));
|
||||
const subsessionStartDate = Utils.toLocalTimeISOString(Utils.truncateToDays(this._subsessionStartDate));
|
||||
const monotonicNow = Policy.monotonicNow();
|
||||
|
||||
let ret = {
|
||||
|
|
|
@ -118,4 +118,35 @@ this.TelemetryUtils = {
|
|||
return (aEndDate.getMonth() - aStartDate.getMonth())
|
||||
+ 12 * (aEndDate.getFullYear() - aStartDate.getFullYear());
|
||||
},
|
||||
|
||||
/**
|
||||
* Date.toISOString() gives us UTC times, this gives us local times in
|
||||
* the ISO date format. See http://www.w3.org/TR/NOTE-datetime
|
||||
* @param {Object} date The input date.
|
||||
* @return {String} The local time ISO string.
|
||||
*/
|
||||
toLocalTimeISOString: function(date) {
|
||||
function padNumber(number, places) {
|
||||
number = number.toString();
|
||||
while (number.length < places) {
|
||||
number = "0" + number;
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
let sign = (n) => n >= 0 ? "+" : "-";
|
||||
// getTimezoneOffset counter-intuitively returns -60 for UTC+1.
|
||||
let tzOffset = - date.getTimezoneOffset();
|
||||
|
||||
// YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
|
||||
return padNumber(date.getFullYear(), 4)
|
||||
+ "-" + padNumber(date.getMonth() + 1, 2)
|
||||
+ "-" + padNumber(date.getDate(), 2)
|
||||
+ "T" + padNumber(date.getHours(), 2)
|
||||
+ ":" + padNumber(date.getMinutes(), 2)
|
||||
+ ":" + padNumber(date.getSeconds(), 2)
|
||||
+ "." + date.getMilliseconds()
|
||||
+ sign(tzOffset) + padNumber(Math.floor(Math.abs(tzOffset / 60)), 2)
|
||||
+ ":" + padNumber(Math.abs(tzOffset % 60), 2);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -42,7 +42,7 @@ function test_histogram(histogram_type, name, min, max, bucket_count) {
|
|||
do_check_eq(i, 1);
|
||||
}
|
||||
var hgrams = Telemetry.histogramSnapshots
|
||||
gh = hgrams[name]
|
||||
let gh = hgrams[name]
|
||||
do_check_eq(gh.histogram_type, histogram_type);
|
||||
|
||||
do_check_eq(gh.min, min)
|
||||
|
@ -602,6 +602,11 @@ function test_histogram_recording_enabled() {
|
|||
Assert.equal(orig.sum + 2, h.snapshot().sum,
|
||||
"When recording is re-enabled add should record.");
|
||||
|
||||
// Check that we're correctly accumulating values other than 1.
|
||||
h.clear();
|
||||
h.add(3);
|
||||
Assert.equal(3, h.snapshot().sum, "Recording counts greater than 1 should work.");
|
||||
|
||||
// Check that a histogram with recording disabled by default behaves correctly
|
||||
h = Telemetry.getHistogramById("TELEMETRY_TEST_COUNT_INIT_NO_RECORD");
|
||||
orig = h.snapshot();
|
||||
|
@ -629,7 +634,7 @@ function test_keyed_histogram_recording_enabled() {
|
|||
|
||||
// Check RecordingEnabled for keyed histograms which are recording by default
|
||||
const TEST_KEY = "record_foo";
|
||||
h = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_RELEASE_OPTOUT");
|
||||
let h = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_RELEASE_OPTOUT");
|
||||
|
||||
h.clear();
|
||||
h.add(TEST_KEY, 1);
|
||||
|
|
|
@ -12,9 +12,21 @@ var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
|||
Cu.import("resource://gre/modules/RemotePageManager.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const gInContentProcess = Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
|
||||
|
||||
Services.cpmm.addMessageListener("gmp-plugin-crash", msg => {
|
||||
let gmpservice = Cc["@mozilla.org/gecko-media-plugin-service;1"]
|
||||
.getService(Ci.mozIGeckoMediaPluginService);
|
||||
|
||||
gmpservice.RunPluginCrashCallbacks(msg.data.pluginID, msg.data.pluginName);
|
||||
});
|
||||
|
||||
// Forward inner-window-destroyed notifications with the inner window ID,
|
||||
// so that code in the parent that should do something when content
|
||||
// windows go away can do it
|
||||
if (gInContentProcess) {
|
||||
Services.obs.addObserver((subject, topic, data) => {
|
||||
let innerWindowID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
Services.cpmm.sendAsyncMessage("Toolkit:inner-window-destroyed", innerWindowID);
|
||||
}, "inner-window-destroyed", false);
|
||||
}
|
||||
|
|
|
@ -19,3 +19,4 @@ skip-if = os == 'android'
|
|||
[test_tree_column_reorder.xul]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_videocontrols.html]
|
||||
[test_videocontrols_onclickplay.html]
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Video controls test</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="text/javascript" src="head.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content">
|
||||
<video id="video" controls mozNoDynamicControls preload="auto"></video>
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var video = document.getElementById("video");
|
||||
|
||||
function startMediaLoad() {
|
||||
// Kick off test once video has loaded, in its canplaythrough event handler.
|
||||
video.src = "seek_with_sound.ogg";
|
||||
video.addEventListener("canplaythrough", runTest, false);
|
||||
}
|
||||
|
||||
function loadevent(event) {
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.cache_size", 40000]]}, startMediaLoad);
|
||||
}
|
||||
|
||||
window.addEventListener("load", loadevent, false);
|
||||
|
||||
function runTest() {
|
||||
video.addEventListener("click", function() {
|
||||
this.play();
|
||||
});
|
||||
ok(video.paused, "video should be paused initially");
|
||||
|
||||
new Promise(resolve => {
|
||||
let timeupdates = 0;
|
||||
video.addEventListener("timeupdate", function timeupdate() {
|
||||
ok(!video.paused, "video should not get paused after clicking in middle");
|
||||
|
||||
if (++timeupdates == 3) {
|
||||
video.removeEventListener("timeupdate", timeupdate);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
synthesizeMouseAtCenter(video, {}, window);
|
||||
}).then(function() {
|
||||
new Promise(resolve => {
|
||||
video.addEventListener("pause", function onpause() {
|
||||
setTimeout(() => {
|
||||
ok(video.paused, "video should still be paused 200ms after pause request");
|
||||
// When the video reaches the end of playback it is automatically paused.
|
||||
// Check during the pause event that the video has not reachd the end
|
||||
// of playback.
|
||||
ok(!video.ended, "video should not have paused due to playback ending");
|
||||
resolve();
|
||||
}, 200);
|
||||
});
|
||||
|
||||
synthesizeMouse(video, 10, video.clientHeight - 10, {}, window);
|
||||
}).then(SimpleTest.finish);
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -211,63 +211,6 @@
|
|||
<label class="errorLabel" anonid="errorGeneric">&error.generic;</label>
|
||||
</vbox>
|
||||
|
||||
<vbox class="statsOverlay" hidden="true">
|
||||
<html:div class="statsDiv" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<table class="statsTable">
|
||||
<tr>
|
||||
<td class="statLabel">&stats.media;</td>
|
||||
<td class="statValue filename"><span class="statFilename"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="statLabel">&stats.size;</td>
|
||||
<td class="statValue size"><span class="statSize"/></td>
|
||||
</tr>
|
||||
<tr style="height: 1em;"/>
|
||||
|
||||
<tr>
|
||||
<td class="statLabel">&stats.activity;</td>
|
||||
<td class="statValue activity">
|
||||
<span class="statActivity">
|
||||
<span class="statActivityPaused">&stats.activityPaused;</span>
|
||||
<span class="statActivityPlaying">&stats.activityPlaying;</span>
|
||||
<span class="statActivityEnded">&stats.activityEnded;</span>
|
||||
<span class="statActivitySeeking">&stats.activitySeeking;</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="statLabel">&stats.volume;</td> <td class="statValue"><span class="statVolume"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<!-- Localization note: readyState is a HTML5 API MediaElement-specific attribute and should not be localized. -->
|
||||
<td class="statLabel">readyState</td> <td class="statValue"><span class="statReadyState"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<!-- Localization note: networkState is a HTML5 API MediaElement-specific attribute and should not be localized. -->
|
||||
<td class="statLabel">networkState</td> <td class="statValue"><span class="statNetState"/></td>
|
||||
</tr>
|
||||
<tr style="height: 1em;"/>
|
||||
|
||||
<tr>
|
||||
<td class="statLabel">&stats.framesParsed;</td>
|
||||
<td class="statValue"><span class="statFramesParsed"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="statLabel">&stats.framesDecoded;</td>
|
||||
<td class="statValue"><span class="statFramesDecoded"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="statLabel">&stats.framesPresented;</td>
|
||||
<td class="statValue"><span class="statFramesPresented"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="statLabel">&stats.framesPainted;</td>
|
||||
<td class="statValue"><span class="statFramesPainted"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
</html:div>
|
||||
</vbox>
|
||||
|
||||
<vbox class="controlsOverlay">
|
||||
<stack flex="1">
|
||||
<spacer class="controlsSpacer" flex="1"/>
|
||||
|
@ -327,7 +270,6 @@
|
|||
statusOverlay : null,
|
||||
controlsSpacer : null,
|
||||
clickToPlay : null,
|
||||
stats : {},
|
||||
controlsOverlay : null,
|
||||
fullscreenButton : null,
|
||||
|
||||
|
@ -474,13 +416,6 @@
|
|||
// _volumeControlWidth, since the volume slider implementation
|
||||
// depends on it.
|
||||
this.updateVolumeControls();
|
||||
|
||||
// Preserve Statistics when toggling fullscreen mode due to bug 714071.
|
||||
if (this.video.mozMediaStatisticsShowing)
|
||||
this.showStatistics(true);
|
||||
|
||||
this._handleCustomEventsBound = this.handleCustomEvents.bind(this);
|
||||
this.video.addEventListener("media-showStatistics", this._handleCustomEventsBound, false, true);
|
||||
},
|
||||
|
||||
setupNewLoadState : function() {
|
||||
|
@ -503,12 +438,6 @@
|
|||
this.startFade(this.controlBar, shouldShow, true);
|
||||
},
|
||||
|
||||
handleCustomEvents : function (e) {
|
||||
if (!e.isTrusted)
|
||||
return;
|
||||
this.showStatistics(e.detail);
|
||||
},
|
||||
|
||||
get dynamicControls() {
|
||||
// Don't fade controls for <audio> elements.
|
||||
var enabled = !this.isAudioOnly;
|
||||
|
@ -702,10 +631,6 @@
|
|||
},
|
||||
|
||||
terminateEventListeners : function () {
|
||||
if (this.statsInterval) {
|
||||
clearInterval(this.statsInterval);
|
||||
this.statsInterval = null;
|
||||
}
|
||||
for (let event of this.videoEvents)
|
||||
this.video.removeEventListener(event, this, false);
|
||||
|
||||
|
@ -714,9 +639,6 @@
|
|||
|
||||
delete this.controlListeners;
|
||||
|
||||
this.video.removeEventListener("media-showStatistics", this._handleCustomEventsBound, false);
|
||||
delete this._handleCustomEventsBound;
|
||||
|
||||
this.log("--- videocontrols terminated ---");
|
||||
},
|
||||
|
||||
|
@ -1112,13 +1034,19 @@
|
|||
return;
|
||||
}
|
||||
|
||||
// Read defaultPrevented asynchronously, since Web content
|
||||
// may want to consume the "click" event but will only
|
||||
// receive it after us.
|
||||
let self = this;
|
||||
setTimeout(function clickToPlayCallback() {
|
||||
if (!e.defaultPrevented)
|
||||
self.togglePause();
|
||||
// Read defaultPrevented and the playback state asynchronously,
|
||||
// since Web content may want to consume the "click" event
|
||||
// but will only receive it after us. If web content
|
||||
// doesn't use preventDefault but still toggles playback,
|
||||
// we will treat that act the same as a call to preventDefault()
|
||||
// so the web content-initiated toggle is not reverted.
|
||||
let previousState = this.video.paused;
|
||||
setTimeout(() => {
|
||||
if (e.defaultPrevented ||
|
||||
this.video.paused != previousState) {
|
||||
return;
|
||||
}
|
||||
this.togglePause();
|
||||
}, 0);
|
||||
},
|
||||
hideClickToPlay : function () {
|
||||
|
@ -1172,91 +1100,6 @@
|
|||
return parseInt(value, 10);
|
||||
},
|
||||
|
||||
STATS_INTERVAL_MS : 500,
|
||||
statsInterval : null,
|
||||
|
||||
showStatistics : function(shouldShow) {
|
||||
if (this.statsInterval) {
|
||||
clearInterval(this.statsInterval);
|
||||
this.statsInterval = null;
|
||||
}
|
||||
|
||||
if (shouldShow) {
|
||||
this.video.mozMediaStatisticsShowing = true;
|
||||
this.statsOverlay.hidden = false;
|
||||
this.statsInterval = setInterval(this.updateStats.bind(this), this.STATS_INTERVAL_MS);
|
||||
this.updateStats();
|
||||
} else {
|
||||
this.video.mozMediaStatisticsShowing = false;
|
||||
this.statsOverlay.hidden = true;
|
||||
}
|
||||
},
|
||||
|
||||
updateStats : function() {
|
||||
if (this.videocontrols.randomID != this.randomID) {
|
||||
this.terminateEventListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
let v = this.video;
|
||||
let s = this.stats;
|
||||
|
||||
let src = v.currentSrc || v.src || "(no source found)";
|
||||
let srcParts = src.split('/');
|
||||
let srcIdx = srcParts.length - 1;
|
||||
if (src.lastIndexOf('/') == src.length - 1)
|
||||
srcIdx--;
|
||||
s.filename.textContent = decodeURI(srcParts[srcIdx]);
|
||||
|
||||
let size = v.videoWidth + "x" + v.videoHeight;
|
||||
if (this._getComputedPropertyValueAsInt(this.video, "width") != v.videoWidth || this._getComputedPropertyValueAsInt(this.video, "height") != v.videoHeight)
|
||||
size += " scaled to " + this._getComputedPropertyValueAsInt(this.video, "width") + "x" + this._getComputedPropertyValueAsInt(this.video, "height");
|
||||
s.size.textContent = size;
|
||||
|
||||
let activity;
|
||||
if (v.paused)
|
||||
activity = "paused";
|
||||
else
|
||||
activity = "playing";
|
||||
if (v.ended)
|
||||
activity = "ended";
|
||||
if (s.activity.getAttribute("activity") != activity)
|
||||
s.activity.setAttribute("activity", activity);
|
||||
if (v.seeking && !s.activity.hasAttribute("seeking"))
|
||||
s.activity.setAttribute("seeking", true);
|
||||
else if (s.activity.hasAttribute("seeking"))
|
||||
s.activity.removeAttribute("seeking");
|
||||
|
||||
let readyState = v.readyState;
|
||||
switch (readyState) {
|
||||
case v.HAVE_NOTHING: readyState = "HAVE_NOTHING"; break;
|
||||
case v.HAVE_METADATA: readyState = "HAVE_METADATA"; break;
|
||||
case v.HAVE_CURRENT_DATA: readyState = "HAVE_CURRENT_DATA"; break;
|
||||
case v.HAVE_FUTURE_DATA: readyState = "HAVE_FUTURE_DATA"; break;
|
||||
case v.HAVE_ENOUGH_DATA: readyState = "HAVE_ENOUGH_DATA"; break;
|
||||
}
|
||||
s.readyState.textContent = readyState;
|
||||
|
||||
let networkState = v.networkState;
|
||||
switch (networkState) {
|
||||
case v.NETWORK_EMPTY: networkState = "NETWORK_EMPTY"; break;
|
||||
case v.NETWORK_IDLE: networkState = "NETWORK_IDLE"; break;
|
||||
case v.NETWORK_LOADING: networkState = "NETWORK_LOADING"; break;
|
||||
case v.NETWORK_NO_SOURCE: networkState = "NETWORK_NO_SOURCE"; break;
|
||||
}
|
||||
s.netState.textContent = networkState;
|
||||
|
||||
s.framesParsed.textContent = v.mozParsedFrames;
|
||||
s.framesDecoded.textContent = v.mozDecodedFrames;
|
||||
s.framesPresented.textContent = v.mozPresentedFrames;
|
||||
s.framesPainted.textContent = v.mozPaintedFrames;
|
||||
|
||||
let volume = Math.round(v.volume * 100) + "%";
|
||||
if (v.muted)
|
||||
volume += " (muted)";
|
||||
s.volume.textContent = volume;
|
||||
},
|
||||
|
||||
keyHandler : function(event) {
|
||||
// Ignore keys when content might be providing its own.
|
||||
if (!this.video.hasAttribute("controls"))
|
||||
|
@ -1375,7 +1218,7 @@
|
|||
|
||||
log : function (msg) {
|
||||
if (this.debug)
|
||||
dump("videoctl: " + msg + "\n");
|
||||
console.log("videoctl: " + msg + "\n");
|
||||
},
|
||||
|
||||
get isTopLevelSyntheticDocument() {
|
||||
|
@ -1476,25 +1319,12 @@
|
|||
this.durationLabel = document.getAnonymousElementByAttribute(binding, "class", "durationLabel");
|
||||
this.positionLabel = document.getAnonymousElementByAttribute(binding, "class", "positionLabel");
|
||||
this.statusOverlay = document.getAnonymousElementByAttribute(binding, "class", "statusOverlay");
|
||||
this.statsOverlay = document.getAnonymousElementByAttribute(binding, "class", "statsOverlay");
|
||||
this.controlsOverlay = document.getAnonymousElementByAttribute(binding, "class", "controlsOverlay");
|
||||
this.controlsSpacer = document.getAnonymousElementByAttribute(binding, "class", "controlsSpacer");
|
||||
this.clickToPlay = document.getAnonymousElementByAttribute(binding, "class", "clickToPlay");
|
||||
this.fullscreenButton = document.getAnonymousElementByAttribute(binding, "class", "fullscreenButton");
|
||||
this.volumeForeground = document.getAnonymousElementByAttribute(binding, "anonid", "volumeForeground");
|
||||
|
||||
this.statsTable = document.getAnonymousElementByAttribute(binding, "class", "statsTable");
|
||||
this.stats.filename = document.getAnonymousElementByAttribute(binding, "class", "statFilename");
|
||||
this.stats.size = document.getAnonymousElementByAttribute(binding, "class", "statSize");
|
||||
this.stats.activity = document.getAnonymousElementByAttribute(binding, "class", "statActivity");
|
||||
this.stats.volume = document.getAnonymousElementByAttribute(binding, "class", "statVolume");
|
||||
this.stats.readyState = document.getAnonymousElementByAttribute(binding, "class", "statReadyState");
|
||||
this.stats.netState = document.getAnonymousElementByAttribute(binding, "class", "statNetState");
|
||||
this.stats.framesParsed = document.getAnonymousElementByAttribute(binding, "class", "statFramesParsed");
|
||||
this.stats.framesDecoded = document.getAnonymousElementByAttribute(binding, "class", "statFramesDecoded");
|
||||
this.stats.framesPresented = document.getAnonymousElementByAttribute(binding, "class", "statFramesPresented");
|
||||
this.stats.framesPainted = document.getAnonymousElementByAttribute(binding, "class", "statFramesPainted");
|
||||
|
||||
this.isAudioOnly = (this.video instanceof HTMLAudioElement);
|
||||
this.setupInitialState();
|
||||
this.setupNewLoadState();
|
||||
|
@ -1517,7 +1347,7 @@
|
|||
}
|
||||
|
||||
addListener(this.muteButton, "command", this.toggleMute);
|
||||
addListener(this.playButton, "command", this.togglePause);
|
||||
addListener(this.playButton, "click", this.clickToPlayClickHandler);
|
||||
addListener(this.fullscreenButton, "command", this.toggleFullscreen);
|
||||
addListener(this.clickToPlay, "click", this.clickToPlayClickHandler);
|
||||
addListener(this.controlsSpacer, "click", this.clickToPlayClickHandler);
|
||||
|
|
|
@ -74,6 +74,7 @@ this.UpdateUtils = {
|
|||
url = url.replace(/%BUILD_ID%/g, Services.appinfo.appBuildID);
|
||||
url = url.replace(/%BUILD_TARGET%/g, Services.appinfo.OS + "_" + this.ABI);
|
||||
url = url.replace(/%OS_VERSION%/g, this.OSVersion);
|
||||
url = url.replace(/%SYSTEM_CAPABILITIES%/g, gSystemCapabilities);
|
||||
if (/%LOCALE%/.test(url)) {
|
||||
url = url.replace(/%LOCALE%/g, this.Locale);
|
||||
}
|
||||
|
@ -150,6 +151,45 @@ XPCOMUtils.defineLazyGetter(UpdateUtils, "Locale", function() {
|
|||
return null;
|
||||
});
|
||||
|
||||
/**
|
||||
* Provides adhoc system capability information for application update.
|
||||
*/
|
||||
XPCOMUtils.defineLazyGetter(this, "gSystemCapabilities", function aus_gSC() {
|
||||
if (AppConstants.platform == "win") {
|
||||
const PF_MMX_INSTRUCTIONS_AVAILABLE = 3; // MMX
|
||||
const PF_XMMI_INSTRUCTIONS_AVAILABLE = 6; // SSE
|
||||
const PF_XMMI64_INSTRUCTIONS_AVAILABLE = 10; // SSE2
|
||||
const PF_SSE3_INSTRUCTIONS_AVAILABLE = 13; // SSE3
|
||||
|
||||
let lib = ctypes.open("kernel32.dll");
|
||||
let IsProcessorFeaturePresent = lib.declare("IsProcessorFeaturePresent",
|
||||
ctypes.winapi_abi,
|
||||
ctypes.int32_t, /* success */
|
||||
ctypes.uint32_t); /* DWORD */
|
||||
let instructionSet = "unknown";
|
||||
try {
|
||||
if (IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE)) {
|
||||
instructionSet = "SSE3";
|
||||
} else if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) {
|
||||
instructionSet = "SSE2";
|
||||
} else if (IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) {
|
||||
instructionSet = "SSE";
|
||||
} else if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE)) {
|
||||
instructionSet = "MMX";
|
||||
}
|
||||
} catch (e) {
|
||||
instructionSet = "error";
|
||||
Cu.reportError("Error getting processor instruction set. " +
|
||||
"Exception: " + e);
|
||||
}
|
||||
|
||||
lib.close();
|
||||
return instructionSet;
|
||||
}
|
||||
|
||||
return "NA"
|
||||
});
|
||||
|
||||
/* Windows only getter that returns the processor architecture. */
|
||||
XPCOMUtils.defineLazyGetter(this, "gWinCPUArch", function aus_gWinCPUArch() {
|
||||
// Get processor architecture
|
||||
|
|
|
@ -349,9 +349,68 @@ function check_test_pt9() {
|
|||
run_test_pt10();
|
||||
}
|
||||
|
||||
// url constructed with %DISTRIBUTION%
|
||||
// url constructed with %SYSTEM_CAPABILITIES%
|
||||
function run_test_pt10() {
|
||||
gCheckFunc = check_test_pt10;
|
||||
let url = URL_PREFIX + "%SYSTEM_CAPABILITIES%/";
|
||||
debugDump("testing url constructed with %SYSTEM_CAPABILITIES% - " + url);
|
||||
setUpdateURLOverride(url);
|
||||
gUpdateChecker.checkForUpdates(updateCheckListener, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides system capability information for application update though it may
|
||||
* be used by other consumers.
|
||||
*/
|
||||
function getSystemCapabilities() {
|
||||
if (IS_WIN) {
|
||||
const PF_MMX_INSTRUCTIONS_AVAILABLE = 3; // MMX
|
||||
const PF_XMMI_INSTRUCTIONS_AVAILABLE = 6; // SSE
|
||||
const PF_XMMI64_INSTRUCTIONS_AVAILABLE = 10; // SSE2
|
||||
const PF_SSE3_INSTRUCTIONS_AVAILABLE = 13; // SSE3
|
||||
|
||||
let lib = ctypes.open("kernel32.dll");
|
||||
let IsProcessorFeaturePresent = lib.declare("IsProcessorFeaturePresent",
|
||||
ctypes.winapi_abi,
|
||||
ctypes.int32_t, /* success */
|
||||
ctypes.uint32_t); /* DWORD */
|
||||
let instructionSet = "unknown";
|
||||
try {
|
||||
if (IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE)) {
|
||||
instructionSet = "SSE3";
|
||||
} else if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) {
|
||||
instructionSet = "SSE2";
|
||||
} else if (IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) {
|
||||
instructionSet = "SSE";
|
||||
} else if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE)) {
|
||||
instructionSet = "MMX";
|
||||
}
|
||||
} catch (e) {
|
||||
Cu.reportError("Error getting processor instruction set. " +
|
||||
"Exception: " + e);
|
||||
}
|
||||
|
||||
lib.close();
|
||||
return instructionSet;
|
||||
}
|
||||
|
||||
return "NA"
|
||||
}
|
||||
|
||||
function check_test_pt10() {
|
||||
let systemCapabilities = "NA";
|
||||
if (IS_WIN) {
|
||||
systemCapabilities = getSystemCapabilities();
|
||||
}
|
||||
|
||||
Assert.equal(getResult(gRequestURL), systemCapabilities,
|
||||
"the url param for %SYSTEM_CAPABILITIES%" + MSG_SHOULD_EQUAL);
|
||||
run_test_pt11();
|
||||
}
|
||||
|
||||
// url constructed with %DISTRIBUTION%
|
||||
function run_test_pt11() {
|
||||
gCheckFunc = check_test_pt11;
|
||||
let url = URL_PREFIX + "%DISTRIBUTION%/";
|
||||
debugDump("testing url constructed with %DISTRIBUTION% - " + url);
|
||||
setUpdateURLOverride(url);
|
||||
|
@ -359,15 +418,15 @@ function run_test_pt10() {
|
|||
gUpdateChecker.checkForUpdates(updateCheckListener, true);
|
||||
}
|
||||
|
||||
function check_test_pt10() {
|
||||
function check_test_pt11() {
|
||||
Assert.equal(getResult(gRequestURL), "test_distro",
|
||||
"the url param for %DISTRIBUTION%" + MSG_SHOULD_EQUAL);
|
||||
run_test_pt11();
|
||||
run_test_pt12();
|
||||
}
|
||||
|
||||
// url constructed with %DISTRIBUTION_VERSION%
|
||||
function run_test_pt11() {
|
||||
gCheckFunc = check_test_pt11;
|
||||
function run_test_pt12() {
|
||||
gCheckFunc = check_test_pt12;
|
||||
let url = URL_PREFIX + "%DISTRIBUTION_VERSION%/";
|
||||
debugDump("testing url constructed with %DISTRIBUTION_VERSION% - " + url);
|
||||
setUpdateURLOverride(url);
|
||||
|
@ -375,15 +434,15 @@ function run_test_pt11() {
|
|||
gUpdateChecker.checkForUpdates(updateCheckListener, true);
|
||||
}
|
||||
|
||||
function check_test_pt11() {
|
||||
function check_test_pt12() {
|
||||
Assert.equal(getResult(gRequestURL), "test_distro_version",
|
||||
"the url param for %DISTRIBUTION_VERSION%" + MSG_SHOULD_EQUAL);
|
||||
run_test_pt12();
|
||||
run_test_pt13();
|
||||
}
|
||||
|
||||
// url with force param that doesn't already have a param - bug 454357
|
||||
function run_test_pt12() {
|
||||
gCheckFunc = check_test_pt12;
|
||||
function run_test_pt13() {
|
||||
gCheckFunc = check_test_pt13;
|
||||
let url = URL_PREFIX;
|
||||
debugDump("testing url with force param that doesn't already have a " +
|
||||
"param - " + url);
|
||||
|
@ -391,38 +450,38 @@ function run_test_pt12() {
|
|||
gUpdateChecker.checkForUpdates(updateCheckListener, true);
|
||||
}
|
||||
|
||||
function check_test_pt12() {
|
||||
function check_test_pt13() {
|
||||
Assert.equal(getResult(gRequestURL), "?force=1",
|
||||
"the url query string for force" + MSG_SHOULD_EQUAL);
|
||||
run_test_pt13();
|
||||
run_test_pt14();
|
||||
}
|
||||
|
||||
// url with force param that already has a param - bug 454357
|
||||
function run_test_pt13() {
|
||||
gCheckFunc = check_test_pt13;
|
||||
function run_test_pt14() {
|
||||
gCheckFunc = check_test_pt14;
|
||||
let url = URL_PREFIX + "?extra=param";
|
||||
debugDump("testing url with force param that already has a param - " + url);
|
||||
setUpdateURLOverride(url);
|
||||
gUpdateChecker.checkForUpdates(updateCheckListener, true);
|
||||
}
|
||||
|
||||
function check_test_pt13() {
|
||||
function check_test_pt14() {
|
||||
Assert.equal(getResult(gRequestURL), "?extra=param&force=1",
|
||||
"the url query string for force with an extra string" +
|
||||
MSG_SHOULD_EQUAL);
|
||||
run_test_pt14();
|
||||
run_test_pt15();
|
||||
}
|
||||
|
||||
function run_test_pt14() {
|
||||
function run_test_pt15() {
|
||||
Services.prefs.setCharPref("app.update.custom", "custom");
|
||||
gCheckFunc = check_test_pt14;
|
||||
gCheckFunc = check_test_pt15;
|
||||
let url = URL_PREFIX + "?custom=%CUSTOM%";
|
||||
debugDump("testing url constructed with %CUSTOM% - " + url);
|
||||
setUpdateURLOverride(url);
|
||||
gUpdateChecker.checkForUpdates(updateCheckListener, true);
|
||||
}
|
||||
|
||||
function check_test_pt14() {
|
||||
function check_test_pt15() {
|
||||
Assert.equal(getResult(gRequestURL), "?custom=custom&force=1",
|
||||
"the url query string for force with a custom string" +
|
||||
MSG_SHOULD_EQUAL);
|
||||
|
|
Загрузка…
Ссылка в новой задаче