Merge mozilla-central to autoland
@ -230,6 +230,7 @@ const SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE = SEC_ERROR_BASE + 30;
|
||||
const SEC_ERROR_OCSP_FUTURE_RESPONSE = SEC_ERROR_BASE + 131;
|
||||
const SEC_ERROR_OCSP_OLD_RESPONSE = SEC_ERROR_BASE + 132;
|
||||
const MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE = MOZILLA_PKIX_ERROR_BASE + 5;
|
||||
const MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE = MOZILLA_PKIX_ERROR_BASE + 6;
|
||||
|
||||
const PREF_BLOCKLIST_CLOCK_SKEW_SECONDS = "services.blocklist.clock_skew_seconds";
|
||||
|
||||
@ -272,10 +273,10 @@ var AboutNetAndCertErrorListener = {
|
||||
onCertErrorDetails(msg) {
|
||||
let div = content.document.getElementById("certificateErrorText");
|
||||
div.textContent = msg.data.info;
|
||||
let learnMoreLink = content.document.getElementById("learnMoreLink");
|
||||
|
||||
switch (msg.data.code) {
|
||||
case SEC_ERROR_UNKNOWN_ISSUER:
|
||||
let learnMoreLink = content.document.getElementById("learnMoreLink");
|
||||
learnMoreLink.href = "https://support.mozilla.org/kb/troubleshoot-SEC_ERROR_UNKNOWN_ISSUER";
|
||||
break;
|
||||
|
||||
@ -286,6 +287,7 @@ var AboutNetAndCertErrorListener = {
|
||||
case SEC_ERROR_OCSP_FUTURE_RESPONSE:
|
||||
case SEC_ERROR_OCSP_OLD_RESPONSE:
|
||||
case MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE:
|
||||
case MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE:
|
||||
|
||||
// use blocklist stats if available
|
||||
if (Services.prefs.getPrefType(PREF_BLOCKLIST_CLOCK_SKEW_SECONDS)) {
|
||||
@ -311,7 +313,8 @@ var AboutNetAndCertErrorListener = {
|
||||
.style.display = "block";
|
||||
}
|
||||
}
|
||||
|
||||
let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "time-errors";
|
||||
learnMoreLink.setAttribute("href", url);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
@ -125,12 +125,14 @@ add_task(function* checkWrongSystemTimeWarning() {
|
||||
let div = doc.getElementById("wrongSystemTimePanel");
|
||||
let systemDateDiv = doc.getElementById("wrongSystemTime_systemDate");
|
||||
let actualDateDiv = doc.getElementById("wrongSystemTime_actualDate");
|
||||
let learnMoreLink = doc.getElementById("learnMoreLink");
|
||||
|
||||
return {
|
||||
divDisplay: content.getComputedStyle(div).display,
|
||||
text: div.textContent,
|
||||
systemDate: systemDateDiv.textContent,
|
||||
actualDate: actualDateDiv.textContent
|
||||
actualDate: actualDateDiv.textContent,
|
||||
learnMoreLink: learnMoreLink.href
|
||||
};
|
||||
});
|
||||
}
|
||||
@ -155,6 +157,7 @@ add_task(function* checkWrongSystemTimeWarning() {
|
||||
ok(message.text.includes("expired.example.com"), "URL found in error message");
|
||||
ok(message.systemDate.includes(localDateFmt), "correct local date displayed");
|
||||
ok(message.actualDate.includes(serverDateFmt), "correct server date displayed");
|
||||
ok(message.learnMoreLink.includes("time-errors"), "time-errors in the Learn More URL");
|
||||
|
||||
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
|
||||
|
@ -220,7 +220,7 @@ add_task(function* test_search_input() {
|
||||
});
|
||||
|
||||
add_task(function* test_datetime_month_week_datetimelocal_input_todos() {
|
||||
for (let type of ["datetime", "month", "week", "datetime-local"]) {
|
||||
for (let type of ["datetime", "week", "datetime-local"]) {
|
||||
let returnedType = yield ContentTask.spawn(gBrowser.selectedBrowser, type, function*(type) {
|
||||
let doc = content.document;
|
||||
let input = doc.getElementById("input_" + type);
|
||||
|
11
browser/branding/aurora/VisualElementsManifest.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<Application xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
|
||||
<VisualElements
|
||||
DisplayName='Firefox Developer Edition'
|
||||
Logo='VisualElements\VisualElements_150.png'
|
||||
SmallLogo='VisualElements\VisualElements_70.png'
|
||||
ForegroundText='light'
|
||||
BackgroundColor='#14171a'/>
|
||||
<DefaultTile ShowName='allLogos'/>
|
||||
<SplashScreen Image='DummyFileNameRequiredByWindows.png'/>
|
||||
</VisualElements>
|
||||
</Application>
|
BIN
browser/branding/aurora/VisualElements_150.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
browser/branding/aurora/VisualElements_70.png
Normal file
After Width: | Height: | Size: 11 KiB |
@ -0,0 +1,8 @@
|
||||
<Application xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
|
||||
<VisualElements
|
||||
ShowNameOnSquare150x150Logo='on'
|
||||
Square150x150Logo='VisualElements\VisualElements_150.png'
|
||||
Square70x70Logo='VisualElements\VisualElements_70.png'
|
||||
ForegroundText='light'
|
||||
BackgroundColor='#14171a'/>
|
||||
</Application>
|
@ -11,6 +11,14 @@ def FirefoxBranding():
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
FINAL_TARGET_FILES['..'] += [
|
||||
'firefox.VisualElementsManifest.xml',
|
||||
'VisualElementsManifest.xml',
|
||||
]
|
||||
FINAL_TARGET_FILES.VisualElements += [
|
||||
'VisualElements_150.png',
|
||||
'VisualElements_70.png',
|
||||
]
|
||||
BRANDING_FILES += [
|
||||
'appname.bmp',
|
||||
'bgintro.bmp',
|
||||
|
11
browser/branding/nightly/VisualElementsManifest.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<Application xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
|
||||
<VisualElements
|
||||
DisplayName='Nightly'
|
||||
Logo='VisualElements\VisualElements_150.png'
|
||||
SmallLogo='VisualElements\VisualElements_70.png'
|
||||
ForegroundText='light'
|
||||
BackgroundColor='#14171a'/>
|
||||
<DefaultTile ShowName='allLogos'/>
|
||||
<SplashScreen Image='DummyFileNameRequiredByWindows.png'/>
|
||||
</VisualElements>
|
||||
</Application>
|
BIN
browser/branding/nightly/VisualElements_150.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
browser/branding/nightly/VisualElements_70.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
@ -0,0 +1,8 @@
|
||||
<Application xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
|
||||
<VisualElements
|
||||
ShowNameOnSquare150x150Logo='on'
|
||||
Square150x150Logo='VisualElements\VisualElements_150.png'
|
||||
Square70x70Logo='VisualElements\VisualElements_70.png'
|
||||
ForegroundText='light'
|
||||
BackgroundColor='#14171a'/>
|
||||
</Application>
|
11
browser/branding/official/VisualElementsManifest.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<Application xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
|
||||
<VisualElements
|
||||
DisplayName='Mozilla Firefox'
|
||||
Logo='VisualElements\VisualElements_150.png'
|
||||
SmallLogo='VisualElements\VisualElements_70.png'
|
||||
ForegroundText='light'
|
||||
BackgroundColor='#0996f8'/>
|
||||
<DefaultTile ShowName='allLogos'/>
|
||||
<SplashScreen Image='DummyFileNameRequiredByWindows.png'/>
|
||||
</VisualElements>
|
||||
</Application>
|
BIN
browser/branding/official/VisualElements_150.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
browser/branding/official/VisualElements_70.png
Normal file
After Width: | Height: | Size: 9.8 KiB |
@ -0,0 +1,8 @@
|
||||
<Application xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
|
||||
<VisualElements
|
||||
ShowNameOnSquare150x150Logo='on'
|
||||
Square150x150Logo='VisualElements\VisualElements_150.png'
|
||||
Square70x70Logo='VisualElements\VisualElements_70.png'
|
||||
ForegroundText='light'
|
||||
BackgroundColor='#0996f8'/>
|
||||
</Application>
|
11
browser/branding/unofficial/VisualElementsManifest.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<Application>
|
||||
<VisualElements
|
||||
DisplayName='Nightly'
|
||||
Logo='VisualElements\VisualElements_150.png'
|
||||
SmallLogo='VisualElements\VisualElements_70.png'
|
||||
ForegroundText='light'
|
||||
BackgroundColor='#14171a'>
|
||||
<DefaultTile ShowName='allLogos'/>
|
||||
<SplashScreen Image='DummyFileNameRequiredByWindows.png'/>
|
||||
</VisualElements>
|
||||
</Application>
|
BIN
browser/branding/unofficial/VisualElements_150.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
browser/branding/unofficial/VisualElements_70.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
@ -0,0 +1,8 @@
|
||||
<Application xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
|
||||
<VisualElements
|
||||
ShowNameOnSquare150x150Logo='on'
|
||||
Square150x150Logo='VisualElements\VisualElements_150.png'
|
||||
Square70x70Logo='VisualElements\VisualElements_70.png'
|
||||
ForegroundText='light'
|
||||
BackgroundColor='#14171a'/>
|
||||
</Application>
|
@ -559,6 +559,7 @@ var PlacesOrganizer = {
|
||||
fp.appendFilter(PlacesUIUtils.getString("bookmarksRestoreFilterName"),
|
||||
RESTORE_FILEPICKER_FILTER_EXT);
|
||||
fp.defaultString = PlacesBackups.getFilenameForDate();
|
||||
fp.defaultExtension = "json";
|
||||
fp.displayDirectory = backupsDir;
|
||||
fp.open(fpCallback);
|
||||
},
|
||||
|
@ -113,6 +113,10 @@
|
||||
; [Base Browser Files]
|
||||
#ifndef XP_UNIX
|
||||
@BINPATH@/@MOZ_APP_NAME@.exe
|
||||
@BINPATH@/firefox.VisualElementsManifest.xml
|
||||
@BINPATH@/VisualElementsManifest.xml
|
||||
@BINPATH@/browser/VisualElements/VisualElements_150.png
|
||||
@BINPATH@/browser/VisualElements/VisualElements_70.png
|
||||
#else
|
||||
@BINPATH@/@MOZ_APP_NAME@-bin
|
||||
@BINPATH@/@MOZ_APP_NAME@
|
||||
@ -438,6 +442,7 @@
|
||||
@RESPATH@/components/nsTaggingService.js
|
||||
@RESPATH@/components/UnifiedComplete.js
|
||||
@RESPATH@/components/nsPlacesExpiration.js
|
||||
@RESPATH@/components/PageIconProtocolHandler.js
|
||||
@RESPATH@/components/PlacesCategoriesStarter.js
|
||||
@RESPATH@/components/ColorAnalyzer.js
|
||||
@RESPATH@/components/PageThumbsProtocol.js
|
||||
|
@ -53,8 +53,6 @@ PluginContent.prototype = {
|
||||
global.addMessageListener("BrowserPlugins:NPAPIPluginProcessCrashed", this);
|
||||
global.addMessageListener("BrowserPlugins:CrashReportSubmitted", this);
|
||||
global.addMessageListener("BrowserPlugins:Test:ClearCrashData", this);
|
||||
|
||||
Services.obs.addObserver(this, "Plugin::HiddenPluginTouched", false);
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
@ -77,8 +75,6 @@ PluginContent.prototype = {
|
||||
global.removeMessageListener("BrowserPlugins:Test:ClearCrashData", this);
|
||||
delete this.global;
|
||||
delete this.content;
|
||||
|
||||
Services.obs.removeObserver(this, "Plugin::HiddenPluginTouched");
|
||||
},
|
||||
|
||||
receiveMessage: function (msg) {
|
||||
@ -120,15 +116,6 @@ PluginContent.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
let pluginTag = aSubject.QueryInterface(Ci.nsIPluginTag);
|
||||
if (aTopic == "Plugin::HiddenPluginTouched") {
|
||||
this._showClickToPlayNotification(pluginTag, false);
|
||||
} else {
|
||||
Cu.reportError("unknown topic observed: " + aTopic);
|
||||
}
|
||||
},
|
||||
|
||||
onPageShow: function (event) {
|
||||
// Ignore events that aren't from the main document.
|
||||
if (!this.content || event.target != this.content.document) {
|
||||
@ -207,45 +194,6 @@ PluginContent.prototype = {
|
||||
};
|
||||
},
|
||||
|
||||
_getPluginInfoForTag: function (pluginTag, tagMimetype) {
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
|
||||
let pluginName = gNavigatorBundle.GetStringFromName("pluginInfo.unknownPlugin");
|
||||
let permissionString = null;
|
||||
let blocklistState = null;
|
||||
|
||||
if (pluginTag) {
|
||||
pluginName = BrowserUtils.makeNicePluginName(pluginTag.name);
|
||||
|
||||
permissionString = pluginHost.getPermissionStringForTag(pluginTag);
|
||||
blocklistState = pluginTag.blocklistState;
|
||||
|
||||
// Convert this from nsIPluginTag so it can be serialized.
|
||||
let properties = ["name", "description", "filename", "version", "enabledState", "niceName"];
|
||||
let pluginTagCopy = {};
|
||||
for (let prop of properties) {
|
||||
pluginTagCopy[prop] = pluginTag[prop];
|
||||
}
|
||||
pluginTag = pluginTagCopy;
|
||||
|
||||
// Make state-softblocked == state-notblocked for our purposes,
|
||||
// they have the same UI. STATE_OUTDATED should not exist for plugin
|
||||
// items, but let's alias it anyway, just in case.
|
||||
if (blocklistState == Ci.nsIBlocklistService.STATE_SOFTBLOCKED ||
|
||||
blocklistState == Ci.nsIBlocklistService.STATE_OUTDATED) {
|
||||
blocklistState = Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
return { mimetype: tagMimetype,
|
||||
pluginName: pluginName,
|
||||
pluginTag: pluginTag,
|
||||
permissionString: permissionString,
|
||||
fallbackType: null,
|
||||
blocklistState: blocklistState,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the visibility of the plugin overlay.
|
||||
*/
|
||||
@ -762,13 +710,7 @@ PluginContent.prototype = {
|
||||
let location = this.content.document.location.href;
|
||||
|
||||
for (let p of plugins) {
|
||||
let pluginInfo;
|
||||
if (p instanceof Ci.nsIPluginTag) {
|
||||
let mimeType = p.getMimeTypes() > 0 ? p.getMimeTypes()[0] : null;
|
||||
pluginInfo = this._getPluginInfoForTag(p, mimeType);
|
||||
} else {
|
||||
pluginInfo = this._getPluginInfo(p);
|
||||
}
|
||||
let pluginInfo = this._getPluginInfo(p);
|
||||
if (pluginInfo.permissionString === null) {
|
||||
Cu.reportError("No permission string for active plugin.");
|
||||
continue;
|
||||
|
@ -43,10 +43,14 @@ if test "$MOZ_BUILD_APP" != js -o -n "$JS_STANDALONE"; then
|
||||
if test -n "$CLANG_CC" -a "$CPU_ARCH" = arm; then
|
||||
CFLAGS="-no-integrated-as $CFLAGS"
|
||||
fi
|
||||
if test "$CROSS_COMPILE"; then
|
||||
export CPPFLAGS CFLAGS LDFLAGS
|
||||
fi
|
||||
ac_configure_args="$ac_configure_args --build=$build --host=$target"
|
||||
if test "$CROSS_COMPILE"; then
|
||||
ac_configure_args="$ac_configure_args \
|
||||
CFLAGS=\"$CFLAGS\" \
|
||||
CPPFLAGS=\"$CPPFLAGS\" \
|
||||
LDFLAGS=\"$LDFLAGS\""
|
||||
fi
|
||||
CFLAGS="$old_cflags"
|
||||
if test "$_MSC_VER"; then
|
||||
# Use a wrapper script for cl and ml that looks more like gcc.
|
||||
# autotools can't quite handle an MSVC build environment yet.
|
||||
@ -83,7 +87,6 @@ if test "$MOZ_BUILD_APP" != js -o -n "$JS_STANDALONE"; then
|
||||
AC_OUTPUT_SUBDIRS(js/src/ctypes/libffi)
|
||||
ac_configure_args="$_SUBDIR_CONFIG_ARGS"
|
||||
CONFIG_FILES=$old_config_files
|
||||
CFLAGS="$old_cflags"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
@ -659,7 +659,7 @@ var DebuggerView = {
|
||||
* @return boolean
|
||||
*/
|
||||
get instrumentsPaneHidden() {
|
||||
return this._instrumentsPane.hasAttribute("pane-collapsed");
|
||||
return this._instrumentsPane.classList.contains("pane-collapsed");
|
||||
},
|
||||
|
||||
/**
|
||||
@ -689,10 +689,10 @@ var DebuggerView = {
|
||||
ViewHelpers.togglePane(aFlags, pane);
|
||||
|
||||
if (aFlags.visible) {
|
||||
button.removeAttribute("pane-collapsed");
|
||||
button.classList.remove("pane-collapsed");
|
||||
button.setAttribute("tooltiptext", this._collapsePaneString);
|
||||
} else {
|
||||
button.setAttribute("pane-collapsed", "");
|
||||
button.classList.add("pane-collapsed");
|
||||
button.setAttribute("tooltiptext", this._expandPaneString);
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,8 @@ function testPanesState() {
|
||||
let instrumentsPaneToggleButton =
|
||||
gDebugger.document.getElementById("instruments-pane-toggle");
|
||||
|
||||
ok(instrumentsPane.hasAttribute("pane-collapsed") &&
|
||||
instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
ok(instrumentsPane.classList.contains("pane-collapsed") &&
|
||||
instrumentsPaneToggleButton.classList.contains("pane-collapsed"),
|
||||
"The debugger view instruments pane should initially be hidden.");
|
||||
is(gPrefs.panesVisibleOnStartup, false,
|
||||
"The debugger view instruments pane should initially be preffed as hidden.");
|
||||
@ -65,8 +65,8 @@ function testInstrumentsPaneCollapse() {
|
||||
"The instruments pane has an incorrect right margin.");
|
||||
ok(!instrumentsPane.hasAttribute("animated"),
|
||||
"The instruments pane has an incorrect animated attribute.");
|
||||
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
ok(!instrumentsPane.classList.contains("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.classList.contains("pane-collapsed"),
|
||||
"The instruments pane should at this point be visible.");
|
||||
|
||||
gDebugger.DebuggerView.toggleInstrumentsPane({ visible: false, animated: true });
|
||||
@ -85,8 +85,8 @@ function testInstrumentsPaneCollapse() {
|
||||
"The instruments pane has an incorrect right margin after collapsing.");
|
||||
ok(instrumentsPane.hasAttribute("animated"),
|
||||
"The instruments pane has an incorrect attribute after an animated collapsing.");
|
||||
ok(instrumentsPane.hasAttribute("pane-collapsed") &&
|
||||
instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
ok(instrumentsPane.classList.contains("pane-collapsed") &&
|
||||
instrumentsPaneToggleButton.classList.contains("pane-collapsed"),
|
||||
"The instruments pane should not be visible after collapsing.");
|
||||
|
||||
gDebugger.DebuggerView.toggleInstrumentsPane({ visible: true, animated: false });
|
||||
@ -104,8 +104,8 @@ function testInstrumentsPaneCollapse() {
|
||||
"The instruments pane has an incorrect right margin after uncollapsing.");
|
||||
ok(!instrumentsPane.hasAttribute("animated"),
|
||||
"The instruments pane has an incorrect attribute after an unanimated uncollapsing.");
|
||||
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
ok(!instrumentsPane.classList.contains("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.classList.contains("pane-collapsed"),
|
||||
"The instruments pane should be visible again after uncollapsing.");
|
||||
}
|
||||
|
||||
@ -118,8 +118,8 @@ function testPanesStartupPref() {
|
||||
is(gPrefs.panesVisibleOnStartup, false,
|
||||
"The debugger view panes should still initially be preffed as hidden.");
|
||||
|
||||
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
ok(!instrumentsPane.classList.contains("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.classList.contains("pane-collapsed"),
|
||||
"The debugger instruments pane should at this point be visible.");
|
||||
is(gPrefs.panesVisibleOnStartup, false,
|
||||
"The debugger view panes should initially be preffed as hidden.");
|
||||
@ -129,8 +129,8 @@ function testPanesStartupPref() {
|
||||
gOptions._showPanesOnStartupItem.setAttribute("checked", "true");
|
||||
gOptions._toggleShowPanesOnStartup();
|
||||
|
||||
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
ok(!instrumentsPane.classList.contains("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.classList.contains("pane-collapsed"),
|
||||
"The debugger instruments pane should at this point be visible.");
|
||||
is(gPrefs.panesVisibleOnStartup, true,
|
||||
"The debugger view panes should now be preffed as visible.");
|
||||
@ -140,8 +140,8 @@ function testPanesStartupPref() {
|
||||
gOptions._showPanesOnStartupItem.setAttribute("checked", "false");
|
||||
gOptions._toggleShowPanesOnStartup();
|
||||
|
||||
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
ok(!instrumentsPane.classList.contains("pane-collapsed") &&
|
||||
!instrumentsPaneToggleButton.classList.contains("pane-collapsed"),
|
||||
"The debugger instruments pane should at this point be visible.");
|
||||
is(gPrefs.panesVisibleOnStartup, false,
|
||||
"The debugger view panes should now be preffed as hidden.");
|
||||
|
@ -144,7 +144,9 @@ ToolSidebar.prototype = {
|
||||
// Add menuitems to the alltabs menu if there are already tabs in the
|
||||
// sidebar
|
||||
for (let [id, tab] of this._tabs) {
|
||||
let item = this._addItemToAllTabsMenu(id, tab, tab.hasAttribute("selected"));
|
||||
let item = this._addItemToAllTabsMenu(id, tab, {
|
||||
selected: tab.hasAttribute("selected")
|
||||
});
|
||||
if (tab.hidden) {
|
||||
item.hidden = true;
|
||||
}
|
||||
@ -179,23 +181,30 @@ ToolSidebar.prototype = {
|
||||
/**
|
||||
* Add an item in the allTabs menu for a given tab.
|
||||
*/
|
||||
_addItemToAllTabsMenu: function (id, tab, selected = false) {
|
||||
_addItemToAllTabsMenu: function (id, tab, options) {
|
||||
if (!this._allTabsBtn) {
|
||||
return;
|
||||
}
|
||||
|
||||
let item = this._panelDoc.createElementNS(XULNS, "menuitem");
|
||||
item.setAttribute("id", "sidebar-alltabs-item-" + id);
|
||||
let idPrefix = "sidebar-alltabs-item-";
|
||||
item.setAttribute("id", idPrefix + id);
|
||||
item.setAttribute("label", tab.getAttribute("label"));
|
||||
item.setAttribute("type", "checkbox");
|
||||
if (selected) {
|
||||
if (options.selected) {
|
||||
item.setAttribute("checked", true);
|
||||
}
|
||||
// The auto-checking of menuitems in this menu doesn't work, so let's do
|
||||
// it manually
|
||||
item.setAttribute("autocheck", false);
|
||||
|
||||
this._allTabsBtn.querySelector("menupopup").appendChild(item);
|
||||
let menu = this._allTabsBtn.querySelector("menupopup");
|
||||
if (options.insertBefore) {
|
||||
let referenceItem = menu.querySelector(`#${idPrefix}${options.insertBefore}`);
|
||||
menu.insertBefore(item, referenceItem);
|
||||
} else {
|
||||
menu.appendChild(item);
|
||||
}
|
||||
|
||||
item.addEventListener("click", () => {
|
||||
this._tabbox.selectedTab = tab;
|
||||
@ -210,10 +219,14 @@ ToolSidebar.prototype = {
|
||||
* Register a tab. A tab is a document.
|
||||
* The document must have a title, which will be used as the name of the tab.
|
||||
*
|
||||
* @param {string} tab uniq id
|
||||
* @param {string} url
|
||||
* @param {string} id The unique id for this tab.
|
||||
* @param {string} url The URL of the document to load in this new tab.
|
||||
* @param {Object} options A set of options for this new tab:
|
||||
* - {Boolean} selected Set to true to make this new tab selected by default.
|
||||
* - {String} insertBefore By default, the new tab is appended at the end of the
|
||||
* tabbox, pass the ID of an existing tab to insert it before that tab instead.
|
||||
*/
|
||||
addTab: function (id, url, selected = false) {
|
||||
addTab: function (id, url, options = {}) {
|
||||
let iframe = this._panelDoc.createElementNS(XULNS, "iframe");
|
||||
iframe.className = "iframe-" + id;
|
||||
iframe.setAttribute("flex", "1");
|
||||
@ -222,13 +235,21 @@ ToolSidebar.prototype = {
|
||||
|
||||
// Creating the tab and adding it to the tabbox
|
||||
let tab = this._panelDoc.createElementNS(XULNS, "tab");
|
||||
this._tabbox.tabs.appendChild(tab);
|
||||
tab.setAttribute("label", ""); // Avoid showing "undefined" while the tab is loading
|
||||
|
||||
tab.setAttribute("id", this.TAB_ID_PREFIX + id);
|
||||
tab.setAttribute("crop", "end");
|
||||
// Avoid showing "undefined" while the tab is loading
|
||||
tab.setAttribute("label", "");
|
||||
|
||||
if (options.insertBefore) {
|
||||
let referenceTab = this.getTab(options.insertBefore);
|
||||
this._tabbox.tabs.insertBefore(tab, referenceTab);
|
||||
} else {
|
||||
this._tabbox.tabs.appendChild(tab);
|
||||
}
|
||||
|
||||
// Add the tab to the allTabs menu if exists
|
||||
let allTabsItem = this._addItemToAllTabsMenu(id, tab, selected);
|
||||
let allTabsItem = this._addItemToAllTabsMenu(id, tab, options);
|
||||
|
||||
let onIFrameLoaded = (event) => {
|
||||
let doc = event.target;
|
||||
@ -251,7 +272,13 @@ ToolSidebar.prototype = {
|
||||
let tabpanel = this._panelDoc.createElementNS(XULNS, "tabpanel");
|
||||
tabpanel.setAttribute("id", this.TABPANEL_ID_PREFIX + id);
|
||||
tabpanel.appendChild(iframe);
|
||||
this._tabbox.tabpanels.appendChild(tabpanel);
|
||||
|
||||
if (options.insertBefore) {
|
||||
let referenceTabpanel = this.getTabPanel(options.insertBefore);
|
||||
this._tabbox.tabpanels.insertBefore(tabpanel, referenceTabpanel);
|
||||
} else {
|
||||
this._tabbox.tabpanels.appendChild(tabpanel);
|
||||
}
|
||||
|
||||
this._tooltip = this._panelDoc.createElementNS(XULNS, "tooltip");
|
||||
this._tooltip.id = "aHTMLTooltip";
|
||||
@ -263,7 +290,7 @@ ToolSidebar.prototype = {
|
||||
// We store the index of this tab.
|
||||
this._tabs.set(id, tab);
|
||||
|
||||
if (selected) {
|
||||
if (options.selected) {
|
||||
this._selectTabSoon(id);
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ function test() {
|
||||
allTabsReady(panel);
|
||||
});
|
||||
|
||||
panel.sidebar.addTab("tab1", tab1URL, true);
|
||||
panel.sidebar.addTab("tab1", tab1URL, {selected: true});
|
||||
panel.sidebar.addTab("tab2", tab2URL);
|
||||
panel.sidebar.addTab("tab3", tab3URL);
|
||||
|
||||
|
@ -67,7 +67,7 @@ function test() {
|
||||
});
|
||||
|
||||
panel.sidebar.once("tab1-selected", () => finishUp(panel));
|
||||
panel.sidebar.addTab("tab1", tab1URL, true);
|
||||
panel.sidebar.addTab("tab1", tab1URL, {selected: true});
|
||||
panel.sidebar.show();
|
||||
}).then(null, console.error);
|
||||
});
|
||||
|
@ -48,7 +48,7 @@ add_task(function* () {
|
||||
info("Adding 10 tabs to the sidebar widget");
|
||||
for (let nb = 0; nb < 10; nb++) {
|
||||
let url = `data:text/html;charset=utf8,<title>tab ${nb}</title><p>Test tab ${nb}</p>`;
|
||||
sidebar.addTab("tab" + nb, url, nb === 0);
|
||||
sidebar.addTab("tab" + nb, url, {selected: nb === 0});
|
||||
}
|
||||
|
||||
info("Fake an overflow event so that the all-tabs menu is visible");
|
||||
|
@ -194,7 +194,7 @@ function CssComputedView(inspector, document, pageStyle) {
|
||||
this.searchClearButton.hidden = true;
|
||||
|
||||
// No results text.
|
||||
this.noResults = this.styleDocument.getElementById("noResults");
|
||||
this.noResults = this.styleDocument.getElementById("computedview-no-results");
|
||||
|
||||
// Refresh panel when color unit changed.
|
||||
this._handlePrefChange = this._handlePrefChange.bind(this);
|
||||
|
@ -34,6 +34,7 @@ support-files =
|
||||
[browser_computed_search-filter_context-menu.js]
|
||||
subsuite = clipboard
|
||||
[browser_computed_search-filter_escape-keypress.js]
|
||||
[browser_computed_search-filter_noproperties.js]
|
||||
[browser_computed_select-and-copy-styles.js]
|
||||
subsuite = clipboard
|
||||
[browser_computed_style-editor-link.js]
|
||||
|
@ -0,0 +1,61 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests that the "no-results" message is displayed when selecting an invalid element or
|
||||
// when all properties have been filtered out.
|
||||
|
||||
const TEST_URI = `
|
||||
<style type="text/css">
|
||||
.matches {
|
||||
color: #F00;
|
||||
background-color: #00F;
|
||||
border-color: #0F0;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<!-- comment node -->
|
||||
<span id="matches" class="matches">Some styled text</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
|
||||
let {inspector, view} = yield openComputedView();
|
||||
let propertyViews = view.propertyViews;
|
||||
|
||||
info("Select the #matches node");
|
||||
let matchesNode = yield getNodeFront("#matches", inspector);
|
||||
let onRefresh = inspector.once("computed-view-refreshed");
|
||||
yield selectNode(matchesNode, inspector);
|
||||
yield onRefresh;
|
||||
|
||||
ok(propertyViews.filter(p => p.visible).length > 0, "CSS properties are displayed");
|
||||
ok(view.noResults.hasAttribute("hidden"), "no-results message is hidden");
|
||||
|
||||
info("Select a comment node");
|
||||
let commentNode = yield inspector.walker.previousSibling(matchesNode);
|
||||
yield selectNode(commentNode, inspector);
|
||||
|
||||
is(propertyViews.filter(p => p.visible).length, 0, "No properties displayed");
|
||||
ok(!view.noResults.hasAttribute("hidden"), "no-results message is displayed");
|
||||
|
||||
info("Select the #matches node again");
|
||||
onRefresh = inspector.once("computed-view-refreshed");
|
||||
yield selectNode(matchesNode, inspector);
|
||||
yield onRefresh;
|
||||
|
||||
ok(propertyViews.filter(p => p.visible).length > 0, "CSS properties are displayed");
|
||||
ok(view.noResults.hasAttribute("hidden"), "no-results message is hidden");
|
||||
|
||||
info("Filter by 'will-not-match' and check the no-results message is displayed");
|
||||
let searchField = view.searchField;
|
||||
searchField.focus();
|
||||
synthesizeKeys("will-not-match", view.styleWindow);
|
||||
yield inspector.once("computed-view-refreshed");
|
||||
|
||||
is(propertyViews.filter(p => p.visible).length, 0, "No properties displayed");
|
||||
ok(!view.noResults.hasAttribute("hidden"), "no-results message is displayed");
|
||||
});
|
@ -383,6 +383,18 @@ InspectorPanel.prototype = {
|
||||
this.searchResultsLabel.textContent = str;
|
||||
},
|
||||
|
||||
get React() {
|
||||
return this._toolbox.React;
|
||||
},
|
||||
|
||||
get ReactDOM() {
|
||||
return this._toolbox.ReactDOM;
|
||||
},
|
||||
|
||||
get browserRequire() {
|
||||
return this._toolbox.browserRequire;
|
||||
},
|
||||
|
||||
/**
|
||||
* Build the sidebar.
|
||||
*/
|
||||
@ -407,19 +419,19 @@ InspectorPanel.prototype = {
|
||||
|
||||
this.ruleview = new RuleViewTool(this, this.panelWin);
|
||||
this.computedview = new ComputedViewTool(this, this.panelWin);
|
||||
|
||||
if (Services.prefs.getBoolPref("devtools.fontinspector.enabled") &&
|
||||
this.canGetUsedFontFaces) {
|
||||
this.fontInspector = new FontInspector(this, this.panelWin);
|
||||
this.sidebar.toggleTab(true, "fontinspector");
|
||||
}
|
||||
|
||||
this.layoutview = new LayoutView(this, this.panelWin);
|
||||
|
||||
if (this.target.form.animationsActor) {
|
||||
this.sidebar.addTab("animationinspector",
|
||||
"chrome://devtools/content/animationinspector/animation-inspector.xhtml",
|
||||
defaultTab == "animationinspector");
|
||||
{selected: defaultTab == "animationinspector",
|
||||
insertBefore: "fontinspector"});
|
||||
}
|
||||
|
||||
if (Services.prefs.getBoolPref("devtools.fontinspector.enabled") &&
|
||||
this.canGetUsedFontFaces) {
|
||||
this.fontInspector = new FontInspector(this, this.panelWin);
|
||||
this.sidebar.toggleTab(true, "fontinspector");
|
||||
}
|
||||
|
||||
this.sidebar.show(defaultTab);
|
||||
@ -431,11 +443,18 @@ InspectorPanel.prototype = {
|
||||
* Add the expand/collapse behavior for the sidebar panel.
|
||||
*/
|
||||
setupSidebarToggle: function () {
|
||||
this._paneToggleButton = this.panelDoc.getElementById("inspector-pane-toggle");
|
||||
this._paneToggleButton.setAttribute("tooltiptext",
|
||||
strings.GetStringFromName("inspector.collapsePane"));
|
||||
this._paneToggleButton.addEventListener("mousedown",
|
||||
this.onPaneToggleButtonClicked);
|
||||
let SidebarToggle = this.React.createFactory(this.browserRequire(
|
||||
"devtools/client/shared/components/sidebar-toggle"));
|
||||
|
||||
let sidebarToggle = SidebarToggle({
|
||||
onClick: this.onPaneToggleButtonClicked,
|
||||
collapsed: false,
|
||||
expandPaneTitle: strings.GetStringFromName("inspector.expandPane"),
|
||||
collapsePaneTitle: strings.GetStringFromName("inspector.collapsePane"),
|
||||
});
|
||||
|
||||
let parentBox = this.panelDoc.getElementById("inspector-sidebar-toggle-box");
|
||||
this._sidebarToggle = this.ReactDOM.render(sidebarToggle, parentBox);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -689,9 +708,6 @@ InspectorPanel.prototype = {
|
||||
|
||||
this.addNodeButton.removeEventListener("click", this.addNode);
|
||||
this.breadcrumbs.destroy();
|
||||
this._paneToggleButton.removeEventListener("mousedown",
|
||||
this.onPaneToggleButtonClicked);
|
||||
this._paneToggleButton = null;
|
||||
this.selection.off("new-node-front", this.onNewSelection);
|
||||
this.selection.off("before-new-node", this.onBeforeNewSelection);
|
||||
this.selection.off("before-new-node-front", this.onBeforeNewSelection);
|
||||
@ -1143,8 +1159,7 @@ InspectorPanel.prototype = {
|
||||
*/
|
||||
onPaneToggleButtonClicked: function (e) {
|
||||
let sidePane = this.panelDoc.querySelector("#inspector-sidebar");
|
||||
let button = this._paneToggleButton;
|
||||
let isVisible = !button.hasAttribute("pane-collapsed");
|
||||
let isVisible = !this._sidebarToggle.state.collapsed;
|
||||
|
||||
// Make sure the sidebar has width and height attributes before collapsing
|
||||
// because ViewHelpers needs it.
|
||||
@ -1165,11 +1180,9 @@ InspectorPanel.prototype = {
|
||||
}, sidePane);
|
||||
|
||||
if (isVisible) {
|
||||
button.setAttribute("pane-collapsed", "");
|
||||
button.setAttribute("tooltiptext", strings.GetStringFromName("inspector.expandPane"));
|
||||
this._sidebarToggle.setState({collapsed: true});
|
||||
} else {
|
||||
button.removeAttribute("pane-collapsed");
|
||||
button.setAttribute("tooltiptext", strings.GetStringFromName("inspector.collapsePane"));
|
||||
this._sidebarToggle.setState({collapsed: false});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -32,4 +32,8 @@
|
||||
* Override `-moz-user-focus:ignore;` from toolkit/content/minimal-xul.css
|
||||
*/
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
}
|
||||
|
||||
#inspector-sidebar-toggle-box {
|
||||
line-height: initial;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
<?xml-stylesheet href="chrome://devtools/skin/computed.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/fonts.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/layout.css" type="text/css"?>
|
||||
<?xml-stylesheet href="resource://devtools/client/shared/components/sidebar-toggle.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % inspectorDTD SYSTEM "chrome://devtools/locale/inspector.dtd"> %inspectorDTD;
|
||||
@ -39,9 +40,8 @@
|
||||
timeout="50"
|
||||
class="devtools-searchinput"
|
||||
placeholder="&inspectorSearchHTML.label3;"/>
|
||||
<html:button id="inspector-pane-toggle"
|
||||
class="devtools-button"
|
||||
tabindex="0" />
|
||||
<div xmlns="http://www.w3.org/1999/xhtml"
|
||||
id="inspector-sidebar-toggle-box" />
|
||||
</html:div>
|
||||
<vbox flex="1" id="markup-box">
|
||||
</vbox>
|
||||
@ -58,13 +58,13 @@
|
||||
<tab id="sidebar-tab-computedview"
|
||||
label="&computedViewTitle;"
|
||||
crop="end"/>
|
||||
<tab id="sidebar-tab-layoutview"
|
||||
label="&layoutViewTitle;"
|
||||
crop="end"/>
|
||||
<tab id="sidebar-tab-fontinspector"
|
||||
label="&fontInspectorTitle;"
|
||||
crop="end"
|
||||
hidden="true"/>
|
||||
<tab id="sidebar-tab-layoutview"
|
||||
label="&layoutViewTitle;"
|
||||
crop="end"/>
|
||||
</tabs>
|
||||
<tabpanels flex="1">
|
||||
<tabpanel id="sidebar-panel-ruleview" class="devtools-monospace theme-sidebar inspector-tabpanel">
|
||||
@ -111,46 +111,11 @@
|
||||
<html:div id="propertyContainer">
|
||||
</html:div>
|
||||
|
||||
<html:div id="noResults" hidden="">
|
||||
<html:div id="computedview-no-results" hidden="">
|
||||
&noPropertiesFound;
|
||||
</html:div>
|
||||
</tabpanel>
|
||||
|
||||
<tabpanel id="sidebar-panel-fontinspector" class="devtools-monospace theme-sidebar inspector-tabpanel">
|
||||
<html:div class="devtools-toolbar">
|
||||
<html:div class="devtools-searchbox">
|
||||
<html:input id="font-preview-text-input"
|
||||
class="devtools-textinput"
|
||||
type="search"
|
||||
placeholder="&previewHint;"/>
|
||||
</html:div>
|
||||
</html:div>
|
||||
|
||||
<html:div id="font-container">
|
||||
<html:ul id="all-fonts"></html:ul>
|
||||
<html:button id="font-showall">&showAllFonts;</html:button>
|
||||
</html:div>
|
||||
|
||||
<html:div id="font-template">
|
||||
<html:section class="font">
|
||||
<html:div class="font-preview-container">
|
||||
<html:img class="font-preview"></html:img>
|
||||
</html:div>
|
||||
<html:div class="font-info">
|
||||
<html:h1 class="font-name"></html:h1>
|
||||
<html:span class="font-is-local">&system;</html:span>
|
||||
<html:span class="font-is-remote">&remote;</html:span>
|
||||
<html:p class="font-format-url">
|
||||
<html:input readonly="readonly" class="font-url"></html:input>
|
||||
<html:span class="font-format"></html:span>
|
||||
</html:p>
|
||||
<html:p class="font-css">&usedAs; "<html:span class="font-css-name"></html:span>"</html:p>
|
||||
<html:pre class="font-css-code"></html:pre>
|
||||
</html:div>
|
||||
</html:section>
|
||||
</html:div>
|
||||
</tabpanel>
|
||||
|
||||
<tabpanel id="sidebar-panel-layoutview" class="devtools-monospace theme-sidebar inspector-tabpanel">
|
||||
<html:div id="layout-wrapper">
|
||||
<html:div id="layout-container">
|
||||
@ -199,6 +164,41 @@
|
||||
</html:div>
|
||||
</html:div>
|
||||
</tabpanel>
|
||||
|
||||
<tabpanel id="sidebar-panel-fontinspector" class="devtools-monospace theme-sidebar inspector-tabpanel">
|
||||
<html:div class="devtools-toolbar">
|
||||
<html:div class="devtools-searchbox">
|
||||
<html:input id="font-preview-text-input"
|
||||
class="devtools-textinput"
|
||||
type="search"
|
||||
placeholder="&previewHint;"/>
|
||||
</html:div>
|
||||
</html:div>
|
||||
|
||||
<html:div id="font-container">
|
||||
<html:ul id="all-fonts"></html:ul>
|
||||
<html:button id="font-showall">&showAllFonts;</html:button>
|
||||
</html:div>
|
||||
|
||||
<html:div id="font-template">
|
||||
<html:section class="font">
|
||||
<html:div class="font-preview-container">
|
||||
<html:img class="font-preview"></html:img>
|
||||
</html:div>
|
||||
<html:div class="font-info">
|
||||
<html:h1 class="font-name"></html:h1>
|
||||
<html:span class="font-is-local">&system;</html:span>
|
||||
<html:span class="font-is-remote">&remote;</html:span>
|
||||
<html:p class="font-format-url">
|
||||
<html:input readonly="readonly" class="font-url"></html:input>
|
||||
<html:span class="font-format"></html:span>
|
||||
</html:p>
|
||||
<html:p class="font-css">&usedAs; "<html:span class="font-css-name"></html:span>"</html:p>
|
||||
<html:pre class="font-css-code"></html:pre>
|
||||
</html:div>
|
||||
</html:section>
|
||||
</html:div>
|
||||
</tabpanel>
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
</box>
|
||||
|
@ -962,12 +962,12 @@ CssRuleView.prototype = {
|
||||
* Show the user that the rule view has no node selected.
|
||||
*/
|
||||
_showEmpty: function () {
|
||||
if (this.styleDocument.getElementById("noResults") > 0) {
|
||||
if (this.styleDocument.getElementById("ruleview-no-results")) {
|
||||
return;
|
||||
}
|
||||
|
||||
createChild(this.element, "div", {
|
||||
id: "noResults",
|
||||
id: "ruleview-no-results",
|
||||
textContent: l10n("rule.empty")
|
||||
});
|
||||
},
|
||||
|
@ -26,11 +26,11 @@ add_task(function* () {
|
||||
let {inspector, view} = yield openRuleView();
|
||||
|
||||
yield selectNode("#testid", inspector);
|
||||
is(view.element.querySelectorAll("#noResults").length, 0,
|
||||
is(view.element.querySelectorAll("#ruleview-no-results").length, 0,
|
||||
"After a highlight, no longer has a no-results element.");
|
||||
|
||||
yield clearCurrentNodeSelection(inspector);
|
||||
is(view.element.querySelectorAll("#noResults").length, 1,
|
||||
is(view.element.querySelectorAll("#ruleview-no-results").length, 1,
|
||||
"After highlighting null, has a no-results element again.");
|
||||
|
||||
yield selectNode("#testid", inspector);
|
||||
|
@ -10,18 +10,18 @@ add_task(function* () {
|
||||
info("Open the inspector in a bottom toolbox host");
|
||||
let {toolbox, inspector} = yield openInspectorForURL("about:blank", "bottom");
|
||||
|
||||
let button = inspector.panelDoc.getElementById("inspector-pane-toggle");
|
||||
let button = inspector.panelDoc.querySelector(".sidebar-toggle");
|
||||
ok(button, "The toggle button exists in the DOM");
|
||||
is(button.parentNode.id, "inspector-toolbar",
|
||||
"The toggle button is in the toolbar");
|
||||
ok(button.getAttribute("tooltiptext"), "The tool tip has initial state");
|
||||
ok(!button.hasAttribute("pane-collapsed"), "The button is in expanded state");
|
||||
is(button.parentNode.id, "inspector-sidebar-toggle-box",
|
||||
"The toggle button has the right parent");
|
||||
ok(button.getAttribute("title"), "The tool tip has initial state");
|
||||
ok(!button.classList.contains("pane-collapsed"), "The button is in expanded state");
|
||||
ok(!!button.getClientRects().length, "The button is visible");
|
||||
|
||||
info("Switch the host to side type");
|
||||
yield toolbox.switchHost("side");
|
||||
|
||||
ok(!!button.getClientRects().length, "The button is still visible");
|
||||
ok(!button.hasAttribute("pane-collapsed"),
|
||||
ok(!button.classList.contains("pane-collapsed"),
|
||||
"The button is still in expanded state");
|
||||
});
|
||||
|
@ -12,31 +12,31 @@ add_task(function* () {
|
||||
let {toolbox, inspector} = yield openInspectorForURL("about:blank", "side");
|
||||
|
||||
let panel = inspector.panelDoc.querySelector("#inspector-sidebar");
|
||||
let button = inspector.panelDoc.getElementById("inspector-pane-toggle");
|
||||
ok(!panel.hasAttribute("pane-collapsed"), "The panel is in expanded state");
|
||||
let button = inspector.panelDoc.querySelector(".sidebar-toggle");
|
||||
ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
|
||||
|
||||
info("Listen to the end of the animation on the sidebar panel");
|
||||
let onTransitionEnd = once(panel, "transitionend");
|
||||
|
||||
info("Click on the toggle button");
|
||||
EventUtils.synthesizeMouseAtCenter(button, {type: "mousedown"},
|
||||
EventUtils.synthesizeMouseAtCenter(button, {},
|
||||
inspector.panelDoc.defaultView);
|
||||
|
||||
yield onTransitionEnd;
|
||||
ok(panel.hasAttribute("pane-collapsed"), "The panel is in collapsed state");
|
||||
ok(panel.classList.contains("pane-collapsed"), "The panel is in collapsed state");
|
||||
ok(!panel.hasAttribute("animated"),
|
||||
"The collapsed panel will not perform unwanted animations");
|
||||
|
||||
info("Switch the host to bottom type");
|
||||
yield toolbox.switchHost("bottom");
|
||||
ok(panel.hasAttribute("pane-collapsed"), "The panel is in collapsed state");
|
||||
ok(panel.classList.contains("pane-collapsed"), "The panel is in collapsed state");
|
||||
|
||||
info("Click on the toggle button to expand the panel again");
|
||||
|
||||
onTransitionEnd = once(panel, "transitionend");
|
||||
EventUtils.synthesizeMouseAtCenter(button, {type: "mousedown"},
|
||||
EventUtils.synthesizeMouseAtCenter(button, {},
|
||||
inspector.panelDoc.defaultView);
|
||||
yield onTransitionEnd;
|
||||
|
||||
ok(!panel.hasAttribute("pane-collapsed"), "The panel is in expanded state");
|
||||
ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
|
||||
});
|
||||
|
@ -9,30 +9,30 @@
|
||||
add_task(function* () {
|
||||
let {inspector} = yield openInspectorForURL("about:blank");
|
||||
|
||||
let button = inspector.panelDoc.getElementById("inspector-pane-toggle");
|
||||
let button = inspector.panelDoc.querySelector(".sidebar-toggle");
|
||||
let panel = inspector.panelDoc.querySelector("#inspector-sidebar");
|
||||
|
||||
ok(!button.hasAttribute("pane-collapsed"), "The button is in expanded state");
|
||||
ok(!button.classList.contains("pane-collapsed"), "The button is in expanded state");
|
||||
|
||||
info("Listen to the end of the animation on the sidebar panel");
|
||||
let onTransitionEnd = once(panel, "transitionend");
|
||||
|
||||
info("Click on the toggle button");
|
||||
EventUtils.synthesizeMouseAtCenter(button, {type: "mousedown"},
|
||||
EventUtils.synthesizeMouseAtCenter(button, {},
|
||||
inspector.panelDoc.defaultView);
|
||||
|
||||
yield onTransitionEnd;
|
||||
ok(button.hasAttribute("pane-collapsed"), "The button is in collapsed state");
|
||||
ok(panel.hasAttribute("pane-collapsed"), "The panel is in collapsed state");
|
||||
ok(button.classList.contains("pane-collapsed"), "The button is in collapsed state");
|
||||
ok(panel.classList.contains("pane-collapsed"), "The panel is in collapsed state");
|
||||
|
||||
info("Listen again to the end of the animation on the sidebar panel");
|
||||
onTransitionEnd = once(panel, "transitionend");
|
||||
|
||||
info("Click on the toggle button again");
|
||||
EventUtils.synthesizeMouseAtCenter(button, {type: "mousedown"},
|
||||
EventUtils.synthesizeMouseAtCenter(button, {},
|
||||
inspector.panelDoc.defaultView);
|
||||
|
||||
yield onTransitionEnd;
|
||||
ok(!button.hasAttribute("pane-collapsed"), "The button is in expanded state");
|
||||
ok(!panel.hasAttribute("pane-collapsed"), "The panel is in expanded state");
|
||||
ok(!button.classList.contains("pane-collapsed"), "The button is in expanded state");
|
||||
ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
|
||||
});
|
||||
|
@ -19,7 +19,7 @@ add_task(function* () {
|
||||
});
|
||||
|
||||
let { inspector, toolbox } = yield openInspectorForURL("about:blank");
|
||||
let button = inspector.panelDoc.getElementById("inspector-pane-toggle");
|
||||
let button = inspector.panelDoc.querySelector(".sidebar-toggle");
|
||||
let panel = inspector.panelDoc.querySelector("#inspector-sidebar");
|
||||
|
||||
info("Changing toolbox host to a window.");
|
||||
@ -33,15 +33,15 @@ add_task(function* () {
|
||||
hostWindow.resizeTo(800, 300);
|
||||
|
||||
// Check the sidebar is expanded when the test starts.
|
||||
ok(!panel.hasAttribute("pane-collapsed"), "The panel is in expanded state");
|
||||
ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
|
||||
|
||||
info("Collapse the inspector sidebar.");
|
||||
let onTransitionEnd = once(panel, "transitionend");
|
||||
EventUtils.synthesizeMouseAtCenter(button, {type: "mousedown"},
|
||||
EventUtils.synthesizeMouseAtCenter(button, {},
|
||||
inspector.panelDoc.defaultView);
|
||||
yield onTransitionEnd;
|
||||
|
||||
ok(panel.hasAttribute("pane-collapsed"), "The panel is in collapsed state");
|
||||
ok(panel.classList.contains("pane-collapsed"), "The panel is in collapsed state");
|
||||
let currentPanelHeight = panel.getBoundingClientRect().height;
|
||||
let currentPanelMarginBottom = panel.style.marginBottom;
|
||||
|
||||
@ -49,7 +49,7 @@ add_task(function* () {
|
||||
hostWindow.resizeTo(300, 800);
|
||||
|
||||
// Check the panel is collapsed, and still has the same dimensions.
|
||||
ok(panel.hasAttribute("pane-collapsed"), "The panel is still collapsed");
|
||||
ok(panel.classList.contains("pane-collapsed"), "The panel is still collapsed");
|
||||
is(panel.getBoundingClientRect().height, currentPanelHeight,
|
||||
"The panel height has not been modified when changing the layout.");
|
||||
is(panel.style.marginBottom, currentPanelMarginBottom,
|
||||
|
@ -250,7 +250,7 @@ var NetMonitorView = {
|
||||
* @return boolean
|
||||
*/
|
||||
get detailsPaneHidden() {
|
||||
return this._detailsPane.hasAttribute("pane-collapsed");
|
||||
return this._detailsPane.classList.contains("pane-collapsed");
|
||||
},
|
||||
|
||||
/**
|
||||
@ -272,12 +272,12 @@ var NetMonitorView = {
|
||||
ViewHelpers.togglePane(flags, pane);
|
||||
|
||||
if (flags.visible) {
|
||||
this._body.removeAttribute("pane-collapsed");
|
||||
button.removeAttribute("pane-collapsed");
|
||||
this._body.classList.remove("pane-collapsed");
|
||||
button.classList.remove("pane-collapsed");
|
||||
button.setAttribute("tooltiptext", this._collapsePaneString);
|
||||
} else {
|
||||
this._body.setAttribute("pane-collapsed", "");
|
||||
button.setAttribute("pane-collapsed", "");
|
||||
this._body.classList.add("pane-collapsed");
|
||||
button.classList.add("pane-collapsed");
|
||||
button.setAttribute("tooltiptext", this._expandPaneString);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
@media (max-width: 700px) {
|
||||
#toolbar-spacer,
|
||||
#details-pane-toggle,
|
||||
#details-pane[pane-collapsed],
|
||||
#details-pane.pane-collapsed,
|
||||
.requests-menu-waterfall,
|
||||
#requests-menu-network-summary-button > .toolbarbutton-text {
|
||||
display: none;
|
||||
|
@ -34,15 +34,15 @@ function test() {
|
||||
|
||||
// Make sure we can now open the details pane
|
||||
NetMonitorView.toggleDetailsPane({ visible: true, animated: false });
|
||||
ok(!detailsPane.hasAttribute("pane-collapsed") &&
|
||||
!detailsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
ok(!detailsPane.classList.contains("pane-collapsed") &&
|
||||
!detailsPaneToggleButton.classList.contains("pane-collapsed"),
|
||||
"The details pane should be visible after clicking the toggle button.");
|
||||
|
||||
// Click clear and make sure the details pane closes
|
||||
EventUtils.sendMouseEvent({ type: "click" }, clearButton);
|
||||
assertNoRequestState(RequestsMenu, detailsPaneToggleButton);
|
||||
ok(detailsPane.hasAttribute("pane-collapsed") &&
|
||||
detailsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
ok(detailsPane.classList.contains("pane-collapsed") &&
|
||||
detailsPaneToggleButton.classList.contains("pane-collapsed"),
|
||||
"The details pane should not be visible clicking 'clear'.");
|
||||
|
||||
teardown(aMonitor).then(finish);
|
||||
|
@ -13,8 +13,8 @@ function test() {
|
||||
let detailsPane = document.getElementById("details-pane");
|
||||
let detailsPaneToggleButton = document.getElementById("details-pane-toggle");
|
||||
|
||||
ok(detailsPane.hasAttribute("pane-collapsed") &&
|
||||
detailsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
ok(detailsPane.classList.contains("pane-collapsed") &&
|
||||
detailsPaneToggleButton.classList.contains("pane-collapsed"),
|
||||
"The details pane should initially be hidden.");
|
||||
|
||||
NetMonitorView.toggleDetailsPane({ visible: true, animated: false });
|
||||
@ -28,8 +28,8 @@ function test() {
|
||||
"The details pane has an incorrect right margin.");
|
||||
ok(!detailsPane.hasAttribute("animated"),
|
||||
"The details pane has an incorrect animated attribute.");
|
||||
ok(!detailsPane.hasAttribute("pane-collapsed") &&
|
||||
!detailsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
ok(!detailsPane.classList.contains("pane-collapsed") &&
|
||||
!detailsPaneToggleButton.classList.contains("pane-collapsed"),
|
||||
"The details pane should at this point be visible.");
|
||||
|
||||
NetMonitorView.toggleDetailsPane({ visible: false, animated: true });
|
||||
@ -43,8 +43,8 @@ function test() {
|
||||
"The details pane has an incorrect right margin after collapsing.");
|
||||
ok(detailsPane.hasAttribute("animated"),
|
||||
"The details pane has an incorrect attribute after an animated collapsing.");
|
||||
ok(detailsPane.hasAttribute("pane-collapsed") &&
|
||||
detailsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
ok(detailsPane.classList.contains("pane-collapsed") &&
|
||||
detailsPaneToggleButton.classList.contains("pane-collapsed"),
|
||||
"The details pane should not be visible after collapsing.");
|
||||
|
||||
NetMonitorView.toggleDetailsPane({ visible: true, animated: false });
|
||||
@ -57,8 +57,8 @@ function test() {
|
||||
"The details pane has an incorrect right margin after uncollapsing.");
|
||||
ok(!detailsPane.hasAttribute("animated"),
|
||||
"The details pane has an incorrect attribute after an unanimated uncollapsing.");
|
||||
ok(!detailsPane.hasAttribute("pane-collapsed") &&
|
||||
!detailsPaneToggleButton.hasAttribute("pane-collapsed"),
|
||||
ok(!detailsPane.classList.contains("pane-collapsed") &&
|
||||
!detailsPaneToggleButton.classList.contains("pane-collapsed"),
|
||||
"The details pane should be visible again after uncollapsing.");
|
||||
|
||||
teardown(aMonitor).then(finish);
|
||||
|
@ -18,7 +18,7 @@ function test() {
|
||||
.hasAttribute("disabled"), true,
|
||||
"The pane toggle button should be disabled when the frontend is opened.");
|
||||
is(document.querySelector("#details-pane-toggle")
|
||||
.hasAttribute("pane-collapsed"), true,
|
||||
.classList.contains("pane-collapsed"), true,
|
||||
"The pane toggle button should indicate that the details pane is " +
|
||||
"collapsed when the frontend is opened.");
|
||||
is(NetMonitorView.detailsPaneHidden, true,
|
||||
@ -31,7 +31,7 @@ function test() {
|
||||
.hasAttribute("disabled"), false,
|
||||
"The pane toggle button should be enabled after the first request.");
|
||||
is(document.querySelector("#details-pane-toggle")
|
||||
.hasAttribute("pane-collapsed"), true,
|
||||
.classList.contains("pane-collapsed"), true,
|
||||
"The pane toggle button should still indicate that the details pane is " +
|
||||
"collapsed after the first request.");
|
||||
is(NetMonitorView.detailsPaneHidden, true,
|
||||
@ -46,7 +46,7 @@ function test() {
|
||||
.hasAttribute("disabled"), false,
|
||||
"The pane toggle button should still be enabled after being pressed.");
|
||||
is(document.querySelector("#details-pane-toggle")
|
||||
.hasAttribute("pane-collapsed"), false,
|
||||
.classList.contains("pane-collapsed"), false,
|
||||
"The pane toggle button should now indicate that the details pane is " +
|
||||
"not collapsed anymore after being pressed.");
|
||||
is(NetMonitorView.detailsPaneHidden, false,
|
||||
@ -63,7 +63,7 @@ function test() {
|
||||
.hasAttribute("disabled"), false,
|
||||
"The pane toggle button should still be enabled after being pressed again.");
|
||||
is(document.querySelector("#details-pane-toggle")
|
||||
.hasAttribute("pane-collapsed"), true,
|
||||
.classList.contains("pane-collapsed"), true,
|
||||
"The pane toggle button should now indicate that the details pane is " +
|
||||
"collapsed after being pressed again.");
|
||||
is(NetMonitorView.detailsPaneHidden, true,
|
||||
|
@ -323,7 +323,7 @@ pref("devtools.editor.enableCodeFolding", true);
|
||||
pref("devtools.editor.autocomplete", true);
|
||||
|
||||
// Enable the Font Inspector
|
||||
pref("devtools.fontinspector.enabled", false);
|
||||
pref("devtools.fontinspector.enabled", true);
|
||||
|
||||
// Pref to store the browser version at the time of a telemetry ping for an
|
||||
// opened developer tool. This allows us to ping telemetry just once per browser
|
||||
|
@ -706,7 +706,7 @@ var ProjectEditor = Class({
|
||||
},
|
||||
|
||||
get sourcesVisible() {
|
||||
return this.sourceToggle.hasAttribute("pane-collapsed");
|
||||
return this.sourceToggle.classList.contains("pane-collapsed");
|
||||
},
|
||||
|
||||
get currentShell() {
|
||||
|
@ -2309,7 +2309,7 @@ ScratchpadSidebar.prototype = {
|
||||
}
|
||||
else {
|
||||
this._sidebar.once("variablesview-ready", onTabReady);
|
||||
this._sidebar.addTab("variablesview", VARIABLES_VIEW_URL, true);
|
||||
this._sidebar.addTab("variablesview", VARIABLES_VIEW_URL, {selected: true});
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
|
@ -15,6 +15,8 @@ DevToolsModules(
|
||||
'h-split-box.js',
|
||||
'notification-box.css',
|
||||
'notification-box.js',
|
||||
'sidebar-toggle.css',
|
||||
'sidebar-toggle.js',
|
||||
'stack-trace.js',
|
||||
'tree.js',
|
||||
)
|
||||
|
@ -50,16 +50,13 @@ define(function (require, exports, module) {
|
||||
return items;
|
||||
}
|
||||
|
||||
let provider = this.props.provider;
|
||||
if (!provider) {
|
||||
return items;
|
||||
}
|
||||
|
||||
let delim;
|
||||
let provider = this.props.provider;
|
||||
|
||||
for (let i = 0; i < array.length && i <= max; i++) {
|
||||
try {
|
||||
let value = provider.getValue(array[i]);
|
||||
let itemGrip = array[i];
|
||||
let value = provider ? provider.getValue(itemGrip) : itemGrip;
|
||||
|
||||
delim = (i == array.length - 1 ? "" : ", ");
|
||||
|
||||
|
24
devtools/client/shared/components/sidebar-toggle.css
Normal file
@ -0,0 +1,24 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.sidebar-toggle {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sidebar-toggle::before {
|
||||
background-image: var(--theme-pane-collapse-image);
|
||||
}
|
||||
|
||||
.sidebar-toggle.pane-collapsed::before {
|
||||
background-image: var(--theme-pane-expand-image);
|
||||
}
|
||||
|
||||
/* Rotate button icon 90deg if the toolbox container is
|
||||
in vertical mode (sidebar displayed under the main panel) */
|
||||
@media (max-width: 700px) {
|
||||
.sidebar-toggle::before {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
66
devtools/client/shared/components/sidebar-toggle.js
Normal file
@ -0,0 +1,66 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { DOM, createClass, PropTypes } = require("devtools/client/shared/vendor/react");
|
||||
|
||||
// Shortcuts
|
||||
const { button } = DOM;
|
||||
|
||||
/**
|
||||
* Sidebar toggle button. This button is used to exapand
|
||||
* and collapse Sidebar.
|
||||
*/
|
||||
var SidebarToggle = createClass({
|
||||
displayName: "SidebarToggle",
|
||||
|
||||
propTypes: {
|
||||
// Set to true if collapsed.
|
||||
collapsed: PropTypes.bool.isRequired,
|
||||
// Tooltip text used when the button indicates expanded state.
|
||||
collapsePaneTitle: PropTypes.string.isRequired,
|
||||
// Tooltip text used when the button indicates collapsed state.
|
||||
expandPaneTitle: PropTypes.string.isRequired,
|
||||
// Click callback
|
||||
onClick: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
return {
|
||||
collapsed: this.props.collapsed,
|
||||
};
|
||||
},
|
||||
|
||||
// Events
|
||||
|
||||
onClick: function (event) {
|
||||
this.props.onClick(event);
|
||||
},
|
||||
|
||||
// Rendering
|
||||
|
||||
render: function () {
|
||||
let title = this.state.collapsed ?
|
||||
this.props.expandPaneTitle :
|
||||
this.props.collapsePaneTitle;
|
||||
|
||||
let classNames = ["devtools-button", "sidebar-toggle"];
|
||||
if (this.state.collapsed) {
|
||||
classNames.push("pane-collapsed");
|
||||
}
|
||||
|
||||
return (
|
||||
button({
|
||||
className: classNames.join(" "),
|
||||
title: title,
|
||||
onClick: this.onClick
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = SidebarToggle;
|
@ -2,6 +2,7 @@
|
||||
support-files =
|
||||
head.js
|
||||
|
||||
[test_frame_01.html]
|
||||
[test_HSplitBox_01.html]
|
||||
[test_notification_box_01.html]
|
||||
[test_notification_box_02.html]
|
||||
@ -11,12 +12,13 @@ support-files =
|
||||
[test_reps_function.html]
|
||||
[test_reps_grip.html]
|
||||
[test_reps_null.html]
|
||||
[test_reps_number.html]
|
||||
[test_reps_object-with-text.html]
|
||||
[test_reps_object-with-url.html]
|
||||
[test_reps_stylesheet.html]
|
||||
[test_reps_undefined.html]
|
||||
[test_reps_window.html]
|
||||
[test_frame_01.html]
|
||||
[test_sidebar_toggle.html]
|
||||
[test_tree_01.html]
|
||||
[test_tree_02.html]
|
||||
[test_tree_03.html]
|
||||
|
@ -0,0 +1,75 @@
|
||||
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test Number rep
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Rep test - Number</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script src="head.js" type="application/javascript;version=1.8"></script>
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
let { Rep } = browserRequire("devtools/client/shared/components/reps/rep");
|
||||
let { Number } = browserRequire("devtools/client/shared/components/reps/number");
|
||||
|
||||
try {
|
||||
yield testInt();
|
||||
yield testBoolean();
|
||||
yield testUnsafeInt();
|
||||
} catch(e) {
|
||||
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
|
||||
} finally {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
||||
function testInt() {
|
||||
const renderedRep = shallowRenderComponent(Rep, { object: getGripStub("testInt") });
|
||||
is(renderedRep.type, Number.rep, `Rep correctly selects ${Number.rep.displayName} for integer value`);
|
||||
|
||||
const renderedComponent = renderComponent(Number.rep, { object: getGripStub("testInt") });
|
||||
is(renderedComponent.textContent, "5", "Number rep has expected text content for integer");
|
||||
}
|
||||
|
||||
function testBoolean() {
|
||||
const renderedRep = shallowRenderComponent(Rep, { object: getGripStub("testTrue") });
|
||||
is(renderedRep.type, Number.rep, `Rep correctly selects ${Number.rep.displayName} for boolean value`);
|
||||
|
||||
let renderedComponent = renderComponent(Number.rep, { object: getGripStub("testTrue") });
|
||||
is(renderedComponent.textContent, "true", "Number rep has expected text content for boolean true");
|
||||
|
||||
renderedComponent = renderComponent(Number.rep, { object: getGripStub("testFalse") });
|
||||
is(renderedComponent.textContent, "false", "Number rep has expected text content for boolean false");
|
||||
}
|
||||
|
||||
function testUnsafeInt() {
|
||||
const renderedComponent = renderComponent(Number.rep, { object: getGripStub("testUnsafeInt") });
|
||||
is(renderedComponent.textContent, "900719925474099100", "Number rep has expected text content for a long number");
|
||||
}
|
||||
|
||||
function getGripStub(name) {
|
||||
switch (name) {
|
||||
case "testInt":
|
||||
return 5;
|
||||
|
||||
case "testTrue":
|
||||
return true;
|
||||
|
||||
case "testFalse":
|
||||
return false;
|
||||
|
||||
case "testUnsafeInt":
|
||||
return 900719925474099122;
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,53 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test sidebar toggle button
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Sidebar toggle button test</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script src="head.js" type="application/javascript;version=1.8"></script>
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
let SidebarToggle = browserRequire("devtools/client/shared/components/sidebar-toggle.js");
|
||||
|
||||
try {
|
||||
yield test();
|
||||
} catch(e) {
|
||||
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
|
||||
} finally {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function test() {
|
||||
const output1 = shallowRenderComponent(SidebarToggle, {
|
||||
collapsed: false,
|
||||
collapsePaneTitle: "Expand",
|
||||
expandPaneTitle: "Collapse"
|
||||
});
|
||||
|
||||
is(output1.type, "button", "Output is a button element");
|
||||
is(output1.props.title, "Expand", "Proper title is set");
|
||||
is(output1.props.className.indexOf("pane-collapsed"), -1,
|
||||
"Proper class name is set");
|
||||
|
||||
const output2 = shallowRenderComponent(SidebarToggle, {
|
||||
collapsed: true,
|
||||
collapsePaneTitle: "Expand",
|
||||
expandPaneTitle: "Collapse"
|
||||
});
|
||||
|
||||
is(output2.props.title, "Collapse", "Proper title is set");
|
||||
ok(output2.props.className.indexOf("pane-collapsed") >= 0,
|
||||
"Proper class name is set");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -534,7 +534,8 @@ DeveloperToolbar.prototype.show = function (focus) {
|
||||
if (!DeveloperToolbar.introShownThisSession) {
|
||||
let intro = require("gcli/ui/intro");
|
||||
intro.maybeShowIntro(this.requisition.commandOutputManager,
|
||||
this.requisition.conversionContext);
|
||||
this.requisition.conversionContext,
|
||||
this.outputPanel);
|
||||
DeveloperToolbar.introShownThisSession = true;
|
||||
}
|
||||
|
||||
|
@ -800,7 +800,7 @@ TableWidget.prototype = {
|
||||
* Removes the row associated with the `item` object.
|
||||
*/
|
||||
remove: function (item) {
|
||||
if (typeof item == "string") {
|
||||
if (typeof item != "object") {
|
||||
item = this.items.get(item);
|
||||
}
|
||||
if (!item) {
|
||||
|
@ -244,7 +244,7 @@ const ViewHelpers = exports.ViewHelpers = {
|
||||
pane.classList.add("generic-toggled-pane");
|
||||
|
||||
// Avoid useless toggles.
|
||||
if (flags.visible == !pane.hasAttribute("pane-collapsed")) {
|
||||
if (flags.visible == !pane.classList.contains("pane-collapsed")) {
|
||||
if (flags.callback) {
|
||||
flags.callback();
|
||||
}
|
||||
@ -267,14 +267,14 @@ const ViewHelpers = exports.ViewHelpers = {
|
||||
pane.style.marginLeft = "0";
|
||||
pane.style.marginRight = "0";
|
||||
pane.style.marginBottom = "0";
|
||||
pane.removeAttribute("pane-collapsed");
|
||||
pane.classList.remove("pane-collapsed");
|
||||
} else {
|
||||
let width = Math.floor(pane.getAttribute("width")) + 1;
|
||||
let height = Math.floor(pane.getAttribute("height")) + 1;
|
||||
pane.style.marginLeft = -width + "px";
|
||||
pane.style.marginRight = -width + "px";
|
||||
pane.style.marginBottom = -height + "px";
|
||||
pane.setAttribute("pane-collapsed", "");
|
||||
pane.classList.add("pane-collapsed");
|
||||
}
|
||||
|
||||
// Wait for the animation to end before calling afterToggle()
|
||||
|
@ -14,7 +14,9 @@ const TEST_CASES = [
|
||||
[["sessionStorage", "http://test1.example.org"],
|
||||
"ss1", "name"],
|
||||
[["cookies", "test1.example.org"],
|
||||
"c1", "name"]
|
||||
"c1", "name"],
|
||||
[["indexedDB", "http://test1.example.org", "idb1", "obj1"],
|
||||
1, "name"]
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
@ -23,18 +25,19 @@ add_task(function* () {
|
||||
let contextMenu = gPanelWindow.document.getElementById("storage-table-popup");
|
||||
let menuDeleteItem = contextMenu.querySelector("#storage-table-popup-delete");
|
||||
|
||||
for (let [ [store, host], rowName, cellToClick] of TEST_CASES) {
|
||||
info(`Selecting tree item ${store} > ${host}`);
|
||||
yield selectTreeItem([store, host]);
|
||||
for (let [ treeItem, rowName, cellToClick] of TEST_CASES) {
|
||||
let treeItemName = treeItem.join(" > ");
|
||||
|
||||
info(`Selecting tree item ${treeItemName}`);
|
||||
yield selectTreeItem(treeItem);
|
||||
|
||||
let row = getRowCells(rowName);
|
||||
ok(gUI.table.items.has(rowName),
|
||||
`There is a row '${rowName}' in ${store} > ${host}`);
|
||||
ok(gUI.table.items.has(rowName), `There is a row '${rowName}' in ${treeItemName}`);
|
||||
|
||||
let eventWait = gUI.once("store-objects-updated");
|
||||
|
||||
yield waitForContextMenu(contextMenu, row[cellToClick], () => {
|
||||
info(`Opened context menu in ${store} > ${host}, row '${rowName}'`);
|
||||
info(`Opened context menu in ${treeItemName}, row '${rowName}'`);
|
||||
menuDeleteItem.click();
|
||||
ok(menuDeleteItem.getAttribute("label").includes(rowName),
|
||||
`Context menu item label contains '${rowName}'`);
|
||||
@ -43,7 +46,7 @@ add_task(function* () {
|
||||
yield eventWait;
|
||||
|
||||
ok(!gUI.table.items.has(rowName),
|
||||
`There is no row '${rowName}' in ${store} > ${host} after deletion`);
|
||||
`There is no row '${rowName}' in ${treeItemName} after deletion`);
|
||||
}
|
||||
|
||||
yield finishTests();
|
||||
|
@ -29,6 +29,8 @@ add_task(function* () {
|
||||
["iframe-u-ss1", "iframe-u-ss2"]],
|
||||
[["sessionStorage", "https://sectest1.example.org"],
|
||||
["iframe-s-ss1"]],
|
||||
[["indexedDB", "http://test1.example.org", "idb1", "obj1"],
|
||||
[1, 2, 3]],
|
||||
];
|
||||
|
||||
yield checkState(beforeState);
|
||||
@ -37,6 +39,7 @@ add_task(function* () {
|
||||
const deleteHosts = [
|
||||
[["localStorage", "https://sectest1.example.org"], "iframe-s-ls1"],
|
||||
[["sessionStorage", "https://sectest1.example.org"], "iframe-s-ss1"],
|
||||
[["indexedDB", "http://test1.example.org", "idb1", "obj1"], 1],
|
||||
];
|
||||
|
||||
for (let [store, rowName] of deleteHosts) {
|
||||
@ -71,6 +74,8 @@ add_task(function* () {
|
||||
["iframe-u-ss1", "iframe-u-ss2"]],
|
||||
[["sessionStorage", "https://sectest1.example.org"],
|
||||
[]],
|
||||
[["indexedDB", "http://test1.example.org", "idb1", "obj1"],
|
||||
[]],
|
||||
];
|
||||
|
||||
yield checkState(afterState);
|
||||
|
@ -20,6 +20,7 @@ add_task(function* () {
|
||||
[["cookies", "test1.example.org"], ["c1", "c3", "cs2", "uc1"]],
|
||||
[["localStorage", "http://test1.example.org"], ["ls1", "ls2"]],
|
||||
[["sessionStorage", "http://test1.example.org"], ["ss1"]],
|
||||
[["indexedDB", "http://test1.example.org", "idb1", "obj1"], [1, 2, 3]],
|
||||
]);
|
||||
|
||||
info("do the delete");
|
||||
@ -27,6 +28,7 @@ add_task(function* () {
|
||||
["cookies", "test1.example.org"],
|
||||
["localStorage", "http://test1.example.org"],
|
||||
["sessionStorage", "http://test1.example.org"],
|
||||
["indexedDB", "http://test1.example.org", "idb1", "obj1"],
|
||||
];
|
||||
|
||||
for (let store of deleteHosts) {
|
||||
@ -54,6 +56,7 @@ add_task(function* () {
|
||||
[["cookies", "test1.example.org"], []],
|
||||
[["localStorage", "http://test1.example.org"], []],
|
||||
[["sessionStorage", "http://test1.example.org"], []],
|
||||
[["indexedDB", "http://test1.example.org", "idb1", "obj1"], []],
|
||||
]);
|
||||
|
||||
yield finishTests();
|
||||
|
@ -253,15 +253,47 @@ StorageUI.prototype = {
|
||||
/**
|
||||
* Event handler for "stores-cleared" event coming from the storage actor.
|
||||
*
|
||||
* @param {object} argument0
|
||||
* @param {object} response
|
||||
* An object containing which storage types were cleared
|
||||
*/
|
||||
onCleared: function (response) {
|
||||
let [type, host] = this.tree.selectedItem;
|
||||
if (response.hasOwnProperty(type) && response[type].indexOf(host) > -1) {
|
||||
this.table.clear();
|
||||
this.hideSidebar();
|
||||
this.emit("store-objects-cleared");
|
||||
function* enumPaths() {
|
||||
for (let type in response) {
|
||||
if (Array.isArray(response[type])) {
|
||||
// Handle the legacy response with array of hosts
|
||||
for (let host of response[type]) {
|
||||
yield [type, host];
|
||||
}
|
||||
} else {
|
||||
// Handle the new format that supports clearing sub-stores in a host
|
||||
for (let host in response[type]) {
|
||||
let paths = response[type][host];
|
||||
|
||||
if (!paths.length) {
|
||||
yield [type, host];
|
||||
} else {
|
||||
for (let path of paths) {
|
||||
try {
|
||||
path = JSON.parse(path);
|
||||
yield [type, host, ...path];
|
||||
} catch (ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let path of enumPaths()) {
|
||||
// Find if the path is selected (there is max one) and clear it
|
||||
if (this.tree.isSelected(path)) {
|
||||
this.table.clear();
|
||||
this.hideSidebar();
|
||||
this.emit("store-objects-cleared");
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -813,16 +845,20 @@ StorageUI.prototype = {
|
||||
|
||||
/**
|
||||
* Fires before a cell context menu with the "Delete" action is shown.
|
||||
* If the current storage actor doesn't support removing items, prevent
|
||||
* If the currently selected storage object doesn't support removing items, prevent
|
||||
* showing the menu.
|
||||
*/
|
||||
onTablePopupShowing: function (event) {
|
||||
if (!this.getCurrentActor().removeItem) {
|
||||
let selectedItem = this.tree.selectedItem;
|
||||
let type = selectedItem[0];
|
||||
let actor = this.getCurrentActor();
|
||||
|
||||
// IndexedDB only supports removing items from object stores (level 4 of the tree)
|
||||
if (!actor.removeItem || (type === "indexedDB" && selectedItem.length !== 4)) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
let [type] = this.tree.selectedItem;
|
||||
let rowId = this.table.contextMenuRowId;
|
||||
let data = this.table.items.get(rowId);
|
||||
let name = addEllipsis(data[this.table.uniqueId]);
|
||||
@ -846,13 +882,20 @@ StorageUI.prototype = {
|
||||
let selectedItem = this.tree.selectedItem;
|
||||
|
||||
if (selectedItem) {
|
||||
// this.currentActor() would return wrong value here
|
||||
let actor = this.storageTypes[selectedItem[0]];
|
||||
let type = selectedItem[0];
|
||||
let actor = this.storageTypes[type];
|
||||
|
||||
// The delete all (aka clear) action is displayed for IndexedDB object stores
|
||||
// (level 4 of tree) and for the whole host (level 2 of tree) of other storage
|
||||
// types (cookies, localStorage, ...).
|
||||
let showDeleteAll = actor.removeAll &&
|
||||
(selectedItem.length === (type === "indexedDB" ? 4 : 2));
|
||||
|
||||
let showDeleteAll = selectedItem.length == 2 && actor.removeAll;
|
||||
this._treePopupDeleteAll.hidden = !showDeleteAll;
|
||||
|
||||
let showDeleteDb = selectedItem.length == 3 && actor.removeDatabase;
|
||||
// The action to delete database is available for IndexedDB databases, i.e.,
|
||||
// at level 3 of the tree.
|
||||
let showDeleteDb = actor.removeDatabase && selectedItem.length === 3;
|
||||
this._treePopupDeleteDatabase.hidden = !showDeleteDb;
|
||||
if (showDeleteDb) {
|
||||
let dbName = addEllipsis(selectedItem[2]);
|
||||
@ -872,12 +915,15 @@ StorageUI.prototype = {
|
||||
* Handles removing an item from the storage
|
||||
*/
|
||||
onRemoveItem: function () {
|
||||
let [, host] = this.tree.selectedItem;
|
||||
let [, host, ...path] = this.tree.selectedItem;
|
||||
let actor = this.getCurrentActor();
|
||||
let rowId = this.table.contextMenuRowId;
|
||||
let data = this.table.items.get(rowId);
|
||||
|
||||
actor.removeItem(host, data[this.table.uniqueId]);
|
||||
let name = data[this.table.uniqueId];
|
||||
if (path.length > 0) {
|
||||
name = JSON.stringify([...path, name]);
|
||||
}
|
||||
actor.removeItem(host, name);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -887,10 +933,10 @@ StorageUI.prototype = {
|
||||
// Cannot use this.currentActor() if the handler is called from the
|
||||
// tree context menu: it returns correct value only after the table
|
||||
// data from server are successfully fetched (and that's async).
|
||||
let [type, host] = this.tree.selectedItem;
|
||||
let [type, host, ...path] = this.tree.selectedItem;
|
||||
let actor = this.storageTypes[type];
|
||||
|
||||
actor.removeAll(host);
|
||||
let name = path.length > 0 ? JSON.stringify(path) : undefined;
|
||||
actor.removeAll(host, name);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -141,10 +141,8 @@
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#noResults {
|
||||
font-size: 110%;
|
||||
margin: 5px;
|
||||
text-align: center;
|
||||
#computedview-no-results {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.onlyuserstyles {
|
||||
|
@ -643,7 +643,7 @@
|
||||
list-style-image: var(--theme-pane-collapse-image);
|
||||
}
|
||||
|
||||
#instruments-pane-toggle[pane-collapsed] {
|
||||
#instruments-pane-toggle.pane-collapsed {
|
||||
list-style-image: var(--theme-pane-expand-image);
|
||||
}
|
||||
|
||||
|
@ -78,26 +78,17 @@
|
||||
font: message-box;
|
||||
}
|
||||
|
||||
/* Expand/collapse panel toolbar button */
|
||||
|
||||
#inspector-pane-toggle::before {
|
||||
background-image: var(--theme-pane-collapse-image);
|
||||
}
|
||||
|
||||
#inspector-pane-toggle[pane-collapsed]::before {
|
||||
background-image: var(--theme-pane-expand-image);
|
||||
}
|
||||
|
||||
/* Rotate button icon 90deg if the toolbox container is
|
||||
in vertical mode (sidebar displayed under the main panel) */
|
||||
@media (max-width: 700px) {
|
||||
#inspector-pane-toggle::before {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add element toolbar button */
|
||||
|
||||
#inspector-element-add-button::before {
|
||||
background-image: url("chrome://devtools/skin/images/add.svg");
|
||||
}
|
||||
|
||||
/* "no results" warning message displayed in the ruleview and in the computed view */
|
||||
|
||||
#ruleview-no-results,
|
||||
#computedview-no-results {
|
||||
color: var(--theme-body-color-inactive);
|
||||
text-align: center;
|
||||
margin: 5px;
|
||||
}
|
||||
|
@ -510,7 +510,7 @@
|
||||
list-style-image: var(--theme-pane-collapse-image);
|
||||
}
|
||||
|
||||
#details-pane-toggle[pane-collapsed] {
|
||||
#details-pane-toggle.pane-collapsed {
|
||||
list-style-image: var(--theme-pane-expand-image);
|
||||
}
|
||||
|
||||
|
@ -198,8 +198,7 @@
|
||||
border-left: solid 10px;
|
||||
}
|
||||
|
||||
.ruleview-rule,
|
||||
#noResults {
|
||||
.ruleview-rule {
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
@ -267,11 +266,6 @@
|
||||
color: #CCCCCC;
|
||||
}
|
||||
|
||||
#noResults {
|
||||
font: message-box;
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
.ruleview-rule + .ruleview-rule {
|
||||
border-top-width: 1px;
|
||||
border-top-style: dotted;
|
||||
|
@ -149,7 +149,7 @@ text {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
#inspector-pane-toggle[pane-collapsed] {
|
||||
#inspector-pane-toggle.pane-collapsed {
|
||||
list-style-image: var(--theme-pane-expand-image);
|
||||
}
|
||||
|
||||
|
@ -186,7 +186,7 @@ a {
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
border-radius: 50%;
|
||||
margin-left: 5px;
|
||||
margin-inline-start: 5px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
}
|
||||
@ -565,7 +565,7 @@ a.learn-more-link.webconsole-learn-more-link {
|
||||
.webconsole-filter-button > .toolbarbutton-menubutton-button:before {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-left: 1px;
|
||||
margin-inline-start: 1px;
|
||||
}
|
||||
.toolbarbutton-menubutton-dropmarker {
|
||||
margin: 0px;
|
||||
|
@ -97,7 +97,7 @@
|
||||
cursor: n-resize;
|
||||
}
|
||||
|
||||
.devtools-responsive-container > .devtools-sidebar-tabs:not([pane-collapsed]) {
|
||||
.devtools-responsive-container > .devtools-sidebar-tabs:not(.pane-collapsed) {
|
||||
/* When the panel is collapsed min/max height should not be applied because
|
||||
collapsing relies on negative margins, which implies constant height. */
|
||||
min-height: 35vh;
|
||||
@ -351,6 +351,7 @@
|
||||
.theme-firebug .breadcrumbs-widget-item {
|
||||
margin-inline-start: 10px;
|
||||
margin-inline-end: 1px;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
color: #141414;
|
||||
border-radius: 2px;
|
||||
|
@ -65,7 +65,7 @@ var ToggleMixin = {
|
||||
* is currently being shown.
|
||||
*/
|
||||
isVisible: function () {
|
||||
return !this.el.hasAttribute("pane-collapsed");
|
||||
return !this.el.classList.contains("pane-collapsed");
|
||||
},
|
||||
|
||||
/**
|
||||
@ -88,11 +88,11 @@ var ToggleMixin = {
|
||||
ViewHelpers.togglePane(flags, this.el);
|
||||
|
||||
if (flags.visible) {
|
||||
this.button.removeAttribute("pane-collapsed");
|
||||
this.button.classList.remove("pane-collapsed");
|
||||
this.button.setAttribute("tooltiptext", this._collapseString);
|
||||
}
|
||||
else {
|
||||
this.button.setAttribute("pane-collapsed", "");
|
||||
this.button.classList.add("pane-collapsed");
|
||||
this.button.setAttribute("tooltiptext", this._expandString);
|
||||
}
|
||||
},
|
||||
|
@ -657,7 +657,7 @@ JSTerm.prototype = {
|
||||
}
|
||||
} else {
|
||||
this.sidebar.once("variablesview-ready", onTabReady);
|
||||
this.sidebar.addTab("variablesview", VARIABLES_VIEW_URL, true);
|
||||
this.sidebar.addTab("variablesview", VARIABLES_VIEW_URL, {selected: true});
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
|
@ -3,11 +3,11 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const { actorBridge } = require("devtools/server/actors/common");
|
||||
const { method, custom, Arg, Option, RetVal } = protocol;
|
||||
const { Actor, ActorClassWithSpec } = require("devtools/shared/protocol");
|
||||
const { actorBridgeWithSpec } = require("devtools/server/actors/common");
|
||||
const { on, once, off, emit } = require("sdk/event/core");
|
||||
const { Framerate } = require("devtools/server/performance/framerate");
|
||||
const { framerateSpec } = require("devtools/shared/specs/framerate");
|
||||
|
||||
/**
|
||||
* An actor wrapper around Framerate. Uses exposed
|
||||
@ -15,48 +15,19 @@ const { Framerate } = require("devtools/server/performance/framerate");
|
||||
*
|
||||
* @see devtools/server/performance/framerate.js for documentation.
|
||||
*/
|
||||
var FramerateActor = exports.FramerateActor = protocol.ActorClass({
|
||||
typeName: "framerate",
|
||||
var FramerateActor = exports.FramerateActor = ActorClassWithSpec(framerateSpec, {
|
||||
initialize: function (conn, tabActor) {
|
||||
protocol.Actor.prototype.initialize.call(this, conn);
|
||||
Actor.prototype.initialize.call(this, conn);
|
||||
this.bridge = new Framerate(tabActor);
|
||||
},
|
||||
destroy: function (conn) {
|
||||
protocol.Actor.prototype.destroy.call(this, conn);
|
||||
Actor.prototype.destroy.call(this, conn);
|
||||
this.bridge.destroy();
|
||||
},
|
||||
|
||||
startRecording: actorBridge("startRecording", {}),
|
||||
|
||||
stopRecording: actorBridge("stopRecording", {
|
||||
request: {
|
||||
beginAt: Arg(0, "nullable:number"),
|
||||
endAt: Arg(1, "nullable:number")
|
||||
},
|
||||
response: { ticks: RetVal("array:number") }
|
||||
}),
|
||||
|
||||
cancelRecording: actorBridge("cancelRecording"),
|
||||
|
||||
isRecording: actorBridge("isRecording", {
|
||||
response: { recording: RetVal("boolean") }
|
||||
}),
|
||||
|
||||
getPendingTicks: actorBridge("getPendingTicks", {
|
||||
request: {
|
||||
beginAt: Arg(0, "nullable:number"),
|
||||
endAt: Arg(1, "nullable:number")
|
||||
},
|
||||
response: { ticks: RetVal("array:number") }
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the FramerateActor.
|
||||
*/
|
||||
var FramerateFront = exports.FramerateFront = protocol.FrontClass(FramerateActor, {
|
||||
initialize: function (client, { framerateActor }) {
|
||||
protocol.Front.prototype.initialize.call(this, client, { actor: framerateActor });
|
||||
this.manage(this);
|
||||
}
|
||||
startRecording: actorBridgeWithSpec("startRecording"),
|
||||
stopRecording: actorBridgeWithSpec("stopRecording"),
|
||||
cancelRecording: actorBridgeWithSpec("cancelRecording"),
|
||||
isRecording: actorBridgeWithSpec("isRecording"),
|
||||
getPendingTicks: actorBridgeWithSpec("getPendingTicks"),
|
||||
});
|
||||
|
@ -537,11 +537,12 @@ StorageActors.createActor({
|
||||
break;
|
||||
|
||||
case "cleared":
|
||||
this.storageActor.update("cleared", "cookies", hosts);
|
||||
break;
|
||||
|
||||
case "reload":
|
||||
this.storageActor.update("reloaded", "cookies", hosts);
|
||||
if (hosts.length) {
|
||||
for (let host of hosts) {
|
||||
data[host] = [];
|
||||
}
|
||||
this.storageActor.update("cleared", "cookies", data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
@ -1392,6 +1393,30 @@ StorageActors.createActor({
|
||||
return this.removeDB(host, principal, name);
|
||||
}),
|
||||
|
||||
removeAll: Task.async(function* (host, name) {
|
||||
let [db, store] = JSON.parse(name);
|
||||
|
||||
let win = this.storageActor.getWindowFromHost(host);
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
|
||||
let principal = win.document.nodePrincipal;
|
||||
this.clearDBStore(host, principal, db, store);
|
||||
}),
|
||||
|
||||
removeItem: Task.async(function* (host, name) {
|
||||
let [db, store, id] = JSON.parse(name);
|
||||
|
||||
let win = this.storageActor.getWindowFromHost(host);
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
|
||||
let principal = win.document.nodePrincipal;
|
||||
this.removeDBRecord(host, principal, db, store, id);
|
||||
}),
|
||||
|
||||
getHostName(location) {
|
||||
if (!location.host) {
|
||||
return location.href;
|
||||
@ -1552,13 +1577,16 @@ StorageActors.createActor({
|
||||
};
|
||||
},
|
||||
|
||||
onDatabaseRemoved(host, name) {
|
||||
if (this.hostVsStores.has(host)) {
|
||||
this.hostVsStores.get(host).delete(name);
|
||||
onItemUpdated(action, host, path) {
|
||||
// Database was removed, remove it from stores map
|
||||
if (action === "deleted" && path.length === 1) {
|
||||
if (this.hostVsStores.has(host)) {
|
||||
this.hostVsStores.get(host).delete(path[0]);
|
||||
}
|
||||
}
|
||||
|
||||
this.storageActor.update("deleted", "indexedDB", {
|
||||
[host]: [ JSON.stringify([name]) ]
|
||||
this.storageActor.update(action, "indexedDB", {
|
||||
[host]: [ JSON.stringify(path) ]
|
||||
});
|
||||
},
|
||||
|
||||
@ -1573,6 +1601,8 @@ StorageActors.createActor({
|
||||
this.getValuesForHost = indexedDBHelpers.getValuesForHost;
|
||||
this.getObjectStoreData = indexedDBHelpers.getObjectStoreData;
|
||||
this.removeDB = indexedDBHelpers.removeDB;
|
||||
this.removeDBRecord = indexedDBHelpers.removeDBRecord;
|
||||
this.clearDBStore = indexedDBHelpers.clearDBStore;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1584,14 +1614,12 @@ StorageActors.createActor({
|
||||
setupParent: "setupParentProcessForIndexedDB"
|
||||
});
|
||||
|
||||
this.getDBMetaData =
|
||||
callParentProcessAsync.bind(null, "getDBMetaData");
|
||||
this.getDBNamesForHost =
|
||||
callParentProcessAsync.bind(null, "getDBNamesForHost");
|
||||
this.getValuesForHost =
|
||||
callParentProcessAsync.bind(null, "getValuesForHost");
|
||||
this.removeDB =
|
||||
callParentProcessAsync.bind(null, "removeDB");
|
||||
this.getDBMetaData = callParentProcessAsync.bind(null, "getDBMetaData");
|
||||
this.getDBNamesForHost = callParentProcessAsync.bind(null, "getDBNamesForHost");
|
||||
this.getValuesForHost = callParentProcessAsync.bind(null, "getValuesForHost");
|
||||
this.removeDB = callParentProcessAsync.bind(null, "removeDB");
|
||||
this.removeDBRecord = callParentProcessAsync.bind(null, "removeDBRecord");
|
||||
this.clearDBStore = callParentProcessAsync.bind(null, "clearDBStore");
|
||||
|
||||
addMessageListener("storage:storage-indexedDB-request-child", msg => {
|
||||
switch (msg.json.method) {
|
||||
@ -1604,9 +1632,9 @@ StorageActors.createActor({
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "onDatabaseRemoved": {
|
||||
let [host, name] = msg.json.args;
|
||||
this.onDatabaseRemoved(host, name);
|
||||
case "onItemUpdated": {
|
||||
let [action, host, path] = msg.json.args;
|
||||
this.onItemUpdated(action, host, path);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1638,13 +1666,13 @@ var indexedDBHelpers = {
|
||||
});
|
||||
},
|
||||
|
||||
onDatabaseRemoved: function (host, name) {
|
||||
onItemUpdated(action, host, path) {
|
||||
let mm = Cc["@mozilla.org/globalmessagemanager;1"]
|
||||
.getService(Ci.nsIMessageListenerManager);
|
||||
|
||||
mm.broadcastAsyncMessage("storage:storage-indexedDB-request-child", {
|
||||
method: "onDatabaseRemoved",
|
||||
args: [ host, name ]
|
||||
method: "onItemUpdated",
|
||||
args: [ action, host, path ]
|
||||
});
|
||||
},
|
||||
|
||||
@ -1665,9 +1693,9 @@ var indexedDBHelpers = {
|
||||
|
||||
success.resolve(this.backToChild("getDBMetaData", dbData));
|
||||
};
|
||||
request.onerror = () => {
|
||||
request.onerror = ({target}) => {
|
||||
console.error(
|
||||
`Error opening indexeddb database ${name} for host ${host}`);
|
||||
`Error opening indexeddb database ${name} for host ${host}`, target.error);
|
||||
success.resolve(this.backToChild("getDBMetaData", null));
|
||||
};
|
||||
return success.promise;
|
||||
@ -1682,24 +1710,24 @@ var indexedDBHelpers = {
|
||||
},
|
||||
|
||||
removeDB: Task.async(function* (host, principal, name) {
|
||||
let request = require("indexedDB").deleteForPrincipal(principal, name);
|
||||
|
||||
let result = new promise(resolve => {
|
||||
let request = require("indexedDB").deleteForPrincipal(principal, name);
|
||||
|
||||
request.onsuccess = () => {
|
||||
resolve({});
|
||||
this.onDatabaseRemoved(host, name);
|
||||
this.onItemUpdated("deleted", host, [name]);
|
||||
};
|
||||
|
||||
request.onblocked = () => {
|
||||
console.error(
|
||||
`Deleting indexedDB database ${name} for host ${host} is blocked`);
|
||||
console.warn(`Deleting indexedDB database ${name} for host ${host} is blocked`);
|
||||
resolve({ blocked: true });
|
||||
};
|
||||
|
||||
request.onerror = () => {
|
||||
console.error(
|
||||
`Error deleting indexedDB database ${name} for host ${host}`);
|
||||
resolve({ error: request.error });
|
||||
let { error } = request;
|
||||
console.warn(
|
||||
`Error deleting indexedDB database ${name} for host ${host}: ${error}`);
|
||||
resolve({ error: error.message });
|
||||
};
|
||||
|
||||
// If the database is blocked repeatedly, the onblocked event will not
|
||||
@ -1711,6 +1739,70 @@ var indexedDBHelpers = {
|
||||
return this.backToChild("removeDB", yield result);
|
||||
}),
|
||||
|
||||
removeDBRecord: Task.async(function* (host, principal, dbName, storeName, id) {
|
||||
let db;
|
||||
|
||||
try {
|
||||
db = yield new promise((resolve, reject) => {
|
||||
let request = this.openWithPrincipal(principal, dbName);
|
||||
request.onsuccess = ev => resolve(ev.target.result);
|
||||
request.onerror = ev => reject(ev.target.error);
|
||||
});
|
||||
|
||||
let transaction = db.transaction(storeName, "readwrite");
|
||||
let store = transaction.objectStore(storeName);
|
||||
|
||||
yield new promise((resolve, reject) => {
|
||||
let request = store.delete(id);
|
||||
request.onsuccess = () => resolve();
|
||||
request.onerror = ev => reject(ev.target.error);
|
||||
});
|
||||
|
||||
this.onItemUpdated("deleted", host, [dbName, storeName, id]);
|
||||
} catch (error) {
|
||||
let recordPath = [dbName, storeName, id].join("/");
|
||||
console.error(`Failed to delete indexedDB record: ${recordPath}: ${error}`);
|
||||
}
|
||||
|
||||
if (db) {
|
||||
db.close();
|
||||
}
|
||||
|
||||
return this.backToChild("removeDBRecord", null);
|
||||
}),
|
||||
|
||||
clearDBStore: Task.async(function* (host, principal, dbName, storeName) {
|
||||
let db;
|
||||
|
||||
try {
|
||||
db = yield new promise((resolve, reject) => {
|
||||
let request = this.openWithPrincipal(principal, dbName);
|
||||
request.onsuccess = ev => resolve(ev.target.result);
|
||||
request.onerror = ev => reject(ev.target.error);
|
||||
});
|
||||
|
||||
let transaction = db.transaction(storeName, "readwrite");
|
||||
let store = transaction.objectStore(storeName);
|
||||
|
||||
yield new promise((resolve, reject) => {
|
||||
let request = store.clear();
|
||||
request.onsuccess = () => resolve();
|
||||
request.onerror = ev => reject(ev.target.error);
|
||||
});
|
||||
|
||||
this.onItemUpdated("cleared", host, [dbName, storeName]);
|
||||
} catch (error) {
|
||||
let storePath = [dbName, storeName].join("/");
|
||||
console.error(`Failed to clear indexedDB store: ${storePath}: ${error}`);
|
||||
}
|
||||
|
||||
if (db) {
|
||||
db.close();
|
||||
}
|
||||
|
||||
return this.backToChild("clearDBStore", null);
|
||||
}),
|
||||
|
||||
/**
|
||||
* Fetches all the databases and their metadata for the given `host`.
|
||||
*/
|
||||
@ -1986,6 +2078,14 @@ var indexedDBHelpers = {
|
||||
let [host, principal, name] = args;
|
||||
return indexedDBHelpers.removeDB(host, principal, name);
|
||||
}
|
||||
case "removeDBRecord": {
|
||||
let [host, principal, db, store, id] = args;
|
||||
return indexedDBHelpers.removeDBRecord(host, principal, db, store, id);
|
||||
}
|
||||
case "clearDBStore": {
|
||||
let [host, principal, db, store] = args;
|
||||
return indexedDBHelpers.clearDBStore(host, principal, db, store);
|
||||
}
|
||||
default:
|
||||
console.error("ERR_DIRECTOR_PARENT_UNKNOWN_METHOD", msg.json.method);
|
||||
throw new Error("ERR_DIRECTOR_PARENT_UNKNOWN_METHOD");
|
||||
@ -2243,16 +2343,13 @@ let StorageActor = protocol.ActorClassWithSpec(specs.storageSpec, {
|
||||
* <host2>: [<store_names34>...],
|
||||
* }
|
||||
* Where host1, host2 are the host in which this change happened and
|
||||
* [<store_namesX] is an array of the names of the changed store
|
||||
* objects. Leave it empty if the host was completely removed.
|
||||
* When the action is "reloaded" or "cleared", `data` is an array of
|
||||
* hosts for which the stores were cleared or reloaded.
|
||||
* [<store_namesX] is an array of the names of the changed store objects.
|
||||
* Pass an empty array if the host itself was affected: either completely
|
||||
* removed or cleared.
|
||||
*/
|
||||
update(action, storeType, data) {
|
||||
if (action == "cleared" || action == "reloaded") {
|
||||
let toSend = {};
|
||||
toSend[storeType] = data;
|
||||
events.emit(this, "stores-" + action, toSend);
|
||||
if (action == "cleared") {
|
||||
events.emit(this, "stores-cleared", { [storeType]: data });
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ window.onload = function() {
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var {FramerateFront} = require("devtools/server/actors/framerate");
|
||||
var {FramerateFront} = require("devtools/shared/fronts/framerate");
|
||||
|
||||
function plotFPS(ticks, interval = 100, clamp = 60) {
|
||||
var timeline = [];
|
||||
|
@ -31,7 +31,7 @@ window.onload = function() {
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var {FramerateFront} = require("devtools/server/actors/framerate");
|
||||
var {FramerateFront} = require("devtools/shared/fronts/framerate");
|
||||
|
||||
function plotFPS(ticks, interval = 100, clamp = 60) {
|
||||
var timeline = [];
|
||||
|
@ -31,7 +31,7 @@ window.onload = function() {
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var {FramerateFront} = require("devtools/server/actors/framerate");
|
||||
var {FramerateFront} = require("devtools/shared/fronts/framerate");
|
||||
var START_TICK = 2000;
|
||||
var STOP_TICK = 3000;
|
||||
var TOTAL_TIME = 5000;
|
||||
|
@ -16,7 +16,7 @@ Bug 1023018 - Tests if the framerate actor keeps recording after navigations.
|
||||
|
||||
window.onload = function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var {FramerateFront} = require("devtools/server/actors/framerate");
|
||||
var {FramerateFront} = require("devtools/shared/fronts/framerate");
|
||||
var {TargetFactory} = require("devtools/client/framework/target");
|
||||
|
||||
var url = document.getElementById("testContent").href;
|
||||
|
@ -31,7 +31,7 @@ window.onload = function() {
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var {FramerateFront} = require("devtools/server/actors/framerate");
|
||||
var {FramerateFront} = require("devtools/shared/fronts/framerate");
|
||||
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
|
@ -16,7 +16,7 @@ Bug 1171489 - Tests if the framerate actor does not record timestamps from multi
|
||||
|
||||
window.onload = function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var {FramerateFront} = require("devtools/server/actors/framerate");
|
||||
var {FramerateFront} = require("devtools/shared/fronts/framerate");
|
||||
var {TargetFactory} = require("devtools/client/framework/target");
|
||||
|
||||
var url = document.getElementById("testContent").href;
|
||||
|
19
devtools/shared/fronts/framerate.js
Normal file
@ -0,0 +1,19 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { Front, FrontClassWithSpec } = require("devtools/shared/protocol");
|
||||
const { framerateSpec } = require("devtools/shared/specs/framerate");
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the FramerateActor.
|
||||
*/
|
||||
var FramerateFront = exports.FramerateFront = FrontClassWithSpec(framerateSpec, {
|
||||
initialize: function (client, { framerateActor }) {
|
||||
Front.prototype.initialize.call(this, client, { actor: framerateActor });
|
||||
this.manage(this);
|
||||
}
|
||||
});
|
||||
|
||||
exports.FramerateFront = FramerateFront;
|
@ -15,6 +15,7 @@ DevToolsModules(
|
||||
'device.js',
|
||||
'director-manager.js',
|
||||
'director-registry.js',
|
||||
'framerate.js',
|
||||
'gcli.js',
|
||||
'highlighters.js',
|
||||
'inspector.js',
|
||||
|
@ -36,7 +36,8 @@ exports.items = [
|
||||
/**
|
||||
* Called when the UI is ready to add a welcome message to the output
|
||||
*/
|
||||
exports.maybeShowIntro = function(commandOutputManager, conversionContext) {
|
||||
exports.maybeShowIntro = function (commandOutputManager, conversionContext,
|
||||
outputPanel) {
|
||||
var hideIntro = conversionContext.system.settings.get('hideIntro');
|
||||
if (hideIntro.value) {
|
||||
return;
|
||||
@ -46,7 +47,7 @@ exports.maybeShowIntro = function(commandOutputManager, conversionContext) {
|
||||
output.type = 'view';
|
||||
commandOutputManager.onOutput({ output: output });
|
||||
|
||||
var viewData = this.createView(null, conversionContext, true);
|
||||
var viewData = this.createView(null, conversionContext, true, outputPanel);
|
||||
|
||||
output.complete({ isTypedData: true, type: 'view', data: viewData });
|
||||
};
|
||||
@ -54,7 +55,8 @@ exports.maybeShowIntro = function(commandOutputManager, conversionContext) {
|
||||
/**
|
||||
* Called when the UI is ready to add a welcome message to the output
|
||||
*/
|
||||
exports.createView = function(ignoreArgs, conversionContext, showHideButton) {
|
||||
exports.createView = function (ignoreArgs, conversionContext, showHideButton,
|
||||
outputPanel) {
|
||||
return view.createView({
|
||||
html:
|
||||
'<div save="${mainDiv}">\n' +
|
||||
@ -81,7 +83,7 @@ exports.createView = function(ignoreArgs, conversionContext, showHideButton) {
|
||||
var settings = conversionContext.system.settings;
|
||||
var hideIntro = settings.get('hideIntro');
|
||||
hideIntro.value = true;
|
||||
this.mainDiv.style.display = 'none';
|
||||
outputPanel.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
34
devtools/shared/specs/framerate.js
Normal file
@ -0,0 +1,34 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { Arg, RetVal, generateActorSpec } = require("devtools/shared/protocol");
|
||||
|
||||
const framerateSpec = generateActorSpec({
|
||||
typeName: "framerate",
|
||||
|
||||
methods: {
|
||||
startRecording: {},
|
||||
stopRecording: {
|
||||
request: {
|
||||
beginAt: Arg(0, "nullable:number"),
|
||||
endAt: Arg(1, "nullable:number")
|
||||
},
|
||||
response: { ticks: RetVal("array:number") }
|
||||
},
|
||||
cancelRecording: {},
|
||||
isRecording: {
|
||||
response: { recording: RetVal("boolean") }
|
||||
},
|
||||
getPendingTicks: {
|
||||
request: {
|
||||
beginAt: Arg(0, "nullable:number"),
|
||||
endAt: Arg(1, "nullable:number")
|
||||
},
|
||||
response: { ticks: RetVal("array:number") }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
exports.framerateSpec = framerateSpec;
|
@ -18,6 +18,7 @@ DevToolsModules(
|
||||
'director-registry.js',
|
||||
'environment.js',
|
||||
'frame.js',
|
||||
'framerate.js',
|
||||
'gcli.js',
|
||||
'heap-snapshot-file.js',
|
||||
'highlighters.js',
|
||||
|
@ -187,7 +187,21 @@ createStorageSpec({
|
||||
name: Arg(1, "string"),
|
||||
},
|
||||
response: RetVal("idbdeleteresult")
|
||||
}
|
||||
},
|
||||
removeAll: {
|
||||
request: {
|
||||
host: Arg(0, "string"),
|
||||
name: Arg(1, "string"),
|
||||
},
|
||||
response: {}
|
||||
},
|
||||
removeItem: {
|
||||
request: {
|
||||
host: Arg(0, "string"),
|
||||
name: Arg(1, "string"),
|
||||
},
|
||||
response: {}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -305,7 +305,7 @@ AutoJSAPI::~AutoJSAPI()
|
||||
ReportException();
|
||||
|
||||
if (mOldWarningReporter.isSome()) {
|
||||
JS::SetWarningReporter(JS_GetRuntime(cx()), mOldWarningReporter.value());
|
||||
JS::SetWarningReporter(cx(), mOldWarningReporter.value());
|
||||
}
|
||||
|
||||
// Leave the request before popping.
|
||||
@ -345,10 +345,9 @@ AutoJSAPI::InitInternal(nsIGlobalObject* aGlobalObject, JSObject* aGlobal,
|
||||
|
||||
ScriptSettingsStack::Push(this);
|
||||
|
||||
JSRuntime* rt = JS_GetRuntime(aCx);
|
||||
mOldWarningReporter.emplace(JS::GetWarningReporter(rt));
|
||||
mOldWarningReporter.emplace(JS::GetWarningReporter(aCx));
|
||||
|
||||
JS::SetWarningReporter(rt, WarningOnlyErrorReporter);
|
||||
JS::SetWarningReporter(aCx, WarningOnlyErrorReporter);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (haveException) {
|
||||
|
@ -682,8 +682,8 @@ nsCopySupport::FireClipboardEvent(EventMessage aEventMessage,
|
||||
RefPtr<DataTransfer> clipboardData;
|
||||
if (chromeShell || Preferences::GetBool("dom.event.clipboardevents.enabled", true)) {
|
||||
clipboardData =
|
||||
new DataTransfer(piWindow, aEventMessage, aEventMessage == ePaste,
|
||||
aClipboardType);
|
||||
new DataTransfer(doc->GetScopeObject(), aEventMessage,
|
||||
aEventMessage == ePaste, aClipboardType);
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
InternalClipboardEvent evt(true, aEventMessage);
|
||||
|
@ -2693,7 +2693,7 @@ nsDocument::ApplySettingsFromCSP(bool aSpeculative)
|
||||
mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
|
||||
mReferrerPolicySet = true;
|
||||
}
|
||||
|
||||
|
||||
// Set up 'block-all-mixed-content' if not already inherited
|
||||
// from the parent context or set by any other CSP.
|
||||
if (!mBlockAllMixedContent) {
|
||||
@ -13375,6 +13375,11 @@ nsIDocument::SetCachedEncoder(already_AddRefed<nsIDocumentEncoder> aEncoder)
|
||||
void
|
||||
nsIDocument::SetContentTypeInternal(const nsACString& aType)
|
||||
{
|
||||
if (!IsHTMLOrXHTML() && mDefaultElementType == kNameSpaceID_None &&
|
||||
aType.EqualsLiteral("application/xhtml+xml")) {
|
||||
mDefaultElementType = kNameSpaceID_XHTML;
|
||||
}
|
||||
|
||||
mCachedEncoder = nullptr;
|
||||
mContentType = aType;
|
||||
}
|
||||
|
@ -13078,13 +13078,6 @@ nsGlobalWindow::ResumeTimeouts(bool aThawChildren, bool aThawWorkers)
|
||||
RefPtr<Promise> d = mAudioContexts[i]->Resume(dummy);
|
||||
}
|
||||
|
||||
// Thaw or resume all of the workers for this window.
|
||||
if (aThawWorkers) {
|
||||
mozilla::dom::workers::ThawWorkersForWindow(AsInner());
|
||||
} else {
|
||||
mozilla::dom::workers::ResumeWorkersForWindow(AsInner());
|
||||
}
|
||||
|
||||
// Restore all of the timeouts, using the stored time remaining
|
||||
// (stored in timeout->mTimeRemaining).
|
||||
|
||||
@ -13129,6 +13122,15 @@ nsGlobalWindow::ResumeTimeouts(bool aThawChildren, bool aThawWorkers)
|
||||
// Add a reference for the new timer's closure.
|
||||
t->AddRef();
|
||||
}
|
||||
|
||||
// Thaw or resume all of the workers for this window. We must do this
|
||||
// after timeouts since workers may have queued events that can trigger
|
||||
// a setTimeout().
|
||||
if (aThawWorkers) {
|
||||
mozilla::dom::workers::ThawWorkersForWindow(AsInner());
|
||||
} else {
|
||||
mozilla::dom::workers::ResumeWorkersForWindow(AsInner());
|
||||
}
|
||||
}
|
||||
|
||||
// Resume our children as well.
|
||||
|
@ -748,10 +748,15 @@ nsImageLoadingContent::LoadImage(const nsAString& aNewURI,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Second, parse the URI string to get image URI
|
||||
nsCOMPtr<nsIURI> imageURI;
|
||||
nsresult rv = StringToURI(aNewURI, doc, getter_AddRefs(imageURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// XXXbiesi fire onerror if that failed?
|
||||
if (NS_FAILED(rv)) {
|
||||
// Cancel image requests and fire error event per spec
|
||||
CancelImageRequests(aNotify);
|
||||
FireEvent(NS_LITERAL_STRING("error"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool equal;
|
||||
|
||||
|
@ -2454,7 +2454,7 @@ nsJSContext::EnsureStatics()
|
||||
AsmJSCacheOpenEntryForWrite,
|
||||
asmjscache::CloseEntryForWrite
|
||||
};
|
||||
JS::SetAsmJSCacheOps(sRuntime, &asmJSCacheOps);
|
||||
JS::SetAsmJSCacheOps(JS_GetContext(sRuntime), &asmJSCacheOps);
|
||||
|
||||
// Set these global xpconnect options...
|
||||
Preferences::RegisterCallbackAndCall(SetMemoryHighWaterMarkPrefChangedCallback,
|
||||
|
@ -19,8 +19,6 @@
|
||||
#include "nsIWeakReference.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -75,8 +73,7 @@ NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsPluginArray,
|
||||
mWindow,
|
||||
mPlugins,
|
||||
mCTPPlugins)
|
||||
mPlugins)
|
||||
|
||||
static void
|
||||
GetPluginMimeTypes(const nsTArray<RefPtr<nsPluginElement> >& aPlugins,
|
||||
@ -156,7 +153,6 @@ nsPluginArray::Refresh(bool aReloadDocuments)
|
||||
}
|
||||
|
||||
mPlugins.Clear();
|
||||
mCTPPlugins.Clear();
|
||||
|
||||
nsCOMPtr<nsIDOMNavigator> navigator = mWindow->GetNavigator();
|
||||
|
||||
@ -232,13 +228,6 @@ nsPluginArray::NamedGetter(const nsAString& aName, bool &aFound)
|
||||
|
||||
nsPluginElement* plugin = FindPlugin(mPlugins, aName);
|
||||
aFound = (plugin != nullptr);
|
||||
if (!aFound) {
|
||||
nsPluginElement* hiddenPlugin = FindPlugin(mCTPPlugins, aName);
|
||||
if (hiddenPlugin) {
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->NotifyObservers(hiddenPlugin->PluginTag(), "Plugin::HiddenPluginTouched", nsString(aName).get());
|
||||
}
|
||||
}
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@ -300,7 +289,7 @@ operator<(const RefPtr<nsPluginElement>& lhs,
|
||||
void
|
||||
nsPluginArray::EnsurePlugins()
|
||||
{
|
||||
if (!mPlugins.IsEmpty() || !mCTPPlugins.IsEmpty()) {
|
||||
if (!mPlugins.IsEmpty()) {
|
||||
// We already have an array of plugin elements.
|
||||
return;
|
||||
}
|
||||
@ -317,31 +306,7 @@ nsPluginArray::EnsurePlugins()
|
||||
// need to wrap each of these with a nsPluginElement, which is
|
||||
// scriptable.
|
||||
for (uint32_t i = 0; i < pluginTags.Length(); ++i) {
|
||||
nsCOMPtr<nsPluginTag> pluginTag = do_QueryInterface(pluginTags[i]);
|
||||
if (!pluginTag) {
|
||||
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
|
||||
} else if (pluginTag->IsActive()) {
|
||||
uint32_t permission = nsIPermissionManager::ALLOW_ACTION;
|
||||
if (pluginTag->IsClicktoplay()) {
|
||||
nsCString name;
|
||||
pluginTag->GetName(name);
|
||||
if (NS_LITERAL_CSTRING("Shockwave Flash").Equals(name)) {
|
||||
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
|
||||
nsCString permString;
|
||||
nsresult rv = pluginHost->GetPermissionStringForTag(pluginTag, 0, permString);
|
||||
if (rv == NS_OK) {
|
||||
nsIPrincipal* principal = mWindow->GetExtantDoc()->NodePrincipal();
|
||||
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
|
||||
permMgr->TestPermissionFromPrincipal(principal, permString.get(), &permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (permission == nsIPermissionManager::ALLOW_ACTION) {
|
||||
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
|
||||
} else {
|
||||
mCTPPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
|
||||
}
|
||||
}
|
||||
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
|
||||
}
|
||||
|
||||
// Alphabetize the enumeration order of non-hidden plugins to reduce
|
||||
|
@ -60,10 +60,6 @@ private:
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||
nsTArray<RefPtr<nsPluginElement> > mPlugins;
|
||||
/* A separate list of click-to-play plugins that we don't tell content
|
||||
* about but keep track of so we can still prompt the user to click to play.
|
||||
*/
|
||||
nsTArray<RefPtr<nsPluginElement> > mCTPPlugins;
|
||||
};
|
||||
|
||||
class nsPluginElement final : public nsISupports,
|
||||
|
@ -3297,46 +3297,23 @@ namespace {
|
||||
|
||||
// This runnable is used to write a deprecation message from a worker to the
|
||||
// console running on the main-thread.
|
||||
class DeprecationWarningRunnable final : public Runnable
|
||||
, public WorkerHolder
|
||||
class DeprecationWarningRunnable final : public WorkerProxyToMainThreadRunnable
|
||||
{
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
nsIDocument::DeprecatedOperations mOperation;
|
||||
|
||||
public:
|
||||
DeprecationWarningRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
nsIDocument::DeprecatedOperations aOperation)
|
||||
: mWorkerPrivate(aWorkerPrivate)
|
||||
: WorkerProxyToMainThreadRunnable(aWorkerPrivate)
|
||||
, mOperation(aOperation)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
}
|
||||
|
||||
void
|
||||
Dispatch()
|
||||
{
|
||||
if (NS_WARN_IF(!HoldWorker(mWorkerPrivate))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(this)))) {
|
||||
ReleaseWorker();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool
|
||||
Notify(Status aStatus) override
|
||||
{
|
||||
// We don't care about the notification. We just want to keep the
|
||||
// mWorkerPrivate alive.
|
||||
return true;
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
void
|
||||
RunOnMainThread() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -3350,40 +3327,11 @@ private:
|
||||
if (window && window->GetExtantDoc()) {
|
||||
window->GetExtantDoc()->WarnOnceAbout(mOperation);
|
||||
}
|
||||
|
||||
ReleaseWorkerHolder();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ReleaseWorkerHolder()
|
||||
{
|
||||
class ReleaseRunnable final : public MainThreadWorkerRunnable
|
||||
{
|
||||
RefPtr<DeprecationWarningRunnable> mRunnable;
|
||||
|
||||
public:
|
||||
ReleaseRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
DeprecationWarningRunnable* aRunnable)
|
||||
: MainThreadWorkerRunnable(aWorkerPrivate)
|
||||
, mRunnable(aRunnable)
|
||||
{}
|
||||
|
||||
virtual bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
mRunnable->ReleaseWorker();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
RefPtr<ReleaseRunnable> runnable =
|
||||
new ReleaseRunnable(mWorkerPrivate, this);
|
||||
NS_WARN_IF(!runnable->Dispatch());
|
||||
}
|
||||
RunBackOnWorkerThread() override
|
||||
{}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -28,8 +28,8 @@ FakeMediaStreamGraph::DispatchToMainThreadAfterStreamStateUpdate(already_AddRefe
|
||||
NS_DispatchToMainThread(task);
|
||||
}
|
||||
|
||||
CameraPreviewMediaStream::CameraPreviewMediaStream(DOMMediaStream* aWrapper)
|
||||
: ProcessedMediaStream(aWrapper)
|
||||
CameraPreviewMediaStream::CameraPreviewMediaStream()
|
||||
: ProcessedMediaStream()
|
||||
, mMutex("mozilla::camera::CameraPreviewMediaStream")
|
||||
, mInvalidatePending(0)
|
||||
, mDiscardedFrames(0)
|
||||
|
@ -40,7 +40,7 @@ class CameraPreviewMediaStream : public ProcessedMediaStream
|
||||
typedef mozilla::layers::Image Image;
|
||||
|
||||
public:
|
||||
explicit CameraPreviewMediaStream(DOMMediaStream* aWrapper);
|
||||
CameraPreviewMediaStream();
|
||||
|
||||
virtual void AddAudioOutput(void* aKey) override;
|
||||
virtual void SetAudioOutputVolume(void* aKey, float aVolume) override;
|
||||
|
@ -259,7 +259,7 @@ nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId,
|
||||
, mSetInitialConfig(false)
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
mInput = new CameraPreviewMediaStream(this);
|
||||
mInput = new CameraPreviewMediaStream();
|
||||
mOwnedStream = mInput;
|
||||
|
||||
BindToOwner(aWindow);
|
||||
|