import changes from `devel' branch of rmottola/Arctic-Fox:

- Bug 1132874 - Improve protections against sending a parent plugin protocol shutdown message to the child after the child has torn down. r=aklotz (b80b45fa7)
- Bug 1103036 - Follow-up to initial patch; r=jchen (51337c2dc)
- Bug 1132874 - Simplify PPluginWidget protocol handling, and avoid sending async messages from the parent. Addresses a problem with sub protocols that are torn down randomly from either side of the connection. r=aklotz (3ad936e84)
- Bug 1128214 - Avoid a crash when attempting to render windows titlebar specific theme elements with e10s. r=roc (b6f17da09)
- Bug 1139368 - Set FilterTypeSet dependency in improveThisTypesForCall. r=h4writer (422de7271)
- Bug 864041 - Remove Firefox 2+3 compat code from about:sessionrestore. r=mak (4cfc6fe9a)
- Bug 1009599 - Restoring from about:sessionrestore fails when there is more than one tab in the window r=smacleod (88ca1cfbc)
- Bug 1146052 - Fix empty about:sessionrestore after crash as well as empty about:welcomeback after resetting the profile r=smacleod (211b50396)
- Bug 1043797: extended popup notifications to create a generic doorhanger for all security notifications incl. mixed content r=adw (f7c2d5ded)
- Bug 900845 - We aren't using the NetUtil module in SessionStore.jsm. (3f5ddd133)
- Bug 898755 - Remove _resume_session_once_on_shutdown code from SessionStore; r=yoric (eb159fec9)
- Bug 902727 - [Session Restore] Remove legacy _writeFileEncoder; r=smacleod (8e375c529)
- space cleanup (cbd71ce91)
- Bug 968923 - part 1 - add infrastructure for defining use counters from UseCounters.conf; original-author=heycam; r=heycam,gfritzsche,mshal (d0dea9997)
- Bug 968923 - part 2 - change MappedAttrParser to store a nsSVGElement directly, instead of its nsIPrincipal; r=smaug (4eff86d7f)
- Merge branch 'devel' of https://github.com/rmottola/Arctic-Fox into devel (feb4378e6)
This commit is contained in:
2020-01-17 09:03:54 +08:00
parent 7bfdfdf34c
commit 3c4a44c16e
55 changed files with 744 additions and 332 deletions
+4
View File
@@ -549,6 +549,10 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(#nav-bar):not(
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#addon-progress-notification");
}
#bad-content-notification {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#bad-content-notification");
}
#click-to-play-plugins-notification {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#click-to-play-plugins-notification");
}
+12 -29
View File
@@ -6472,43 +6472,26 @@ var gIdentityHandler = {
// Ensure the doorhanger is shown when mixed active content is blocked.
if (state & nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT)
this.showMixedContentDoorhanger();
this.showBadContentDoorhanger(state);
},
/**
* Display the Mixed Content Blocker doohanger, providing an option
* to the user to override mixed content blocking
*/
showMixedContentDoorhanger : function() {
showBadContentDoorhanger : function(state) {
var currentNotification =
PopupNotifications.getNotification("bad-content",
gBrowser.selectedBrowser);
// If we've already got an active notification, bail out to avoid showing it repeatedly.
if (PopupNotifications.getNotification("mixed-content-blocked", gBrowser.selectedBrowser))
if (currentNotification && currentNotification.options.state == state)
return;
let brandBundle = document.getElementById("bundle_brand");
let brandShortName = brandBundle.getString("brandShortName");
let messageString = gNavigatorBundle.getFormattedString("mixedContentBlocked.message", [brandShortName]);
let action = {
label: gNavigatorBundle.getString("mixedContentBlocked.keepBlockingButton.label"),
accessKey: gNavigatorBundle.getString("mixedContentBlocked.keepBlockingButton.accesskey"),
callback: function() { /* NOP */ }
};
let secondaryActions = [
{
label: gNavigatorBundle.getString("mixedContentBlocked.unblock.label"),
accessKey: gNavigatorBundle.getString("mixedContentBlocked.unblock.accesskey"),
callback: function() {
// Reload the page with the content unblocked
BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT);
}
}
];
let options = {
dismissed: true,
learnMoreURL: Services.urlFormatter.formatURLPref("browser.mixedcontent.warning.infoURL"),
state: state
};
PopupNotifications.show(gBrowser.selectedBrowser, "mixed-content-blocked",
messageString, "mixed-content-blocked-notification-icon",
action, secondaryActions, options);
PopupNotifications.show(gBrowser.selectedBrowser, "bad-content",
"", "bad-content-blocked-notification-icon",
null, null, options);
},
/**
+1 -1
View File
@@ -441,7 +441,7 @@
<image id="webapps-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="plugins-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="web-notifications-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="mixed-content-blocked-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="bad-content-blocked-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="webRTC-sharingDevices-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="pointerLock-notification-icon" class="notification-anchor-icon" role="button"/>
@@ -88,10 +88,3 @@
<label id="pointerLock-cancel" value="&pointerLock.notification.message;"/>
</popupnotificationcontent>
</popupnotification>
<popupnotification id="mixed-content-blocked-notification" hidden="true">
<popupnotificationcontent orient="vertical" align="start">
<separator/>
<description id="mixed-content-blocked-moreinfo">&mixedContentBlocked.moreinfo;</description>
</popupnotificationcontent>
</popupnotification>
+106
View File
@@ -10,6 +10,8 @@
%notificationDTD;
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
%browserDTD;
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
%brandDTD;
]>
<bindings id="urlbarBindings" xmlns="http://www.mozilla.org/xbl"
@@ -1264,6 +1266,110 @@
</implementation>
</binding>
<binding id="bad-content-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
<content>
<xul:hbox align="start">
<xul:image class="popup-notification-icon" xbl:inherits="popupid"/>
<xul:vbox>
<!-- header -->
<xul:vbox>
<xul:description anonid="badContentBlocked.title"
class="popup-notification-item-title" xbl:inherits="popupid">
</xul:description>
<xul:description class="popup-notification-item-message"
xbl:inherits="popupid">
&badContentBlocked.moreinfo;
</xul:description>
</xul:vbox>
<!-- mixed content -->
<xul:vbox anonid="mixedContent" hidden="true">
<xul:separator class="groove"/>
<xul:hbox align="start">
<xul:vbox>
<xul:description class="popup-notification-item-title"
xbl:inherits="popupid">
&mixedContentBlocked2.message;
</xul:description>
<xul:description class="popup-notification-item-message"
xbl:inherits="popupid">
&mixedContentBlocked2.moreinfo;
</xul:description>
<xul:label anonid="mixedContent.helplink"
class="text-link plain" href=""
value="&mixedContentBlocked2.learnMore;"/>
</xul:vbox>
<xul:button
type="menu" label="&mixedContentBlocked2.options;"
sizetopopup="none">
<xul:menupopup>
<xul:menuitem anonid="mixedContentAction.unblock"
hidden="true" label="&mixedContentBlocked2.unblock.label;"
accesskey="&mixedContentBlocked2.unblock.accesskey;"
oncommand="document.getBindingParent(this).disableMixedContentProtection();"/>
</xul:menupopup>
</xul:button>
</xul:hbox>
</xul:vbox>
</xul:vbox>
</xul:hbox>
</content>
<resources>
<stylesheet src="chrome://global/skin/notification.css"/>
</resources>
<implementation>
<field name="_brandShortName">
document.getElementById("bundle_brand").getString("brandShortName")
</field>
<field name="_doorhangerTitle">
document.getAnonymousElementByAttribute(this, "anonid",
"badContentBlocked.title")
</field>
<field name="_mixedContent">
document.getAnonymousElementByAttribute(this, "anonid",
"mixedContent")
</field>
<field name="_mixedContentUnblock">
document.getAnonymousElementByAttribute(this, "anonid",
"mixedContentAction.unblock")
</field>
<field name="_mixedContentHelplink">
document.getAnonymousElementByAttribute(this, "anonid",
"mixedContent.helplink")
</field>
<constructor><![CDATA[
// default title
_doorhangerTitle.value =
gNavigatorBundle.getFormattedString(
"badContentBlocked.notblocked.message", [this._brandShortName]);
if (this.notification.options.state &
Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT) {
_doorhangerTitle.value =
gNavigatorBundle.getFormattedString(
"badContentBlocked.blocked.message", [this._brandShortName]);
_mixedContent.hidden = false;
_mixedContentUnblock.hidden = false;
_mixedContentHelplink.href =
Services.urlFormatter.formatURLPref("app.support.baseURL")
+ "mixed-content";
}
]]></constructor>
<method name="disableMixedContentProtection">
<body><![CDATA[
// Use telemetry to measure how often unblocking happens
const kMIXED_CONTENT_UNBLOCK_EVENT = 2;
let histogram =
Services.telemetry.getHistogramById(
"MIXED_CONTENT_UNBLOCK_COUNTER");
histogram.add(kMIXED_CONTENT_UNBLOCK_EVENT);
// Reload the page with the content unblocked
BrowserReloadWithFlags(
nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT);
]]></body>
</method>
</implementation>
</binding>
<binding id="click-to-play-plugins-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
<content align="start" class="click-to-play-plugins-notification-content">
<xul:vbox flex="1" align="stretch" class="popup-notification-main-box"
@@ -72,14 +72,9 @@ let SessionMigrationInternal = {
win._closedTabs = [];
return win;
});
let wrappedState = {
url: "about:welcomeback",
formdata: {
id: {"sessionData": state},
xpath: {}
}
};
return {windows: [{tabs: [{entries: [wrappedState]}]}]};
let url = "about:welcomeback";
let formdata = {id: {sessionData: state}, url};
return {windows: [{tabs: [{entries: [{url}], formdata}]}]};
},
/**
* Asynchronously read session restore state (JSON) from a path
@@ -138,9 +138,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivacyFilter",
XPCOMUtils.defineLazyModuleGetter(this, "RunState",
"resource:///modules/sessionstore/RunState.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
#ifdef MOZ_DEVTOOLS
Object.defineProperty(this, "HUDService", {
@@ -409,16 +406,6 @@ let SessionStoreInternal = {
// Whether session has been initialized
_sessionInitialized: false,
// The original "sessionstore.resume_session_once" preference value before it
// was modified by saveState. saveState will set the
// "sessionstore.resume_session_once" to true when the
// the "sessionstore.resume_from_crash" preference is false (crash recovery
// is disabled) so that pinned tabs will be restored in the case of a
// crash. This variable is used to restore the original value so the
// previous session is not always restored when
// "sessionstore.resume_from_crash" is true.
_resume_session_once_on_shutdown: null,
// Keep busy state counters per window.
_windowBusyStates: new WeakMap(),
@@ -500,14 +487,9 @@ let SessionStoreInternal = {
if (this._needsRestorePage(state, this._recentCrashes)) {
// replace the crashed session with a restore-page-only session
let pageData = {
url: "about:sessionrestore",
formdata: {
id: { "sessionData": state },
xpath: {}
}
};
state = { windows: [{ tabs: [{ entries: [pageData] }] }] };
let url = "about:sessionrestore";
let formdata = {id: {sessionData: state}, url};
state = { windows: [{ tabs: [{ entries: [{url}], formdata }] }] };
} else if (this._hasSingleTabWithURL(state.windows,
"about:welcomeback")) {
// On a single about:welcomeback URL that crashed, replace about:welcomeback
@@ -544,20 +526,11 @@ let SessionStoreInternal = {
this._prefBranch.getBoolPref("sessionstore.resume_session_once"))
this._prefBranch.setBoolPref("sessionstore.resume_session_once", false);
this._initEncoding();
this._sessionInitialized = true;
TelemetryStopwatch.finish("FX_SESSION_RESTORE_STARTUP_INIT_SESSION_MS");
return state;
},
_initEncoding : function ssi_initEncoding() {
// The (UTF-8) encoder used to write to files.
XPCOMUtils.defineLazyGetter(this, "_writeFileEncoder", function () {
return new TextEncoder();
});
},
_initPrefs : function() {
this._prefBranch = Services.prefs.getBranch("browser.");
@@ -864,7 +837,7 @@ let SessionStoreInternal = {
// it happens before observers are notified
this._globalState.setFromState(aInitialState);
let overwrite = this._isCmdLineEmpty(aWindow, aInitialState);
let overwrite = this._isCmdLineEmpty(aWindow, aInitialState);
let options = {firstWindow: true, overwriteTabs: overwrite};
this.restoreWindow(aWindow, aInitialState, options);
}
@@ -1209,15 +1182,6 @@ let SessionStoreInternal = {
// browser is about to exit anyway.
Services.obs.removeObserver(this, "browser:purge-session-history");
}
else if (this._resume_session_once_on_shutdown != null) {
// if the sessionstore.resume_session_once preference was changed by
// saveState because crash recovery is disabled then restore the
// preference back to the value it was prior to that. This will prevent
// SessionStore from always restoring the session when crash recovery is
// disabled.
this._prefBranch.setBoolPref("sessionstore.resume_session_once",
this._resume_session_once_on_shutdown);
}
if (aData != "restart") {
// Throw away the previous session on shutdown
@@ -4,7 +4,6 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
var gStateObject;
var gTreeData;
@@ -20,19 +19,7 @@ window.onload = function() {
return;
}
// remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
if (sessionData.value.charAt(0) == '(')
sessionData.value = sessionData.value.slice(1, -1);
try {
gStateObject = JSON.parse(sessionData.value);
}
catch (exJSON) {
var s = new Cu.Sandbox("about:blank", {sandboxName: 'aboutSessionRestore'});
gStateObject = Cu.evalInSandbox("(" + sessionData.value + ")", s);
// If we couldn't parse the string with JSON.parse originally, make sure
// that the value in the textbox will be parsable.
sessionData.value = JSON.stringify(gStateObject);
}
gStateObject = JSON.parse(sessionData.value);
// make sure the data is tracked to be restored in case of a subsequent crash
var event = document.createEvent("UIEvents");
@@ -111,14 +98,20 @@ function restoreSession() {
// restore the session into a new window and close the current tab
var newWindow = top.openDialog(top.location, "_blank", "chrome,dialog=no,all");
newWindow.addEventListener("load", function() {
newWindow.removeEventListener("load", arguments.callee, true);
var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
obs.addObserver(function observe(win, topic) {
if (win != newWindow) {
return;
}
obs.removeObserver(observe, topic);
ss.setWindowState(newWindow, stateString, true);
var tabbrowser = top.gBrowser;
var tabIndex = tabbrowser.getBrowserIndexForDocument(document);
tabbrowser.removeTab(tabbrowser.tabs[tabIndex]);
}, true);
}, "browser-delayed-startup-finished", false);
}
function startNewSession() {
@@ -0,0 +1,46 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const CRASH_SHENTRY = {url: "about:mozilla"};
const CRASH_TAB = {entries: [CRASH_SHENTRY]};
const CRASH_STATE = {windows: [{tabs: [CRASH_TAB]}]};
const TAB_FORMDATA = {id: {sessionData: CRASH_STATE}};
const TAB_SHENTRY = {url: "about:sessionrestore", formdata: TAB_FORMDATA};
const TAB_STATE = {entries: [TAB_SHENTRY]};
const FRAME_SCRIPT = "data:," +
"content.document.getElementById('errorTryAgain').click()";
add_task(function* () {
// Prepare a blank tab.
let tab = gBrowser.addTab("about:blank");
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
// Fake a post-crash tab.
ss.setTabState(tab, JSON.stringify(TAB_STATE));
yield promiseTabRestored(tab);
ok(gBrowser.tabs.length > 1, "we have more than one tab");
browser.messageManager.loadFrameScript(FRAME_SCRIPT, true);
// Wait until the new window was restored.
let win = yield waitForNewWindow();
yield promiseWindowClosed(win);
let [{tabs: [{entries: [{url}]}]}] = JSON.parse(ss.getClosedWindowData());
is(url, "about:mozilla", "session was restored correctly");
ss.forgetClosedWindow(0);
});
function waitForNewWindow() {
return new Promise(resolve => {
Services.obs.addObserver(function observe(win, topic) {
Services.obs.removeObserver(observe, topic);
resolve(win);
}, "browser-delayed-startup-finished", false);
});
}
@@ -645,7 +645,15 @@ just addresses the organization to follow, e.g. "This site is run by " -->
<!ENTITY webrtcIndicatorButton.label "Camera / Microphone Access">
<!ENTITY webrtcIndicatorButton.tooltip "Display sites you are currently sharing your camera or microphone with">
<!ENTITY mixedContentBlocked.moreinfo "Most websites will still work properly even when this content is blocked.">
<!-- Bad Content Blocker Doorhanger Notification -->
<!ENTITY badContentBlocked.moreinfo "Most websites will work properly even if content is blocked.">
<!ENTITY mixedContentBlocked2.message "Insecure content">
<!ENTITY mixedContentBlocked2.moreinfo "Some unencrypted elements on this website have been blocked.">
<!ENTITY mixedContentBlocked2.learnMore "Learn More">
<!ENTITY mixedContentBlocked2.options "Options">
<!ENTITY mixedContentBlocked2.unblock.label "Disable protection for now">
<!ENTITY mixedContentBlocked2.unblock.accesskey "D">
<!ENTITY pointerLock.notification.message "Press ESC at any time to show it again.">
@@ -112,6 +112,11 @@ popupWarningDontShowFromMessage=Don't show this message when pop-ups are blocked
popupWarningDontShowFromLocationbar=Don't show info bar when pop-ups are blocked
popupShowPopupPrefix=Show '%S'
# Bad Content Blocker Doorhanger Notification
# %S is brandShortName
badContentBlocked.blocked.message=%S is blocking content on this page.
badContentBlocked.notblocked.message=%S is not blocking any content on this page.
crashedpluginsMessage.title=The %S plugin has crashed.
crashedpluginsMessage.reloadButton.label=Reload page
crashedpluginsMessage.reloadButton.accesskey=R
@@ -456,14 +461,6 @@ getUserMedia.sharingCamera.message2 = You are currently sharing your camera with
getUserMedia.sharingMicrophone.message2 = You are currently sharing your microphone with this page.
getUserMedia.sharingCameraAndMicrophone.message2 = You are currently sharing your camera and microphone with this page.
# Mixed Content Blocker Doorhanger Notification
# LOCALIZATION NOTE - %S is brandShortName
mixedContentBlocked.message = %S has blocked content that isn't secure.
mixedContentBlocked.keepBlockingButton.label = Keep Blocking
mixedContentBlocked.keepBlockingButton.accesskey = B
mixedContentBlocked.unblock.label = Disable Protection on This Page
mixedContentBlocked.unblock.accesskey = D
# LOCALIZATION NOTE - %S is brandShortName
slowStartup.message = %S seems slow… to… start.
slowStartup.helpButton.label = Learn How to Speed It Up

Before

Width:  |  Height:  |  Size: 346 B

After

Width:  |  Height:  |  Size: 346 B

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

+1
View File
@@ -1922,6 +1922,7 @@ toolbar[mode="text"] toolbarbutton.chevron > .toolbarbutton-icon {
%include ../../../toolkit/themes/shared/devtools/commandline.inc.css
%endif
%include ../shared/plugin-doorhanger.inc.css
%include ../shared/badcontent-doorhanger.inc.css
%ifdef MOZ_DEVTOOLS
.gcli-panel {
+2 -2
View File
@@ -36,8 +36,8 @@ browser.jar:
skin/classic/browser/identity-icons-https-mixed-active.png
skin/classic/browser/Info.png
skin/classic/browser/KUI-close.png
skin/classic/browser/mixed-content-blocked-16.png
skin/classic/browser/mixed-content-blocked-64.png
skin/classic/browser/bad-content-blocked-16.png
skin/classic/browser/bad-content-blocked-64.png
skin/classic/browser/monitor.png
skin/classic/browser/monitor_16-10.png
skin/classic/browser/notification-16.png

Before

Width:  |  Height:  |  Size: 346 B

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 B

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

+1
View File
@@ -2249,6 +2249,7 @@ toolbar[brighttext] #addonbar-closebutton {
%include ../../../toolkit/themes/shared/devtools/commandline.inc.css
%endif
%include ../shared/plugin-doorhanger.inc.css
%include ../shared/badcontent-doorhanger.inc.css
%ifdef MOZ_DEVTOOLS
/* Error counter */
+4 -2
View File
@@ -43,8 +43,10 @@ browser.jar:
skin/classic/browser/livemark-folder.png
skin/classic/browser/menu-back.png
skin/classic/browser/menu-forward.png
skin/classic/browser/mixed-content-blocked-16.png
skin/classic/browser/mixed-content-blocked-64.png
skin/classic/browser/bad-content-blocked-16.png
skin/classic/browser/bad-content-blocked-16@2x.png
skin/classic/browser/bad-content-blocked-64.png
skin/classic/browser/bad-content-blocked-64@2x.png
skin/classic/browser/monitor.png
skin/classic/browser/monitor_16-10.png
skin/classic/browser/notification-16.png
@@ -0,0 +1,7 @@
.popup-notification-item-title[popupid="bad-content"] {
font-weight: bold;
}
.popup-notification-item-message[popupid="bad-content"] {
width: 17em;
}

Before

Width:  |  Height:  |  Size: 346 B

After

Width:  |  Height:  |  Size: 346 B

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

+1
View File
@@ -2686,6 +2686,7 @@ toolbar[brighttext] #addonbar-closebutton {
%include ../../../toolkit/themes/shared/devtools/commandline.inc.css
%endif
%include ../shared/plugin-doorhanger.inc.css
%include ../shared/badcontent-doorhanger.inc.css
%ifdef MOZ_DEVTOOLS
/* Error counter */
+2 -2
View File
@@ -43,8 +43,8 @@ browser.jar:
skin/classic/browser/livemark-folder.png
skin/classic/browser/menu-back.png
skin/classic/browser/menu-forward.png
skin/classic/browser/mixed-content-blocked-16.png
skin/classic/browser/mixed-content-blocked-64.png
skin/classic/browser/bad-content-blocked-16.png
skin/classic/browser/bad-content-blocked-64.png
skin/classic/browser/monitor.png
skin/classic/browser/monitor_16-10.png
skin/classic/browser/notification-16.png
+8
View File
@@ -0,0 +1,8 @@
# 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/.
INSTALL_TARGETS += usecounterlist
usecounterlist_FILES := UseCounterList.h
usecounterlist_DEST = $(DIST)/include/mozilla/dom
usecounterlist_TARGET := export
+27
View File
@@ -0,0 +1,27 @@
/* -*- 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 UseCounter_h_
#define UseCounter_h_
namespace mozilla {
enum UseCounter {
eUseCounter_UNKNOWN = -1,
#define USE_COUNTER_DOM_METHOD(interface_, name_) \
eUseCounter_##interface_##_##name_,
#define USE_COUNTER_DOM_ATTRIBUTE(interface_, name_) \
eUseCounter_##interface_##_##name_,
#define USE_COUNTER_CSS_PROPERTY(name_, id_) \
eUseCounter_property_##id_,
#include "mozilla/dom/UseCounterList.h"
#undef USE_COUNTER_DOM_METHOD
#undef USE_COUNTER_DOM_ATTRIBUTE
#undef USE_COUNTER_CSS_PROPERTY
eUseCounter_Count
};
}
#endif
+33
View File
@@ -0,0 +1,33 @@
// 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/.
// This file defines a list of use counters, which are things that can
// record usage of Web platform features and then report this information
// through Telemetry.
//
// The format of this file is very strict. Each line can be:
//
// (a) a blank line
//
// (b) a comment, which is a line that begins with "//"
//
// (c) an #if/ifdef/else/endif preprocessor directive
//
// (d) one of three possible use counter declarations:
//
// method <IDL interface name>.<IDL operation name>
// attribute <IDL interface name>.<IDL attribute name>
// property <CSS property name>
//
// To actually cause use counters to be incremented, DOM methods
// and attributes must have a [UseCounter] extended attribute in
// the Web IDL file, and CSS properties must be declared with
// the CSS_PROPERTY_HAS_USE_COUNTER flag in nsCSSPropList.h.
//
// You might reasonably ask why we have this file and we require
// annotating things with [UseCounter] in the relevant WebIDL file as
// well. Generating things from bindings codegen and ensuring all the
// dependencies were correct would have been rather difficult, and
// annotating the WebIDL files does nothing for identifying CSS
// property usage, which we would also like to track.
+79
View File
@@ -0,0 +1,79 @@
#!/usr/bin/env python
# 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/.
from __future__ import print_function
import json
import os
import sys
sys.path.append(os.path.dirname(__file__))
import usecounters
AUTOGENERATED_WARNING_COMMENT = "/* THIS FILE IS AUTOGENERATED BY gen-usercounters.py - DO NOT EDIT */"
def generate_list(f, counters):
def print_optional_macro_declare(name):
print('''
#ifndef %(name)s
#define %(name)s(interface_, name_) // nothing
#define DEFINED_%(name)s
#endif
''' % { 'name': name }, file=f)
def print_optional_macro_undeclare(name):
print('''
#ifdef DEFINED_%(name)s
#undef DEFINED_%(name)s
#undef %(name)s
#endif
''' % { 'name': name }, file=f)
print(AUTOGENERATED_WARNING_COMMENT, file=f)
print_optional_macro_declare('USE_COUNTER_DOM_METHOD')
print_optional_macro_declare('USE_COUNTER_DOM_ATTRIBUTE')
print_optional_macro_declare('USE_COUNTER_CSS_PROPERTY')
for counter in counters:
if counter['type'] == 'method':
print('USE_COUNTER_DOM_METHOD(%s, %s)' % (counter['interface_name'], counter['method_name']), file=f)
elif counter['type'] == 'attribute':
print('USE_COUNTER_DOM_ATTRIBUTE(%s, %s)' % (counter['interface_name'], counter['attribute_name']), file=f)
elif counter['type'] == 'property':
prop = counter['property_name']
print('USE_COUNTER_CSS_PROPERTY(%s, %s)' % (prop, prop.replace('-', '_')), file=f)
print_optional_macro_undeclare('USE_COUNTER_DOM_METHOD')
print_optional_macro_undeclare('USE_COUNTER_DOM_ATTRIBUTE')
print_optional_macro_undeclare('USE_COUNTER_CSS_PROPERTY')
def generate_property_map(f, counters):
print(AUTOGENERATED_WARNING_COMMENT, file=f)
print('''
enum {
// XXX is this the right define?
#define CSS_PROP_LIST_INCLUDE_LOGICAL
#define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_, \\
kwtable_, stylestruct_, stylestructoffset_, animtype_) \\
USE_COUNTER_FOR_CSS_PROPERTY_##id_ = eUseCounter_UNKNOWN,
#include "nsCSSPropList.h"
#undef CSS_PROP
#undef CSS_PROP_LIST_INCLUDE_LOGICAL
};
''', file=f)
for counter in counters:
if counter['type'] == 'property':
prop = counter['property_name'].replace('-', '_')
print('#define USE_COUNTER_FOR_CSS_PROPERTY_%s eUseCounter_property_%s' % (prop, prop), file=f)
def use_counter_list(output_header, conf_filename):
counters = usecounters.read_conf(conf_filename)
generate_list(output_header, counters)
def property_map(output_map, conf_filename):
counters = usecounters.read_conf(conf_filename)
generate_property_map(output_map, counters)
+14
View File
@@ -142,6 +142,7 @@ EXPORTS.mozilla += [
'CORSMode.h',
'FeedWriterEnabled.h',
'TextInputProcessor.h',
'UseCounter.h',
]
EXPORTS.mozilla.dom += [
@@ -457,3 +458,16 @@ if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']:
if CONFIG['MOZ_X11']:
CXXFLAGS += CONFIG['TK_CFLAGS']
GENERATED_FILES += [
'PropertyUseCounterMap.inc',
'UseCounterList.h',
]
countermap = GENERATED_FILES['PropertyUseCounterMap.inc']
countermap.script = 'gen-usecounters.py:property_map'
countermap.inputs = ['UseCounters.conf']
counterlist = GENERATED_FILES['UseCounterList.h']
counterlist.script = 'gen-usecounters.py:use_counter_list'
counterlist.inputs = ['UseCounters.conf']
+78
View File
@@ -0,0 +1,78 @@
# 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/.
import buildconfig
import collections
import re
import StringIO
import sys
from mozbuild.preprocessor import preprocess
def read_conf(conf_filename):
# Invoking the preprocessor ourselves is easier than writing build rules
# to do it for us.
processed = StringIO.StringIO()
preprocess(includes=[conf_filename],
defines=buildconfig.defines,
output=processed)
# Can't read/write from a single StringIO, so make a new one for reading.
stream = StringIO.StringIO(processed.getvalue())
def parse_counters(stream):
for line_num, line in enumerate(stream):
line = line.rstrip('\n')
if not line or line.startswith('//'):
# empty line or comment
continue
m = re.match(r'method ([A-Za-z0-9]+)\.([A-Za-z0-9]+)$', line)
if m:
interface_name, method_name = m.groups()
yield { 'type': 'method',
'interface_name': interface_name,
'method_name': method_name }
continue
m = re.match(r'attribute ([A-Za-z0-9]+)\.([A-Za-z0-9]+)$', line)
if m:
interface_name, attribute_name = m.groups()
yield { 'type': 'attribute',
'interface_name': interface_name,
'attribute_name': attribute_name }
continue
m = re.match(r'property ([a-z0-9-]+)$', line)
if m:
property_name = m.group(1)
yield { 'type': 'property',
'property_name': property_name }
continue
raise ValueError('error parsing %s at line %d' % (conf_filename, line_num))
return parse_counters(stream)
def generate_histograms(filename):
# The mapping for use counters to telemetry histograms depends on the
# ordering of items in the dictionary.
items = collections.OrderedDict()
for counter in read_conf(filename):
def append_counter(name, desc):
items[name] = { 'expires_in_version': 'never',
'kind' : 'boolean',
'description': desc }
def append_counters(name, desc):
append_counter('USE_COUNTER_%s_DOCUMENT' % name, 'Whether a document %s' % desc)
append_counter('USE_COUNTER_%s_PAGE' % name, 'Whether a page %s' % desc)
if counter['type'] == 'method':
method = '%s.%s' % (counter['interface_name'], counter['method_name'])
append_counters(method.replace('.', '_').upper(), 'called %s' % method)
elif counter['type'] == 'attribute':
attr = '%s.%s' % (counter['interface_name'], counter['attribute_name'])
append_counters(attr.replace('.', '_').upper(), 'got or set %s' % attr)
elif counter['type'] == 'property':
prop = counter['property_name']
append_counters('PROPERTY_%s' % prop.replace('-', '_').upper(), "used the '%s' property" % prop)
return items
+25 -5
View File
@@ -47,6 +47,7 @@
#include "mozilla/layers/PCompositorChild.h"
#include "mozilla/layers/SharedBufferManagerChild.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/plugins/PluginInstanceParent.h"
#include "mozilla/plugins/PluginModuleParent.h"
#if defined(MOZ_CONTENT_SANDBOX)
@@ -2624,11 +2625,10 @@ ContentChild::RecvShutdown()
if (os) {
os->NotifyObservers(this, "content-child-shutdown", nullptr);
}
// Let the parent know we're done and let it close the channel.
// Both sides will clean up even if an error occurs here.
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &ContentChild::SendFinishShutdown));
// Ignore errors here. If this fails, the parent will kill us after a
// timeout.
unused << SendFinishShutdown();
return true;
}
@@ -2644,6 +2644,26 @@ ContentChild::GetBrowserOrId(TabChild* aTabChild)
}
}
bool
ContentChild::RecvUpdateWindow(const uintptr_t& aChildId)
{
#if defined(XP_WIN)
NS_ASSERTION(aChildId, "Expected child hwnd value for remote plugin instance.");
mozilla::plugins::PluginInstanceParent* parentInstance =
mozilla::plugins::PluginInstanceParent::LookupPluginInstanceByID(aChildId);
NS_ASSERTION(parentInstance, "Expected matching plugin instance");
if (parentInstance) {
// sync! update call to the plugin instance that forces the
// plugin to paint its child window.
parentInstance->CallUpdateWindow();
}
return true;
#else
NS_NOTREACHED("ContentChild::RecvUpdateWindow calls unexpected on this platform.");
return false;
#endif
}
// This code goes here rather than nsGlobalWindow.cpp because nsGlobalWindow.cpp
// can't include ContentChild.h since it includes windows.h.
+1
View File
@@ -372,6 +372,7 @@ public:
const base::ProcessId& aProcessId) override;
virtual bool RecvLoadPluginResult(const uint32_t& aPluginId,
const bool& aResult) override;
virtual bool RecvUpdateWindow(const uintptr_t& aChildId) override;
virtual bool RecvStartProfiler(const uint32_t& aEntries,
const double& aInterval,
+33 -13
View File
@@ -854,6 +854,27 @@ ContentParent::GetInitialProcessPriority(Element* aFrameElement)
PROCESS_PRIORITY_FOREGROUND;
}
#if defined(XP_WIN)
extern const wchar_t* kPluginWidgetContentParentProperty;
/*static*/ void
ContentParent::SendAsyncUpdate(nsIWidget* aWidget)
{
if (!aWidget || aWidget->Destroyed()) {
return;
}
printf_stderr("TabParent::SendAsyncUpdate()\n");
// Fire off an async request to the plugin to paint its window
HWND hwnd = (HWND)aWidget->GetNativeData(NS_NATIVE_WINDOW);
NS_ASSERTION(hwnd, "Expected valid hwnd value.");
ContentParent* cp = reinterpret_cast<ContentParent*>(
::GetPropW(hwnd, kPluginWidgetContentParentProperty));
if (cp && !cp->IsDestroyed()) {
cp->SendUpdateWindow((uintptr_t)hwnd);
}
}
#endif // defined(XP_WIN)
bool
ContentParent::PreallocatedProcessReady()
{
@@ -1538,8 +1559,7 @@ ContentParent::ShutDownProcess(ShutDownMethod aMethod)
// other methods. We first call Shutdown() in the child. After the child is
// ready, it calls FinishShutdown() on us. Then we close the channel.
if (aMethod == SEND_SHUTDOWN_MESSAGE) {
if (SendShutdown()) {
if (mIPCOpen && SendShutdown()) {
mShutdownPending = true;
}
@@ -1803,7 +1823,7 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
// Signal shutdown completion regardless of error state,
// so we can finish waiting in the xpcom-shutdown observer.
mShutdownComplete = true;
mIPCOpen = false;
if (why == NormalShutdown && !mCalledClose) {
// If we shut down normally but haven't called Close, assume somebody
@@ -1999,7 +2019,7 @@ ContentParent::InitializeMembers()
mCalledKillHard = false;
mCreatedPairedMinidumps = false;
mShutdownPending = false;
mShutdownComplete = false;
mIPCOpen = true;
mHangMonitorActor = nullptr;
}
@@ -2741,15 +2761,15 @@ ContentParent::Observe(nsISupports* aSubject,
const char16_t* aData)
{
if (!strcmp(aTopic, "xpcom-shutdown") && mSubprocess) {
if (mShutdownPending) {
// Wait for shutdown to complete, so that we receive any shutdown
// data (e.g. telemetry) from the child before we quit.
while (!mShutdownComplete) {
NS_ProcessNextEvent(nullptr, true);
}
} else {
// Just close the channel if we never tried shutting down.
ShutDownProcess(CLOSE_CHANNEL);
if (!mShutdownPending && mIPCOpen) {
ShutDownProcess(SEND_SHUTDOWN_MESSAGE);
}
// Wait for shutdown to complete, so that we receive any shutdown
// data (e.g. telemetry) from the child before we quit.
// This loop terminate prematurely based on mForceKillTimer.
while (mIPCOpen) {
NS_ProcessNextEvent(nullptr, true);
}
NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess");
}
+16 -1
View File
@@ -34,6 +34,7 @@ class nsIDOMBlob;
class nsIDumpGCAndCCLogsCallback;
class nsIMemoryReporter;
class ParentIdleListener;
class nsIWidget;
namespace mozilla {
class PRemoteSpellcheckEngineParent;
@@ -143,6 +144,20 @@ public:
static void NotifyUpdatedDictionaries();
#if defined(XP_WIN)
/**
* Windows helper for firing off an update window request to a plugin
* instance.
*
* aWidget - the eWindowType_plugin_ipc_chrome widget associated with
* this plugin window.
*/
static void SendAsyncUpdate(nsIWidget* aWidget);
#endif
// Let managees query if it is safe to send messages.
bool IsDestroyed() { return !mIPCOpen; }
virtual bool RecvCreateChildProcess(const IPCTabContext& aContext,
const hal::ProcessPriority& aPriority,
const TabId& aOpenerTabId,
@@ -831,7 +846,7 @@ private:
bool mCalledKillHard;
bool mCreatedPairedMinidumps;
bool mShutdownPending;
bool mShutdownComplete;
bool mIPCOpen;
nsRefPtr<nsConsoleService> mConsoleService;
nsConsoleService* GetConsoleService();
+6
View File
@@ -569,6 +569,12 @@ child:
async LoadProcessScript(nsString url);
/**
* Requests a full native update of a native plugin child window. This is
* a Windows specific call.
*/
async UpdateWindow(uintptr_t aChildId);
parent:
/**
* Tell the parent process a new accessible document has been created.
-16
View File
@@ -31,11 +31,7 @@ sync protocol PPluginWidget {
parent:
async __delete__();
parent:
sync Create() returns (nsresult aResult);
async Destroy();
async SetFocus(bool aRaise);
/**
@@ -45,18 +41,6 @@ parent:
* native HWND of the plugin widget.
*/
sync GetNativePluginPort() returns (uintptr_t value);
child:
/**
* Event indicating the parent is shutting down.
* aWhichSide - indicates which side intititated the shutdown.
*/
async ParentShutdown(uint16_t aWhichSide);
/**
* Requests a full update of the plugin window.
*/
async UpdateWindow(uintptr_t aChildId);
};
}
+2 -1
View File
@@ -265,7 +265,8 @@ public:
Create(nsIContentChild* aManager, const TabId& aTabId, const TabContext& aContext, uint32_t aChromeFlags);
bool IsRootContentDocument();
// Let managees query if it is safe to send messages.
bool IsDestroyed() { return mDestroyed; }
const TabId GetTabId() const {
MOZ_ASSERT(mUniqueId != 0);
return mUniqueId;
+12 -39
View File
@@ -3,18 +3,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/plugins/PluginWidgetChild.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/plugins/PluginWidgetParent.h"
#include "PluginWidgetProxy.h"
#include "mozilla/unused.h"
#include "mozilla/DebugOnly.h"
#include "nsDebug.h"
#if defined(XP_WIN)
#include "mozilla/plugins/PluginInstanceParent.h"
using mozilla::plugins::PluginInstanceParent;
#endif
#define PWLOG(...)
// #define PWLOG(...) printf_stderr(__VA_ARGS__)
//#define PWLOG(...) printf_stderr(__VA_ARGS__)
namespace mozilla {
namespace plugins {
@@ -22,11 +21,13 @@ namespace plugins {
PluginWidgetChild::PluginWidgetChild() :
mWidget(nullptr)
{
PWLOG("PluginWidgetChild::PluginWidgetChild()\n");
MOZ_COUNT_CTOR(PluginWidgetChild);
}
PluginWidgetChild::~PluginWidgetChild()
{
PWLOG("PluginWidgetChild::~PluginWidgetChild()\n");
MOZ_COUNT_DTOR(PluginWidgetChild);
}
@@ -37,8 +38,11 @@ PluginWidgetChild::ProxyShutdown()
{
PWLOG("PluginWidgetChild::ProxyShutdown()\n");
if (mWidget) {
SendDestroy();
mWidget = nullptr;
auto tab = static_cast<mozilla::dom::TabChild*>(Manager());
if (!tab->IsDestroyed()) {
unused << Send__delete__(this);
}
}
}
@@ -55,40 +59,9 @@ PluginWidgetChild::KillWidget()
void
PluginWidgetChild::ActorDestroy(ActorDestroyReason aWhy)
{
PWLOG("PluginWidgetChild::ActorDestroy()\n");
PWLOG("PluginWidgetChild::ActorDestroy(%d)\n", aWhy);
KillWidget();
}
bool
PluginWidgetChild::RecvParentShutdown(const uint16_t& aType)
{
PWLOG("PluginWidgetChild::RecvParentShutdown()\n");
KillWidget();
if (aType == PluginWidgetParent::CONTENT) {
Send__delete__(this);
}
return true;
}
bool
PluginWidgetChild::RecvUpdateWindow(const uintptr_t& aChildId)
{
#if defined(XP_WIN)
NS_ASSERTION(aChildId, "Expected child hwnd value for remote plugin instance.");
PluginInstanceParent* parentInstance =
PluginInstanceParent::LookupPluginInstanceByID(aChildId);
NS_ASSERTION(parentInstance, "Expected matching plugin instance");
if (parentInstance) {
// sync! update call to the plugin instance that forces the
// plugin to paint its child window.
parentInstance->CallUpdateWindow();
}
return true;
#else
NS_NOTREACHED("PluginWidgetChild::RecvUpdateWindow calls unexpected on this platform.");
return false;
#endif
}
} // namespace plugins
} // namespace mozilla
-2
View File
@@ -19,9 +19,7 @@ public:
PluginWidgetChild();
virtual ~PluginWidgetChild();
virtual bool RecvUpdateWindow(const uintptr_t& aChildId) override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
virtual bool RecvParentShutdown(const uint16_t& aType) override;
void SetWidget(mozilla::widget::PluginWidgetProxy* aWidget) {
mWidget = aWidget;
+29 -73
View File
@@ -7,9 +7,10 @@
#include "mozilla/dom/ContentParent.h"
#include "nsComponentManagerUtils.h"
#include "nsWidgetsCID.h"
#include "mozilla/unused.h"
#include "mozilla/DebugOnly.h"
#include "nsDebug.h"
#include "mozilla/unused.h"
#if defined(MOZ_WIDGET_GTK)
#include "nsPluginNativeWindowGtk.h"
@@ -19,17 +20,20 @@ using namespace mozilla;
using namespace mozilla::widget;
#define PWLOG(...)
// #define PWLOG(...) printf_stderr(__VA_ARGS__)
//#define PWLOG(...) printf_stderr(__VA_ARGS__)
#if defined(XP_WIN)
namespace mozilla {
namespace dom {
// For nsWindow
const wchar_t* kPluginWidgetContentParentProperty =
L"kPluginWidgetParentProperty";
} }
#endif
namespace mozilla {
namespace plugins {
#if defined(XP_WIN)
// For nsWindow
const wchar_t* kPluginWidgetParentProperty =
L"kPluginWidgetParentProperty";
#endif
static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
// This macro returns true to prevent an abort in the child process when
@@ -41,22 +45,6 @@ static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
} \
}
/*
* Tear down scenarios
* layout (plugin content unloading):
* - PluginWidgetProxy::Destroy() calls PluginWidgetChild::ProxyShutdown(), calls SendDestroy()
* - PluginWidgetParent::RecvDestroy(), sends async ParentShutdown(CONTENT)
* - PluginWidgetChild::RecvParentShutdown(CONTENT), calls Send__delete__()
* - PluginWidgetParent::ActorDestroy() called in response to __delete__
* PBrowser teardown (tab closing):
* - PluginWidgetParent::ParentDestroy() called by TabParent::Destroy(), sends async ParentShutdown(TAB_CLOSURE)
* - PluginWidgetChild::RecvParentShutdown(TAB_CLOSURE) (PluginWidgetProxy disabled)
* - PluginWidgetParent::ActorDestroy()
* - PluginWidgetParent::~PluginWidgetParent() in response to PBrowserParent::DeallocSubtree()
* - PluginWidgetChild::ActorDestroy() from PPluginWidgetChild::DestroySubtree
* - ~PluginWidgetChild() in response to PBrowserChild::DeallocSubtree()
**/
PluginWidgetParent::PluginWidgetParent()
{
PWLOG("PluginWidgetParent::PluginWidgetParent()\n");
@@ -70,18 +58,7 @@ PluginWidgetParent::~PluginWidgetParent()
// A destroy call can actually get skipped if a widget is associated
// with the last out-of-process page, make sure and cleanup any left
// over widgets if we have them.
if (mWidget) {
#if defined(MOZ_WIDGET_GTK)
mWidget->SetNativeData(NS_NATIVE_PLUGIN_OBJECT_PTR, (uintptr_t)0);
mWrapper = nullptr;
#elif defined(XP_WIN)
::RemovePropW((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW),
kPluginWidgetParentProperty);
#endif
mWidget->UnregisterPluginWindowForRemoteUpdates();
mWidget->Destroy();
mWidget = nullptr;
}
KillWidget();
}
mozilla::dom::TabParent*
@@ -98,25 +75,6 @@ PluginWidgetParent::SetParent(nsIWidget* aParent)
}
}
#if defined(XP_WIN)
// static
void
PluginWidgetParent::SendAsyncUpdate(nsIWidget* aWidget)
{
if (!aWidget || aWidget->Destroyed()) {
return;
}
// Fire off an async request to the plugin to paint its window
HWND hwnd = (HWND)aWidget->GetNativeData(NS_NATIVE_WINDOW);
NS_ASSERTION(hwnd, "Expected valid hwnd value.");
PluginWidgetParent* parent = reinterpret_cast<PluginWidgetParent*>(
::GetPropW(hwnd, mozilla::plugins::kPluginWidgetParentProperty));
if (parent && !parent->ActorDestroyed()) {
parent->SendUpdateWindow((uintptr_t)hwnd);
}
}
#endif // defined(XP_WIN)
// When plugins run in chrome, nsPluginNativeWindow(Plat) implements platform
// specific functionality that wraps plugin widgets. With e10s we currently
// bypass this code on Window, and reuse a bit of it on Linux. Content still
@@ -135,6 +93,7 @@ PluginWidgetParent::RecvCreate(nsresult* aResult)
// we can send over to content -> plugin.
PLUG_NewPluginNativeWindow((nsPluginNativeWindow**)&mWrapper);
if (!mWrapper) {
KillWidget();
return false;
}
// Give a copy of this to the widget, which handles some update
@@ -147,6 +106,7 @@ PluginWidgetParent::RecvCreate(nsresult* aResult)
// If this fails, bail.
if (!parentWidget) {
*aResult = NS_ERROR_NOT_AVAILABLE;
KillWidget();
return true;
}
@@ -158,8 +118,7 @@ PluginWidgetParent::RecvCreate(nsresult* aResult)
*aResult = mWidget->Create(parentWidget.get(), nullptr, nsIntRect(0,0,0,0),
&initData);
if (NS_FAILED(*aResult)) {
mWidget->Destroy();
mWidget = nullptr;
KillWidget();
// This should never fail, abort.
return false;
}
@@ -178,7 +137,8 @@ PluginWidgetParent::RecvCreate(nsresult* aResult)
#elif defined(XP_WIN)
DebugOnly<DWORD> winres =
::SetPropW((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW),
kPluginWidgetParentProperty, this);
mozilla::dom::kPluginWidgetContentParentProperty,
GetTabParent()->Manager()->AsContentParent());
NS_ASSERTION(winres, "SetPropW call failure");
#endif
@@ -192,21 +152,29 @@ PluginWidgetParent::RecvCreate(nsresult* aResult)
}
void
PluginWidgetParent::Shutdown(ShutdownType aType)
PluginWidgetParent::KillWidget()
{
PWLOG("PluginWidgetParent::KillWidget() widget=%p\n", (void*)mWidget.get());
if (mWidget) {
mWidget->UnregisterPluginWindowForRemoteUpdates();
DebugOnly<nsresult> rv = mWidget->Destroy();
NS_ASSERTION(NS_SUCCEEDED(rv), "widget destroy failure");
#if defined(MOZ_WIDGET_GTK)
mWidget->SetNativeData(NS_NATIVE_PLUGIN_OBJECT_PTR, (uintptr_t)0);
mWrapper = nullptr;
#elif defined(XP_WIN)
::RemovePropW((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW),
mozilla::dom::kPluginWidgetContentParentProperty);
#endif
mWidget = nullptr;
unused << SendParentShutdown(aType);
}
}
void
PluginWidgetParent::ActorDestroy(ActorDestroyReason aWhy)
{
PWLOG("PluginWidgetParent::ActorDestroy()\n");
PWLOG("PluginWidgetParent::ActorDestroy(%d)\n", aWhy);
KillWidget();
}
// Called by TabParent's Destroy() in response to an early tear down (Early
@@ -216,17 +184,6 @@ void
PluginWidgetParent::ParentDestroy()
{
PWLOG("PluginWidgetParent::ParentDestroy()\n");
Shutdown(TAB_CLOSURE);
}
// Called by the child when a plugin is torn down within a tab
// normally. Messages back via ParentShutdown().
bool
PluginWidgetParent::RecvDestroy()
{
PWLOG("PluginWidgetParent::RecvDestroy()\n");
Shutdown(CONTENT);
return true;
}
bool
@@ -242,7 +199,6 @@ bool
PluginWidgetParent::RecvGetNativePluginPort(uintptr_t* value)
{
ENSURE_CHANNEL;
PWLOG("PluginWidgetParent::RecvGetNativeData()\n");
#if defined(MOZ_WIDGET_GTK)
*value = (uintptr_t)mWrapper->window;
NS_ASSERTION(*value, "no xid??");
+1 -17
View File
@@ -24,20 +24,11 @@ namespace plugins {
class PluginWidgetParent : public PPluginWidgetParent
{
public:
/**
* Windows helper for firing off an update window request to a plugin.
*
* aWidget - the eWindowType_plugin_ipc_chrome widget associated with
* this plugin window.
*/
static void SendAsyncUpdate(nsIWidget* aWidget);
PluginWidgetParent();
virtual ~PluginWidgetParent();
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
virtual bool RecvCreate(nsresult* aResult) override;
virtual bool RecvDestroy() override;
virtual bool RecvSetFocus(const bool& aRaise) override;
virtual bool RecvGetNativePluginPort(uintptr_t* value) override;
@@ -54,15 +45,8 @@ private:
// The tab our connection is associated with.
mozilla::dom::TabParent* GetTabParent();
public:
// Identifies the side of the connection that initiates shutdown.
enum ShutdownType {
TAB_CLOSURE = 1,
CONTENT = 2
};
private:
void Shutdown(ShutdownType aType);
void KillWidget();
// The chrome side native widget.
nsCOMPtr<nsIWidget> mWidget;
+9 -7
View File
@@ -1127,7 +1127,7 @@ public:
MappedAttrParser(css::Loader* aLoader,
nsIURI* aDocURI,
already_AddRefed<nsIURI> aBaseURI,
nsIPrincipal* aNodePrincipal);
nsSVGElement* aElement);
~MappedAttrParser();
// Parses a mapped attribute value.
@@ -1147,18 +1147,20 @@ private:
// Arguments for nsCSSParser::ParseProperty
nsIURI* mDocURI;
nsCOMPtr<nsIURI> mBaseURI;
nsIPrincipal* mNodePrincipal;
// Declaration for storing parsed values (lazily initialized)
css::Declaration* mDecl;
// For reporting use counters
nsSVGElement* mElement;
};
MappedAttrParser::MappedAttrParser(css::Loader* aLoader,
nsIURI* aDocURI,
already_AddRefed<nsIURI> aBaseURI,
nsIPrincipal* aNodePrincipal)
nsSVGElement* aElement)
: mParser(aLoader), mDocURI(aDocURI), mBaseURI(aBaseURI),
mNodePrincipal(aNodePrincipal), mDecl(nullptr)
mDecl(nullptr), mElement(aElement)
{
}
@@ -1185,7 +1187,7 @@ MappedAttrParser::ParseMappedAttrValue(nsIAtom* aMappedAttrName,
if (propertyID != eCSSProperty_UNKNOWN) {
bool changed; // outparam for ParseProperty. (ignored)
mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI,
mNodePrincipal, mDecl, &changed, false, true);
mElement->NodePrincipal(), mDecl, &changed, false, true);
return;
}
MOZ_ASSERT(aMappedAttrName == nsGkAtoms::lang,
@@ -1232,7 +1234,7 @@ nsSVGElement::UpdateContentStyleRule()
nsIDocument* doc = OwnerDoc();
MappedAttrParser mappedAttrParser(doc->CSSLoader(), doc->GetDocumentURI(),
GetBaseURI(), NodePrincipal());
GetBaseURI(), this);
for (uint32_t i = 0; i < attrCount; ++i) {
const nsAttrName* attrName = mAttrsAndChildren.AttrNameAt(i);
@@ -1323,7 +1325,7 @@ nsSVGElement::UpdateAnimatedContentStyleRule()
}
MappedAttrParser mappedAttrParser(doc->CSSLoader(), doc->GetDocumentURI(),
GetBaseURI(), NodePrincipal());
GetBaseURI(), this);
doc->PropertyTable(SMIL_MAPPED_ATTR_ANIMVAL)->
Enumerate(this, ParseMappedAttrAnimValueCallback, &mappedAttrParser);
+5
View File
@@ -10063,6 +10063,11 @@ IonBuilder::improveThisTypesForCall()
MFilterTypeSet *filter = MFilterTypeSet::New(alloc(), thisDef, types);
current->add(filter);
current->rewriteAtDepth(-2, filter);
// FilterTypeSetPolicy::adjustInputs will insert an infallible Unbox(Object)
// for the input. Don't hoist this unbox above the getprop or getelem
// operation.
filter->setDependency(current->peek(-1)->toInstruction());
return true;
}
+5 -5
View File
@@ -22,7 +22,7 @@ histoenums_TARGET := export
include $(topsrcdir)/config/rules.mk
histograms_file := $(srcdir)/Histograms.json
histogram_files := $(srcdir)/Histograms.json $(topsrcdir)/dom/base/UseCounters.conf
histogram_enum_file := TelemetryHistogramEnums.h
histogram_data_file := TelemetryHistogramData.inc
@@ -36,9 +36,9 @@ data_python_deps := \
$(srcdir)/histogram_tools.py \
$(NULL)
$(histogram_enum_file): $(histograms_file) $(enum_python_deps)
$(PYTHON) $(srcdir)/gen-histogram-enum.py $< > $@
$(histogram_data_file): $(histograms_file) $(data_python_deps)
$(PYTHON) $(srcdir)/gen-histogram-data.py $< > $@
$(histogram_enum_file): $(histogram_files) $(enum_python_deps)
$(PYTHON) $(srcdir)/gen-histogram-enum.py $(histogram_files) > $@
$(histogram_data_file): $(histogram_files) $(data_python_deps)
$(PYTHON) $(srcdir)/gen-histogram-data.py $(histogram_files) > $@
GARBAGE += $(histogram_enum_file)
@@ -17,10 +17,11 @@ from collections import OrderedDict
startup_histogram_re = re.compile("SQLITE|HTTP|SPDY|CACHE|DNS")
def main(argv):
filename = argv[0]
filenames = argv
all_histograms = OrderedDict()
for histogram in histogram_tools.from_file(filename):
for histogram in histogram_tools.from_files(filenames):
name = histogram.name()
parameters = OrderedDict()
table = {
@@ -187,9 +187,9 @@ def write_debug_histogram_ranges(histograms):
print "#endif"
def main(argv):
filename = argv[0]
filenames = argv
histograms = list(histogram_tools.from_file(filename))
histograms = list(histogram_tools.from_files(filenames))
print banner
write_histogram_table(histograms)
@@ -3,28 +3,63 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Write out a C++ enum definition whose members are the names of
# histograms. The histograms are defined in a file provided as a
# command-line argument.
# histograms as well as the following other members:
#
# - HistogramCount
# - HistogramFirstUseCounter
# - HistogramLastUseCounter
# - HistogramUseCounterCount
#
# The histograms are defined in files provided as command-line arguments.
import sys
import histogram_tools
import itertools
import sys
banner = """/* This file is auto-generated, see gen-histogram-enum.py. */
"""
def main(argv):
filename = argv[0]
filenames = argv
print banner
print "enum ID : uint32_t {"
for histogram in histogram_tools.from_file(filename):
cpp_guard = histogram.cpp_guard()
if cpp_guard:
print "#if defined(%s)" % cpp_guard
print " %s," % histogram.name()
if cpp_guard:
print "#endif"
print " HistogramCount"
groups = itertools.groupby(histogram_tools.from_files(filenames),
lambda h: h.name().startswith("USE_COUNTER_"))
seen_use_counters = False
# Note that histogram_tools.py guarantees that all of the USE_COUNTER_*
# histograms are defined in a contiguous block. We therefore assume
# that there's at most one group for which use_counter_group is true.
for (use_counter_group, histograms) in groups:
if use_counter_group:
seen_use_counters = True
# The HistogramDUMMY* enum variables are used to make the computation
# of Histogram{First,Last}UseCounter easier. Otherwise, we'd have to
# special case the first and last histogram in the group.
if use_counter_group:
print " HistogramFirstUseCounter,"
print " HistogramDUMMY1 = HistogramFirstUseCounter - 1,"
for histogram in histograms:
cpp_guard = histogram.cpp_guard()
if cpp_guard:
print "#if defined(%s)" % cpp_guard
print " %s," % histogram.name()
if cpp_guard:
print "#endif"
if use_counter_group:
print " HistogramDUMMY2,"
print " HistogramLastUseCounter = HistogramDUMMY2 - 1,"
print " HistogramCount,"
if seen_use_counters:
print " HistogramUseCounterCount = HistogramLastUseCounter - HistogramFirstUseCounter + 1"
else:
print " HistogramUseCounterCount = 0"
print "};"
main(sys.argv[1:])
@@ -2,9 +2,16 @@
# 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/.
import buildconfig
import json
import math
import os
import re
import sys
# Need to update sys.path to be able to find usecounters.
sys.path.append(os.path.join(buildconfig.topsrcdir, 'dom/base/'))
import usecounters
from collections import OrderedDict
@@ -246,11 +253,57 @@ is enabled."""
definition['high'],
definition['n_buckets'])
def from_file(filename):
"""Return an iterator that provides a sequence of Histograms for
the histograms defined in filename.
"""
# We support generating histograms from multiple different input files, not
# just Histograms.json. For each file's basename, we have a specific
# routine to parse that file, and return a dictionary mapping histogram
# names to histogram parameters.
def from_Histograms_json(filename):
with open(filename, 'r') as f:
histograms = json.load(f, object_pairs_hook=OrderedDict)
try:
histograms = json.load(f, object_pairs_hook=OrderedDict)
except ValueError, e:
raise BaseException, "error parsing histograms in %s: %s" % (filename, e.message)
return histograms
def from_UseCounters_conf(filename):
return usecounters.generate_histograms(filename)
FILENAME_PARSERS = {
'Histograms.json': from_Histograms_json,
'UseCounters.conf': from_UseCounters_conf,
}
def from_files(filenames):
"""Return an iterator that provides a sequence of Histograms for
the histograms defined in filenames.
"""
all_histograms = OrderedDict()
for filename in filenames:
parser = FILENAME_PARSERS[os.path.basename(filename)]
histograms = parser(filename)
# OrderedDicts are important, because then the iteration order over
# the parsed histograms is stable, which makes the insertion into
# all_histograms stable, which makes ordering in generated files
# stable, which makes builds more deterministic.
if not isinstance(histograms, OrderedDict):
raise BaseException, "histogram parser didn't provide an OrderedDict"
for (name, definition) in histograms.iteritems():
yield Histogram(name, definition)
if all_histograms.has_key(name):
raise DefinitionException, "duplicate histogram name %s" % name
all_histograms[name] = definition
# We require that all USE_COUNTER_* histograms be defined in a contiguous
# block.
use_counter_indices = filter(lambda x: x[1].startswith("USE_COUNTER_"),
enumerate(all_histograms.iterkeys()));
if use_counter_indices:
lower_bound = use_counter_indices[0][0]
upper_bound = use_counter_indices[-1][0]
n_counters = upper_bound - lower_bound + 1
if n_counters != len(use_counter_indices):
raise DefinitionException, "use counter histograms must be defined in a contiguous block"
for (name, definition) in all_histograms.iteritems():
yield Histogram(name, definition)
+4
View File
@@ -122,6 +122,10 @@ PluginWidgetProxy::GetNativeData(uint32_t aDataType)
if (!mActor) {
return nullptr;
}
auto tab = static_cast<mozilla::dom::TabChild*>(mActor->Manager());
if (tab && tab->IsDestroyed()) {
return nullptr;
}
switch (aDataType) {
case NS_NATIVE_PLUGIN_PORT:
case NS_NATIVE_WINDOW:
+19
View File
@@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Testcase for bug 1128214</title>
<style type="text/css">
html,body {
color:black;
background-color:white;
font-size:16px;
padding:10px;
margin:0;
}
</style>
</head>
<body>
<div style="-moz-appearance:-moz-window-button-close; background-color: #ffd800; width:20px; height:20px;"></div>
</body>
</html>
+1
View File
@@ -1,3 +1,4 @@
load 303901-1.html
load 303901-2.html
load 380359-1.xhtml
load 1128214.html
+6
View File
@@ -65,6 +65,12 @@ nsNativeThemeWin::~nsNativeThemeWin()
static int32_t
GetTopLevelWindowActiveState(nsIFrame *aFrame)
{
// Used by window frame and button box rendering. We can end up in here in
// the content process when rendering one of these moz styles freely in a
// page. Bail in this case, there is no applicable window focus state.
if (XRE_GetProcessType() != GeckoProcessType_Default) {
return mozilla::widget::themeconst::FS_INACTIVE;
}
// Get the widget. nsIFrame's GetNearestWidget walks up the view chain
// until it finds a real window.
nsIWidget* widget = aFrame->GetNearestWidget();
+2 -14
View File
@@ -7,10 +7,6 @@
* nsWindowGfx - Painting and aceleration.
*/
// XXX Future: this should really be a stand alone class stored as
// a member of nsWindow with getters and setters for things like render
// mode and methods for handling paint.
/**************************************************************
**************************************************************
**
@@ -21,10 +17,9 @@
**************************************************************
**************************************************************/
#include "mozilla/dom/ContentParent.h"
#include "mozilla/plugins/PluginInstanceParent.h"
using mozilla::plugins::PluginInstanceParent;
#include "mozilla/plugins/PluginWidgetParent.h"
using mozilla::plugins::PluginWidgetParent;
#include "nsWindowGfx.h"
#include "nsAppRunner.h"
@@ -57,13 +52,6 @@ extern "C" {
#include "pixman.h"
}
namespace mozilla {
namespace plugins {
// For plugins with e10s
extern const wchar_t* kPluginWidgetParentProperty;
}
}
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::layers;
@@ -214,7 +202,7 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel)
if (mWindowType == eWindowType_plugin_ipc_chrome) {
// Fire off an async request to the plugin to paint its window
PluginWidgetParent::SendAsyncUpdate(this);
mozilla::dom::ContentParent::SendAsyncUpdate(this);
ValidateRect(mWnd, nullptr);
return true;
}