Merge inbound to central, a=merge

MozReview-Commit-ID: IrZXJHbiqpa
This commit is contained in:
Wes Kocher 2017-06-09 15:28:10 -07:00
Родитель a4cc130bcc 8f0a832c01
Коммит 07d7985523
41 изменённых файлов: 610 добавлений и 392 удалений

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

@ -390,8 +390,8 @@ var gPluginHandler = {
switch (pluginInfo.fallbackType) {
case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
message = gNavigatorBundle.getFormattedString(
"pluginActivateNew.message",
[pluginName, origin]);
"pluginActivationWarning.message",
[brand]);
break;
case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE:
message = gNavigatorBundle.getFormattedString(

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

@ -20,11 +20,23 @@
* - group this attribute must be set to "sidebar".
*/
var SidebarUI = {
browser: null,
// Avoid getting the browser element from init() to avoid triggering the
// <browser> constructor during startup if the sidebar is hidden.
get browser() {
if (this._browser)
return this._browser;
return this._browser = document.getElementById("sidebar");
},
POSITION_START_PREF: "sidebar.position_start",
_box: null,
_title: null,
// The constructor of this label accesses the browser element due to the
// control="sidebar" attribute, so avoid getting this label during startup.
get _title() {
if (this.__title)
return this.__title;
return this.__title = document.getElementById("sidebar-title");
},
_splitter: null,
_icon: null,
_reversePositionButton: null,
@ -34,8 +46,6 @@ var SidebarUI = {
init() {
this._box = document.getElementById("sidebar-box");
this.browser = document.getElementById("sidebar");
this._title = document.getElementById("sidebar-title");
this._splitter = document.getElementById("sidebar-splitter");
this._icon = document.getElementById("sidebar-icon");
this._reversePositionButton = document.getElementById("sidebar-reverse-position");

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

@ -817,11 +817,11 @@
this.mBrowser.mIconURL = null;
}
let unifiedComplete = this.mTabBrowser._unifiedComplete;
let userContextId = this.mBrowser.getAttribute("usercontextid") || 0;
if (this.mBrowser.registeredOpenURI) {
unifiedComplete.unregisterOpenPage(this.mBrowser.registeredOpenURI,
userContextId);
this.mTabBrowser._unifiedComplete
.unregisterOpenPage(this.mBrowser.registeredOpenURI,
userContextId);
delete this.mBrowser.registeredOpenURI;
}
// Tabs in private windows aren't registered as "Open" so
@ -829,7 +829,8 @@
if (!isBlankPageURL(aLocation.spec) &&
(!PrivateBrowsingUtils.isWindowPrivate(window) ||
PrivateBrowsingUtils.permanentPrivateBrowsing)) {
unifiedComplete.registerOpenPage(aLocation, userContextId);
this.mTabBrowser._unifiedComplete
.registerOpenPage(aLocation, userContextId);
this.mBrowser.registeredOpenURI = aLocation;
}
}

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

@ -47,22 +47,23 @@ const startupPhases = {
// For the following phases of startup we have only a black list for now
// We are at this phase after creating the first browser window (ie. after final-ui-startup).
"before opening first browser window": {blacklist: {
components: new Set([
"nsSearchService.js",
])
}},
"before opening first browser window": {},
// We reach this phase right after showing the first browser window.
// This means that anything already loaded at this point has been loaded
// before first paint and delayed it.
"before first paint": {},
"before first paint": {blacklist: {
components: new Set([
"nsSearchService.js",
"UnifiedComplete.js",
])
}},
// We are at this phase once we are ready to handle user events.
// Anything loaded at this phase or before gets in the way of the user
// interacting with the first browser window.
"before handling user events": {},
}
};
function test() {
if (!AppConstants.NIGHTLY_BUILD && !AppConstants.DEBUG) {

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

@ -72,8 +72,4 @@ add_task(async function() {
await promiseTabLoadEvent(gBrowser.selectedTab, gHttpTestRoot + "plugin_small_2.html");
let notification = await waitForNotificationBar("plugin-hidden", gBrowser.selectedBrowser);
ok(notification, "There should be a notification shown for the new page.");
// Ensure that the notification is showing information about
// the x-second-test plugin.
let label = notification.label;
ok(label.includes("Second Test"), "Should mention the second plugin");
});

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

@ -121,7 +121,9 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
cxmenu.insertBefore(pasteAndGo, insertLocation.nextSibling);
}
this._enableOrDisableOneOffSearches();
this.popup.addEventListener("popupshowing", () => {
this._enableOrDisableOneOffSearches();
}, {capturing: true, once: true});
// The autocomplete controller uses heuristic on some internal caches
// to handle cases like backspace, autofill or repeated searches.
@ -2763,7 +2765,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
};
switch (action.blocklistState) {
case Ci.nsIBlocklistService.STATE_NOT_BLOCKED:
label = "pluginActivateNew.message";
label = "pluginActivate2.message";
linkLabel = "pluginActivate.learnMore";
button2.default = true;
break;

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

@ -70,6 +70,8 @@
<implementation implements="nsIObserver">
<constructor><![CDATA[
this._textbox.placeholder = this._stringBundle.getString("searchPlaceholder");
if (this.parentNode.parentNode.localName == "toolbarpaletteitem")
return;
@ -77,27 +79,36 @@
this._initialized = true;
Services.search.init(aStatus => {
// Bail out if the binding's been destroyed
if (!this._initialized)
return;
(window.delayedStartupPromise || Promise.resolve()).then(() => {
window.requestIdleCallback(() => {
Services.search.init(aStatus => {
// Bail out if the binding's been destroyed
if (!this._initialized)
return;
if (Components.isSuccessCode(aStatus)) {
// Refresh the display (updating icon, etc)
this.updateDisplay();
BrowserSearch.updateOpenSearchBadge();
} else {
Components.utils.reportError("Cannot initialize search service, bailing out: " + aStatus);
}
if (Components.isSuccessCode(aStatus)) {
// Refresh the display (updating icon, etc)
this.updateDisplay();
BrowserSearch.updateOpenSearchBadge();
} else {
Components.utils.reportError("Cannot initialize search service, bailing out: " + aStatus);
}
});
});
});
// Some accessibility tests create their own <searchbar> that doesn't
// use the popup binding below, so null-check oneOffButtons.
if (this.textbox.popup.oneOffButtons) {
this.textbox.popup.oneOffButtons.telemetryOrigin = "searchbar";
this.textbox.popup.oneOffButtons.popup = this.textbox.popup;
this.textbox.popup.oneOffButtons.textbox = this.textbox;
}
// Wait until the popupshowing event to avoid forcing immediate
// attachment of the search-one-offs binding.
this.textbox.popup.addEventListener("popupshowing", () => {
let oneOffButtons = this.textbox.popup.oneOffButtons;
// Some accessibility tests create their own <searchbar> that doesn't
// use the popup binding below, so null-check oneOffButtons.
if (oneOffButtons) {
oneOffButtons.telemetryOrigin = "searchbar";
oneOffButtons.popup = this.textbox.popup;
oneOffButtons.textbox = this.textbox;
}
}, {capturing: true, once: true});
]]></constructor>
<destructor><![CDATA[
@ -286,8 +297,6 @@
var name = this.currentEngine.name;
var text = this._stringBundle.getFormattedString("searchtip", [name]);
this._textbox.placeholder = this._stringBundle.getString("searchPlaceholder");
this._textbox.label = text;
this._textbox.tooltipText = text;
]]></body>
@ -567,108 +576,115 @@
<binding id="searchbar-textbox"
extends="chrome://global/content/bindings/autocomplete.xml#autocomplete">
<implementation implements="nsIObserver">
<implementation>
<constructor><![CDATA[
const kXULNS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
if (document.getBindingParent(this).parentNode.parentNode.localName ==
"toolbarpaletteitem")
return;
// Initialize fields
this._stringBundle = document.getBindingParent(this)._stringBundle;
this._suggestEnabled =
Services.prefs.getBoolPref("browser.search.suggest.enabled");
if (Services.prefs.getBoolPref("browser.urlbar.clickSelectsAll"))
this.setAttribute("clickSelectsAll", true);
// Add items to context menu and attach controller to handle them
var textBox = document.getAnonymousElementByAttribute(this,
"anonid", "textbox-input-box");
var cxmenu = document.getAnonymousElementByAttribute(textBox,
"anonid", "input-box-contextmenu");
var pasteAndSearch;
cxmenu.addEventListener("popupshowing", function() {
BrowserSearch.searchBar._textbox.closePopup();
if (!pasteAndSearch)
return;
var controller = document.commandDispatcher.getControllerForCommand("cmd_paste");
var enabled = controller.isCommandEnabled("cmd_paste");
if (enabled)
pasteAndSearch.removeAttribute("disabled");
else
pasteAndSearch.setAttribute("disabled", "true");
});
var element, label, akey;
element = document.createElementNS(kXULNS, "menuseparator");
cxmenu.appendChild(element);
cxmenu.addEventListener("popupshowing",
() => { this.initContextMenu(cxmenu); },
{capturing: true, once: true});
this.setAttribute("aria-owns", this.popup.id);
var insertLocation = cxmenu.firstChild;
while (insertLocation.nextSibling &&
insertLocation.getAttribute("cmd") != "cmd_paste")
insertLocation = insertLocation.nextSibling;
if (insertLocation) {
element = document.createElementNS(kXULNS, "menuitem");
label = this._stringBundle.getString("cmd_pasteAndSearch");
element.setAttribute("label", label);
element.setAttribute("anonid", "paste-and-search");
element.setAttribute("oncommand", "BrowserSearch.pasteAndSearch(event)");
cxmenu.insertBefore(element, insertLocation.nextSibling);
pasteAndSearch = element;
}
element = document.createElementNS(kXULNS, "menuitem");
label = this._stringBundle.getString("cmd_clearHistory");
akey = this._stringBundle.getString("cmd_clearHistory_accesskey");
element.setAttribute("label", label);
element.setAttribute("accesskey", akey);
element.setAttribute("cmd", "cmd_clearhistory");
cxmenu.appendChild(element);
element = document.createElementNS(kXULNS, "menuitem");
label = this._stringBundle.getString("cmd_showSuggestions");
akey = this._stringBundle.getString("cmd_showSuggestions_accesskey");
element.setAttribute("anonid", "toggle-suggest-item");
element.setAttribute("label", label);
element.setAttribute("accesskey", akey);
element.setAttribute("cmd", "cmd_togglesuggest");
element.setAttribute("type", "checkbox");
element.setAttribute("checked", this._suggestEnabled);
element.setAttribute("autocheck", "false");
this._suggestMenuItem = element;
cxmenu.appendChild(element);
this.addEventListener("keypress", aEvent => {
if (navigator.platform.startsWith("Mac") && aEvent.keyCode == KeyEvent.VK_F4)
this.openSearch()
}, true);
this.controllers.appendController(this.searchbarController);
document.getBindingParent(this)._textboxInitialized = true;
// Add observer for suggest preference
Services.prefs.addObserver("browser.search.suggest.enabled", this);
]]></constructor>
<destructor><![CDATA[
Services.prefs.removeObserver("browser.search.suggest.enabled", this);
// Because XBL and the customize toolbar code interacts poorly,
// there may not be anything to remove here
// If the context menu has never been opened, there won't be anything
// to remove here.
// Also, XBL and the customize toolbar code sometimes interact poorly.
try {
this.controllers.removeController(this.searchbarController);
} catch (ex) { }
]]></destructor>
<field name="_stringBundle"/>
<field name="_suggestMenuItem"/>
<field name="_suggestEnabled"/>
// Add items to context menu and attach controller to handle them the
// first time the context menu is opened.
<method name="initContextMenu">
<parameter name="aMenu"/>
<body><![CDATA[
const kXULNS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let stringBundle = document.getBindingParent(this)._stringBundle;
let pasteAndSearch, suggestMenuItem;
let element, label, akey;
element = document.createElementNS(kXULNS, "menuseparator");
aMenu.appendChild(element);
let insertLocation = aMenu.firstChild;
while (insertLocation.nextSibling &&
insertLocation.getAttribute("cmd") != "cmd_paste")
insertLocation = insertLocation.nextSibling;
if (insertLocation) {
element = document.createElementNS(kXULNS, "menuitem");
label = stringBundle.getString("cmd_pasteAndSearch");
element.setAttribute("label", label);
element.setAttribute("anonid", "paste-and-search");
element.setAttribute("oncommand", "BrowserSearch.pasteAndSearch(event)");
aMenu.insertBefore(element, insertLocation.nextSibling);
pasteAndSearch = element;
}
element = document.createElementNS(kXULNS, "menuitem");
label = stringBundle.getString("cmd_clearHistory");
akey = stringBundle.getString("cmd_clearHistory_accesskey");
element.setAttribute("label", label);
element.setAttribute("accesskey", akey);
element.setAttribute("cmd", "cmd_clearhistory");
aMenu.appendChild(element);
element = document.createElementNS(kXULNS, "menuitem");
label = stringBundle.getString("cmd_showSuggestions");
akey = stringBundle.getString("cmd_showSuggestions_accesskey");
element.setAttribute("anonid", "toggle-suggest-item");
element.setAttribute("label", label);
element.setAttribute("accesskey", akey);
element.setAttribute("cmd", "cmd_togglesuggest");
element.setAttribute("type", "checkbox");
element.setAttribute("autocheck", "false");
suggestMenuItem = element;
aMenu.appendChild(element);
if (AppConstants.platform == "macosx") {
this.addEventListener("keypress", aEvent => {
if (aEvent.keyCode == KeyEvent.DOM_VK_F4)
this.openSearch()
}, true);
}
this.controllers.appendController(this.searchbarController);
let onpopupshowing = function() {
BrowserSearch.searchBar._textbox.closePopup();
if (suggestMenuItem) {
let enabled =
Services.prefs.getBoolPref("browser.search.suggest.enabled");
suggestMenuItem.setAttribute("checked", enabled);
}
if (!pasteAndSearch)
return;
let controller = document.commandDispatcher.getControllerForCommand("cmd_paste");
let enabled = controller.isCommandEnabled("cmd_paste");
if (enabled)
pasteAndSearch.removeAttribute("disabled");
else
pasteAndSearch.setAttribute("disabled", "true");
};
aMenu.addEventListener("popupshowing", onpopupshowing);
onpopupshowing();
]]></body>
</method>
<!--
This overrides the searchParam property in autocomplete.xml. We're
@ -749,19 +765,6 @@
]]></body>
</method>
<method name="observe">
<parameter name="aSubject"/>
<parameter name="aTopic"/>
<parameter name="aData"/>
<body><![CDATA[
if (aTopic == "nsPref:changed") {
this._suggestEnabled =
Services.prefs.getBoolPref("browser.search.suggest.enabled");
this._suggestMenuItem.setAttribute("checked", this._suggestEnabled);
}
]]></body>
</method>
<method name="openSearch">
<body>
<![CDATA[
@ -863,10 +866,10 @@
this._self.value = "";
break;
case "cmd_togglesuggest":
// The pref observer will update _suggestEnabled and the menu
// checkmark.
let enabled =
Services.prefs.getBoolPref("browser.search.suggest.enabled");
Services.prefs.setBoolPref("browser.search.suggest.enabled",
!this._self._suggestEnabled);
!enabled);
break;
default:
// do nothing with unrecognized command

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

@ -232,6 +232,14 @@ add_task(async function testAutocomplete() {
});
add_task(async function testClearHistory() {
// Open the textbox context menu to trigger controller attachment.
let textbox = searchBar.textbox;
let popupShownPromise = BrowserTestUtils.waitForEvent(textbox, "popupshown");
EventUtils.synthesizeMouseAtCenter(textbox, { type: "contextmenu", button: 2 });
await popupShownPromise;
// Close the context menu.
EventUtils.synthesizeKey("VK_ESCAPE", {});
let controller = searchBar.textbox.controllers.getControllerForCommand("cmd_clearhistory")
ok(controller.isCommandEnabled("cmd_clearhistory"), "Clear history command enabled");
controller.doCommand("cmd_clearhistory");

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

@ -6,6 +6,12 @@ const {classes: Cc, utils: Cu, interfaces: Ci} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/AppConstants.jsm");
let firstPaintNotification = "widget-first-paint";
// widget-first-paint fires much later than expected on Linux.
if (AppConstants.platform == "linux")
firstPaintNotification = "xul-window-visible";
/**
* The startupRecorder component observes notifications at various stages of
@ -42,7 +48,7 @@ startupRecorder.prototype = {
let topics = [
"profile-do-change", // This catches stuff loaded during app-startup
"toplevel-window-ready", // Catches stuff from final-ui-startup
"widget-first-paint",
firstPaintNotification,
"sessionstore-windows-restored",
];
for (let t of topics)
@ -61,8 +67,8 @@ startupRecorder.prototype = {
const topicsToNames = {
"profile-do-change": "before profile selection",
"toplevel-window-ready": "before opening first browser window",
"widget-first-paint": "before first paint",
};
topicsToNames[firstPaintNotification] = "before first paint";
this.record(topicsToNames[topic]);
}
}

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

@ -272,11 +272,16 @@ keywordURIFixup.dismiss=No thanks
keywordURIFixup.dismiss.accesskey=N
## Plugin doorhanger strings
# LOCALIZATION NOTE (pluginActivateNew.message): Used for newly-installed
# plugins which are not known to be unsafe. %1$S is the plugin name and %2$S
# is the site domain.
pluginActivateNew.message=Allow %2$S to run “%1$S”?
# LOCALIZATION NOTE (pluginActivate2.message):
# Used for normal plugin activation if we don't know of a specific security issue.
# %1$S is the plugin name, %2$S is the domain, and %3$S is brandShortName.
pluginActivate2.message=Would you like to allow %2$S to run %1$S? Plugins may slow %3$S.
pluginActivateMultiple.message=Allow %S to run plugins?
# LOCALIZATION NOTE (pluginActivationWarning.message): this should use the
# same string as "pluginActivationWarning" in pluginproblem.dtd
pluginActivationWarning.message=This site uses a plugin that may slow %S.
pluginActivate.learnMore=Learn More…
# LOCALIZATION NOTE (pluginActivateOutdated.message, pluginActivateOutdated.label):
# These strings are used when an unsafe plugin has an update available.

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

@ -29,6 +29,7 @@ const RequestListColumnWaterfall = createClass({
propTypes: {
firstRequestStartedMillis: PropTypes.number.isRequired,
item: PropTypes.object.isRequired,
onWaterfallMouseDown: PropTypes.func.isRequired,
},
shouldComponentUpdate(nextProps) {
@ -37,7 +38,7 @@ const RequestListColumnWaterfall = createClass({
},
render() {
let { firstRequestStartedMillis, item } = this.props;
let { firstRequestStartedMillis, item, onWaterfallMouseDown } = this.props;
const { boxes, tooltip } = timingBoxes(item);
return (
@ -47,6 +48,7 @@ const RequestListColumnWaterfall = createClass({
style: {
paddingInlineStart: `${item.startedMillis - firstRequestStartedMillis}px`,
},
onMouseDown: onWaterfallMouseDown,
},
boxes,
)

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

@ -45,6 +45,7 @@ const RequestListContent = createClass({
onSecurityIconMouseDown: PropTypes.func.isRequired,
onSelectDelta: PropTypes.func.isRequired,
onThumbnailMouseDown: PropTypes.func.isRequired,
onWaterfallMouseDown: PropTypes.func.isRequired,
scale: PropTypes.number,
selectedRequestId: PropTypes.string,
},
@ -229,6 +230,7 @@ const RequestListContent = createClass({
onItemMouseDown,
onSecurityIconMouseDown,
onThumbnailMouseDown,
onWaterfallMouseDown,
selectedRequestId,
} = this.props;
@ -255,6 +257,7 @@ const RequestListContent = createClass({
onCauseBadgeMouseDown: () => onCauseBadgeMouseDown(item.cause),
onSecurityIconMouseDown: () => onSecurityIconMouseDown(item.securityState),
onThumbnailMouseDown: () => onThumbnailMouseDown(),
onWaterfallMouseDown: () => onWaterfallMouseDown(),
}))
)
)
@ -299,5 +302,11 @@ module.exports = connect(
onThumbnailMouseDown: () => {
dispatch(Actions.selectDetailsPanelTab("response"));
},
/**
* A handler that opens the timing sidebar panel if the waterfall is clicked.
*/
onWaterfallMouseDown: () => {
dispatch(Actions.selectDetailsPanelTab("timings"));
},
}),
)(RequestListContent);

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

@ -87,6 +87,7 @@ const RequestListItem = createClass({
onMouseDown: PropTypes.func.isRequired,
onSecurityIconMouseDown: PropTypes.func.isRequired,
onThumbnailMouseDown: PropTypes.func.isRequired,
onWaterfallMouseDown: PropTypes.func.isRequired,
waterfallWidth: PropTypes.number,
},
@ -124,6 +125,7 @@ const RequestListItem = createClass({
onCauseBadgeMouseDown,
onSecurityIconMouseDown,
onThumbnailMouseDown,
onWaterfallMouseDown,
} = this.props;
let classList = ["request-list-item", index % 2 ? "odd" : "even"];
@ -162,7 +164,8 @@ const RequestListItem = createClass({
columns.get("duration") && RequestListColumnDuration({ item }),
columns.get("latency") && RequestListColumnLatency({ item }),
columns.get("waterfall") &&
RequestListColumnWaterfall({ item, firstRequestStartedMillis }),
RequestListColumnWaterfall({ item, firstRequestStartedMillis,
onWaterfallMouseDown }),
)
);
}

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

@ -128,6 +128,7 @@ skip-if = (os == 'linux' && debug && bits == 32) # Bug 1303439
[browser_net_open_request_in_tab.js]
[browser_net_pane-collapse.js]
[browser_net_pane-toggle.js]
[browser_net_persistent_logs.js]
[browser_net_post-data-01.js]
[browser_net_post-data-02.js]
[browser_net_post-data-03.js]
@ -167,4 +168,4 @@ skip-if = true # Bug 1258809
skip-if = true # TODO: fix the test
[browser_net_timing-division.js]
[browser_net_truncate.js]
[browser_net_persistent_logs.js]
[browser_net_waterfall-click.js]

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

@ -0,0 +1,36 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Test that clicking on the waterfall opens the timing sidebar panel.
*/
add_task(function* () {
let { tab, monitor } = yield initNetMonitor(CONTENT_TYPE_WITHOUT_CACHE_URL);
let { document } = monitor.panelWin;
yield performRequestsAndWait();
let wait = waitForDOM(document, "#timings-panel");
let timing = document.querySelectorAll(".requests-list-timings")[0];
info("Clicking waterfall and waiting for panel update.");
EventUtils.synthesizeMouseAtCenter(timing, {}, monitor.panelWin);
yield wait;
ok(document.querySelector("#timings-tab[aria-selected=true]"),
"Timings tab is selected.");
return teardown(monitor);
function* performRequestsAndWait() {
let onAllEvents = waitForNetworkEvents(monitor, CONTENT_TYPE_WITHOUT_CACHE_REQUESTS);
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
content.wrappedJSObject.performRequests();
});
yield onAllEvents;
}
});

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

@ -23,6 +23,7 @@
#include "js/Value.h"
#include "Layers.h"
#include "MediaDecoder.h"
#include "nsAppRunner.h"
// nsNPAPIPluginInstance must be included before nsIDocument.h, which is included in mozAutoDocUpdate.h.
#include "nsNPAPIPluginInstance.h"
#include "gfxDrawable.h"
@ -304,8 +305,10 @@ bool nsContentUtils::sLowerNetworkPriority = false;
#ifndef RELEASE_OR_BETA
bool nsContentUtils::sBypassCSSOMOriginCheck = false;
#endif
bool nsContentUtils::sIsBytecodeCacheEnabled = false;
int32_t nsContentUtils::sBytecodeCacheStrategy = 0;
nsCString* nsContentUtils::sJSBytecodeMimeType = nullptr;
int32_t nsContentUtils::sPrivacyMaxInnerWidth = 1000;
int32_t nsContentUtils::sPrivacyMaxInnerHeight = 1000;
@ -733,6 +736,9 @@ nsContentUtils::Init()
Preferences::AddIntVarCache(&sBytecodeCacheStrategy,
"dom.script_loader.bytecode_cache.strategy", 0);
nsDependentCString buildID(mozilla::PlatformBuildID());
sJSBytecodeMimeType = new nsCString(NS_LITERAL_CSTRING("javascript/moz-bytecode-") + buildID);
Element::InitCCCallbacks();
Unused << nsRFPService::GetOrCreate();
@ -2137,6 +2143,9 @@ nsContentUtils::Shutdown()
delete sModifierSeparator;
sModifierSeparator = nullptr;
delete sJSBytecodeMimeType;
sJSBytecodeMimeType = nullptr;
NS_IF_RELEASE(sSameOriginChecker);
if (sUserInteractionObserver) {

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

@ -2993,6 +2993,10 @@ public:
// heuristic strategy should be used to trigger the caching of the bytecode.
static int32_t BytecodeCacheStrategy() { return sBytecodeCacheStrategy; }
// Alternate data MIME type used by the ScriptLoader to register and read
// bytecode out of the nsCacheInfoChannel.
static nsCString& JSBytecodeMimeType() { return *sJSBytecodeMimeType; }
/**
* Checks if the passed-in name should override an existing name on the
* window. Values which should not override include: "", "_blank", "_top",
@ -3157,6 +3161,10 @@ private:
static nsString* sAltText;
static nsString* sModifierSeparator;
// Alternate data mime type, used by the ScriptLoader to register and read the
// bytecode out of the nsCacheInfoChannel.
static nsCString* sJSBytecodeMimeType;
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
static bool sDOMWindowDumpEnabled;
#endif

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

@ -8,6 +8,8 @@
#include "ScriptLoader.h"
#include "ScriptTrace.h"
#include "nsContentUtils.h"
#include "mozilla/dom/EncodingUtils.h"
#include "mozilla/Telemetry.h"
@ -277,10 +279,11 @@ ScriptLoadHandler::EnsureKnownDataType(nsIIncrementalStreamLoader* aLoader)
if (cic) {
nsAutoCString altDataType;
cic->GetAlternativeDataType(altDataType);
if (altDataType.EqualsLiteral("javascript/moz-bytecode-" NS_STRINGIFY(MOZ_BUILDID))) {
if (altDataType.Equals(nsContentUtils::JSBytecodeMimeType())) {
mRequest->mDataType = ScriptLoadRequest::DataType::Bytecode;
TRACE_FOR_TEST(mRequest->mElement, "scriptloader_load_bytecode");
} else {
MOZ_ASSERT(altDataType.IsEmpty());
mRequest->mDataType = ScriptLoadRequest::DataType::Source;
TRACE_FOR_TEST(mRequest->mElement, "scriptloader_load_source");
}

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

@ -77,10 +77,9 @@ LazyLogModule ScriptLoader::gScriptLoaderLog("ScriptLoader");
#define LOG(args) \
MOZ_LOG(gScriptLoaderLog, mozilla::LogLevel::Debug, args)
// These are the Alternate Data MIME type used by the ScriptLoader to
// register and read bytecode out of the nsCacheInfoChannel.
static NS_NAMED_LITERAL_CSTRING(
kBytecodeMimeType, "javascript/moz-bytecode-" NS_STRINGIFY(MOZ_BUILDID));
// Alternate Data MIME type used by the ScriptLoader to register that we want to
// store bytecode without reading it.
static NS_NAMED_LITERAL_CSTRING(kNullMimeType, "javascript/null");
//////////////////////////////////////////////////////////////
@ -909,7 +908,7 @@ ScriptLoader::StartLoad(ScriptLoadRequest* aRequest)
NS_ENSURE_SUCCESS(rv, rv);
// To avoid decoding issues, the JSVersion is explicitly guarded here, and the
// build-id is part of the kBytecodeMimeType constant.
// build-id is part of the JSBytecodeMimeType constant.
aRequest->mCacheInfo = nullptr;
nsCOMPtr<nsICacheInfoChannel> cic(do_QueryInterface(channel));
if (cic && nsContentUtils::IsBytecodeCacheEnabled() &&
@ -918,7 +917,7 @@ ScriptLoader::StartLoad(ScriptLoadRequest* aRequest)
// Inform the HTTP cache that we prefer to have information coming from the
// bytecode cache instead of the sources, if such entry is already registered.
LOG(("ScriptLoadRequest (%p): Maybe request bytecode", aRequest));
cic->PreferAlternativeDataType(kBytecodeMimeType);
cic->PreferAlternativeDataType(nsContentUtils::JSBytecodeMimeType());
} else {
// If we are explicitly loading from the sources, such as after a
// restarted request, we might still want to save the bytecode after.
@ -1989,15 +1988,15 @@ ScriptLoader::ShouldCacheBytecode(ScriptLoadRequest* aRequest)
LOG(("ScriptLoadRequest (%p): Bytecode-cache: Cannot get lastFetched.", aRequest));
return false;
}
TimeStamp now = TimeStamp::NowLoRes();
TimeStamp last = TimeStamp() + TimeDuration::FromSeconds(lastFetched);
if (now < last) {
uint32_t now = PR_Now() / PR_USEC_PER_SEC;
if (now < lastFetched) {
LOG(("ScriptLoadRequest (%p): Bytecode-cache: (What?) lastFetched set in the future.", aRequest));
return false;
}
TimeDuration since = TimeDuration::FromSeconds(now - lastFetched);
LOG(("ScriptLoadRequest (%p): Bytecode-cache: lastFetched = %f sec. ago.",
aRequest, (now - last).ToSeconds()));
if (now - last >= timeSinceLastFetched) {
aRequest, since.ToSeconds()));
if (since >= timeSinceLastFetched) {
return false;
}
}
@ -2264,7 +2263,7 @@ ScriptLoader::EncodeRequestBytecode(JSContext* aCx, ScriptLoadRequest* aRequest)
// might fail if the stream is already open by another request, in which
// case, we just ignore the current one.
nsCOMPtr<nsIOutputStream> output;
rv = aRequest->mCacheInfo->OpenAlternativeOutputStream(kBytecodeMimeType,
rv = aRequest->mCacheInfo->OpenAlternativeOutputStream(nsContentUtils::JSBytecodeMimeType(),
getter_AddRefs(output));
if (NS_FAILED(rv)) {
LOG(("ScriptLoadRequest (%p): Cannot open bytecode cache (rv = %X, output = %p)",

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

@ -211,10 +211,12 @@ function* run_test_2(generator)
{
// Load the profile and populate it.
do_load_profile();
for (let i = 0; i < 3000; ++i) {
let uri = NetUtil.newURI("http://" + i + ".com/");
Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null);
}
Services.cookies.runInTransaction(_=>{
for (let i = 0; i < 3000; ++i) {
let uri = NetUtil.newURI("http://" + i + ".com/");
Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null);
}
});
// Close the profile.
do_close_profile(sub_generator);
@ -281,16 +283,18 @@ function* run_test_3(generator)
// Load the profile and populate it.
do_load_profile();
for (let i = 0; i < 10; ++i) {
let uri = NetUtil.newURI("http://hither.com/");
Services.cookies.setCookieString(uri, null, "oh" + i + "=hai; max-age=1000",
null);
}
for (let i = 10; i < 3000; ++i) {
let uri = NetUtil.newURI("http://haithur.com/");
Services.cookies.setCookieString(uri, null, "oh" + i + "=hai; max-age=1000",
null);
}
Services.cookies.runInTransaction(_=>{
for (let i = 0; i < 10; ++i) {
let uri = NetUtil.newURI("http://hither.com/");
Services.cookies.setCookieString(uri, null, "oh" + i + "=hai; max-age=1000",
null);
}
for (let i = 10; i < 3000; ++i) {
let uri = NetUtil.newURI("http://haithur.com/");
Services.cookies.setCookieString(uri, null, "oh" + i + "=hai; max-age=1000",
null);
}
});
// Close the profile.
do_close_profile(sub_generator);
@ -372,78 +376,12 @@ function* run_test_4(generator)
{
// Load the profile and populate it.
do_load_profile();
for (let i = 0; i < 3000; ++i) {
let uri = NetUtil.newURI("http://" + i + ".com/");
Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null);
}
// Close the profile.
do_close_profile(sub_generator);
yield;
// Corrupt the database file.
let size = do_corrupt_db(do_get_cookie_file(profile));
// Load the profile.
do_load_profile();
// At this point, the database connection should be open. Ensure that it
// succeeded.
do_check_false(do_get_backup_file(profile).exists());
// Synchronously read in the first cookie. This will cause it to go into the
// cookie table, whereupon it will be written out during database rebuild.
do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1);
// Queue up an INSERT for the same base domain. This should also go into
// memory and be written out during database rebuild.
let uri = NetUtil.newURI("http://0.com/");
Services.cookies.setCookieString(uri, null, "oh2=hai; max-age=1000", null);
// Wait for the asynchronous read to choke and the insert to fail shortly
// thereafter, at which point the backup file will be created and the database
// rebuilt.
new _observer(sub_generator, "cookie-db-rebuilding");
yield;
do_execute_soon(function() { do_run_generator(sub_generator); });
yield;
// Close the profile.
do_close_profile(sub_generator);
yield;
// Check that the original database was renamed.
do_check_true(do_get_backup_file(profile).exists());
do_check_eq(do_get_backup_file(profile).fileSize, size);
let db = Services.storage.openDatabase(do_get_cookie_file(profile));
do_check_eq(do_count_cookies_in_db(db, "0.com"), 2);
db.close();
// Load the profile, and check that it contains the new cookie.
do_load_profile();
do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 2);
do_check_eq(do_count_cookies(), 2);
// Close the profile.
do_close_profile(sub_generator);
yield;
// Clean up.
do_get_cookie_file(profile).remove(false);
do_get_backup_file(profile).remove(false);
do_check_false(do_get_cookie_file(profile).exists());
do_check_false(do_get_backup_file(profile).exists());
do_run_generator(generator);
}
function* run_test_4(generator)
{
// Load the profile and populate it.
do_load_profile();
for (let i = 0; i < 3000; ++i) {
let uri = NetUtil.newURI("http://" + i + ".com/");
Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null);
}
Services.cookies.runInTransaction(_=>{
for (let i = 0; i < 3000; ++i) {
let uri = NetUtil.newURI("http://" + i + ".com/");
Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null);
}
});
// Close the profile.
do_close_profile(sub_generator);
@ -512,13 +450,15 @@ function* run_test_5(generator)
{
// Load the profile and populate it.
do_load_profile();
let uri = NetUtil.newURI("http://bar.com/");
Services.cookies.setCookieString(uri, null, "oh=hai; path=/; max-age=1000",
null);
for (let i = 0; i < 3000; ++i) {
let uri = NetUtil.newURI("http://" + i + ".com/");
Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null);
}
Services.cookies.runInTransaction(_=>{
let uri = NetUtil.newURI("http://bar.com/");
Services.cookies.setCookieString(uri, null, "oh=hai; path=/; max-age=1000",
null);
for (let i = 0; i < 3000; ++i) {
let uri = NetUtil.newURI("http://" + i + ".com/");
Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null);
}
});
// Close the profile.
do_close_profile(sub_generator);

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

@ -11,6 +11,7 @@
#ifdef BUILD_ARM_NEON
#include "mozilla/arm.h"
#include "LuminanceNEON.h"
#endif
namespace mozilla {
@ -76,6 +77,15 @@ ComputesRGBLuminanceMask(const uint8_t *aSourceData,
const IntSize &aSize,
float aOpacity)
{
#ifdef BUILD_ARM_NEON
if (mozilla::supports_neon()) {
ComputesRGBLuminanceMask_NEON(aSourceData, aSourceStride,
aDestData, aDestStride,
aSize, aOpacity);
return;
}
#endif
int32_t redFactor = 55 * aOpacity; // 255 * 0.2125 * opacity
int32_t greenFactor = 183 * aOpacity; // 255 * 0.7154 * opacity
int32_t blueFactor = 18 * aOpacity; // 255 * 0.0721

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

@ -116,7 +116,6 @@ DrawTargetD2D1::EnsureLuminanceEffect()
already_AddRefed<SourceSurface>
DrawTargetD2D1::IntoLuminanceSource(LuminanceType aLuminanceType, float aOpacity)
{
//return DrawTarget::IntoLuminanceSource(aLuminanceType, aOpacity);
if (aLuminanceType != LuminanceType::LUMINANCE) {
return DrawTarget::IntoLuminanceSource(aLuminanceType, aOpacity);
}

88
gfx/2d/LuminanceNEON.cpp Normal file
Просмотреть файл

@ -0,0 +1,88 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include <arm_neon.h>
#include "LuminanceNEON.h"
using namespace mozilla::gfx;
/**
* Byte offsets of channels in a native packed gfxColor or cairo image surface.
*/
#ifdef IS_BIG_ENDIAN
#define GFX_ARGB32_OFFSET_A 0
#define GFX_ARGB32_OFFSET_R 1
#define GFX_ARGB32_OFFSET_G 2
#define GFX_ARGB32_OFFSET_B 3
#else
#define GFX_ARGB32_OFFSET_A 3
#define GFX_ARGB32_OFFSET_R 2
#define GFX_ARGB32_OFFSET_G 1
#define GFX_ARGB32_OFFSET_B 0
#endif
void
ComputesRGBLuminanceMask_NEON(const uint8_t *aSourceData,
int32_t aSourceStride,
uint8_t *aDestData,
int32_t aDestStride,
const IntSize &aSize,
float aOpacity)
{
int32_t redFactor = 55 * aOpacity; // 255 * 0.2125 * opacity
int32_t greenFactor = 183 * aOpacity; // 255 * 0.7154 * opacity
int32_t blueFactor = 18 * aOpacity; // 255 * 0.0721
const uint8_t *sourcePixel = aSourceData;
int32_t sourceOffset = aSourceStride - 4 * aSize.width;
uint8_t *destPixel = aDestData;
int32_t destOffset = aDestStride - aSize.width;
sourcePixel = aSourceData;
int32_t remainderWidth = aSize.width % 8;
int32_t roundedWidth = aSize.width - remainderWidth;
uint16x8_t temp;
uint8x8_t gray;
uint8x8_t redVector = vdup_n_u8(redFactor);
uint8x8_t greenVector = vdup_n_u8(greenFactor);
uint8x8_t blueVector = vdup_n_u8(blueFactor);
uint8x8_t fullBitVector = vdup_n_u8(255);
uint8x8_t oneVector = vdup_n_u8(1);
for (int32_t y = 0; y < aSize.height; y++) {
// Calculate luminance by neon with 8 pixels per loop
for (int32_t x = 0; x < roundedWidth; x += 8) {
uint8x8x4_t argb = vld4_u8(sourcePixel);
temp = vmull_u8(argb.val[GFX_ARGB32_OFFSET_R], redVector); // temp = red * redFactor
temp = vmlal_u8(temp, argb.val[GFX_ARGB32_OFFSET_G], greenVector); // temp += green * greenFactor
temp = vmlal_u8(temp, argb.val[GFX_ARGB32_OFFSET_B], blueVector); // temp += blue * blueFactor
gray = vshrn_n_u16(temp, 8); // gray = temp >> 8
// Check alpha value
uint8x8_t alphaVector = vtst_u8(argb.val[GFX_ARGB32_OFFSET_A], fullBitVector);
gray = vmul_u8(gray, vand_u8(alphaVector, oneVector));
// Put the result to the 8 pixels
vst1_u8(destPixel, gray);
sourcePixel += 8 * 4;
destPixel += 8;
}
// Calculate the rest pixels of the line by cpu
for (int32_t x = 0; x < remainderWidth; x++) {
if (sourcePixel[GFX_ARGB32_OFFSET_A] > 0) {
*destPixel = (redFactor * sourcePixel[GFX_ARGB32_OFFSET_R]+
greenFactor * sourcePixel[GFX_ARGB32_OFFSET_G] +
blueFactor * sourcePixel[GFX_ARGB32_OFFSET_B]) >> 8;
} else {
*destPixel = 0;
}
sourcePixel += 4;
destPixel++;
}
sourcePixel += sourceOffset;
destPixel += destOffset;
}
}

19
gfx/2d/LuminanceNEON.h Normal file
Просмотреть файл

@ -0,0 +1,19 @@
/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef __LUMINANCENEON_H__
#define __LUMINANCENEON_H__
#include "mozilla/gfx/Point.h"
void
ComputesRGBLuminanceMask_NEON(const uint8_t *aSourceData,
int32_t aSourceStride,
uint8_t *aDestData,
int32_t aDestStride,
const mozilla::gfx::IntSize &aSize,
float aOpacity);
#endif /* __LUMINANCENEON_H__ */

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

@ -220,9 +220,11 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']:
SOURCES += [
'BlurNEON.cpp',
'LuminanceNEON.cpp',
'SwizzleNEON.cpp',
]
SOURCES['BlurNEON.cpp'].flags += CONFIG['NEON_FLAGS']
SOURCES['LuminanceNEON.cpp'].flags += CONFIG['NEON_FLAGS']
SOURCES['SwizzleNEON.cpp'].flags += CONFIG['NEON_FLAGS']
include('/ipc/chromium/chromium-config.mozbuild')

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

@ -124,13 +124,13 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(MaskParams& aParams)
nsSVGUtils::PaintFrameWithEffects(kid, *tmpCtx, m, aParams.imgParams);
}
if (StyleSVG()->mColorInterpolation ==
NS_STYLE_COLOR_INTERPOLATION_LINEARRGB) {
maskType = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB;
}
RefPtr<SourceSurface> surface;
if (maskType == NS_STYLE_MASK_TYPE_LUMINANCE) {
if (StyleSVG()->mColorInterpolation ==
NS_STYLE_COLOR_INTERPOLATION_LINEARRGB) {
maskType = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB;
}
RefPtr<SourceSurface> maskSnapshot =
maskDT->IntoLuminanceSource(GetLuminanceType(maskType),
aParams.opacity);

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

@ -244,6 +244,12 @@ CookieServiceChild::SetCookieStringFromHttp(nsIURI *aHostURI,
aServerTime, true);
}
NS_IMETHODIMP
CookieServiceChild::RunInTransaction(nsICookieTransactionCallback* aCallback)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
} // namespace net
} // namespace mozilla

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

@ -2264,6 +2264,27 @@ nsCookieService::CreatePurgeList(nsICookie2* aCookie)
return removedList.forget();
}
/******************************************************************************
* nsCookieService:
* public transaction helper impl
******************************************************************************/
NS_IMETHODIMP
nsCookieService::RunInTransaction(nsICookieTransactionCallback* aCallback)
{
NS_ENSURE_ARG(aCallback);
if (NS_WARN_IF(!mDefaultDBState->dbConn)) {
return NS_ERROR_NOT_AVAILABLE;
}
mozStorageTransaction transaction(mDefaultDBState->dbConn, true);
if (NS_FAILED(aCallback->Callback())) {
Unused << transaction.Rollback();
return NS_ERROR_FAILURE;
}
return NS_OK;
}
/******************************************************************************
* nsCookieService:
* pref observer impl

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

@ -9,6 +9,15 @@ interface nsIURI;
interface nsIPrompt;
interface nsIChannel;
/**
* @see nsICookieService::runInTransaction
*/
[scriptable, function, uuid(0fc41ffb-f1b7-42d9-9a42-8dc420c158c1)]
interface nsICookieTransactionCallback : nsISupports
{
void callback();
};
/**
* nsICookieService
*
@ -190,4 +199,19 @@ interface nsICookieService : nsISupports
* provided, the cookies will be assumed third-party.)
*/
void setCookieStringFromHttp(in nsIURI aURI, in nsIURI aFirstURI, in nsIPrompt aPrompt, in string aCookie, in string aServerTime, in nsIChannel aChannel);
/*
* Batch SQLite operations into one transaction. By default each call to
* CookieService that affects the underlying SQLite database (add, remove,
* setCookieString etc.) runs in a separate transaction. If you do this many
* times in a row, it's faster and suggested to wrap them all in a single
* transaction by setting all the operations into the callback parameter.
* Example: test scripts that need to construct a large cookie database.
* @param aCallback
* nsICookieTransactionCallback interface to call
* @throws NS_ERROR_FAILURE if aCallback() fails.
* @throws NS_ERROR_NOT_AVAILABLE if the connection is not established.
*/
void runInTransaction(in nsICookieTransactionCallback aCallback);
};

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

@ -2685,7 +2685,7 @@ NS_IMETHODIMP
HttpChannelChild::GetCacheTokenFetchCount(int32_t *_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
if (!mCacheEntryAvailable || !mAltDataCacheEntryAvailable) {
if (!mCacheEntryAvailable && !mAltDataCacheEntryAvailable) {
return NS_ERROR_NOT_AVAILABLE;
}
@ -2697,7 +2697,7 @@ NS_IMETHODIMP
HttpChannelChild::GetCacheTokenLastFetched(uint32_t *_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
if (!mCacheEntryAvailable || !mAltDataCacheEntryAvailable) {
if (!mCacheEntryAvailable && !mAltDataCacheEntryAvailable) {
return NS_ERROR_NOT_AVAILABLE;
}

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

@ -6,7 +6,7 @@
// Note: window.location.search doesn't work with nsSimpleURIs used for about:* addresses.
var search = window.location.href.match(/^.*\?(.*)$/);
var searchParams = new URLSearchParams(search ? search[1] : "");
var storage = searchParams.get("storage");
var storage = searchParams.get("storage") || "";
var cacheContext = searchParams.get("context");
// The context is in a format as used by the HTTP cache v2 back end

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

@ -21,7 +21,6 @@ const STOREDB_FILENAME = "xulstore.json";
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
function XULStore() {
@ -65,11 +64,7 @@ XULStore.prototype = {
this._storeFile = Services.dirsvc.get("ProfD", Ci.nsIFile);
this._storeFile.append(STOREDB_FILENAME);
if (!this._storeFile.exists()) {
this.import();
} else {
this.readFile();
}
this.readFile();
},
observe(subject, topic, data) {
@ -89,58 +84,6 @@ XULStore.prototype = {
Services.console.logStringMessage("XULStore: " + message);
},
import() {
let localStoreFile = Services.dirsvc.get("ProfD", Ci.nsIFile);
localStoreFile.append("localstore.rdf");
if (!localStoreFile.exists()) {
return;
}
const RDF = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
const persistKey = RDF.GetResource("http://home.netscape.com/NC-rdf#persist");
this.log("Import localstore from " + localStoreFile.path);
let localStoreURI = Services.io.newFileURI(localStoreFile).spec;
let localStore = RDF.GetDataSourceBlocking(localStoreURI);
let resources = localStore.GetAllResources();
while (resources.hasMoreElements()) {
let resource = resources.getNext().QueryInterface(Ci.nsIRDFResource);
let uri;
try {
uri = NetUtil.newURI(resource.ValueUTF8);
} catch (ex) {
continue; // skip invalid uris
}
// If this has a ref, then this is an attribute reference. Otherwise,
// this is a document reference.
if (!uri.hasRef)
continue;
// Verify that there the persist key is connected up.
let docURI = uri.specIgnoringRef;
if (!localStore.HasAssertion(RDF.GetResource(docURI), persistKey, resource, true))
continue;
let id = uri.ref;
let attrs = localStore.ArcLabelsOut(resource);
while (attrs.hasMoreElements()) {
let attr = attrs.getNext().QueryInterface(Ci.nsIRDFResource);
let value = localStore.GetTarget(resource, attr, true);
if (value instanceof Ci.nsIRDFLiteral) {
this.setValue(docURI, id, attr.ValueUTF8, value.Value);
}
}
}
},
readFile() {
const MODE_RDONLY = 0x01;
const FILE_PERMS = 0o600;
@ -153,7 +96,8 @@ XULStore.prototype = {
this._data = json.decodeFromStream(stream, stream.available());
} catch (e) {
this.log("Error reading JSON: " + e);
// Ignore problem, we'll just continue on with an empty dataset.
// This exception could mean that the file didn't exist.
// We'll just ignore the error and start with a blank slate.
} finally {
stream.close();
}

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

@ -22,7 +22,7 @@ function run_test() {
function checkValue(uri, id, attr, reference) {
let value = XULStore.getValue(uri, id, attr);
do_check_true(value === reference);
do_check_eq(value, reference);
}
function checkValueExists(uri, id, attr, exists) {
@ -59,31 +59,31 @@ function getAttributes(uri, id) {
function checkArrays(a, b) {
a.sort();
b.sort();
do_check_true(a.toString() == b.toString());
do_check_eq(a.toString(), b.toString());
}
function checkOldStore() {
checkArrays(["addon-bar", "main-window", "sidebar-title"], getIDs(browserURI));
checkArrays(["collapsed"], getAttributes(browserURI, "addon-bar"));
checkArrays(["height", "screenX", "screenY", "sizemode", "width"],
checkArrays([], getIDs(browserURI));
checkArrays([], getAttributes(browserURI, "addon-bar"));
checkArrays([],
getAttributes(browserURI, "main-window"));
checkArrays(["value"], getAttributes(browserURI, "sidebar-title"));
checkArrays([], getAttributes(browserURI, "sidebar-title"));
checkValue(browserURI, "addon-bar", "collapsed", "true");
checkValue(browserURI, "main-window", "width", "994");
checkValue(browserURI, "main-window", "height", "768");
checkValue(browserURI, "main-window", "screenX", "4");
checkValue(browserURI, "main-window", "screenY", "22");
checkValue(browserURI, "main-window", "sizemode", "normal");
checkValue(browserURI, "addon-bar", "collapsed", "");
checkValue(browserURI, "main-window", "width", "");
checkValue(browserURI, "main-window", "height", "");
checkValue(browserURI, "main-window", "screenX", "");
checkValue(browserURI, "main-window", "screenY", "");
checkValue(browserURI, "main-window", "sizemode", "");
checkValue(browserURI, "sidebar-title", "value", "");
checkArrays(["lockCol", "prefCol"], getIDs(aboutURI));
checkArrays(["ordinal"], getAttributes(aboutURI, "lockCol"));
checkArrays(["ordinal", "sortDirection"], getAttributes(aboutURI, "prefCol"));
checkArrays([], getIDs(aboutURI));
checkArrays([], getAttributes(aboutURI, "lockCol"));
checkArrays([], getAttributes(aboutURI, "prefCol"));
checkValue(aboutURI, "prefCol", "ordinal", "1");
checkValue(aboutURI, "prefCol", "sortDirection", "ascending");
checkValue(aboutURI, "lockCol", "ordinal", "3");
checkValue(aboutURI, "prefCol", "ordinal", "");
checkValue(aboutURI, "prefCol", "sortDirection", "");
checkValue(aboutURI, "lockCol", "ordinal", "");
}
add_task(async function testImport() {
@ -92,9 +92,12 @@ add_task(async function testImport() {
await OS.File.copy(src, dst);
// Importing relies on XULStore not yet being loaded before this point.
// Test to make sure that localstore.rdf isn't imported any more.
XULStore = Cc["@mozilla.org/xul/xulstore;1"].getService(Ci.nsIXULStore);
checkOldStore();
// Set a value that a future test depends on manually
XULStore.setValue(browserURI, "main-window", "width", "994");
});
add_task(async function testTruncation() {
@ -133,21 +136,21 @@ add_task(async function testSetValue() {
checkValue(browserURI, "side-bar", "width", "");
XULStore.setValue(browserURI, "side-bar", "width", "1000");
checkValue(browserURI, "side-bar", "width", "1000");
checkArrays(["addon-bar", "main-window", "side-bar", "sidebar-title"], getIDs(browserURI));
checkArrays(["main-window", "side-bar"], getIDs(browserURI));
checkArrays(["width"], getAttributes(browserURI, "side-bar"));
// Modify existing property
checkValue(browserURI, "side-bar", "width", "1000");
XULStore.setValue(browserURI, "side-bar", "width", "1024");
checkValue(browserURI, "side-bar", "width", "1024");
checkArrays(["addon-bar", "main-window", "side-bar", "sidebar-title"], getIDs(browserURI));
checkArrays(["main-window", "side-bar"], getIDs(browserURI));
checkArrays(["width"], getAttributes(browserURI, "side-bar"));
// Add another attribute
checkValue(browserURI, "side-bar", "height", "");
XULStore.setValue(browserURI, "side-bar", "height", "1000");
checkValue(browserURI, "side-bar", "height", "1000");
checkArrays(["addon-bar", "main-window", "side-bar", "sidebar-title"], getIDs(browserURI));
checkArrays(["main-window", "side-bar"], getIDs(browserURI));
checkArrays(["width", "height"], getAttributes(browserURI, "side-bar"));
});
@ -157,14 +160,14 @@ add_task(async function testRemoveValue() {
XULStore.removeValue(browserURI, "side-bar", "width");
checkValue(browserURI, "side-bar", "width", "");
checkValueExists(browserURI, "side-bar", "width", false);
checkArrays(["addon-bar", "main-window", "side-bar", "sidebar-title"], getIDs(browserURI));
checkArrays(["main-window", "side-bar"], getIDs(browserURI));
checkArrays(["height"], getAttributes(browserURI, "side-bar"));
// Remove second attribute
checkValue(browserURI, "side-bar", "height", "1000");
XULStore.removeValue(browserURI, "side-bar", "height");
checkValue(browserURI, "side-bar", "height", "");
checkArrays(["addon-bar", "main-window", "sidebar-title"], getIDs(browserURI));
checkArrays(["main-window"], getIDs(browserURI));
// Removing an attribute that doesn't exists shouldn't fail
XULStore.removeValue(browserURI, "main-window", "bar");

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

@ -185,14 +185,11 @@
return innerRect;
]]></getter>
</property>
<property name="scrollboxPaddingStart" readonly="true">
<getter><![CDATA[
var ltr = (window.getComputedStyle(this).direction == "ltr");
var paddingStartName = ltr ? "padding-left" : "padding-right";
var scrollboxStyle = window.getComputedStyle(this._scrollbox);
return parseFloat(scrollboxStyle.getPropertyValue(paddingStartName));
]]></getter>
</property>
<field name="scrollboxPaddingStart"><![CDATA[
parseFloat(window.getComputedStyle(this._scrollbox)[
this._isRTLScrollbox ? "paddingRight" : "paddingLeft"
]);
]]></field>
<property name="scrollPosition">
<getter><![CDATA[
return this.orient == "vertical" ?
@ -208,12 +205,9 @@
]]></setter>
</property>
<property name="_startEndProps" readonly="true">
<getter><![CDATA[
return this.orient == "vertical" ?
["top", "bottom"] : ["left", "right"];
]]></getter>
</property>
<field name="_startEndProps"><![CDATA[
this.orient == "vertical" ? ["top", "bottom"] : ["left", "right"];
]]></field>
<field name="_isRTLScrollbox"><![CDATA[
this.orient != "vertical" &&
@ -222,10 +216,39 @@
<field name="_scrollTarget">null</field>
<method name="_boundsWithoutFlushing">
<parameter name="element"/>
<body><![CDATA[
if (!("_DOMWindowUtils" in this)) {
try {
this._DOMWindowUtils =
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
} catch (e) {
// Can't access nsIDOMWindowUtils if we're unprivileged.
this._DOMWindowUtils = null;
}
}
return this._DOMWindowUtils ?
this._DOMWindowUtils.getBoundsWithoutFlushing(element) :
element.getBoundingClientRect();
]]></body>
</method>
<method name="_canScrollToElement">
<parameter name="element"/>
<body><![CDATA[
return window.getComputedStyle(element).display != "none";
if (element.hidden) {
return false;
}
// See if the element is hidden via CSS without the hidden attribute.
// If we get only zeros for the client rect, this means the element
// is hidden. As a performance optimization, we don't flush layout
// here which means that on the fly changes aren't fully supported.
let rect = this._boundsWithoutFlushing(element);
return !!(rect.top || rect.left || rect.width || rect.height);
]]></body>
</method>

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

@ -3,6 +3,7 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!-- LOCALIZATION NOTE (tapToPlayPlugin): Mobile (used for touch interfaces) only has one type of plugin possible. -->
<!ENTITY pluginActivationWarning "This site uses a plugin that may slow &brandShortName;.">
<!ENTITY tapToPlayPlugin "Tap here to activate plugin.">
<!ENTITY clickToActivatePlugin "Activate plugin.">
<!ENTITY checkForUpdates "Check for updates…">

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

@ -27,6 +27,7 @@
<html:label>
<html:button class="icon" anonid="icon"/>
<html:div class="msg msgVulnerabilityStatus" anonid="vulnerabilityStatus"><!-- set at runtime --></html:div>
<html:div class="msg msgActivationWarning">&pluginActivationWarning;</html:div>
<html:div class="msg msgTapToPlay">&tapToPlayPlugin;</html:div>
<html:div class="msg msgClickToPlay" anonid="clickToPlay">&clickToActivatePlugin;</html:div>
</html:label>

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

@ -86,14 +86,13 @@ a .hoverBox,
}
a .msgClickToPlay,
a .msgTapToPlay,
:-moz-handler-clicktoplay .msgClickToPlay,
:-moz-handler-clicktoplay .msgActivationWarning,
:-moz-handler-vulnerable-updatable .msgVulnerabilityStatus,
:-moz-handler-vulnerable-updatable .msgCheckForUpdates,
:-moz-handler-vulnerable-updatable .msgClickToPlay,
:-moz-handler-vulnerable-no-update .msgVulnerabilityStatus,
:-moz-handler-vulnerable-no-update .msgClickToPlay,
:-moz-handler-clicktoplay .msgTapToPlay,
:-moz-handler-blocked .msgBlocked,
:-moz-handler-crashed .msgCrashed {
display: block;

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

@ -32,11 +32,8 @@
background-color: rgb(65, 65, 65);
}
:-moz-handler-clicktoplay .hoverBox:active .msgTapToPlay,
:-moz-handler-clicktoplay .hoverBox:active .msgClickToPlay,
:-moz-handler-vulnerable-updatable .hoverBox:active .msgTapToPlay,
:-moz-handler-vulnerable-updatable .hoverBox:active .msgClickToPlay,
:-moz-handler-vulnerable-no-update .hoverBox:active .msgTapToPlay,
:-moz-handler-vulnerable-no-update .hoverBox:active .msgClickToPlay {
color: red;
}
@ -93,23 +90,14 @@ a .icon,
}
}
.msgTapToPlay,
.msgClickToPlay {
text-decoration: underline;
}
@media not all and (-moz-touch-enabled) {
:-moz-handler-clicktoplay .msgTapToPlay,
a .msgTapToPlay {
display: none;
}
}
@media (-moz-touch-enabled) {
:-moz-handler-clicktoplay .msgClickToPlay,
a .msgClickToPlay {
display: none;
}
/* on desktop, don't ever show the tap-to-play UI: that is for mobile only */
:-moz-handler-clicktoplay .msgTapToPlay,
a .msgTapToPlay {
display: none;
}
.submitStatus div {

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

@ -468,6 +468,7 @@ public:
// NS_STYLE_FONT_* system font constants.
enum FontID {
eFont_Caption = 1, // css2
FontID_MINIMUM = eFont_Caption,
eFont_Icon,
eFont_Menu,
eFont_MessageBox,
@ -486,7 +487,8 @@ public:
eFont_Field,
eFont_Tooltips, // moz
eFont_Widget
eFont_Widget,
FontID_MAXIMUM = eFont_Widget
};
/**

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

@ -9,7 +9,6 @@
#include "nsStyleConsts.h"
#include "nsUXThemeData.h"
#include "nsUXThemeConstants.h"
#include "gfxFont.h"
#include "WinUtils.h"
#include "mozilla/Telemetry.h"
#include "mozilla/WindowsVersion.h"
@ -663,14 +662,43 @@ nsLookAndFeel::GetFontImpl(FontID anID, nsString &aFontName,
gfxFontStyle &aFontStyle,
float aDevPixPerCSSPixel)
{
HDC tdc = GetDC(nullptr);
bool status = GetSysFontInfo(tdc, anID, aFontName, aFontStyle);
ReleaseDC(nullptr, tdc);
CachedSystemFont &cacheSlot = mSystemFontCache[anID];
bool status;
if (cacheSlot.mCacheValid) {
status = cacheSlot.mHaveFont;
if (status) {
aFontName = cacheSlot.mFontName;
aFontStyle = cacheSlot.mFontStyle;
}
} else {
HDC tdc = GetDC(nullptr);
status = GetSysFontInfo(tdc, anID, aFontName, aFontStyle);
ReleaseDC(nullptr, tdc);
cacheSlot.mCacheValid = true;
cacheSlot.mHaveFont = status;
if (status) {
cacheSlot.mFontName = aFontName;
cacheSlot.mFontStyle = aFontStyle;
}
}
// now convert the logical font size from GetSysFontInfo into device pixels for layout
aFontStyle.size *= aDevPixPerCSSPixel;
return status;
}
/* virtual */ void
nsLookAndFeel::RefreshImpl()
{
nsXPLookAndFeel::RefreshImpl();
for (auto e = mSystemFontCache.begin(), end = mSystemFontCache.end();
e != end; ++e) {
e->mCacheValid = false;
}
}
/* virtual */
char16_t
nsLookAndFeel::GetPasswordCharacterImpl()

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

@ -7,6 +7,8 @@
#define __nsLookAndFeel
#include "nsXPLookAndFeel.h"
#include "gfxFont.h"
#include "mozilla/RangedArray.h"
/*
* Gesture System Metrics
@ -36,16 +38,17 @@ public:
nsLookAndFeel();
virtual ~nsLookAndFeel();
virtual nsresult NativeGetColor(ColorID aID, nscolor &aResult);
virtual nsresult GetIntImpl(IntID aID, int32_t &aResult);
virtual nsresult GetFloatImpl(FloatID aID, float &aResult);
virtual bool GetFontImpl(FontID aID, nsString& aFontName,
gfxFontStyle& aFontStyle,
float aDevPixPerCSSPixel);
virtual char16_t GetPasswordCharacterImpl();
nsresult NativeGetColor(ColorID aID, nscolor &aResult) override;
nsresult GetIntImpl(IntID aID, int32_t &aResult) override;
nsresult GetFloatImpl(FloatID aID, float &aResult) override;
bool GetFontImpl(FontID aID, nsString& aFontName,
gfxFontStyle& aFontStyle,
float aDevPixPerCSSPixel) override;
void RefreshImpl() override;
char16_t GetPasswordCharacterImpl() override;
virtual nsTArray<LookAndFeelInt> GetIntCacheImpl();
virtual void SetIntCacheImpl(const nsTArray<LookAndFeelInt>& aLookAndFeelIntCache);
nsTArray<LookAndFeelInt> GetIntCacheImpl() override;
void SetIntCacheImpl(const nsTArray<LookAndFeelInt>& aLookAndFeelIntCache) override;
private:
// Content process cached values that get shipped over from the browser
@ -53,6 +56,21 @@ private:
int32_t mUseAccessibilityTheme;
int32_t mUseDefaultTheme; // is the current theme a known default?
int32_t mNativeThemeId; // see LookAndFeel enum 'WindowsTheme'
struct CachedSystemFont {
CachedSystemFont()
: mCacheValid(false)
{}
bool mCacheValid;
bool mHaveFont;
nsString mFontName;
gfxFontStyle mFontStyle;
};
mozilla::RangedArray<CachedSystemFont,
FontID_MINIMUM,
FontID_MAXIMUM + 1 - FontID_MINIMUM> mSystemFontCache;
};
#endif