зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to central, a=merge
MozReview-Commit-ID: IrZXJHbiqpa
This commit is contained in:
Коммит
07d7985523
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче