import change from rmottola/Arctic-Fox:

- Add legacycollector.org to add-ons whitelist (dc69faacb)
- Bug 1112469 - Part 1: Implement an XPCOM service responsible to trigger daily updates of service workers; r=nsm (74f735500)
- Bug 1133601 - Implement about:serviceworkers, r=ehsan (e21767ec1)
- Bug 1038811 - Push Notifications - Move old push to simplepush. (14b0a1547)
- Bug 1041339 - ServiceWorkers: Update implementation based on clarification of force-refresh. r=nsm (484675660)
- Bug 1154547 - Part 1: Linkify the worker script URLs in about:serviceworkers; r=baku (db2097fa7)
- Bug 1154547 - Part 2: Make it possible to update a service worker from about:serviceworkers; r=baku (03d7363aa)
- Bug 1154721 - Add an Unregister button to about:serviceworkers, r=ehsan (7b5a9873f)
- Bug 1156052 - Add push information to about:serviceworkers. r=baku (995f5b1d3)
- Bug 1158811 - remove the flickering in about:serviceworkers, r=ehsan (70a4cb1bc)
- Bug 1158361 - Improve the localized messages in about:serviceworkers, r=ehsan, f=stef (751202c01)
- Bug 1151664 - Make claim return undefined for now. r=nsm (84f36584b)
- Bug 1142693 - Recognize EMSGSIZE as non-fatal on OS X for IPC sendmsg(). r=bent (c133bb505)
- Bug 1150916 - Non-unified bustage follow-up fix. (19adaff8b)
- Bug 1151607 - Step 1: Add Linux sandboxing hook for when child processes are still single-threaded. r=kang r=bent (e5e67f4b1)
- Bug 1151607 - Step 1.5: Avoid unlikely false positives in Linux SandboxInfo feature detection. r=kang (944805781)
- Bug 1151607 - Step 2: Apply net/ipc namespace separation and chroot to media plugins. r=kang (3dc0e575f)
- Bug 1151607 - Step 0: sort includes to make the following patches cleaner. r=kang (9b918989b)
- Bug 1038811 - Push Notifications - Firefox front end changes for preferences, and permission notification. r=MattN+bmo@mozilla.com (fdb4c7636)
- (adapted) Bug 1147281 - Shared browser notification icon CSS. r=MattN (2243c83a1)
- Bug 1123523 - Part 1: Add an nsIAnimationObserver interface to watch adding/changing/removing AnimationPlayer objects. r=smaug (d889e512c)
- Bug 1123523 - Part 2: Add an animations option for MutationObservers and expose chrome-only animation members on MutationRecords. r=smaug (6c9622c0f)
- Bug 1123523 - Part 3: Store a flag on AnimationPlayer for whether it is exposed by Element.getAnimationPlayers(). r=birtles (d146779c0)
- Bug 1123523 - Part 4: Add macro for notifying observers only when they implement a specific derived interface. r=smaug (38714002f)
- Bug 1123523 - Part 5: Record on a document whether it might have any nsIAnimationObservers registered. r=smaug (585e30299)
- Bug 1123523 - Part 6: Listen for nsIAnimationObserver notifications and translate them to MutationObserver notifications. r=smaug (9980c91e5)
- Bug 1123523 - Part 7: Add utility functions to notify registered nsIAnimationObservers. r=smaug (82d3a15cf)
- Bug 1123523 - Part 8: Dispatch nsIAnimationObserver notifications when an animation is added or removed. r=birtles (056b8bf7a)
- Bug 1123523 - Part 9: Dispatch an nsIAnimationObserver notification when an animation is changed. r=birtles (5787cdbc1)
- Bug 1123523 - Part 10: Tests. r=birtles (d134aa3b0)
- Bug 1123523 - Followup build fix. (b88bae25d)
- Bug 1137515 part 1 - Change to configure.in r=mwu (150534251)
- Bug 1136065 - Remove GetRangeCount() in Selection.h. r=ehsan (bd35dba49)
- Bug 1129249 - Expose the element id in Gecko profiler for Restyle. r=dholbert r=benwa (77231d128)
- Bug 979293 - Add a FrozenAtomSet to clarify how |permanentAtoms| works. r=bhackett. (1c4ca9315)
- Bug 979293 - Don't write collision bits in HashTable unnecessarily. r=luke. (c42ebc7b5)
- Bug 1135200: Hook up nsCSSParser's pref-backed bool variables in a startup method. r=heycam (e129dcfc8)
- Bug 1107378 - Part 1: Create a JS-implemented "CSS Unprefixing Service" that can convert certain -webkit prefixed CSS to an unprefixed form. r=dbaron (c860167d2)
- Bug 1107378 - Part 2: Make the CSS Parser call out to the unprefixing service, when it detects a vendor-prefixed property name (if pref is enabled). r=dbaron (1fe4e48dd)
- Bug 1107378 - Part 3: In cases where we're unprefixing, treat "display:-webkit-box" as "display: flex" (& same for "-moz-box" if we previously saw "-webkit-box"). r=dbaron (00299fb08)
- Bug 1107378 - Part 4: Add mochitest for our CSS unprefixing functionality. r=dbaron (95a0e6c41)
- Bug 1132743: Only allow CSS Unprefixing Service to be activated for hosts on a small, hardcoded whitelist. r=dbaron f=bz (6afd0dd07)
- Bug 1132743 followup: hook up nsPrincipal.cpp's gCodeBasePrincipalSupport in new InitializeStatics method, instead of lazily. implicit rs=dbaron (7223553f1)
- Bug 1124503 move AppConstants.jsm to toolkit r=gavin (0a90334ff)
- Bug 1130195: Report the failed bitmap creation, but still crash. (9e8c8fcde)
- Bug 1136241 - making sure that hint/role strings are returned with no spaces to support localization. r=eeejay (665243ab4)
- Bug 1127084 - Remove __iterator__ from ContentPrefStore. (126621dbf)
- Bug 1133449 - [B2G] The default audio type didn't be set correctly when the call screen app is launched. r=baku (0470b702a)
- Bug 1133449 - [B2G] The default audio type didn't be set correctly when the call screen app is launched. r=baku (016b84983)
- Bug 1130175 - nICEr: avoid sysctl.h include. r=bwc (5446f87d1)
- Bug 794984 - [mozprocess] Add ability to separate stderr from stdout. r=ahal (9388e0e08)
- Bug 1136803 - Properly remove the force-dtc override flag on retained layers when listeners are removed. r=botond (1047b11a7)
- Bug 1134493 - Ensure we don't set the force-empty-hit-region flag when a subdocument has mozpasspointerevents. r=botond (fda5e8176)
- Bug 1136487: Destroy the compositors for all windows when any window detects a device reset. r=jrmuizel (22d45787c)
- bits of Bug 1135773 - Initialize QI return values to null in the cycle collector. (rest was already part of 1119482 (6f30ef196)
- Bug 1135772 - Return null on failure in nsXPCWrappedJS's QueryInterface. r=smaug (67fca5218)
- Bug 1136584 - Copy JIT options from global settings. r=bhackett (6696b345e)
- Bug 1135912 - Don't repaint vibrant regions on mouseover. (1de120955)
- Bug 961887 - Refactor mVisibleAboveRegion management. r=roc (8281fb9f8)
- Bug 961887 - Make FindOpaqueBackgroundColorFor take a region instead of a PaintedLayerData. r=roc (f42ddc1a1)
- Bug 961887 - Find uniform opaque background colors under ContainerLayers. r=roc (7378892b8)
This commit is contained in:
2019-08-10 10:57:52 +08:00
parent 23551d1911
commit 18084d9cce
183 changed files with 7850 additions and 1034 deletions
+1 -1
View File
@@ -139,7 +139,7 @@ AccTextSelChangeEvent::~AccTextSelChangeEvent() { }
bool
AccTextSelChangeEvent::IsCaretMoveOnly() const
{
return mSel->GetRangeCount() == 1 && mSel->IsCollapsed() &&
return mSel->RangeCount() == 1 && mSel->IsCollapsed() &&
((mReason & (nsISelectionListener::COLLAPSETOSTART_REASON |
nsISelectionListener::COLLAPSETOEND_REASON)) == 0);
}
+1 -1
View File
@@ -49,7 +49,7 @@ HyperTextAccessible::AddToSelection(int32_t aStartOffset, int32_t aEndOffset)
{
dom::Selection* domSel = DOMSelection();
return domSel &&
SetSelectionBoundsAt(domSel->GetRangeCount(), aStartOffset, aEndOffset);
SetSelectionBoundsAt(domSel->RangeCount(), aStartOffset, aEndOffset);
}
inline void
+4 -4
View File
@@ -1137,7 +1137,7 @@ HyperTextAccessible::SetSelectionRange(int32_t aStartPos, int32_t aEndPos)
NS_ENSURE_STATE(domSel);
// Set up the selection.
for (int32_t idx = domSel->GetRangeCount() - 1; idx > 0; idx--)
for (int32_t idx = domSel->RangeCount() - 1; idx > 0; idx--)
domSel->RemoveRange(domSel->GetRangeAt(idx));
SetSelectionBoundsAt(0, aStartPos, aEndPos);
@@ -1442,7 +1442,7 @@ HyperTextAccessible::SetSelectionBoundsAt(int32_t aSelectionNum,
return false;
nsRefPtr<nsRange> range;
uint32_t rangeCount = domSel->GetRangeCount();
uint32_t rangeCount = domSel->RangeCount();
if (aSelectionNum == static_cast<int32_t>(rangeCount))
range = new nsRange(mContent);
else
@@ -1470,7 +1470,7 @@ HyperTextAccessible::RemoveFromSelection(int32_t aSelectionNum)
if (!domSel)
return false;
if (aSelectionNum < 0 || aSelectionNum >= domSel->GetRangeCount())
if (aSelectionNum < 0 || aSelectionNum >= static_cast<int32_t>(domSel->RangeCount()))
return false;
domSel->RemoveRange(domSel->GetRangeAt(aSelectionNum));
@@ -1901,7 +1901,7 @@ HyperTextAccessible::GetSpellTextAttr(nsINode* aNode,
if (!domSel)
return;
int32_t rangeCount = domSel->GetRangeCount();
int32_t rangeCount = domSel->RangeCount();
if (rangeCount <= 0)
return;
+1 -1
View File
@@ -223,7 +223,7 @@ let OutputGenerator = {
},
_getOutputName: function _getOutputName(aName) {
return aName.replace(' ', '');
return aName.replace(/\s/g, '');
},
roleRuleMap: {
+2 -1
View File
@@ -848,7 +848,8 @@ PivotContext.prototype = {
hints.push(hint);
} else if (aAccessible.actionCount > 0) {
hints.push({
string: Utils.AccRetrieval.getStringRole(aAccessible.role) + '-hint'
string: Utils.AccRetrieval.getStringRole(
aAccessible.role).replace(/\s/g, '') + '-hint'
});
}
});
@@ -43,6 +43,9 @@
accOrElmOrID: 'nested_link3',
expectedHints: [{string: 'link-hint'}, {string: 'pushbutton-hint'},
"Double tap and hold to activate"]
}, {
accOrElmOrID: 'menuitemradio',
expectedHints: [{string: 'radiomenuitem-hint'}]
}];
// Test hints.
@@ -80,6 +83,7 @@
<a href="#" id="link_with_hint_override" aria-moz-hint="Tap and hold to get to menu">I am a special link</a>
<button id="button_with_default_hint">Toggle</button>
<button id="button_with_hint_override" aria-moz-hint="Tap and hold to activate">Special</button>
<span id="menuitemradio" role="menuitemradio">Item 1</span>
</div>
</body>
</html>
+1
View File
@@ -50,6 +50,7 @@ MOZ_APP_ID={3c2e2abc-06d4-11e1-ac3b-374f68613e61}
MOZ_TIME_MANAGER=1
MOZ_SIMPLEPUSH=1
MOZ_PAY=1
MOZ_TOOLKIT_SEARCH=
MOZ_PLACES=
+2
View File
@@ -537,6 +537,8 @@
@BINPATH@/components/formautofill.manifest
@BINPATH@/components/FormAutofillContentService.js
@BINPATH@/components/FormAutofillStartup.js
@BINPATH@/components/CSSUnprefixingService.js
@BINPATH@/components/CSSUnprefixingService.manifest
@BINPATH@/components/contentAreaDropListener.manifest
@BINPATH@/components/contentAreaDropListener.js
@BINPATH@/components/messageWakeupService.js
+2 -1
View File
@@ -201,7 +201,7 @@ pref("extensions.dss.switchPending", false); // Non-dynamic switch pending af
pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.name", "chrome://browser/locale/browser.properties");
pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description", "chrome://browser/locale/browser.properties");
pref("xpinstall.whitelist.add", "addons.mozilla.org,www.palemoon.org,addons.palemoon.org");
pref("xpinstall.whitelist.add", "addons.mozilla.org,www.palemoon.org,addons.palemoon.org,legacycollector.org");
pref("xpinstall.whitelist.add.36", "");
pref("xpinstall.whitelist.add.180", "");
pref("xpinstall.whitelist.required", false);
@@ -756,6 +756,7 @@ pref("goanna.handlerService.allowRegisterFromDifferentHost", false);
pref("browser.geolocation.warning.infoURL", "http://www.palemoon.org/info-url/geolocation.shtml");
pref("browser.mixedcontent.warning.infoURL", "http://www.palemoon.org/info-url/mixedcontent.shtml");
pref("browser.push.warning.infoURL", "https://www.mozilla.org/%LOCALE%/firefox/push/");
pref("browser.EULA.version", 3);
pref("browser.rights.version", 3);
+1
View File
@@ -431,6 +431,7 @@
<box id="notification-popup-box" hidden="true" align="center">
<image id="default-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="geo-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="push-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="password-notification-icon" class="notification-anchor-icon" role="button"/>
+40 -1
View File
@@ -1773,6 +1773,42 @@ ContentPermissionPrompt.prototype = {
}
},
_promptPush : function(aRequest) {
var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
var requestingURI = aRequest.principal.URI;
var message = browserBundle.formatStringFromName("push.enablePush",
[requestingURI.host], 1);
var actions = [
{
stringId: "push.alwaysAllow",
action: Ci.nsIPermissionManager.ALLOW_ACTION,
expireType: null,
callback: function() {}
},
{
stringId: "push.allowForSession",
action: Ci.nsIPermissionManager.ALLOW_ACTION,
expireType: Ci.nsIPermissionManager.EXPIRE_SESSION,
callback: function() {}
},
{
stringId: "push.alwaysBlock",
action: Ci.nsIPermissionManager.DENY_ACTION,
expireType: null,
callback: function() {}
}]
var options = {
learnMoreURL: Services.urlFormatter.formatURLPref("browser.push.warning.infoURL"),
};
this._showPrompt(aRequest, message, "push", actions, "push",
"push-notification-icon", options);
},
_promptGeo : function(aRequest) {
var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
var requestingURI = aRequest.principal.URI;
@@ -1897,7 +1933,6 @@ ContentPermissionPrompt.prototype = {
},
prompt: function CPP_prompt(request) {
// Only allow exactly one permission rquest here.
let types = request.types.QueryInterface(Ci.nsIArray);
if (types.length != 1) {
@@ -1909,6 +1944,7 @@ ContentPermissionPrompt.prototype = {
const kFeatureKeys = { "geolocation" : "geo",
"desktop-notification" : "desktop-notification",
"pointerLock" : "pointerLock",
"push" : "push"
};
// Make sure that we support the request.
@@ -1952,6 +1988,9 @@ ContentPermissionPrompt.prototype = {
case "pointerLock":
this._promptPointerLock(request, autoAllow);
break;
case "push":
this._promptPush(request);
break;
}
},
@@ -483,12 +483,12 @@ let AboutPermissions = {
*/
_supportedPermissions: ["password", "image", "popup", "cookie",
"desktop-notification", "install", "geo", "indexedDB",
"fullscreen", "pointerLock"],
"fullscreen", "push", "pointerLock"],
/**
* Permissions that don't have a global "Allow" option.
*/
_noGlobalAllow: ["desktop-notification", "geo", "indexedDB", "fullscreen",
_noGlobalAllow: ["desktop-notification", "geo", "indexedDB", "fullscreen", "push"
"pointerLock"],
/**
@@ -537,6 +537,7 @@ let AboutPermissions = {
Services.prefs.addObserver("dom.indexedDB.enabled", this, false);
Services.prefs.addObserver("plugins.click_to_play", this, false);
Services.prefs.addObserver("full-screen-api.enabled", this, false);
Services.prefs.addObserver("dom.push.enabled", this, false);
Services.prefs.addObserver("full-screen-api.pointer-lock.enabled", this, false);
Services.prefs.addObserver("permissions.places-sites-limit", this, false);
@@ -689,6 +690,7 @@ let AboutPermissions = {
Services.prefs.removeObserver("dom.indexedDB.enabled", this, false);
Services.prefs.removeObserver("plugins.click_to_play", this, false);
Services.prefs.removeObserver("full-screen-api.enabled", this, false);
Services.prefs.removeObserver("dom.push.enabled", this, false);
Services.prefs.removeObserver("full-screen-api.pointer-lock.enabled", this, false);
Services.prefs.removeObserver("permissions.places-sites-limit", this, false);
@@ -360,7 +360,28 @@
oncommand="AboutPermissions.onPermissionCommand(event, true);"/>
</hbox>
</vbox>
</hbox>
</hbox>
<!-- Push Notifications -->
<hbox id="push-pref-item"
class="pref-item" align="top">
<image class="pref-icon" type="push"/>
<vbox>
<label class="pref-title" value="&push.label;"/>
<hbox align="center">
<menulist id="push-menulist"
class="pref-menulist"
type="push"
oncommand="AboutPermissions.onPermissionCommand(event);">
<menupopup>
<menuitem id="push-0" value="0" label="&permission.alwaysAsk;"/>
<menuitem id="push-1" value="1" label="&permission.allow;"/>
<menuitem id="push-2" value="2" label="&permission.block;"/>
</menupopup>
</menulist>
</hbox>
</vbox>
</hbox>
<!-- PointerLock -->
<hbox id="pointerLock-pref-item"
+2
View File
@@ -491,6 +491,8 @@
@RESPATH@/components/formautofill.manifest
@RESPATH@/components/FormAutofillContentService.js
@RESPATH@/components/FormAutofillStartup.js
@RESPATH@/components/CSSUnprefixingService.js
@RESPATH@/components/CSSUnprefixingService.manifest
@RESPATH@/components/contentAreaDropListener.manifest
@RESPATH@/components/contentAreaDropListener.js
@RESPATH@/browser/components/BrowserProfileMigrators.manifest
@@ -305,6 +305,15 @@ webNotifications.neverShow=Always Block Notifications
webNotifications.neverShow.accesskey=N
webNotifications.showFromSite=Would you like to show notifications from %S?
# Push Notifications
push.allowForSession=Allow for Session
push.allowForSession.accesskey=S
push.alwaysAllow=Always Allow Push Notifications
push.alwaysAllow.accesskey=A
push.alwaysBlock=Always Block Push Notifications
push.alwaysBlock.accesskey=B
push.enablePush=Would you like to allow Push Notifications for %S?
# Pointer lock UI
pointerLock.allow2=Hide pointer
@@ -53,4 +53,6 @@
<!ENTITY fullscreen.label "Fullscreen">
<!ENTITY push.label "Receive Push Notifications">
<!ENTITY pointerLock.label "Hide the Mouse Pointer">
View File
View File
+1 -170
View File
@@ -1153,35 +1153,7 @@ toolbar[iconsize="small"] #webrtc-status-button {
min-width: 280px;
}
.popup-notification-icon {
width: 64px;
height: 64px;
-moz-margin-end: 10px;
}
.popup-notification-icon[popupid="geolocation"] {
list-style-image: url(chrome://browser/skin/Geolocation-64.png);
}
.popup-notification-icon[popupid="xpinstall-disabled"],
.popup-notification-icon[popupid="addon-progress"],
.popup-notification-icon[popupid="addon-install-cancelled"],
.popup-notification-icon[popupid="addon-install-blocked"],
.popup-notification-icon[popupid="addon-install-origin-blocked"],
.popup-notification-icon[popupid="addon-install-failed"],
.popup-notification-icon[popupid="addon-install-complete"] {
list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png);
width: 32px;
height: 32px;
}
.popup-notification-icon[popupid="click-to-play-plugins"] {
list-style-image: url(chrome://mozapps/skin/plugins/pluginBlocked-64.png);
}
.popup-notification-icon[popupid="web-notifications"] {
list-style-image: url(chrome://browser/skin/notification-64.png);
}
%include ../shared/notification-icons.inc.css
.addon-progress-description {
width: 350px;
@@ -1206,66 +1178,13 @@ toolbar[iconsize="small"] #webrtc-status-button {
list-style-image: url("moz-icon://stock/gtk-cancel?size=menu");
}
.popup-notification-icon[popupid="indexedDB-permissions-prompt"],
.popup-notification-icon[popupid="indexedDB-quota-prompt"],
.popup-notification-icon[popupid*="offline-app-requested"],
.popup-notification-icon[popupid="offline-app-usage"] {
list-style-image: url(chrome://global/skin/icons/question-64.png);
}
.popup-notification-icon[popupid="password-save"],
.popup-notification-icon[popupid="password-change"] {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
}
.popup-notification-icon[popupid="webapps-install"] {
list-style-image: url(chrome://browser/skin/webapps-64.png);
}
.popup-notification-icon[popupid="mixed-content-blocked"] {
list-style-image: url(chrome://browser/skin/mixed-content-blocked-64.png);
}
.popup-notification-icon[popupid="webRTC-sharingDevices"],
.popup-notification-icon[popupid="webRTC-shareDevices"] {
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-64.png);
}
.popup-notification-icon[popupid="pointerLock"] {
list-style-image: url(chrome://browser/skin/pointerLock-64.png);
}
/* Notification icon box */
#notification-popup-box {
position: relative;
background-color: #fff;
background-clip: padding-box;
padding-left: 4px;
border-radius: 2.5px 0 0 2.5px;
border-width: 0 8px 0 0;
border-style: solid;
border-image: url("chrome://browser/skin/urlbar-arrow.png") 0 8 0 0 fill;
-moz-margin-end: -8px;
margin-top: -1px;
margin-bottom: -1px;
}
#notification-popup-box:not([hidden]) + #identity-box {
-moz-padding-start: 10px;
border-radius: 0;
}
#notification-popup-box:-moz-locale-dir(rtl),
.notification-anchor-icon:-moz-locale-dir(rtl) {
transform: scaleX(-1);
}
.notification-anchor-icon {
width: 16px;
height: 16px;
margin: 0 2px;
}
.notification-anchor-icon:-moz-focusring {
outline: 1px dotted -moz-DialogText;
}
@@ -1275,101 +1194,13 @@ toolbar[iconsize="small"] #webrtc-status-button {
list-style-image: url(chrome://global/skin/icons/information-16.png);
}
.geo-notification-icon,
#geo-notification-icon {
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
}
#addons-notification-icon {
list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric-16.png);
}
.indexedDB-notification-icon,
#indexedDB-notification-icon {
list-style-image: url(chrome://global/skin/icons/question-16.png);
}
#password-notification-icon {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-16.png);
}
#webapps-notification-icon {
list-style-image: url(chrome://browser/skin/webapps-16.png);
}
#plugins-notification-icon {
list-style-image: url(chrome://browser/skin/notification-pluginNormal.png);
}
#alert-plugins-notification-icon {
list-style-image: url(chrome://browser/skin/notification-pluginAlert.png);
}
#blocked-plugins-notification-icon {
list-style-image: url(chrome://browser/skin/notification-pluginBlocked.png);
}
#plugins-notification-icon,
#alert-plugins-notification-icon,
#blocked-plugins-notification-icon {
-moz-image-region: rect(0, 16px, 16px, 0);
}
#plugins-notification-icon:hover,
#alert-plugins-notification-icon:hover,
#blocked-plugins-notification-icon:hover {
-moz-image-region: rect(0, 32px, 16px, 16px);
}
#plugins-notification-icon:active,
#alert-plugins-notification-icon:active,
#blocked-plugins-notification-icon:active {
-moz-image-region: rect(0, 48px, 16px, 32px);
}
#notification-popup-box[hidden] {
/* Override display:none to make the pluginBlockedNotification animation work
when showing the notification repeatedly. */
display: -moz-box;
visibility: collapse;
}
#blocked-plugins-notification-icon[showing] {
animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
}
@keyframes pluginBlockedNotification {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.mixed-content-blocked-notification-icon,
#mixed-content-blocked-notification-icon {
list-style-image: url(chrome://browser/skin/mixed-content-blocked-16.png);
}
.webRTC-shareDevices-notification-icon,
#webRTC-shareDevices-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-16.png);
}
.webRTC-sharingDevices-notification-icon,
#webRTC-sharingDevices-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-sharingDevice-16.png);
}
.web-notifications-notification-icon,
#web-notifications-notification-icon {
list-style-image: url(chrome://browser/skin/notification-16.png);
}
#pointerLock-notification-icon {
list-style-image: url(chrome://browser/skin/pointerLock-16.png);
}
#pointerLock-cancel {
margin: 0px;
}
+2
View File
@@ -22,6 +22,8 @@ browser.jar:
* skin/classic/browser/engineManager.css
skin/classic/browser/Geolocation-16.png
skin/classic/browser/Geolocation-64.png
skin/classic/browser/Push-16.png
skin/classic/browser/Push-64.png
skin/classic/browser/Go-arrow.png
skin/classic/browser/identity.png
skin/classic/browser/imagedocument.png
@@ -98,6 +98,9 @@
.pref-icon[type="geo"] {
list-style-image: url(chrome://browser/skin/Geolocation-64.png);
}
.pref-icon[type="push"] {
list-style-image: url(chrome://browser/skin/Push-64.png);
}
.pref-icon[type="indexedDB"] {
list-style-image: url(chrome://global/skin/icons/question-64.png);
}
View File
View File
View File
View File
+1 -143
View File
@@ -1872,27 +1872,6 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
-moz-margin-end: 0;
}
.popup-notification-icon {
width: 64px;
height: 64px;
-moz-margin-end: 10px;
}
.popup-notification-icon[popupid="geolocation"] {
list-style-image: url(chrome://browser/skin/Geolocation-64.png);
}
.popup-notification-icon[popupid="xpinstall-disabled"],
.popup-notification-icon[popupid="addon-progress"],
.popup-notification-icon[popupid="addon-install-cancelled"],
.popup-notification-icon[popupid="addon-install-blocked"],
.popup-notification-icon[popupid="addon-install-origin-blocked"],
.popup-notification-icon[popupid="addon-install-failed"],
.popup-notification-icon[popupid="addon-install-complete"] {
list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png);
width: 32px;
height: 32px;
}
.popup-notification-icon[popupid="click-to-play-plugins"] {
list-style-image: url(chrome://mozapps/skin/plugins/pluginBlocked-64.png);
@@ -1935,61 +1914,11 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
-moz-image-region: rect(32px, 32px, 48px, 16px);
}
.popup-notification-icon[popupid="indexedDB-permissions-prompt"],
.popup-notification-icon[popupid="indexedDB-quota-prompt"],
.popup-notification-icon[popupid*="offline-app-requested"],
.popup-notification-icon[popupid="offline-app-usage"] {
list-style-image: url(chrome://global/skin/icons/question-64.png);
}
.popup-notification-icon[popupid="password-save"],
.popup-notification-icon[popupid="password-change"] {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
}
.popup-notification-icon[popupid="webapps-install"] {
list-style-image: url(chrome://browser/skin/webapps-64.png);
}
.popup-notification-icon[popupid="mixed-content-blocked"] {
list-style-image: url(chrome://browser/skin/mixed-content-blocked-64.png);
}
.popup-notification-icon[popupid="webRTC-sharingDevices"],
.popup-notification-icon[popupid="webRTC-shareDevices"] {
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-64.png);
}
.popup-notification-icon[popupid="pointerLock"] {
list-style-image: url(chrome://browser/skin/pointerLock-64.png);
}
%include ../shared/notification-icons.inc.css
/* Notification icon box */
#notification-popup-box {
position: relative;
background-color: #fff;
background-clip: padding-box;
padding-left: 3px;
border-radius: 2.5px 0 0 2.5px;
border-width: 0 8px 0 0;
border-style: solid;
border-image: url("chrome://browser/skin/urlbar-arrow.png") 0 8 0 0 fill;
-moz-margin-end: -8px;
}
@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container > #urlbar > #notification-popup-box {
padding-left: 5px;
}
#notification-popup-box:-moz-locale-dir(rtl),
.notification-anchor-icon:-moz-locale-dir(rtl) {
transform: scaleX(-1);
}
.notification-anchor-icon {
width: 16px;
height: 16px;
margin: 0 2px;
}
.notification-anchor-icon:-moz-focusring {
@@ -1997,44 +1926,7 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
outline-offset: -3px;
}
.default-notification-icon,
#default-notification-icon {
list-style-image: url(chrome://global/skin/icons/information-16.png);
}
.geo-notification-icon,
#geo-notification-icon {
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
}
#addons-notification-icon {
list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric-16.png);
}
.indexedDB-notification-icon,
#indexedDB-notification-icon {
list-style-image: url(chrome://global/skin/icons/question-16.png);
}
#password-notification-icon {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-16.png);
}
#webapps-notification-icon {
list-style-image: url(chrome://browser/skin/webapps-16.png);
}
#plugins-notification-icon {
list-style-image: url(chrome://browser/skin/notification-pluginNormal.png);
}
#alert-plugins-notification-icon {
list-style-image: url(chrome://browser/skin/notification-pluginAlert.png);
}
#blocked-plugins-notification-icon {
list-style-image: url(chrome://browser/skin/notification-pluginBlocked.png);
}
#plugins-notification-icon,
#alert-plugins-notification-icon,
@@ -2054,45 +1946,11 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
-moz-image-region: rect(0, 48px, 16px, 32px);
}
#notification-popup-box[hidden] {
/* Override display:none to make the pluginBlockedNotification animation work
when showing the notification repeatedly. */
display: -moz-box;
visibility: collapse;
}
#blocked-plugins-notification-icon[showing] {
animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
}
@keyframes pluginBlockedNotification {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.mixed-content-blocked-notification-icon,
#mixed-content-blocked-notification-icon {
list-style-image: url(chrome://browser/skin/mixed-content-blocked-16.png);
}
.webRTC-shareDevices-notification-icon,
#webRTC-shareDevices-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-16.png);
}
.webRTC-sharingDevices-notification-icon,
#webRTC-sharingDevices-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-sharingDevice-16.png);
}
.web-notifications-notification-icon,
#web-notifications-notification-icon {
list-style-image: url(chrome://browser/skin/notification-16.png);
}
#pointerLock-notification-icon {
list-style-image: url(chrome://browser/skin/pointerLock-16.png);
+4
View File
@@ -23,6 +23,10 @@ browser.jar:
* skin/classic/browser/engineManager.css
skin/classic/browser/Geolocation-16.png
skin/classic/browser/Geolocation-64.png
skin/classic/browser/Push-16.png
skin/classic/browser/Push-16@2x.png
skin/classic/browser/Push-64.png
skin/classic/browser/Push-64@2x.png
skin/classic/browser/Info.png
skin/classic/browser/identity.png
skin/classic/browser/imagedocument.png
@@ -101,6 +101,9 @@
.pref-icon[type="geo"] {
list-style-image: url(chrome://browser/skin/Geolocation-64.png);
}
.pref-icon[type="push"] {
list-style-image: url(chrome://browser/skin/Push-64.png);
}
.pref-icon[type="indexedDB"] {
list-style-image: url(chrome://global/skin/icons/question-64.png);
}
@@ -0,0 +1,455 @@
%if 0
/* 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/. */
%endif
.popup-notification-icon {
width: 64px;
height: 64px;
-moz-margin-end: 10px;
}
.popup-notification-icon[popupid="geolocation"] {
list-style-image: url(chrome://browser/skin/Geolocation-64.png);
}
.popup-notification-icon[popupid="push"] {
list-style-image: url(chrome://browser/skin/Push-64.png);
}
.popup-notification-icon[popupid="xpinstall-disabled"],
.popup-notification-icon[popupid="addon-progress"],
.popup-notification-icon[popupid="addon-install-blocked"],
.popup-notification-icon[popupid="addon-install-failed"],
.popup-notification-icon[popupid="addon-install-confirmation"],
.popup-notification-icon[popupid="addon-install-complete"] {
list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png);
width: 32px;
height: 32px;
}
.popup-notification-icon[popupid="click-to-play-plugins"] {
list-style-image: url(chrome://mozapps/skin/plugins/pluginBlocked-64.png);
}
.popup-notification-icon[popupid="web-notifications"] {
list-style-image: url(chrome://browser/skin/notification-64.png);
}
.popup-notification-icon[popupid="indexedDB-permissions-prompt"],
.popup-notification-icon[popupid*="offline-app-requested"],
.popup-notification-icon[popupid="offline-app-usage"] {
list-style-image: url(chrome://global/skin/icons/question-64.png);
}
.popup-notification-icon[popupid="password"] {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
}
.popup-notification-icon[popupid="webapps-install-progress"],
.popup-notification-icon[popupid="webapps-install"] {
list-style-image: url(chrome://global/skin/icons/webapps-64.png);
}
.popup-notification-icon[popupid="bad-content"] {
list-style-image: url(chrome://browser/skin/bad-content-blocked-64.png);
}
.popup-notification-icon[popupid="bad-content"][mixedblockdisabled],
.popup-notification-icon[popupid="bad-content"][trackingblockdisabled] {
list-style-image: url(chrome://browser/skin/bad-content-unblocked-64.png);
}
.popup-notification-icon[popupid="webRTC-sharingDevices"],
.popup-notification-icon[popupid="webRTC-shareDevices"] {
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-64.png);
}
.popup-notification-icon[popupid="webRTC-sharingMicrophone"],
.popup-notification-icon[popupid="webRTC-shareMicrophone"] {
list-style-image: url(chrome://browser/skin/webRTC-shareMicrophone-64.png);
}
.popup-notification-icon[popupid="webRTC-sharingScreen"],
.popup-notification-icon[popupid="webRTC-shareScreen"] {
list-style-image: url(chrome://browser/skin/webRTC-shareScreen-64.png);
}
.popup-notification-icon[popupid="pointerLock"] {
list-style-image: url(chrome://browser/skin/pointerLock-64.png);
}
/* Notification icon box */
#notification-popup-box {
position: relative;
background-color: #fff;
background-clip: padding-box;
padding-left: 3px;
border-width: 0 8px 0 0;
border-style: solid;
border-image: url("chrome://browser/skin/urlbar-arrow.png") 0 8 0 0 fill;
-moz-margin-end: -8px;
}
@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box {
padding-left: 7px;
}
#notification-popup-box:-moz-locale-dir(rtl),
.notification-anchor-icon:-moz-locale-dir(rtl) {
transform: scaleX(-1);
}
.notification-anchor-icon {
width: 16px;
height: 16px;
margin: 0 2px;
}
.default-notification-icon,
#default-notification-icon {
list-style-image: url(chrome://global/skin/icons/information-16.png);
}
.identity-notification-icon,
#identity-notification-icon {
list-style-image: url(chrome://mozapps/skin/profile/profileicon.png);
/* XXX: need HiDPI version */
}
.geo-notification-icon,
#geo-notification-icon {
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
}
#push-notification-icon {
list-style-image: url(chrome://browser/skin/Push-16.png);
}
#addons-notification-icon {
list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric-16.png);
}
.indexedDB-notification-icon,
#indexedDB-notification-icon {
list-style-image: url(chrome://global/skin/icons/question-16.png);
}
#password-notification-icon {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-16.png);
}
.webapps-notification-icon,
#webapps-notification-icon {
list-style-image: url(chrome://global/skin/icons/webapps-16.png);
}
#plugins-notification-icon {
list-style-image: url(chrome://browser/skin/notification-pluginNormal.png);
}
#plugins-notification-icon.plugin-hidden {
list-style-image: url(chrome://browser/skin/notification-pluginAlert.png);
}
#plugins-notification-icon.plugin-blocked {
list-style-image: url(chrome://browser/skin/notification-pluginBlocked.png);
}
#plugins-notification-icon {
-moz-image-region: rect(0, 16px, 16px, 0);
}
#plugins-notification-icon:hover {
-moz-image-region: rect(0, 32px, 16px, 16px);
}
#plugins-notification-icon:active {
-moz-image-region: rect(0, 48px, 16px, 32px);
}
#notification-popup-box[hidden] {
/* Override display:none to make the pluginBlockedNotification animation work
when showing the notification repeatedly. */
display: -moz-box;
visibility: collapse;
}
#plugins-notification-icon.plugin-blocked[showing] {
animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
}
@keyframes pluginBlockedNotification {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.bad-content-blocked-notification-icon,
#bad-content-blocked-notification-icon {
list-style-image: url(chrome://browser/skin/bad-content-blocked-16.png);
}
.bad-content-unblocked-notification-icon,
#bad-content-unblocked-notification-icon {
list-style-image: url(chrome://browser/skin/bad-content-unblocked-16.png);
}
.webRTC-shareDevices-notification-icon,
#webRTC-shareDevices-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-16.png);
}
.webRTC-sharingDevices-notification-icon,
#webRTC-sharingDevices-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-sharingDevice-16.png);
}
.webRTC-shareMicrophone-notification-icon,
#webRTC-shareMicrophone-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-shareMicrophone-16.png);
}
.webRTC-sharingMicrophone-notification-icon,
#webRTC-sharingMicrophone-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-sharingMicrophone-16.png);
}
.webRTC-shareScreen-notification-icon,
#webRTC-shareScreen-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-shareScreen-16.png);
}
.webRTC-sharingScreen-notification-icon,
#webRTC-sharingScreen-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-sharingScreen-16.png);
}
.web-notifications-notification-icon,
#web-notifications-notification-icon {
list-style-image: url(chrome://browser/skin/notification-16.png);
}
.pointerLock-notification-icon,
#pointerLock-notification-icon {
list-style-image: url(chrome://browser/skin/pointerLock-16.png);
}
.translate-notification-icon,
#translate-notification-icon {
list-style-image: url(chrome://browser/skin/translation-16.png);
-moz-image-region: rect(0px, 16px, 16px, 0px);
}
.translated-notification-icon,
#translated-notification-icon {
list-style-image: url(chrome://browser/skin/translation-16.png);
-moz-image-region: rect(0px, 32px, 16px, 16px);
}
.popup-notification-icon[popupid="servicesInstall"] {
list-style-image: url(chrome://browser/skin/social/services-64.png);
}
#servicesInstall-notification-icon {
list-style-image: url(chrome://browser/skin/social/services-16.png);
}
/* EME notifications */
.popup-notification-icon[popupid="drmContentPlaying"],
#eme-notification-icon {
list-style-image: url("chrome://browser/skin/drm-icon.svg#chains");
}
#eme-notification-icon:hover:active {
list-style-image: url("chrome://browser/skin/drm-icon.svg#chains-pressed");
}
#eme-notification-icon[firstplay=true] {
animation: emeTeachingMoment 0.2s linear 0s 5 normal;
}
@keyframes emeTeachingMoment {
0% {transform: translateX(0); }
25% {transform: translateX(3px) }
75% {transform: translateX(-3px) }
100% { transform: translateX(0); }
}
%ifdef XP_MACOSX
/* HiDPI notification icons */
@media (min-resolution: 2dppx) {
#notification-popup-box {
border-image: url("chrome://browser/skin/urlbar-arrow@2x.png") 0 16 0 0 fill;
}
.default-notification-icon,
#default-notification-icon {
list-style-image: url(chrome://global/skin/icons/information-32.png);
}
.geo-notification-icon,
#geo-notification-icon {
list-style-image: url(chrome://browser/skin/Geolocation-16@2x.png);
}
#push-notification-icon {
list-style-image: url(chrome://browser/skin/Push-16@2x.png);
}
.indexedDB-notification-icon,
#indexedDB-notification-icon {
list-style-image: url(chrome://global/skin/icons/question-32.png);
}
#addons-notification-icon {
list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png);
}
#password-notification-icon {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-16@2x.png);
}
.webapps-notification-icon,
#webapps-notification-icon {
list-style-image: url(chrome://global/skin/icons/webapps-16@2x.png);
}
#plugins-notification-icon {
list-style-image: url(chrome://browser/skin/notification-pluginNormal@2x.png);
}
#plugins-notification-icon.plugin-hidden {
list-style-image: url(chrome://browser/skin/notification-pluginAlert@2x.png);
}
#plugins-notification-icon.plugin-blocked {
list-style-image: url(chrome://browser/skin/notification-pluginBlocked@2x.png);
}
#plugins-notification-icon {
-moz-image-region: rect(0, 32px, 32px, 0);
}
#plugins-notification-icon:hover {
-moz-image-region: rect(0, 64px, 32px, 32px);
}
#plugins-notification-icon:active {
-moz-image-region: rect(0, 96px, 32px, 64px);
}
#bad-content-blocked-notification-icon {
list-style-image: url(chrome://browser/skin/bad-content-blocked-16@2x.png);
}
#bad-content-unblocked-notification-icon {
list-style-image: url(chrome://browser/skin/bad-content-unblocked-16@2x.png);
}
.webRTC-shareDevices-notification-icon,
#webRTC-shareDevices-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-16@2x.png);
}
.webRTC-sharingDevices-notification-icon,
#webRTC-sharingDevices-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-sharingDevice-16@2x.png);
}
.webRTC-shareMicrophone-notification-icon,
#webRTC-shareMicrophone-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-shareMicrophone-16@2x.png);
}
.webRTC-sharingMicrophone-notification-icon,
#webRTC-sharingMicrophone-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-sharingMicrophone-16@2x.png);
}
.webRTC-shareScreen-notification-icon,
#webRTC-shareScreen-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-shareScreen-16@2x.png);
}
.webRTC-sharingScreen-notification-icon,
#webRTC-sharingScreen-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-sharingScreen-16@2x.png);
}
.web-notifications-notification-icon,
#web-notifications-notification-icon {
list-style-image: url(chrome://browser/skin/notification-16@2x.png);
}
.pointerLock-notification-icon,
#pointerLock-notification-icon {
list-style-image: url(chrome://browser/skin/pointerLock-16@2x.png);
}
.translate-notification-icon,
#translate-notification-icon {
list-style-image: url(chrome://browser/skin/translation-16@2x.png);
-moz-image-region: rect(0px, 32px, 32px, 0px);
}
.translated-notification-icon,
#translated-notification-icon {
list-style-image: url(chrome://browser/skin/translation-16@2x.png);
-moz-image-region: rect(0px, 64px, 32px, 32px);
}
.popup-notification-icon[popupid="geolocation"] {
list-style-image: url(chrome://browser/skin/Geolocation-64@2x.png);
}
.popup-notification-icon[popupid="push"] {
list-style-image: url(chrome://browser/skin/Push-64@2x.png);
}
.popup-notification-icon[popupid="web-notifications"] {
list-style-image: url(chrome://browser/skin/notification-64@2x.png);
}
.popup-notification-icon[popupid="bad-content"] {
list-style-image: url(chrome://browser/skin/bad-content-blocked-64@2x.png);
}
.popup-notification-icon[popupid="bad-content"][mixedblockdisabled],
.popup-notification-icon[popupid="bad-content"][trackingblockdisabled] {
list-style-image: url(chrome://browser/skin/bad-content-unblocked-64@2x.png);
}
.popup-notification-icon[popupid="pointerLock"] {
list-style-image: url(chrome://browser/skin/pointerLock-64@2x.png);
}
.popup-notification-icon[popupid="webRTC-sharingDevices"],
.popup-notification-icon[popupid="webRTC-shareDevices"] {
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-64@2x.png);
}
.popup-notification-icon[popupid="webRTC-sharingMicrophone"],
.popup-notification-icon[popupid="webRTC-shareMicrophone"] {
list-style-image: url(chrome://browser/skin/webRTC-shareMicrophone-64@2x.png);
}
.popup-notification-icon[popupid="webRTC-sharingScreen"],
.popup-notification-icon[popupid="webRTC-shareScreen"] {
list-style-image: url(chrome://browser/skin/webRTC-shareScreen-64@2x.png);
}
.popup-notification-icon[popupid="servicesInstall"] {
list-style-image: url(chrome://browser/skin/social/services-64@2x.png);
}
#servicesInstall-notification-icon {
list-style-image: url(chrome://browser/skin/social/services-16@2x.png);
}
}
%endif
View File
View File
+1 -181
View File
@@ -2362,35 +2362,7 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
-moz-margin-end: 0;
}
.popup-notification-icon {
width: 64px;
height: 64px;
-moz-margin-end: 10px;
}
.popup-notification-icon[popupid="geolocation"] {
list-style-image: url(chrome://browser/skin/Geolocation-64.png);
}
.popup-notification-icon[popupid="xpinstall-disabled"],
.popup-notification-icon[popupid="addon-progress"],
.popup-notification-icon[popupid="addon-install-cancelled"],
.popup-notification-icon[popupid="addon-install-blocked"],
.popup-notification-icon[popupid="addon-install-origin-blocked"],
.popup-notification-icon[popupid="addon-install-failed"],
.popup-notification-icon[popupid="addon-install-complete"] {
list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png);
width: 32px;
height: 32px;
}
.popup-notification-icon[popupid="click-to-play-plugins"] {
list-style-image: url(chrome://mozapps/skin/plugins/pluginBlocked-64.png);
}
.popup-notification-icon[popupid="web-notifications"] {
list-style-image: url(chrome://browser/skin/notification-64.png);
}
%include ../shared/notification-icons.inc.css
.addon-progress-description {
width: 350px;
@@ -2423,61 +2395,9 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
-moz-image-region: rect(32px, 32px, 48px, 16px);
}
.popup-notification-icon[popupid="indexedDB-permissions-prompt"],
.popup-notification-icon[popupid="indexedDB-quota-prompt"],
.popup-notification-icon[popupid*="offline-app-requested"],
.popup-notification-icon[popupid="offline-app-usage"] {
list-style-image: url(chrome://global/skin/icons/question-64.png);
}
.popup-notification-icon[popupid="password-save"],
.popup-notification-icon[popupid="password-change"] {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
}
.popup-notification-icon[popupid="webapps-install"] {
list-style-image: url(chrome://browser/skin/webapps-64.png);
}
.popup-notification-icon[popupid="mixed-content-blocked"] {
list-style-image: url(chrome://browser/skin/mixed-content-blocked-64.png);
}
.popup-notification-icon[popupid="webRTC-sharingDevices"],
.popup-notification-icon[popupid="webRTC-shareDevices"] {
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-64.png);
}
.popup-notification-icon[popupid="pointerLock"] {
list-style-image: url(chrome://browser/skin/pointerLock-64.png);
}
/* Notification icon box */
#notification-popup-box {
position: relative;
background-color: #fff;
background-clip: padding-box;
padding-left: 3px;
border-radius: var(--toolbarbutton-border-radius) 0 0 var(--toolbarbutton-border-radius);
border-width: 0 8px 0 0;
border-style: solid;
border-image: url("chrome://browser/skin/urlbar-arrow.png") 0 8 0 0 fill;
-moz-margin-end: -8px;
}
@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container > #urlbar > #notification-popup-box {
padding-left: 5px;
}
#notification-popup-box:-moz-locale-dir(rtl),
.notification-anchor-icon:-moz-locale-dir(rtl) {
transform: scaleX(-1);
}
.notification-anchor-icon {
width: 16px;
height: 16px;
margin: 0 2px;
}
.notification-anchor-icon:-moz-focusring {
@@ -2485,106 +2405,6 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
outline-offset: -3px;
}
.default-notification-icon,
#default-notification-icon {
list-style-image: url(chrome://global/skin/icons/information-16.png);
}
.geo-notification-icon,
#geo-notification-icon {
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
}
#addons-notification-icon {
list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric-16.png);
}
.indexedDB-notification-icon,
#indexedDB-notification-icon {
list-style-image: url(chrome://global/skin/icons/question-16.png);
}
#password-notification-icon {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-16.png);
}
#webapps-notification-icon {
list-style-image: url(chrome://browser/skin/webapps-16.png);
}
#plugins-notification-icon {
list-style-image: url(chrome://browser/skin/notification-pluginNormal.png);
}
#alert-plugins-notification-icon {
list-style-image: url(chrome://browser/skin/notification-pluginAlert.png);
}
#blocked-plugins-notification-icon {
list-style-image: url(chrome://browser/skin/notification-pluginBlocked.png);
}
#plugins-notification-icon,
#alert-plugins-notification-icon,
#blocked-plugins-notification-icon {
-moz-image-region: rect(0, 16px, 16px, 0);
}
#plugins-notification-icon:hover,
#alert-plugins-notification-icon:hover,
#blocked-plugins-notification-icon:hover {
-moz-image-region: rect(0, 32px, 16px, 16px);
}
#plugins-notification-icon:active,
#alert-plugins-notification-icon:active,
#blocked-plugins-notification-icon:active {
-moz-image-region: rect(0, 48px, 16px, 32px);
}
#notification-popup-box[hidden] {
/* Override display:none to make the pluginBlockedNotification animation work
when showing the notification repeatedly. */
display: -moz-box;
visibility: collapse;
}
#blocked-plugins-notification-icon[showing] {
animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
}
@keyframes pluginBlockedNotification {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.mixed-content-blocked-notification-icon,
#mixed-content-blocked-notification-icon {
list-style-image: url(chrome://browser/skin/mixed-content-blocked-16.png);
}
.webRTC-shareDevices-notification-icon,
#webRTC-shareDevices-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-16.png);
}
.webRTC-sharingDevices-notification-icon,
#webRTC-sharingDevices-notification-icon {
list-style-image: url(chrome://browser/skin/webRTC-sharingDevice-16.png);
}
.web-notifications-notification-icon,
#web-notifications-notification-icon {
list-style-image: url(chrome://browser/skin/notification-16.png);
}
#pointerLock-notification-icon {
list-style-image: url(chrome://browser/skin/pointerLock-16.png);
}
#pointerLock-cancel {
margin: 0px;
}
+2
View File
@@ -24,6 +24,8 @@ browser.jar:
* skin/classic/browser/engineManager.css
skin/classic/browser/Geolocation-16.png
skin/classic/browser/Geolocation-64.png
skin/classic/browser/Push-16.png
skin/classic/browser/Push-64.png
skin/classic/browser/Info.png
skin/classic/browser/identity.png
skin/classic/browser/imagedocument.png
@@ -101,6 +101,9 @@
.pref-icon[type="geo"] {
list-style-image: url(chrome://browser/skin/Geolocation-64.png);
}
.pref-icon[type="push"] {
list-style-image: url(chrome://browser/skin/Push-64.png);
}
.pref-icon[type="indexedDB"] {
list-style-image: url(chrome://global/skin/icons/question-48.png);
}
+10 -1
View File
@@ -20,7 +20,7 @@ interface nsIContentSecurityPolicy;
[ptr] native JSPrincipals(JSPrincipals);
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
[scriptable, builtinclass, uuid(204555e7-04ad-4cc8-9f0e-840615cc43e8)]
[scriptable, builtinclass, uuid(264fe8ca-c382-11e4-95a6-782bcbaebb28)]
interface nsIPrincipal : nsISerializable
{
/**
@@ -230,6 +230,15 @@ interface nsIPrincipal : nsISerializable
* unknown, hence assumed minimally privileged, security context).
*/
[infallible] readonly attribute boolean isNullPrincipal;
/**
* Returns true if this principal's origin is recognized as being on the
* whitelist of sites that can use the CSS Unprefixing Service.
*
* (This interface provides a trivial implementation, just returning false;
* subclasses can implement something more complex as-needed.)
*/
[noscript,notxpcom,nostdcall] bool IsOnCSSUnprefixingWhitelist();
};
/**
+6
View File
@@ -318,6 +318,12 @@ nsNullPrincipal::GetBaseDomain(nsACString& aBaseDomain)
return mURI->GetPath(aBaseDomain);
}
bool
nsNullPrincipal::IsOnCSSUnprefixingWhitelist()
{
return false;
}
/**
* nsISerializable implementation
*/
+164 -10
View File
@@ -14,12 +14,14 @@
#include "pratom.h"
#include "nsIURI.h"
#include "nsJSPrincipals.h"
#include "nsIEffectiveTLDService.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsIClassInfoImpl.h"
#include "nsIProtocolHandler.h"
#include "nsError.h"
#include "nsIContentSecurityPolicy.h"
#include "nsNetCID.h"
#include "jswrapper.h"
#include "mozilla/dom/ScriptSettings.h"
@@ -31,8 +33,8 @@
using namespace mozilla;
static bool gIsWhitelistingTestDomains = false;
static bool gCodeBasePrincipalSupport = false;
static bool gIsObservingCodeBasePrincipalSupport = false;
static bool URIIsImmutable(nsIURI* aURI)
{
@@ -72,15 +74,6 @@ nsBasePrincipal::Release()
nsBasePrincipal::nsBasePrincipal()
{
if (!gIsObservingCodeBasePrincipalSupport) {
nsresult rv =
Preferences::AddBoolVarCache(&gCodeBasePrincipalSupport,
"signed.applets.codebase_principal_support",
false);
gIsObservingCodeBasePrincipalSupport = NS_SUCCEEDED(rv);
NS_WARN_IF_FALSE(gIsObservingCodeBasePrincipalSupport,
"Installing gCodeBasePrincipalSupport failed!");
}
}
nsBasePrincipal::~nsBasePrincipal(void)
@@ -126,6 +119,19 @@ NS_IMPL_CI_INTERFACE_GETTER(nsPrincipal,
NS_IMPL_ADDREF_INHERITED(nsPrincipal, nsBasePrincipal)
NS_IMPL_RELEASE_INHERITED(nsPrincipal, nsBasePrincipal)
// Called at startup:
/* static */ void
nsPrincipal::InitializeStatics()
{
Preferences::AddBoolVarCache(
&gIsWhitelistingTestDomains,
"layout.css.unprefixing-service.include-test-domains");
Preferences::AddBoolVarCache(&gCodeBasePrincipalSupport,
"signed.applets.codebase_principal_support",
false);
}
nsPrincipal::nsPrincipal()
: mAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID)
, mInMozBrowser(false)
@@ -608,6 +614,145 @@ nsPrincipal::GetAppStatus()
return nsScriptSecurityManager::AppStatusForPrincipal(this);
}
// Helper-function to indicate whether the CSS Unprefixing Service
// whitelist should include dummy domains that are only intended for
// use in testing. (Controlled by a pref.)
static inline bool
IsWhitelistingTestDomains()
{
return gIsWhitelistingTestDomains;
}
// Checks if the given URI's host is on our "full domain" whitelist
// (i.e. if it's an exact match against a domain that needs unprefixing)
static bool
IsOnFullDomainWhitelist(nsIURI* aURI)
{
nsAutoCString hostStr;
nsresult rv = aURI->GetHost(hostStr);
NS_ENSURE_SUCCESS(rv, false);
// NOTE: This static whitelist is expected to be short. If that changes,
// we should consider a different representation; e.g. hash-set, prefix tree.
static const nsLiteralCString sFullDomainsOnWhitelist[] = {
// 0th entry only active when testing:
NS_LITERAL_CSTRING("test1.example.org"),
NS_LITERAL_CSTRING("map.baidu.com"),
NS_LITERAL_CSTRING("music.baidu.com"),
NS_LITERAL_CSTRING("3g.163.com"),
NS_LITERAL_CSTRING("3glogo.gtimg.com"), // for 3g.163.com
NS_LITERAL_CSTRING("info.3g.qq.com"), // for 3g.qq.com
NS_LITERAL_CSTRING("3gimg.qq.com"), // for 3g.qq.com
NS_LITERAL_CSTRING("img.m.baidu.com"), // for [shucheng|ks].baidu.com
NS_LITERAL_CSTRING("m.mogujie.com"),
NS_LITERAL_CSTRING("touch.qunar.com"),
};
static const size_t sNumFullDomainsOnWhitelist =
MOZ_ARRAY_LENGTH(sFullDomainsOnWhitelist);
// Skip 0th (dummy) entry in whitelist, unless a pref is enabled.
const size_t firstWhitelistIdx = IsWhitelistingTestDomains() ? 0 : 1;
for (size_t i = firstWhitelistIdx; i < sNumFullDomainsOnWhitelist; ++i) {
if (hostStr == sFullDomainsOnWhitelist[i]) {
return true;
}
}
return false;
}
// Checks if the given URI's host is on our "base domain" whitelist
// (i.e. if it's a subdomain of some host that we've whitelisted as needing
// unprefixing for all its subdomains)
static bool
IsOnBaseDomainWhitelist(nsIURI* aURI)
{
static const nsLiteralCString sBaseDomainsOnWhitelist[] = {
// 0th entry only active when testing:
NS_LITERAL_CSTRING("test2.example.org"),
NS_LITERAL_CSTRING("tbcdn.cn"), // for m.taobao.com
NS_LITERAL_CSTRING("dpfile.com"), // for m.dianping.com
NS_LITERAL_CSTRING("hao123img.com"), // for hao123.com
};
static const size_t sNumBaseDomainsOnWhitelist =
MOZ_ARRAY_LENGTH(sBaseDomainsOnWhitelist);
nsCOMPtr<nsIEffectiveTLDService> tldService =
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
if (tldService) {
// Skip 0th test-entry in whitelist, unless the testing pref is enabled.
const size_t firstWhitelistIdx = IsWhitelistingTestDomains() ? 0 : 1;
// Right now, the test base-domain "test2.example.org" is the only entry in
// its whitelist with a nonzero "depth". So we'll only bother going beyond
// 0 depth (to 1) if that entry is enabled. (No point in slowing down the
// normal codepath, for the benefit of a disabled test domain.) If we add a
// "real" base-domain with a depth of >= 1 to our whitelist, we can get rid
// of this conditional & just make this a static variable.
const uint32_t maxSubdomainDepth = IsWhitelistingTestDomains() ? 1 : 0;
for (uint32_t subdomainDepth = 0;
subdomainDepth <= maxSubdomainDepth; ++subdomainDepth) {
// Get the base domain (to depth |subdomainDepth|) from passed-in URI:
nsAutoCString baseDomainStr;
nsresult rv = tldService->GetBaseDomain(aURI, subdomainDepth,
baseDomainStr);
if (NS_FAILED(rv)) {
// aURI doesn't have |subdomainDepth| levels of subdomains. If we got
// here without a match yet, then aURI is not on our whitelist.
return false;
}
// Compare the base domain against each entry in our whitelist:
for (size_t i = firstWhitelistIdx; i < sNumBaseDomainsOnWhitelist; ++i) {
if (baseDomainStr == sBaseDomainsOnWhitelist[i]) {
return true;
}
}
}
}
return false;
}
// The actual (non-cached) implementation of IsOnCSSUnprefixingWhitelist():
static bool
IsOnCSSUnprefixingWhitelistImpl(nsIURI* aURI)
{
// Check scheme, so we can drop any non-HTTP/HTTPS URIs right away
nsAutoCString schemeStr;
nsresult rv = aURI->GetScheme(schemeStr);
NS_ENSURE_SUCCESS(rv, false);
// Only proceed if scheme is "http" or "https"
if (!(StringBeginsWith(schemeStr, NS_LITERAL_CSTRING("http")) &&
(schemeStr.Length() == 4 ||
(schemeStr.Length() == 5 && schemeStr[4] == 's')))) {
return false;
}
return (IsOnFullDomainWhitelist(aURI) ||
IsOnBaseDomainWhitelist(aURI));
}
bool
nsPrincipal::IsOnCSSUnprefixingWhitelist()
{
if (mIsOnCSSUnprefixingWhitelist.isNothing()) {
// Value not cached -- perform our lazy whitelist-check.
// (NOTE: If our URI is mutable, we just assume it's not on the whitelist,
// since our caching strategy won't work. This isn't expected to be common.)
mIsOnCSSUnprefixingWhitelist.emplace(
mCodebaseImmutable &&
IsOnCSSUnprefixingWhitelistImpl(mCodebase));
}
return *mIsOnCSSUnprefixingWhitelist;
}
/************************************************************************************************************************/
static const char EXPANDED_PRINCIPAL_SPEC[] = "[Expanded Principal]";
@@ -823,6 +968,15 @@ nsExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain)
return NS_ERROR_NOT_AVAILABLE;
}
bool
nsExpandedPrincipal::IsOnCSSUnprefixingWhitelist()
{
// CSS Unprefixing Whitelist is a per-origin thing; doesn't really make sense
// for an expanded principal. (And probably shouldn't be needed.)
return false;
}
void
nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
{
+8
View File
@@ -66,6 +66,7 @@ public:
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) override;
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal) override;
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
virtual bool IsOnCSSUnprefixingWhitelist() override;
#ifdef DEBUG
virtual void dumpImpl() override;
#endif
@@ -102,6 +103,11 @@ public:
*/
static nsresult GetOriginForURI(nsIURI* aURI, char **aOrigin);
/**
* Called at startup to setup static data, e.g. about:config pref-observers.
*/
static void InitializeStatics();
nsCOMPtr<nsIURI> mDomain;
nsCOMPtr<nsIURI> mCodebase;
uint32_t mAppId;
@@ -110,6 +116,7 @@ public:
bool mCodebaseImmutable;
bool mDomainImmutable;
bool mInitialized;
mozilla::Maybe<bool> mIsOnCSSUnprefixingWhitelist; // Lazily-computed
protected:
virtual ~nsPrincipal();
@@ -149,6 +156,7 @@ public:
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) override;
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal) override;
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
virtual bool IsOnCSSUnprefixingWhitelist() override;
#ifdef DEBUG
virtual void dumpImpl() override;
#endif
+7
View File
@@ -201,6 +201,13 @@ nsSystemPrincipal::GetBaseDomain(nsACString& aBaseDomain)
return NS_OK;
}
bool
nsSystemPrincipal::IsOnCSSUnprefixingWhitelist()
{
// chrome stylesheets should not be fed to the CSS Unprefixing Service.
return false;
}
//////////////////////////////////////////
// Methods implementing nsISerializable //
//////////////////////////////////////////
+12
View File
@@ -293,6 +293,8 @@ if test -n "$gonkdir" ; then
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
MOZ_AUDIO_OFFLOAD=1
MOZ_OMX_DECODER=1
MOZ_OMX_ENCODER=1
AC_DEFINE(MOZ_OMX_ENCODER)
AC_SUBST(MOZ_AUDIO_OFFLOAD)
AC_DEFINE(MOZ_AUDIO_OFFLOAD)
MOZ_FMP4=
@@ -3913,6 +3915,7 @@ MOZ_ANDROID_MLS_STUMBLER=
MOZ_ANDROID_SHARE_OVERLAY=
ACCESSIBILITY=
MOZ_TIME_MANAGER=
MOZ_SIMPLEPUSH=
MOZ_PAY=
MOZ_AUDIO_CHANNEL_MANAGER=
NSS_NO_LIBPKIX=
@@ -7258,6 +7261,15 @@ if test -n "$MOZ_B2G_CAMERA"; then
fi
AC_SUBST(MOZ_B2G_CAMERA)
dnl ========================================================
dnl = Enable Support for SimplePush (Gonk usually)
dnl This will disable the Push API.
dnl ========================================================
if test -n "$MOZ_SIMPLEPUSH"; then
AC_DEFINE(MOZ_SIMPLEPUSH)
fi
AC_SUBST(MOZ_SIMPLEPUSH)
dnl ========================================================
dnl = Enable Support for Payment API
dnl ========================================================
+4
View File
@@ -99,6 +99,10 @@ static RedirEntry kRedirMap[] = {
"webrtc", "chrome://global/content/aboutwebrtc/aboutWebrtc.xhtml",
nsIAboutModule::ALLOW_SCRIPT
},
{
"serviceworkers", "chrome://global/content/aboutServiceWorkers.xhtml",
nsIAboutModule::ALLOW_SCRIPT
},
// about:srcdoc is unresolvable by specification. It is included here
// because the security manager would disallow srcdoc iframes otherwise.
{
+1
View File
@@ -173,6 +173,7 @@ const mozilla::Module::ContractIDEntry kDocShellContracts[] = {
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "networking", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "webrtc", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "srcdoc", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "serviceworkers", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_URI_LOADER_CONTRACTID, &kNS_URI_LOADER_CID },
{ NS_DOCUMENTLOADER_SERVICE_CONTRACTID, &kNS_DOCUMENTLOADER_SERVICE_CID },
{ NS_EXTERNALHELPERAPPSERVICE_CONTRACTID, &kNS_EXTERNALHELPERAPPSERVICE_CID },
+37
View File
@@ -51,6 +51,16 @@ struct AnimationTiming
return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH ||
mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BACKWARDS;
}
bool operator==(const AnimationTiming& aOther) const {
return mIterationDuration == aOther.mIterationDuration &&
mDelay == aOther.mDelay &&
mIterationCount == aOther.mIterationCount &&
mDirection == aOther.mDirection &&
mFillMode == aOther.mFillMode;
}
bool operator!=(const AnimationTiming& aOther) const {
return !(*this == aOther);
}
};
/**
@@ -104,6 +114,14 @@ public:
}
Type GetType() const { return mType; }
uint32_t GetSteps() const { return mSteps; }
bool operator==(const ComputedTimingFunction& aOther) const {
return mType == aOther.mType &&
mTimingFunction == aOther.mTimingFunction &&
mSteps == aOther.mSteps;
}
bool operator!=(const ComputedTimingFunction& aOther) const {
return !(*this == aOther);
}
private:
Type mType;
@@ -116,12 +134,31 @@ struct AnimationPropertySegment
float mFromKey, mToKey;
StyleAnimationValue mFromValue, mToValue;
ComputedTimingFunction mTimingFunction;
bool operator==(const AnimationPropertySegment& aOther) const {
return mFromKey == aOther.mFromKey &&
mToKey == aOther.mToKey &&
mFromValue == aOther.mFromValue &&
mToValue == aOther.mToValue &&
mTimingFunction == aOther.mTimingFunction;
}
bool operator!=(const AnimationPropertySegment& aOther) const {
return !(*this == aOther);
}
};
struct AnimationProperty
{
nsCSSProperty mProperty;
InfallibleTArray<AnimationPropertySegment> mSegments;
bool operator==(const AnimationProperty& aOther) const {
return mProperty == aOther.mProperty &&
mSegments == aOther.mSegments;
}
bool operator!=(const AnimationProperty& aOther) const {
return !(*this == aOther);
}
};
struct ElementPropertyTransition;
+18
View File
@@ -128,6 +128,7 @@ AnimationPlayer::SetSource(Animation* aSource)
if (mSource) {
mSource->SetParentTime(GetCurrentTime());
}
UpdateRelevance();
}
void
@@ -213,6 +214,8 @@ AnimationPlayer::Cancel()
mHoldTime.SetNull();
mStartTime.SetNull();
UpdateSourceContent();
}
bool
@@ -226,6 +229,20 @@ AnimationPlayer::IsRunning() const
return computedTiming.mPhase == ComputedTiming::AnimationPhase_Active;
}
void
AnimationPlayer::UpdateRelevance()
{
bool wasRelevant = mIsRelevant;
mIsRelevant = HasCurrentSource() || HasInEffectSource();
// Notify animation observers.
if (wasRelevant && !mIsRelevant) {
nsNodeUtils::AnimationRemoved(this);
} else if (!wasRelevant && mIsRelevant) {
nsNodeUtils::AnimationAdded(this);
}
}
bool
AnimationPlayer::CanThrottle() const
{
@@ -356,6 +373,7 @@ AnimationPlayer::UpdateSourceContent()
{
if (mSource) {
mSource->SetParentTime(GetCurrentTime());
UpdateRelevance();
}
}
+8 -1
View File
@@ -48,7 +48,7 @@ class AnimationPlayer : public nsISupports,
public nsWrapperCache
{
protected:
virtual ~AnimationPlayer() { }
virtual ~AnimationPlayer() {}
public:
explicit AnimationPlayer(AnimationTimeline* aTimeline)
@@ -56,6 +56,7 @@ public:
, mIsPending(false)
, mIsRunningOnCompositor(false)
, mIsPreviousStateFinished(false)
, mIsRelevant(false)
{
}
@@ -185,6 +186,9 @@ public:
return GetSource() && GetSource()->IsInEffect();
}
bool IsRelevant() const { return mIsRelevant; }
void UpdateRelevance();
void SetIsRunningOnCompositor() { mIsRunningOnCompositor = true; }
void ClearIsRunningOnCompositor() { mIsRunningOnCompositor = false; }
@@ -250,6 +254,9 @@ protected:
// probably remove this and check if the promise has been settled yet
// or not instead.
bool mIsPreviousStateFinished; // Spec calls this "previous finished state"
// Indicates that the player should be exposed in an element's
// getAnimationPlayers() list.
bool mIsRelevant;
};
} // namespace dom
+1
View File
@@ -1 +1,2 @@
[chrome/test_animation_observers.html]
[chrome/test_running_on_compositor.html]
@@ -0,0 +1,698 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Test chrome-only MutationObserver animation notifications</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
<style>
@keyframes anim {
to { transform: translate(100px); }
}
#target {
width: 100px;
height: 100px;
background-color: yellow;
line-height: 16px;
}
</style>
<div id=container><div id=target></div></div>
<script>
var div = document.getElementById("target");
var gRecords = [];
var gRecordPromiseResolvers = [];
var gObserver = new MutationObserver(function(newRecords) {
dump(`got a record ${newRecords[0].addedAnimations.length}/${newRecords[0].changedAnimations.length}/${newRecords[0].removedAnimations.length}\n`);
gRecords.push(...newRecords);
var resolvers = gRecordPromiseResolvers;
gRecordPromiseResolvers = [];
resolvers.forEach(fn => fn());
});
// Asynchronous testing framework based on layout/style/test/animation_utils.js.
var gTests = [];
var gCurrentTestName;
function addAsyncAnimTest(aName, aOptions, aTestGenerator) {
aTestGenerator.testName = aName;
aTestGenerator.options = aOptions || {};
gTests.push(aTestGenerator);
}
function runAsyncTest(aTestGenerator) {
return await_frame().then(function() {
var generator;
function step(arg) {
var next;
try {
next = generator.next(arg);
} catch (e) {
return Promise.reject(e);
}
if (next.done) {
return Promise.resolve(next.value);
} else {
return Promise.resolve(next.value).then(step);
}
}
var subtree = aTestGenerator.options.subtree;
gCurrentTestName = aTestGenerator.testName;
if (subtree) {
gCurrentTestName += ":subtree";
}
gRecords = [];
gObserver.disconnect();
gObserver.observe(aTestGenerator.options.observe,
{ animations: true, subtree: subtree});
generator = aTestGenerator();
return step();
});
};
function runAllAsyncTests() {
return gTests.reduce(function(sequence, test) {
return sequence.then(() => runAsyncTest(test));
}, Promise.resolve());
}
// Wrap is and ok with versions that prepend the current sub-test name
// to the assertion description.
var old_is = is, old_ok = ok;
is = function(a, b, message) {
if (gCurrentTestName && message) {
message = `[${gCurrentTestName}] ${message}`;
}
old_is(a, b, message);
}
ok = function(a, message) {
if (gCurrentTestName && message) {
message = `[${gCurrentTestName}] ${message}`;
}
old_ok(a, message);
}
// Returns a Promise that is resolved by a requestAnimationFrame callback.
function await_frame() {
return new Promise(function(aResolve) {
requestAnimationFrame(function() {
aResolve();
});
});
}
// Adds an event listener and returns a Promise that is resolved when the
// event listener is called.
function await_event(aElement, aEventName) {
return new Promise(function(aResolve) {
function listener(aEvent) {
aElement.removeEventListener(aEventName, listener);
aResolve();
}
aElement.addEventListener(aEventName, listener, false);
});
}
// Returns a Promise that is resolved after a given timeout duration.
function await_timeout(aTimeout) {
return new Promise(function(aResolve) {
setTimeout(function() {
aResolve();
}, aTimeout);
});
}
// Returns a Promise that is resolved when the MutationObserver is next
// invoked.
function await_records() {
return new Promise(function(aResolve) {
gRecordPromiseResolvers.push(aResolve);
});
}
function assert_record_list(actual, expected, desc, index, listName) {
is(actual.length, expected.length, `${desc} - record[${index}].${listName} length`);
if (actual.length != expected.length) {
return;
}
for (var i = 0; i < actual.length; i++) {
ok(actual.indexOf(expected[i]) != -1,
`${desc} - record[${index}].${listName} contains expected AnimationPlayer`);
}
}
function assert_records(expected, desc) {
var records = gRecords;
gRecords = [];
is(records.length, expected.length, `${desc} - number of records`);
if (records.length != expected.length) {
return;
}
for (var i = 0; i < records.length; i++) {
assert_record_list(records[i].addedAnimations, expected[i].added, desc, i, "addedAnimations");
assert_record_list(records[i].changedAnimations, expected[i].changed, desc, i, "changedAnimations");
assert_record_list(records[i].removedAnimations, expected[i].removed, desc, i, "removedAnimations");
}
}
// -- Tests ------------------------------------------------------------------
// We run all tests first targetting the div and observing the div, then again
// targetting the div and observing its parent while using the subtree:true
// MutationObserver option.
[
{ observe: div, target: div, subtree: false },
{ observe: div.parentNode, target: div, subtree: true },
].forEach(function(aOptions) {
var e = aOptions.target;
// Test that starting a single transition that completes normally
// dispatches an added notification and then a removed notification.
addAsyncAnimTest("single_transition", aOptions, function*() {
// Start a transition.
e.style = "transition: background-color 0.001s; background-color: lime;";
// Register for the end of the transition.
var transitionEnd = await_event(e, "transitionend");
// The transition should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after transition start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
"records after transition start");
yield transitionEnd;
// After the transition has finished, the AnimationPlayer should disappear.
is(e.getAnimationPlayers().length, 0, "getAnimationPlayers().length after transition end");
// Wait for the single MutationRecord for the AnimationPlayer removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
"records after transition end");
e.style = "";
});
// Test that starting a single transition that is cancelled by resetting
// the transition-property property dispatches an added notification and
// then a removed notification.
addAsyncAnimTest("single_transition_cancelled_property", aOptions, function*() {
// Start a long transition.
e.style = "transition: background-color 100s; background-color: lime;";
// The transition should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after transition start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
"records after transition start");
// Cancel the transition by setting transition-property.
e.style.transitionProperty = "none";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
"records after transition end");
e.style = "";
});
// Test that starting a single transition that is cancelled by setting
// style to the currently animated value dispatches an added
// notification and then a removed notification.
addAsyncAnimTest("single_transition_cancelled_value", aOptions, function*() {
// Start a long transition with a predictable value.
e.style = "transition: background-color 100s steps(2, end) -51s; background-color: lime;";
// The transition should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after transition start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
"records after transition start");
// Cancel the transition by setting the current animation value.
var value = "rgb(128, 255, 0)";
is(getComputedStyle(e).backgroundColor, value, "half-way transition value");
e.style.backgroundColor = value;
// Wait for the single MutationRecord for the AnimationPlayer removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
"records after transition end");
e.style = "";
});
// Test that starting a single transition that is cancelled by setting
// style to a non-interpolable value dispatches an added notification
// and then a removed notification.
addAsyncAnimTest("single_transition_cancelled_noninterpolable", aOptions, function*() {
// Start a long transition.
e.style = "transition: line-height 100s; line-height: 100px;";
// The transition should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after transition start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
"records after transition start");
// Cancel the transition by setting line-height to a non-interpolable value.
e.style.lineHeight = "normal";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
"records after transition end");
e.style = "";
});
// Test that starting a single transition and then reversing it
// dispatches an added notification, then a simultaneous removed and
// added notification, then a removed notification once finished.
addAsyncAnimTest("single_transition_reversed", aOptions, function*() {
// Start a long transition.
e.style = "transition: background-color 100s step-start; background-color: lime;";
// The transition should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after transition start");
var firstPlayer = players[0];
// Wait for the single MutationRecord for the AnimationPlayer addition to
// be delivered.
yield await_frame();
assert_records([{ added: [firstPlayer], changed: [], removed: [] }],
"records after transition start");
// Wait a bit longer for the transition to take effect.
yield await_frame();
// Reverse the transition by setting the background-color back to its
// original value.
e.style.backgroundColor = "yellow";
// The reversal should cause the creation of a new AnimationPlayer.
players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after transition reversal");
var secondPlayer = players[0];
// Wait for the single MutationRecord for the removal of the original
// AnimationPlayer and the addition of the new AnimationPlayer to
// be delivered.
yield await_frame();
assert_records([{ added: [secondPlayer], changed: [], removed: [firstPlayer] }],
"records after transition reversal");
// Cancel the transition.
e.style.transitionProperty = "none";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: [secondPlayer] }],
"records after transition end");
e.style = "";
});
// Test that multiple transitions starting and ending on an element
// at the same time get batched up into a single MutationRecord.
addAsyncAnimTest("multiple_transitions", aOptions, function*() {
// Start three long transitions.
e.style = "transition-duration: 100s; " +
"transition-property: color, background-color, line-height; " +
"color: blue; background-color: lime; line-height: 24px;";
// The transitions should cause the creation of three AnimationPlayers.
var players = e.getAnimationPlayers();
is(players.length, 3, "getAnimationPlayers().length after transition starts");
// Wait for the single MutationRecord for the AnimationPlayer additions to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
"records after transition starts");
// Wait for the AnimationPlayers to get going.
yield await_frame();
is(players.filter(p => p.playState == "running").length, 3, "number of running AnimationPlayers");
// Cancel one of the transitions by setting transition-property.
e.style.transitionProperty = "background-color, line-height";
var colorPlayer = players.filter(p => p.playState != "running");
var otherPlayers = players.filter(p => p.playState == "running");
is(colorPlayer.length, 1, "number of non-running AnimationPlayers after cancelling one");
is(otherPlayers.length, 2, "number of running AnimationPlayers after cancelling one");
// Wait for a MutationRecord for one of the AnimationPlayer
// removals to be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: colorPlayer }],
"records after color transition end");
// Cancel the remaining transitions.
e.style.transitionProperty = "none";
// Wait for the MutationRecord for the other two AnimationPlayer
// removals to be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: otherPlayers }],
"records after other transition ends");
e.style = "";
});
// Test that starting a single animation that completes normally
// dispatches an added notification and then a removed notification.
addAsyncAnimTest("single_animation", aOptions, function*() {
// Start an animation.
e.style = "animation: anim 0.001s;";
// Register for the end of the animation.
var animationEnd = await_event(e, "animationend");
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
"records after animation start");
yield animationEnd;
// After the animation has finished, the AnimationPlayer should disappear.
is(e.getAnimationPlayers().length, 0, "getAnimationPlayers().length after animation end");
// Wait for the single MutationRecord for the AnimationPlayer removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
"records after animation end");
e.style = "";
});
// Test that starting a single animation that is cancelled by resetting
// the animation-name property dispatches an added notification and
// then a removed notification.
addAsyncAnimTest("single_animation_cancelled_name", aOptions, function*() {
// Start a long animation.
e.style = "animation: anim 100s;";
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
"records after animation start");
// Cancel the animation by setting animation-name.
e.style.animationName = "none";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
"records after animation end");
e.style = "";
});
// Test that starting a single animation that is cancelled by updating
// the animation-duration property dispatches an added notification and
// then a removed notification.
addAsyncAnimTest("single_animation_cancelled_duration", aOptions, function*() {
// Start a long animation.
e.style = "animation: anim 100s;";
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
"records after animation start");
// Advance the animation by a second.
players[0].currentTime += 1000;
// Cancel the animation by setting animation-duration to a value less
// than a second.
e.style.animationDuration = "0.1s";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
"records after animation end");
e.style = "";
});
// Test that starting a single animation that is cancelled by updating
// the animation-delay property dispatches an added notification and
// then a removed notification.
addAsyncAnimTest("single_animation_cancelled_delay", aOptions, function*() {
// Start a long animation.
e.style = "animation: anim 100s;";
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
"records after animation start");
// Cancel the animation by setting animation-delay.
e.style.animationDelay = "-200s";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
"records after animation end");
e.style = "";
});
// Test that starting a single animation that is cancelled by updating
// the animation-fill-mode property dispatches an added notification and
// then a removed notification.
addAsyncAnimTest("single_animation_cancelled_fill", aOptions, function*() {
// Start a short, filled animation.
e.style = "animation: anim 0.001s forwards;";
// Register for the end of the animation.
var animationEnd = await_event(e, "animationend");
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
"records after animation start");
// Wait until we are definitely filling.
yield animationEnd;
// No changes to the list of animations at this point.
assert_records([], "records after animation starts filling");
// Cancel the animation by setting animation-fill-mode.
e.style.animationFillMode = "none";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
"records after animation end");
e.style = "";
});
// Test that starting a single animation that is cancelled by updating
// the animation-iteration-count property dispatches an added notification
// and then a removed notification.
addAsyncAnimTest("single_animation_cancelled_fill", aOptions, function*() {
// Start a short, repeated animation.
e.style = "animation: anim 0.5s infinite;";
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
"records after animation start");
// Advance the animation until we are past the first iteration.
players[0].currentTime += 1000;
// No changes to the list of animations at this point.
assert_records([], "records after animation starts repeating");
// Cancel the animation by setting animation-iteration-count.
e.style.animationIterationCount = "1";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
"records after animation end");
e.style = "";
});
// Test that updating an animation property dispatches a changed notification.
[
{ name: "duration", prop: "animationDuration", val: "200s" },
{ name: "timing", prop: "animationTimingFunction", val: "linear" },
{ name: "iteration", prop: "animationIterationCount", val: "2" },
{ name: "direction", prop: "animationDirection", val: "reverse" },
{ name: "state", prop: "animationPlayState", val: "paused" },
{ name: "delay", prop: "animationDelay", val: "-1s" },
{ name: "fill", prop: "animationFillMode", val: "both" },
].forEach(function(aChangeTest) {
addAsyncAnimTest(`single_animation_change_${aChangeTest.name}`, aOptions, function*() {
// Start a long animation.
e.style = "animation: anim 100s;";
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
"records after animation start");
// Change a property of the animation such that it keeps running.
e.style[aChangeTest.prop] = aChangeTest.val;
// Wait for the single MutationRecord for the AnimationPlayer change to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: players, removed: [] }],
"records after animation change");
// Cancel the animation.
e.style.animationName = "none";
// Wait for the addition, change and removal MutationRecords to be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
"records after animation end");
e.style = "";
});
});
// Test that a non-cancelling change to an animation followed immediately by a
// cancelling change will only send an animation removal notification.
addAsyncAnimTest("coalesce_change_cancel", aOptions, function*() {
// Start a long animation.
e.style = "animation: anim 100s;";
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
"records after animation start");
// Update the animation's delay such that it is still running.
e.style.animationDelay = "-1s";
// Then cancel the animation by updating its duration.
e.style.animationDuration = "0.5s";
// We should get a single removal notification.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
"records after animation end");
e.style = "";
});
// Test that attempting to start an animation that should already be finished
// does not send any notifications.
addAsyncAnimTest("already_finished", aOptions, function*() {
// Start an animation that should already be finished.
e.style = "animation: anim 1s -2s;";
// The animation should cause no AnimationPlayers to be created.
var players = e.getAnimationPlayers();
is(players.length, 0, "getAnimationPlayers().length after animation start");
// And we should get no notifications.
yield await_frame();
assert_records([], "records after attempted animation start");
e.style = "";
});
});
// Run the tests.
SimpleTest.waitForExplicitFinish();
runAllAsyncTests().then(function() {
SimpleTest.finish();
}, function(aError) {
ok(false, "Something failed: " + aError);
});
</script>
+20 -9
View File
@@ -507,15 +507,15 @@ AudioChannelService::ProcessContentOrNormalChannelIsActive(uint64_t aChildID)
void
AudioChannelService::SetDefaultVolumeControlChannel(int32_t aChannel,
bool aHidden)
bool aVisible)
{
SetDefaultVolumeControlChannelInternal(aChannel, aHidden,
SetDefaultVolumeControlChannelInternal(aChannel, aVisible,
CONTENT_PROCESS_ID_MAIN);
}
void
AudioChannelService::SetDefaultVolumeControlChannelInternal(int32_t aChannel,
bool aHidden,
bool aVisible,
uint64_t aChildID)
{
if (XRE_GetProcessType() != GoannaProcessType_Default) {
@@ -525,15 +525,26 @@ AudioChannelService::SetDefaultVolumeControlChannelInternal(int32_t aChannel,
// If this child is in the background and mDefChannelChildID is set to
// others then it means other child in the foreground already set it's
// own default channel already.
if ((!aHidden && mDefChannelChildID != aChildID) ||
(mDefChannelChildID != aChildID &&
mDefChannelChildID != CONTENT_PROCESS_ID_UNKNOWN)) {
if (!aVisible && mDefChannelChildID != aChildID) {
return;
}
// Workaround for the call screen app. The call screen app is running on the
// main process, that will results in wrong visible state. Because we use the
// docshell's active state as visible state, the main process is always
// active. Therefore, we will see the strange situation that the visible
// state of the call screen is always true. If the mDefChannelChildID is set
// to others then it means other child in the foreground already set it's
// own default channel already.
// Summary :
// Child process : foreground app always can set type.
// Parent process : check the mDefChannelChildID.
else if (aChildID == CONTENT_PROCESS_ID_MAIN &&
mDefChannelChildID != CONTENT_PROCESS_ID_UNKNOWN) {
return;
}
mDefChannelChildID = aChildID;
nsString channelName;
mDefChannelChildID = aVisible ? aChildID : CONTENT_PROCESS_ID_UNKNOWN;
nsAutoString channelName;
if (aChannel == -1) {
channelName.AssignASCII("unknown");
} else {
+2 -2
View File
@@ -99,7 +99,7 @@ public:
* AudioChannel enum.
*/
virtual void SetDefaultVolumeControlChannel(int32_t aChannel,
bool aHidden);
bool aVisible);
bool AnyAudioChannelIsActive();
@@ -153,7 +153,7 @@ protected:
/* Send the default-volume-channel-changed notification */
void SetDefaultVolumeControlChannelInternal(int32_t aChannel,
bool aHidden, uint64_t aChildID);
bool aVisible, uint64_t aChildID);
AudioChannelState CheckTelephonyPolicy(AudioChannel aChannel,
uint64_t aChildID);
+1 -1
View File
@@ -3255,7 +3255,7 @@ Element::GetAnimationPlayers(nsTArray<nsRefPtr<AnimationPlayer> >& aPlayers)
playerIdx < collection->mPlayers.Length();
playerIdx++) {
AnimationPlayer* player = collection->mPlayers[playerIdx];
if (player->HasCurrentSource() || player->HasInEffectSource()) {
if (player->IsRelevant()) {
aPlayers.AppendElement(player);
}
}
+3
View File
@@ -79,6 +79,7 @@ EXPORTS += [
'nsGkAtoms.h',
'nsHostObjectProtocolHandler.h',
'nsHostObjectURI.h',
'nsIAnimationObserver.h',
'nsIAttribute.h',
'nsIContent.h',
'nsIContentInlines.h',
@@ -117,6 +118,7 @@ EXPORTS += [
'nsSandboxFlags.h',
'nsScriptLoader.h',
'nsStructuredCloneContainer.h',
'nsStubAnimationObserver.h',
'nsStubDocumentObserver.h',
'nsStubMutationObserver.h',
'nsStyledElement.h',
@@ -300,6 +302,7 @@ UNIFIED_SOURCES += [
'nsScriptLoader.cpp',
'nsScriptNameSpaceManager.cpp',
'nsStructuredCloneContainer.cpp',
'nsStubAnimationObserver.cpp',
'nsStubDocumentObserver.cpp',
'nsStubMutationObserver.cpp',
'nsStyledElement.cpp',
+2 -2
View File
@@ -6839,7 +6839,7 @@ nsContentUtils::GetSelectionInTextControl(Selection* aSelection,
{
MOZ_ASSERT(aSelection && aRoot);
if (!aSelection->GetRangeCount()) {
if (!aSelection->RangeCount()) {
// Nothing selected
aOutStartOffset = aOutEndOffset = 0;
return;
@@ -6900,7 +6900,7 @@ nsContentUtils::GetSelectionBoundingRect(Selection* aSel)
res = nsLayoutUtils::TransformFrameRectToAncestor(frame, res, relativeTo);
}
} else {
int32_t rangeCount = aSel->GetRangeCount();
int32_t rangeCount = aSel->RangeCount();
nsLayoutUtils::RectAccumulator accumulator;
for (int32_t idx = 0; idx < rangeCount; ++idx) {
nsRange* range = aSel->GetRangeAt(idx);
+3
View File
@@ -20,6 +20,9 @@
0x45f27d10, 0x987b, 0x11d2, \
{0xbd, 0x40, 0x00, 0x10, 0x5a, 0xa4, 0x5e, 0x89} }
#define SERVICEWORKERPERIODICUPDATER_CONTRACTID \
"@mozilla.org/service-worker-periodic-updater;1"
//The dom cannot provide the crypto or pkcs11 classes that
//were used in older days, so if someone wants to provide
//the service they must implement an object and give it
+162 -9
View File
@@ -56,6 +56,8 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsDOMMutationRecord,
mTarget,
mPreviousSibling, mNextSibling,
mAddedNodes, mRemovedNodes,
mAddedAnimations, mRemovedAnimations,
mChangedAnimations,
mNext, mOwner)
// Observer
@@ -267,7 +269,7 @@ nsMutationReceiver::ContentRemoved(nsIDocument* aDocument,
// Try to avoid creating transient observer if the node
// already has an observer observing the same set of nodes.
nsMutationReceiver* orig = GetParent() ? GetParent() : this;
if (Observer()->GetReceiverFor(aChild, false) != orig) {
if (Observer()->GetReceiverFor(aChild, false, false) != orig) {
bool transientExists = false;
nsCOMArray<nsMutationReceiver>* transientReceivers = nullptr;
Observer()->mTransientReceivers.Get(aChild, &transientReceivers);
@@ -285,7 +287,13 @@ nsMutationReceiver::ContentRemoved(nsIDocument* aDocument,
if (!transientExists) {
// Make sure the elements which are removed from the
// subtree are kept in the same observation set.
transientReceivers->AppendObject(new nsMutationReceiver(aChild, orig));
nsMutationReceiver* tr;
if (orig->Animations()) {
tr = nsAnimationReceiver::Create(aChild, orig);
} else {
tr = nsMutationReceiver::Create(aChild, orig);
}
transientReceivers->AppendObject(tr);
}
}
}
@@ -314,6 +322,87 @@ void nsMutationReceiver::NodeWillBeDestroyed(const nsINode *aNode)
Disconnect(true);
}
void
nsAnimationReceiver::RecordAnimationMutation(AnimationPlayer* aPlayer,
AnimationMutation aMutationType)
{
Animation* source = aPlayer->GetSource();
if (!source) {
return;
}
Element* animationTarget = source->GetTarget();
if (!animationTarget) {
return;
}
if (!Animations() || !(Subtree() || animationTarget == Target()) ||
animationTarget->ChromeOnlyAccess()) {
return;
}
if (nsAutoAnimationMutationBatch::IsBatching()) {
if (nsAutoAnimationMutationBatch::GetBatchTarget() != animationTarget) {
return;
}
switch (aMutationType) {
case eAnimationMutation_Added:
nsAutoAnimationMutationBatch::AnimationAdded(aPlayer);
break;
case eAnimationMutation_Changed:
nsAutoAnimationMutationBatch::AnimationChanged(aPlayer);
break;
case eAnimationMutation_Removed:
nsAutoAnimationMutationBatch::AnimationRemoved(aPlayer);
break;
}
nsAutoAnimationMutationBatch::AddObserver(Observer());
return;
}
nsDOMMutationRecord* m =
Observer()->CurrentRecord(nsGkAtoms::animations);
NS_ASSERTION(!m->mTarget, "Wrong target!");
m->mTarget = animationTarget;
switch (aMutationType) {
case eAnimationMutation_Added:
m->mAddedAnimations.AppendElement(aPlayer);
break;
case eAnimationMutation_Changed:
m->mChangedAnimations.AppendElement(aPlayer);
break;
case eAnimationMutation_Removed:
m->mRemovedAnimations.AppendElement(aPlayer);
break;
}
}
void
nsAnimationReceiver::AnimationAdded(AnimationPlayer* aPlayer)
{
RecordAnimationMutation(aPlayer, eAnimationMutation_Added);
}
void
nsAnimationReceiver::AnimationChanged(AnimationPlayer* aPlayer)
{
RecordAnimationMutation(aPlayer, eAnimationMutation_Changed);
}
void
nsAnimationReceiver::AnimationRemoved(AnimationPlayer* aPlayer)
{
RecordAnimationMutation(aPlayer, eAnimationMutation_Removed);
}
NS_IMPL_ISUPPORTS_INHERITED(nsAnimationReceiver, nsMutationReceiver,
nsIAnimationObserver)
// Observer
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMMutationObserver)
@@ -353,8 +442,13 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMMutationObserver)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
nsMutationReceiver*
nsDOMMutationObserver::GetReceiverFor(nsINode* aNode, bool aMayCreate)
nsDOMMutationObserver::GetReceiverFor(nsINode* aNode, bool aMayCreate,
bool aWantsAnimations)
{
MOZ_ASSERT(aMayCreate || !aWantsAnimations,
"the value of aWantsAnimations doesn't matter when aMayCreate is "
"false, so just pass in false for it");
if (!aMayCreate && !aNode->MayHaveDOMMutationObserver()) {
return nullptr;
}
@@ -368,7 +462,12 @@ nsDOMMutationObserver::GetReceiverFor(nsINode* aNode, bool aMayCreate)
return nullptr;
}
nsMutationReceiver* r = new nsMutationReceiver(aNode, this);
nsMutationReceiver* r;
if (aWantsAnimations) {
r = nsAnimationReceiver::Create(aNode, this);
} else {
r = nsMutationReceiver::Create(aNode, this);
}
mReceivers.AppendObject(r);
return r;
}
@@ -387,7 +486,7 @@ nsDOMMutationObserver::GetAllSubtreeObserversFor(nsINode* aNode,
nsINode* n = aNode;
while (n) {
if (n->MayHaveDOMMutationObserver()) {
nsMutationReceiver* r = GetReceiverFor(n, false);
nsMutationReceiver* r = GetReceiverFor(n, false, false);
if (r && r->Subtree() && !aReceivers.Contains(r)) {
aReceivers.AppendElement(r);
// If we've found all the receivers the observer has,
@@ -467,6 +566,10 @@ nsDOMMutationObserver::Observe(nsINode& aTarget,
bool characterDataOldValue =
aOptions.mCharacterDataOldValue.WasPassed() &&
aOptions.mCharacterDataOldValue.Value();
bool animations =
aOptions.mAnimations.WasPassed() &&
aOptions.mAnimations.Value() &&
nsContentUtils::ThreadsafeIsCallerChrome();
if (!aOptions.mAttributes.WasPassed() &&
(aOptions.mAttributeOldValue.WasPassed() ||
@@ -479,7 +582,7 @@ nsDOMMutationObserver::Observe(nsINode& aTarget,
characterData = true;
}
if (!(childList || attributes || characterData)) {
if (!(childList || attributes || characterData || animations)) {
aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
return;
}
@@ -522,7 +625,7 @@ nsDOMMutationObserver::Observe(nsINode& aTarget,
}
}
nsMutationReceiver* r = GetReceiverFor(&aTarget, true);
nsMutationReceiver* r = GetReceiverFor(&aTarget, true, animations);
r->SetChildList(childList);
r->SetAttributes(attributes);
r->SetCharacterData(characterData);
@@ -531,6 +634,7 @@ nsDOMMutationObserver::Observe(nsINode& aTarget,
r->SetCharacterDataOldValue(characterDataOldValue);
r->SetAttributeFilter(filters);
r->SetAllAttributes(allAttrs);
r->SetAnimations(animations);
r->RemoveClones();
#ifdef DEBUG
@@ -582,6 +686,7 @@ nsDOMMutationObserver::GetObservingInfo(nsTArray<Nullable<MutationObservingInfo>
info.mSubtree = mr->Subtree();
info.mAttributeOldValue.Construct(mr->AttributeOldValue());
info.mCharacterDataOldValue.Construct(mr->CharacterDataOldValue());
info.mAnimations.Construct(mr->Animations());
nsCOMArray<nsIAtom>& filters = mr->AttributeFilter();
if (filters.Count()) {
info.mAttributeFilter.Construct();
@@ -852,10 +957,16 @@ nsAutoMutationBatch::Done()
for (uint32_t k = 0; k < allObservers.Length(); ++k) {
nsMutationReceiver* r = allObservers[k];
nsMutationReceiver* orig = r->GetParent() ? r->GetParent() : r;
if (ob->GetReceiverFor(removed, false) != orig) {
if (ob->GetReceiverFor(removed, false, false) != orig) {
// Make sure the elements which are removed from the
// subtree are kept in the same observation set.
transientReceivers->AppendObject(new nsMutationReceiver(removed, orig));
nsMutationReceiver* tr;
if (orig->Animations()) {
tr = nsAnimationReceiver::Create(removed, orig);
} else {
tr = nsMutationReceiver::Create(removed, orig);
}
transientReceivers->AppendObject(tr);
}
}
}
@@ -882,3 +993,45 @@ nsAutoMutationBatch::Done()
}
nsDOMMutationObserver::LeaveMutationHandling();
}
nsAutoAnimationMutationBatch*
nsAutoAnimationMutationBatch::sCurrentBatch = nullptr;
void
nsAutoAnimationMutationBatch::Done()
{
if (sCurrentBatch != this) {
return;
}
sCurrentBatch = mPreviousBatch;
if (mObservers.IsEmpty()) {
nsDOMMutationObserver::LeaveMutationHandling();
// Nothing to do.
return;
}
for (nsDOMMutationObserver* ob : mObservers) {
nsRefPtr<nsDOMMutationRecord> m =
new nsDOMMutationRecord(nsGkAtoms::animations, ob->GetParentObject());
m->mTarget = mBatchTarget;
for (const Entry& e : mEntries) {
if (e.mState == eState_Added) {
m->mAddedAnimations.AppendElement(e.mPlayer);
} else if (e.mState == eState_Removed) {
m->mRemovedAnimations.AppendElement(e.mPlayer);
} else if (e.mState == eState_RemainedPresent && e.mChanged) {
m->mChangedAnimations.AppendElement(e.mPlayer);
}
}
if (!m->mAddedAnimations.IsEmpty() ||
!m->mChangedAnimations.IsEmpty() ||
!m->mRemovedAnimations.IsEmpty()) {
ob->AppendMutationRecord(m.forget());
ob->ScheduleForRun();
}
}
nsDOMMutationObserver::LeaveMutationHandling();
}
+273 -14
View File
@@ -11,7 +11,7 @@
#include "nsCycleCollectionParticipant.h"
#include "nsPIDOMWindow.h"
#include "nsIScriptContext.h"
#include "nsStubMutationObserver.h"
#include "nsStubAnimationObserver.h"
#include "nsCOMArray.h"
#include "nsTArray.h"
#include "nsAutoPtr.h"
@@ -24,6 +24,8 @@
#include "nsWrapperCache.h"
#include "mozilla/dom/MutationObserverBinding.h"
#include "nsIDocument.h"
#include "mozilla/dom/AnimationPlayer.h"
#include "nsIAnimationObserver.h"
class nsDOMMutationObserver;
using mozilla::dom::MutationObservingInfo;
@@ -34,6 +36,8 @@ class nsDOMMutationRecord final : public nsISupports,
virtual ~nsDOMMutationRecord() {}
public:
typedef nsTArray<nsRefPtr<mozilla::dom::AnimationPlayer>> AnimationPlayerArray;
nsDOMMutationRecord(nsIAtom* aType, nsISupports* aOwner)
: mType(aType), mAttrNamespace(NullString()), mPrevValue(NullString()), mOwner(aOwner)
{
@@ -91,6 +95,21 @@ public:
aRetVal.SetOwnedString(mPrevValue);
}
void GetAddedAnimations(AnimationPlayerArray& aRetVal) const
{
aRetVal = mAddedAnimations;
}
void GetRemovedAnimations(AnimationPlayerArray& aRetVal) const
{
aRetVal = mRemovedAnimations;
}
void GetChangedAnimations(AnimationPlayerArray& aRetVal) const
{
aRetVal = mChangedAnimations;
}
nsCOMPtr<nsINode> mTarget;
nsCOMPtr<nsIAtom> mType;
nsCOMPtr<nsIAtom> mAttrName;
@@ -100,6 +119,9 @@ public:
nsRefPtr<nsSimpleContentList> mRemovedNodes;
nsCOMPtr<nsINode> mPreviousSibling;
nsCOMPtr<nsINode> mNextSibling;
AnimationPlayerArray mAddedAnimations;
AnimationPlayerArray mRemovedAnimations;
AnimationPlayerArray mChangedAnimations;
nsRefPtr<nsDOMMutationRecord> mNext;
nsCOMPtr<nsISupports> mOwner;
@@ -107,7 +129,7 @@ public:
// Base class just prevents direct access to
// members to make sure we go through getters/setters.
class nsMutationReceiverBase : public nsStubMutationObserver
class nsMutationReceiverBase : public nsStubAnimationObserver
{
public:
virtual ~nsMutationReceiverBase() { }
@@ -168,6 +190,13 @@ public:
mAllAttributes = aAll;
}
bool Animations() { return mParent ? mParent->Animations() : mAnimations; }
void SetAnimations(bool aAnimations)
{
NS_ASSERTION(!mParent, "Shouldn't have parent");
mAnimations = aAnimations;
}
bool AttributeOldValue() {
return mParent ? mParent->AttributeOldValue()
: mAttributeOldValue;
@@ -200,9 +229,6 @@ protected:
nsMutationReceiverBase(nsINode* aTarget, nsDOMMutationObserver* aObserver)
: mTarget(aTarget), mObserver(aObserver), mRegisterTarget(aTarget)
{
mRegisterTarget->AddMutationObserver(this);
mRegisterTarget->SetMayHaveDOMMutationObserver();
mRegisterTarget->OwnerDoc()->SetMayHaveDOMMutationObservers();
}
nsMutationReceiverBase(nsINode* aRegisterTarget,
@@ -211,7 +237,13 @@ protected:
mRegisterTarget(aRegisterTarget), mKungFuDeathGrip(aParent->Target())
{
NS_ASSERTION(mParent->Subtree(), "Should clone a non-subtree observer!");
mRegisterTarget->AddMutationObserver(this);
}
virtual void AddMutationObserver() = 0;
void AddObserver()
{
AddMutationObserver();
mRegisterTarget->SetMayHaveDOMMutationObserver();
mRegisterTarget->OwnerDoc()->SetMayHaveDOMMutationObservers();
}
@@ -263,6 +295,7 @@ private:
bool mAttributes;
bool mAllAttributes;
bool mAttributeOldValue;
bool mAnimations;
nsCOMArray<nsIAtom> mAttributeFilter;
};
@@ -273,14 +306,20 @@ protected:
virtual ~nsMutationReceiver() { Disconnect(false); }
public:
nsMutationReceiver(nsINode* aTarget, nsDOMMutationObserver* aObserver);
nsMutationReceiver(nsINode* aRegisterTarget, nsMutationReceiverBase* aParent)
: nsMutationReceiverBase(aRegisterTarget, aParent)
static nsMutationReceiver* Create(nsINode* aTarget,
nsDOMMutationObserver* aObserver)
{
NS_ASSERTION(!static_cast<nsMutationReceiver*>(aParent)->GetParent(),
"Shouldn't create deep observer hierarchies!");
aParent->AddClone(this);
nsMutationReceiver* r = new nsMutationReceiver(aTarget, aObserver);
r->AddObserver();
return r;
}
static nsMutationReceiver* Create(nsINode* aRegisterTarget,
nsMutationReceiverBase* aParent)
{
nsMutationReceiver* r = new nsMutationReceiver(aRegisterTarget, aParent);
r->AddObserver();
return r;
}
nsMutationReceiver* GetParent()
@@ -331,6 +370,72 @@ public:
AttributeWillChange(aDocument, aElement, aNameSpaceID, aAttribute,
nsIDOMMutationEvent::MODIFICATION);
}
protected:
nsMutationReceiver(nsINode* aTarget, nsDOMMutationObserver* aObserver);
nsMutationReceiver(nsINode* aRegisterTarget, nsMutationReceiverBase* aParent)
: nsMutationReceiverBase(aRegisterTarget, aParent)
{
NS_ASSERTION(!static_cast<nsMutationReceiver*>(aParent)->GetParent(),
"Shouldn't create deep observer hierarchies!");
aParent->AddClone(this);
}
virtual void AddMutationObserver() override
{
mRegisterTarget->AddMutationObserver(this);
}
};
class nsAnimationReceiver : public nsMutationReceiver
{
public:
static nsAnimationReceiver* Create(nsINode* aTarget,
nsDOMMutationObserver* aObserver)
{
nsAnimationReceiver* r = new nsAnimationReceiver(aTarget, aObserver);
r->AddObserver();
return r;
}
static nsAnimationReceiver* Create(nsINode* aRegisterTarget,
nsMutationReceiverBase* aParent)
{
nsAnimationReceiver* r = new nsAnimationReceiver(aRegisterTarget, aParent);
r->AddObserver();
return r;
}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONADDED
NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONCHANGED
NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONREMOVED
protected:
virtual ~nsAnimationReceiver() {}
nsAnimationReceiver(nsINode* aTarget, nsDOMMutationObserver* aObserver)
: nsMutationReceiver(aTarget, aObserver) {}
nsAnimationReceiver(nsINode* aRegisterTarget, nsMutationReceiverBase* aParent)
: nsMutationReceiver(aRegisterTarget, aParent) {}
virtual void AddMutationObserver() override
{
mRegisterTarget->AddAnimationObserver(this);
}
private:
enum AnimationMutation {
eAnimationMutation_Added,
eAnimationMutation_Changed,
eAnimationMutation_Removed
};
void RecordAnimationMutation(mozilla::dom::AnimationPlayer* aPlayer,
AnimationMutation aMutationType);
};
#define NS_DOM_MUTATION_OBSERVER_IID \
@@ -419,8 +524,12 @@ protected:
virtual ~nsDOMMutationObserver();
friend class nsMutationReceiver;
friend class nsAnimationReceiver;
friend class nsAutoMutationBatch;
nsMutationReceiver* GetReceiverFor(nsINode* aNode, bool aMayCreate);
friend class nsAutoAnimationMutationBatch;
nsMutationReceiver* GetReceiverFor(nsINode* aNode,
bool aMayCreate,
bool aWantsAnimations);
void RemoveReceiver(nsMutationReceiver* aReceiver);
already_AddRefed<nsIVariant> TakeRecords();
@@ -596,6 +705,156 @@ private:
nsCOMPtr<nsINode> mNextSibling;
};
class nsAutoAnimationMutationBatch
{
struct Entry;
public:
explicit nsAutoAnimationMutationBatch(nsINode* aTarget)
: mBatchTarget(nullptr)
{
Init(aTarget);
}
void Init(nsINode* aTarget)
{
if (aTarget && aTarget->OwnerDoc()->MayHaveDOMMutationObservers()) {
mBatchTarget = aTarget;
mPreviousBatch = sCurrentBatch;
sCurrentBatch = this;
nsDOMMutationObserver::EnterMutationHandling();
}
}
~nsAutoAnimationMutationBatch()
{
Done();
}
void Done();
static bool IsBatching()
{
return !!sCurrentBatch;
}
static nsAutoAnimationMutationBatch* GetCurrentBatch()
{
return sCurrentBatch;
}
static void AddObserver(nsDOMMutationObserver* aObserver)
{
if (sCurrentBatch->mObservers.Contains(aObserver)) {
return;
}
sCurrentBatch->mObservers.AppendElement(aObserver);
}
static nsINode* GetBatchTarget()
{
return sCurrentBatch->mBatchTarget;
}
static void AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer)
{
if (!IsBatching()) {
return;
}
Entry* entry = sCurrentBatch->FindEntry(aPlayer);
if (entry) {
switch (entry->mState) {
case eState_RemainedAbsent:
entry->mState = eState_Added;
break;
case eState_Removed:
entry->mState = eState_RemainedPresent;
break;
default:
NS_NOTREACHED("shouldn't have observed an animation being added "
"twice");
}
} else {
entry = sCurrentBatch->mEntries.AppendElement();
entry->mPlayer = aPlayer;
entry->mState = eState_Added;
entry->mChanged = false;
}
}
static void AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer)
{
Entry* entry = sCurrentBatch->FindEntry(aPlayer);
if (entry) {
NS_ASSERTION(entry->mState == eState_RemainedPresent ||
entry->mState == eState_Added,
"shouldn't have observed an animation being changed after "
"being removed");
entry->mChanged = true;
} else {
entry = sCurrentBatch->mEntries.AppendElement();
entry->mPlayer = aPlayer;
entry->mState = eState_RemainedPresent;
entry->mChanged = true;
}
}
static void AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer)
{
Entry* entry = sCurrentBatch->FindEntry(aPlayer);
if (entry) {
switch (entry->mState) {
case eState_RemainedPresent:
entry->mState = eState_Removed;
break;
case eState_Added:
entry->mState = eState_RemainedAbsent;
break;
default:
NS_NOTREACHED("shouldn't have observed an animation being removed "
"twice");
}
} else {
entry = sCurrentBatch->mEntries.AppendElement();
entry->mPlayer = aPlayer;
entry->mState = eState_Removed;
entry->mChanged = false;
}
}
private:
Entry* FindEntry(mozilla::dom::AnimationPlayer* aPlayer)
{
for (Entry& e : mEntries) {
if (e.mPlayer == aPlayer) {
return &e;
}
}
return nullptr;
}
enum State {
eState_RemainedPresent,
eState_RemainedAbsent,
eState_Added,
eState_Removed
};
struct Entry
{
nsRefPtr<mozilla::dom::AnimationPlayer> mPlayer;
State mState;
bool mChanged;
};
static nsAutoAnimationMutationBatch* sCurrentBatch;
nsAutoAnimationMutationBatch* mPreviousBatch;
nsAutoTArray<nsDOMMutationObserver*, 2> mObservers;
nsTArray<Entry> mEntries;
nsINode* mBatchTarget;
};
inline
nsDOMMutationObserver*
nsMutationReceiverBase::Observer()
-1
View File
@@ -4767,7 +4767,6 @@ nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
nsLoadFlags loadFlags = 0;
channel->GetLoadFlags(&loadFlags);
// If we are shift-reloaded, don't associate with a ServiceWorker.
// FIXME(nsm): Bug 1041339.
if (loadFlags & nsIRequest::LOAD_BYPASS_CACHE) {
NS_WARNING("Page was shift reloaded, skipping ServiceWorker control");
return;
+1 -1
View File
@@ -1355,7 +1355,7 @@ nsHTMLCopyEncoder::SetSelection(nsISelection* aSelection)
nsCOMPtr<nsIDOMRange> range;
nsCOMPtr<nsIDOMNode> commonParent;
Selection* selection = static_cast<Selection*>(aSelection);
uint32_t rangeCount = selection->GetRangeCount();
uint32_t rangeCount = selection->RangeCount();
// if selection is uninitialized return
if (!rangeCount)
+1
View File
@@ -88,6 +88,7 @@ GK_ATOM(ancestor, "ancestor")
GK_ATOM(ancestorOrSelf, "ancestor-or-self")
GK_ATOM(anchor, "anchor")
GK_ATOM(_and, "and")
GK_ATOM(animations, "animations")
GK_ATOM(anonid, "anonid")
GK_ATOM(any, "any")
GK_ATOM(mozapp, "mozapp")
+66
View File
@@ -0,0 +1,66 @@
/* -*- 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 nsIAnimationObserver_h___
#define nsIAnimationObserver_h___
#include "nsIMutationObserver.h"
namespace mozilla {
namespace dom {
class AnimationPlayer;
}
}
#define NS_IANIMATION_OBSERVER_IID \
{ 0xed025fc7, 0xdeda, 0x48b9, \
{ 0x9c, 0x35, 0xf2, 0xb6, 0x1e, 0xeb, 0xd0, 0x8d } }
class nsIAnimationObserver : public nsIMutationObserver
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IANIMATION_OBSERVER_IID)
virtual void AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer) = 0;
virtual void AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer) = 0;
virtual void AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIAnimationObserver, NS_IANIMATION_OBSERVER_IID)
#define NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONADDED \
virtual void AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer) \
override;
#define NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONCHANGED \
virtual void AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer) \
override;
#define NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONREMOVED \
virtual void AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer) \
override;
#define NS_IMPL_NSIANIMATIONOBSERVER_STUB(class_) \
void \
class_::AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer) \
{ \
} \
void \
class_::AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer) \
{ \
} \
void \
class_::AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer) \
{ \
} \
NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(class_) \
NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(class_)
#define NS_DECL_NSIANIMATIONOBSERVER \
NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONADDED \
NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONCHANGED \
NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONREMOVED \
NS_DECL_NSIMUTATIONOBSERVER
#endif // nsIAnimationObserver_h___
+13
View File
@@ -2252,6 +2252,16 @@ public:
mMayHaveDOMMutationObservers = true;
}
bool MayHaveAnimationObservers()
{
return mMayHaveAnimationObservers;
}
void SetMayHaveAnimationObservers()
{
mMayHaveAnimationObservers = true;
}
bool IsInSyncOperation()
{
return mInSyncOperationCount != 0;
@@ -2764,6 +2774,9 @@ protected:
// True if a DOMMutationObserver is perhaps attached to a node in the document.
bool mMayHaveDOMMutationObservers;
// True if an nsIAnimationObserver is perhaps attached to a node in the document.
bool mMayHaveAnimationObservers;
// True if a document has loaded Mixed Active Script (see nsMixedContentBlocker.cpp)
bool mHasMixedActiveContentLoaded;
+16
View File
@@ -104,6 +104,7 @@
#include "nsGlobalWindow.h"
#include "nsDOMMutationObserver.h"
#include "GeometryUtils.h"
#include "nsIAnimationObserver.h"
using namespace mozilla;
using namespace mozilla::dom;
@@ -2981,3 +2982,18 @@ nsINode::GetScopeChainParent() const
{
return nullptr;
}
void
nsINode::AddAnimationObserver(nsIAnimationObserver* aAnimationObserver)
{
AddMutationObserver(aAnimationObserver);
OwnerDoc()->SetMayHaveAnimationObservers();
}
void
nsINode::AddAnimationObserverUnlessExists(
nsIAnimationObserver* aAnimationObserver)
{
AddMutationObserverUnlessExists(aAnimationObserver);
OwnerDoc()->SetMayHaveAnimationObservers();
}
+21
View File
@@ -33,6 +33,7 @@ class nsAttrAndChildArray;
class nsChildContentList;
struct nsCSSSelectorList;
class nsDOMAttributeMap;
class nsIAnimationObserver;
class nsIContent;
class nsIDocument;
class nsIDOMElement;
@@ -955,6 +956,9 @@ public:
* adding observers while inside a notification is not a good idea. An
* observer that is already observing the node must not be added without
* being removed first.
*
* For mutation observers that implement nsIAnimationObserver, use
* AddAnimationObserver instead.
*/
void AddMutationObserver(nsIMutationObserver* aMutationObserver)
{
@@ -968,6 +972,9 @@ public:
/**
* Same as above, but only adds the observer if its not observing
* the node already.
*
* For mutation observers that implement nsIAnimationObserver, use
* AddAnimationObserverUnlessExists instead.
*/
void AddMutationObserverUnlessExists(nsIMutationObserver* aMutationObserver)
{
@@ -975,6 +982,20 @@ public:
s->mMutationObservers.AppendElementUnlessExists(aMutationObserver);
}
/**
* Same as AddMutationObserver, but for nsIAnimationObservers. This
* additionally records on the document that animation observers have
* been registered, which is used to determine whether notifications
* must be fired when animations are added, removed or changed.
*/
void AddAnimationObserver(nsIAnimationObserver* aAnimationObserver);
/**
* Same as above, but only adds the observer if its not observing
* the node already.
*/
void AddAnimationObserverUnlessExists(nsIAnimationObserver* aAnimationObserver);
/**
* Removes a mutation observer.
*/
+96
View File
@@ -71,6 +71,34 @@ using mozilla::AutoJSContext;
} \
PR_END_MACRO
#define IMPL_ANIMATION_NOTIFICATION(func_, content_, params_) \
PR_BEGIN_MACRO \
bool needsEnterLeave = doc->MayHaveDOMMutationObservers(); \
if (needsEnterLeave) { \
nsDOMMutationObserver::EnterMutationHandling(); \
} \
nsINode* node = content_; \
do { \
nsINode::nsSlots* slots = node->GetExistingSlots(); \
if (slots && !slots->mMutationObservers.IsEmpty()) { \
/* No need to explicitly notify the first observer first \
since that'll happen anyway. */ \
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS_WITH_QI( \
slots->mMutationObservers, nsIMutationObserver, \
nsIAnimationObserver, func_, params_); \
} \
ShadowRoot* shadow = ShadowRoot::FromNode(node); \
if (shadow) { \
node = shadow->GetPoolHost(); \
} else { \
node = node->GetParentNode(); \
} \
} while (node); \
if (needsEnterLeave) { \
nsDOMMutationObserver::LeaveMutationHandling(); \
} \
PR_END_MACRO
void
nsNodeUtils::CharacterDataWillChange(nsIContent* aContent,
CharacterDataChangeInfo* aInfo)
@@ -185,6 +213,70 @@ nsNodeUtils::ContentRemoved(nsINode* aContainer,
aPreviousSibling));
}
static inline Element*
GetTarget(AnimationPlayer* aPlayer)
{
Animation* source = aPlayer->GetSource();
if (!source) {
return nullptr;
}
Element* target;
nsCSSPseudoElements::Type pseudoType;
source->GetTarget(target, pseudoType);
// If the animation targets a pseudo-element, we don't dispatch
// notifications for it. (In the future we will have PseudoElement
// objects we can use as the target of the notifications.)
if (pseudoType != nsCSSPseudoElements::ePseudo_NotPseudoElement) {
return nullptr;
}
return source->GetTarget();
}
void
nsNodeUtils::AnimationAdded(AnimationPlayer* aPlayer)
{
Element* target = GetTarget(aPlayer);
if (!target) {
return;
}
nsIDocument* doc = target->OwnerDoc();
if (doc->MayHaveAnimationObservers()) {
IMPL_ANIMATION_NOTIFICATION(AnimationAdded, target, (aPlayer));
}
}
void
nsNodeUtils::AnimationChanged(AnimationPlayer* aPlayer)
{
Element* target = GetTarget(aPlayer);
if (!target) {
return;
}
nsIDocument* doc = target->OwnerDoc();
if (doc->MayHaveAnimationObservers()) {
IMPL_ANIMATION_NOTIFICATION(AnimationChanged, target, (aPlayer));
}
}
void
nsNodeUtils::AnimationRemoved(AnimationPlayer* aPlayer)
{
Element* target = GetTarget(aPlayer);
if (!target) {
return;
}
nsIDocument* doc = target->OwnerDoc();
if (doc->MayHaveAnimationObservers()) {
IMPL_ANIMATION_NOTIFICATION(AnimationRemoved, target, (aPlayer));
}
}
void
nsNodeUtils::LastRelease(nsINode* aNode)
{
@@ -457,6 +549,10 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
newDoc->SetMayHaveDOMMutationObservers();
}
if (oldDoc != newDoc && oldDoc->MayHaveAnimationObservers()) {
newDoc->SetMayHaveAnimationObservers();
}
if (elem) {
elem->RecompileScriptEventListeners();
}
+9
View File
@@ -16,6 +16,11 @@ class nsIVariant;
class nsIDOMNode;
template<class E> class nsCOMArray;
class nsCycleCollectionTraversalCallback;
namespace mozilla {
namespace dom {
class AnimationPlayer;
}
}
class nsNodeUtils
{
@@ -122,6 +127,10 @@ public:
}
}
static void AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer);
static void AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer);
static void AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer);
/**
* To be called when reference count of aNode drops to zero.
* @param aNode The node which is going to be deleted.
+8
View File
@@ -0,0 +1,8 @@
/* -*- 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 "nsStubAnimationObserver.h"
NS_IMPL_NSIANIMATIONOBSERVER_STUB(nsStubAnimationObserver)
+16
View File
@@ -0,0 +1,16 @@
/* -*- 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 nsStubAnimationObserver_h_
#define nsStubAnimationObserver_h_
#include "nsIAnimationObserver.h"
class nsStubAnimationObserver : public nsIAnimationObserver {
public:
NS_DECL_NSIANIMATIONOBSERVER
};
#endif // !defined(nsStubAnimationObserver_h_)
@@ -5,21 +5,35 @@
#include "domstubs.idl"
interface nsIArray;
interface nsIDocument;
interface nsIInterceptedChannel;
interface nsIPrincipal;
interface nsIURI;
[builtinclass, uuid(d4367ffe-e435-4195-95f8-0a51b1bbfdfb)]
[scriptable, uuid(52ee2c9d-ee87-4caf-9588-23ae77ff8798)]
interface nsIServiceWorkerUnregisterCallback : nsISupports
{
// aState is true if the unregistration succeded.
// It's false if this ServiceWorkerRegistration doesn't exist.
[noscript] void UnregisterSucceeded(in bool aState);
[noscript] void UnregisterFailed();
void unregisterSucceeded(in bool aState);
void unregisterFailed();
};
[builtinclass, uuid(e4c8baa5-237a-4bf6-82d4-ea06eb4b76ba)]
[scriptable, builtinclass, uuid(8ce0d197-5740-4ddf-aa4a-e5a63e611d03)]
interface nsIServiceWorkerInfo : nsISupports
{
readonly attribute nsIPrincipal principal;
readonly attribute DOMString scope;
readonly attribute DOMString scriptSpec;
readonly attribute DOMString currentWorkerURL;
readonly attribute DOMString activeCacheName;
readonly attribute DOMString waitingCacheName;
};
[scriptable, builtinclass, uuid(861b55e9-d6ac-47cf-a528-8590e9b44de6)]
interface nsIServiceWorkerManager : nsISupports
{
/**
@@ -103,6 +117,10 @@ interface nsIServiceWorkerManager : nsISupports
// Testing
DOMString getScopeForUrl(in DOMString path);
// This is meant to be used only by about:serviceworkers. It returns an array
// of nsIServiceWorkerInfo.
nsIArray getAllRegistrations();
};
%{ C++
+3
View File
@@ -2779,6 +2779,9 @@ NS_EXPORT void
AfterNuwaFork()
{
SetCurrentProcessPrivileges(base::PRIVILEGES_DEFAULT);
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
mozilla::SandboxEarlyInit(XRE_GetProcessType(), /* isNuwa: */ false);
#endif
}
#endif // MOZ_NUWA_PROCESS
+5 -1
View File
@@ -74,7 +74,6 @@ DIRS += [
'notification',
'offline',
'power',
'push',
'quota',
'security',
'settings',
@@ -136,6 +135,11 @@ if CONFIG['MOZ_GAMEPAD']:
if CONFIG['MOZ_NFC']:
DIRS += ['nfc']
if CONFIG['MOZ_SIMPLEPUSH']:
DIRS += ['simplepush']
else:
DIRS += ['push']
if CONFIG['MOZ_SECUREELEMENT']:
DIRS += ['secureelement']
+147
View File
@@ -0,0 +1,147 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// Don't modify this, instead set services.push.debug.
let gDebuggingEnabled = false;
function debug(s) {
if (gDebuggingEnabled)
dump("-*- Push.js: " + s + "\n");
}
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");
const PUSH_CID = Components.ID("{cde1d019-fad8-4044-b141-65fb4fb7a245}");
/**
* The Push component runs in the child process and exposes the SimplePush API
* to the web application. The PushService running in the parent process is the
* one actually performing all operations.
*/
function Push() {
debug("Push Constructor");
}
Push.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
contractID: "@mozilla.org/push/PushManager;1",
classID : PUSH_CID,
QueryInterface : XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
Ci.nsISupportsWeakReference,
Ci.nsIObserver]),
init: function(aWindow) {
// Set debug first so that all debugging actually works.
// NOTE: We don't add an observer here like in PushService. Flipping the
// pref will require a reload of the app/page, which seems acceptable.
gDebuggingEnabled = Services.prefs.getBoolPref("services.push.debug");
debug("init()");
let principal = aWindow.document.nodePrincipal;
let appsService = Cc["@mozilla.org/AppsService;1"]
.getService(Ci.nsIAppsService);
this._manifestURL = appsService.getManifestURLByLocalId(principal.appId);
this._pageURL = principal.URI;
this.initDOMRequestHelper(aWindow, [
"PushService:Register:OK",
"PushService:Register:KO",
"PushService:Unregister:OK",
"PushService:Unregister:KO",
"PushService:Registrations:OK",
"PushService:Registrations:KO"
]);
this._cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
.getService(Ci.nsISyncMessageSender);
},
receiveMessage: function(aMessage) {
debug("receiveMessage()");
let request = this.getRequest(aMessage.data.requestID);
let json = aMessage.data;
if (!request) {
debug("No request " + json.requestID);
return;
}
switch (aMessage.name) {
case "PushService:Register:OK":
Services.DOMRequest.fireSuccess(request, json.pushEndpoint);
break;
case "PushService:Register:KO":
Services.DOMRequest.fireError(request, json.error);
break;
case "PushService:Unregister:OK":
Services.DOMRequest.fireSuccess(request, json.pushEndpoint);
break;
case "PushService:Unregister:KO":
Services.DOMRequest.fireError(request, json.error);
break;
case "PushService:Registrations:OK":
Services.DOMRequest.fireSuccess(request, json.registrations);
break;
case "PushService:Registrations:KO":
Services.DOMRequest.fireError(request, json.error);
break;
default:
debug("NOT IMPLEMENTED! receiveMessage for " + aMessage.name);
}
},
register: function() {
debug("register()");
let req = this.createRequest();
if (!Services.prefs.getBoolPref("services.push.connection.enabled")) {
// If push socket is disabled by the user, immediately error rather than
// timing out.
Services.DOMRequest.fireErrorAsync(req, "NetworkError");
return req;
}
this._cpmm.sendAsyncMessage("Push:Register", {
pageURL: this._pageURL.spec,
manifestURL: this._manifestURL,
requestID: this.getRequestId(req)
});
return req;
},
unregister: function(aPushEndpoint) {
debug("unregister(" + aPushEndpoint + ")");
let req = this.createRequest();
this._cpmm.sendAsyncMessage("Push:Unregister", {
pageURL: this._pageURL.spec,
manifestURL: this._manifestURL,
requestID: this.getRequestId(req),
pushEndpoint: aPushEndpoint
});
return req;
},
registrations: function() {
debug("registrations()");
let req = this.createRequest();
this._cpmm.sendAsyncMessage("Push:Registrations", {
manifestURL: this._manifestURL,
requestID: this.getRequestId(req)
});
return req;
}
}
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Push]);
+8
View File
@@ -0,0 +1,8 @@
# DOM API
component {cde1d019-fad8-4044-b141-65fb4fb7a245} Push.js
contract @mozilla.org/push/PushManager;1 {cde1d019-fad8-4044-b141-65fb4fb7a245}
# Component to initialize PushService on startup.
component {4b8caa3b-3c58-4f3c-a7f5-7bd9cb24c11d} PushServiceLauncher.js
contract @mozilla.org/push/ServiceLauncher;1 {4b8caa3b-3c58-4f3c-a7f5-7bd9cb24c11d}
category app-startup PushServiceLauncher @mozilla.org/push/ServiceLauncher;1
File diff suppressed because it is too large Load Diff
+43
View File
@@ -0,0 +1,43 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
function PushServiceLauncher() {
};
PushServiceLauncher.prototype = {
classID: Components.ID("{4b8caa3b-3c58-4f3c-a7f5-7bd9cb24c11d}"),
contractID: "@mozilla.org/push/ServiceLauncher;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
observe: function observe(subject, topic, data) {
switch (topic) {
case "app-startup":
Services.obs.addObserver(this, "final-ui-startup", true);
break;
case "final-ui-startup":
Services.obs.removeObserver(this, "final-ui-startup");
if (!Services.prefs.getBoolPref("services.push.enabled")) {
return;
}
Cu.import("resource://gre/modules/PushService.jsm");
PushService.init();
break;
}
}
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PushServiceLauncher]);
+14
View File
@@ -0,0 +1,14 @@
# vim: set filetype=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/.
EXTRA_COMPONENTS += [
'Push.js',
'Push.manifest',
'PushServiceLauncher.js',
]
EXTRA_JS_MODULES += [
'PushService.jsm',
]
+13
View File
@@ -6,6 +6,9 @@
#ifndef NS_SMILKEYSPLINE_H_
#define NS_SMILKEYSPLINE_H_
#include "mozilla/ArrayUtils.h"
#include "mozilla/PodOperations.h"
/**
* Utility class to provide scaling defined in a keySplines element.
*/
@@ -44,6 +47,16 @@ public:
void GetSplineDerivativeValues(double aX, double& aDX, double& aDY) const;
bool operator==(const nsSMILKeySpline& aOther) const {
return mX1 == aOther.mX1 &&
mY1 == aOther.mY1 &&
mX2 == aOther.mX2 &&
mY2 == aOther.mY2;
}
bool operator!=(const nsSMILKeySpline& aOther) const {
return !(*this == aOther);
}
private:
void
CalcSampleValues();
+8
View File
@@ -28,6 +28,12 @@ interface MutationRecord {
readonly attribute DOMString? attributeNamespace;
[Constant]
readonly attribute DOMString? oldValue;
[Constant,Cached,ChromeOnly]
readonly attribute sequence<AnimationPlayer> addedAnimations;
[Constant,Cached,ChromeOnly]
readonly attribute sequence<AnimationPlayer> changedAnimations;
[Constant,Cached,ChromeOnly]
readonly attribute sequence<AnimationPlayer> removedAnimations;
};
[Constructor(MutationCallback mutationCallback)]
@@ -52,6 +58,8 @@ dictionary MutationObserverInit {
boolean subtree = false;
boolean attributeOldValue;
boolean characterDataOldValue;
// [ChromeOnly]
boolean animations;
sequence<DOMString> attributeFilter;
};
+15
View File
@@ -0,0 +1,15 @@
/* -*- Mode: IDL; 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/.
*/
[NavigatorProperty="push",
JSImplementation="@mozilla.org/push/PushManager;1",
CheckPermissions="push",
Pref="services.push.enabled"]
interface PushManager {
DOMRequest register();
DOMRequest unregister(DOMString pushEndpoint);
DOMRequest registrations();
};
+6 -1
View File
@@ -346,7 +346,6 @@ WEBIDL_FILES = [
'ProfileTimelineMarker.webidl',
'Promise.webidl',
'PromiseDebugging.webidl',
'PushManager.webidl',
'RadioNodeList.webidl',
'Range.webidl',
'Rect.webidl',
@@ -659,6 +658,12 @@ if CONFIG['MOZ_B2G_RIL']:
'MozIccManager.webidl',
]
if CONFIG['MOZ_SIMPLEPUSH']:
WEBIDL_FILES += SimplePushManager.webidl
else:
WEBIDL_FILES += [
]
if CONFIG['MOZ_NFC']:
WEBIDL_FILES += [
'MozIsoDepTech.webidl',
+1 -1
View File
@@ -306,6 +306,6 @@ ServiceWorkerClients::Claim()
return nullptr;
}
promise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
promise->MaybeResolve(JS::UndefinedHandleValue);
return promise.forget();
}
+131 -4
View File
@@ -13,6 +13,7 @@
#include "nsIHttpChannelInternal.h"
#include "nsIHttpHeaderVisitor.h"
#include "nsINetworkInterceptController.h"
#include "nsIMutableArray.h"
#include "nsPIDOMWindow.h"
#include "nsScriptLoader.h"
#include "nsDebug.h"
@@ -1613,7 +1614,7 @@ private:
nsRefPtr<ServiceWorkerRegistrationInfo> registration;
if (!swm->mServiceWorkerRegistrationInfos.Get(mScope, getter_AddRefs(registration))) {
// "If registration is null, then, resolve promise with false."
return mCallback->UnregisterSucceeded(false);
return mCallback ? mCallback->UnregisterSucceeded(false) : NS_OK;
}
MOZ_ASSERT(registration);
@@ -1621,7 +1622,7 @@ private:
// "Set registration's uninstalling flag."
registration->mPendingUninstall = true;
// "Resolve promise with true"
nsresult rv = mCallback->UnregisterSucceeded(true);
nsresult rv = mCallback ? mCallback->UnregisterSucceeded(true) : NS_OK;
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@@ -1659,8 +1660,10 @@ ServiceWorkerManager::Unregister(nsIPrincipal* aPrincipal,
const nsAString& aScope)
{
AssertIsOnMainThread();
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(aCallback);
if (!aPrincipal) {
return NS_ERROR_FAILURE;
}
// This is not accessible by content, and callers should always ensure scope is
// a correct URI, so this is wrapped in DEBUG
@@ -2812,6 +2815,130 @@ ServiceWorkerManager::RemoveRegistration(ServiceWorkerRegistrationInfo* aRegistr
mActor->SendUnregisterServiceWorker(principalInfo, NS_ConvertUTF8toUTF16(reg->mScope));
}
class ServiceWorkerDataInfo final : public nsIServiceWorkerInfo
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISERVICEWORKERINFO
static already_AddRefed<ServiceWorkerDataInfo>
Create(const ServiceWorkerRegistrationData& aData);
private:
ServiceWorkerDataInfo()
{}
~ServiceWorkerDataInfo()
{}
nsCOMPtr<nsIPrincipal> mPrincipal;
nsString mScope;
nsString mScriptSpec;
nsString mCurrentWorkerURL;
nsString mActiveCacheName;
nsString mWaitingCacheName;
};
NS_IMPL_ISUPPORTS(ServiceWorkerDataInfo, nsIServiceWorkerInfo)
/* static */ already_AddRefed<ServiceWorkerDataInfo>
ServiceWorkerDataInfo::Create(const ServiceWorkerRegistrationData& aData)
{
AssertIsOnMainThread();
nsRefPtr<ServiceWorkerDataInfo> info = new ServiceWorkerDataInfo();
info->mPrincipal = PrincipalInfoToPrincipal(aData.principal());
if (!info->mPrincipal) {
return nullptr;
}
CopyUTF8toUTF16(aData.scope(), info->mScope);
CopyUTF8toUTF16(aData.scriptSpec(), info->mScriptSpec);
CopyUTF8toUTF16(aData.currentWorkerURL(), info->mCurrentWorkerURL);
info->mActiveCacheName = aData.activeCacheName();
info->mWaitingCacheName = aData.waitingCacheName();
return info.forget();
}
NS_IMETHODIMP
ServiceWorkerDataInfo::GetPrincipal(nsIPrincipal** aPrincipal)
{
AssertIsOnMainThread();
NS_ADDREF(*aPrincipal = mPrincipal);
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerDataInfo::GetScope(nsAString& aScope)
{
AssertIsOnMainThread();
aScope = mScope;
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerDataInfo::GetScriptSpec(nsAString& aScriptSpec)
{
AssertIsOnMainThread();
aScriptSpec = mScriptSpec;
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerDataInfo::GetCurrentWorkerURL(nsAString& aCurrentWorkerURL)
{
AssertIsOnMainThread();
aCurrentWorkerURL = mCurrentWorkerURL;
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerDataInfo::GetActiveCacheName(nsAString& aActiveCacheName)
{
AssertIsOnMainThread();
aActiveCacheName = mActiveCacheName;
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerDataInfo::GetWaitingCacheName(nsAString& aWaitingCacheName)
{
AssertIsOnMainThread();
aWaitingCacheName = mWaitingCacheName;
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerManager::GetAllRegistrations(nsIArray** aResult)
{
AssertIsOnMainThread();
nsRefPtr<ServiceWorkerRegistrar> swr = ServiceWorkerRegistrar::Get();
MOZ_ASSERT(swr);
nsTArray<ServiceWorkerRegistrationData> data;
swr->GetRegistrations(data);
nsCOMPtr<nsIMutableArray> array(do_CreateInstance(NS_ARRAY_CONTRACTID));
if (!array) {
return NS_ERROR_OUT_OF_MEMORY;
}
for (uint32_t i = 0, len = data.Length(); i < len; ++i) {
nsCOMPtr<nsIServiceWorkerInfo> info = ServiceWorkerDataInfo::Create(data[i]);
if (!info) {
return NS_ERROR_FAILURE;
}
array->AppendElement(info, false);
}
array.forget(aResult);
return NS_OK;
}
void
ServiceWorkerInfo::AppendWorker(ServiceWorker* aWorker)
{
@@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
* 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 "ServiceWorkerPeriodicUpdater.h"
#include "mozilla/ClearOnShutdown.h"
#define OBSERVER_TOPIC_IDLE_DAILY "idle-daily"
namespace mozilla {
namespace dom {
namespace workers {
NS_IMPL_ISUPPORTS(ServiceWorkerPeriodicUpdater, nsIObserver)
StaticRefPtr<ServiceWorkerPeriodicUpdater>
ServiceWorkerPeriodicUpdater::sInstance;
already_AddRefed<ServiceWorkerPeriodicUpdater>
ServiceWorkerPeriodicUpdater::GetSingleton()
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
if (!sInstance) {
sInstance = new ServiceWorkerPeriodicUpdater();
ClearOnShutdown(&sInstance);
}
nsRefPtr<ServiceWorkerPeriodicUpdater> copy(sInstance.get());
return copy.forget();
}
ServiceWorkerPeriodicUpdater::ServiceWorkerPeriodicUpdater()
{
}
ServiceWorkerPeriodicUpdater::~ServiceWorkerPeriodicUpdater()
{
}
NS_IMETHODIMP
ServiceWorkerPeriodicUpdater::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
if (strcmp(aTopic, OBSERVER_TOPIC_IDLE_DAILY) == 0) {
// TODO: Update the service workers NOW!!!!!
}
return NS_OK;
}
} // namespace workers
} // namespace dom
} // namespace mozilla
@@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
* 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 mozilla_ServiceWorkerPeriodicUpdater_h
#define mozilla_ServiceWorkerPeriodicUpdater_h
#include "nsCOMPtr.h"
#include "nsIObserver.h"
#include "mozilla/StaticPtr.h"
namespace mozilla {
namespace dom {
namespace workers {
class ServiceWorkerPeriodicUpdater final : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
static already_AddRefed<ServiceWorkerPeriodicUpdater> GetSingleton();
private:
ServiceWorkerPeriodicUpdater();
~ServiceWorkerPeriodicUpdater();
static StaticRefPtr<ServiceWorkerPeriodicUpdater> sInstance;
};
} // namespace workers
} // namespace dom
} // namespace mozilla
#endif
+2
View File
@@ -18,6 +18,7 @@ EXPORTS.mozilla.dom += [
EXPORTS.mozilla.dom.workers += [
'ServiceWorkerManager.h',
'ServiceWorkerPeriodicUpdater.h',
'WorkerDebuggerManager.h',
'Workers.h',
]
@@ -68,6 +69,7 @@ UNIFIED_SOURCES += [
'ServiceWorkerContainer.cpp',
'ServiceWorkerEvents.cpp',
'ServiceWorkerManager.cpp',
'ServiceWorkerPeriodicUpdater.cpp',
'ServiceWorkerRegistrar.cpp',
'ServiceWorkerRegistration.cpp',
'ServiceWorkerScriptCache.cpp',
+1 -1
View File
@@ -86,7 +86,7 @@ NS_IMETHODIMP TypeInState::NotifySelectionChanged(nsIDOMDocument *, nsISelection
nsRefPtr<Selection> selection = static_cast<Selection*>(aSelection);
if (aSelection) {
int32_t rangeCount = selection->GetRangeCount();
int32_t rangeCount = selection->RangeCount();
if (selection->Collapsed() && rangeCount) {
nsCOMPtr<nsIDOMNode> selNode;
+3 -3
View File
@@ -3606,7 +3606,7 @@ nsEditor::GetStartNodeAndOffset(Selection* aSelection, nsINode** aStartNode,
*aStartNode = nullptr;
*aStartOffset = 0;
NS_ENSURE_TRUE(aSelection->GetRangeCount(), NS_ERROR_FAILURE);
NS_ENSURE_TRUE(aSelection->RangeCount(), NS_ERROR_FAILURE);
const nsRange* range = aSelection->GetRangeAt(0);
NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
@@ -3653,7 +3653,7 @@ nsEditor::GetEndNodeAndOffset(Selection* aSelection, nsINode** aEndNode,
*aEndNode = nullptr;
*aEndOffset = 0;
NS_ENSURE_TRUE(aSelection->GetRangeCount(), NS_ERROR_FAILURE);
NS_ENSURE_TRUE(aSelection->RangeCount(), NS_ERROR_FAILURE);
const nsRange* range = aSelection->GetRangeAt(0);
NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
@@ -4207,7 +4207,7 @@ nsEditor::CreateTxnForDeleteSelection(EDirection aAction,
// allocate the out-param transaction
nsRefPtr<EditAggregateTxn> aggTxn = new EditAggregateTxn();
for (int32_t rangeIdx = 0; rangeIdx < selection->GetRangeCount(); ++rangeIdx) {
for (uint32_t rangeIdx = 0; rangeIdx < selection->RangeCount(); ++rangeIdx) {
nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
NS_ENSURE_STATE(range);
+6 -6
View File
@@ -315,7 +315,7 @@ nsHTMLEditRules::BeforeEdit(EditAction action,
nsRefPtr<Selection> selection = mHTMLEditor->GetSelection();
// get the selection location
NS_ENSURE_STATE(selection->GetRangeCount());
NS_ENSURE_STATE(selection->RangeCount());
mRangeItem->startNode = selection->GetRangeAt(0)->GetStartParent();
mRangeItem->startOffset = selection->GetRangeAt(0)->StartOffset();
mRangeItem->endNode = selection->GetRangeAt(0)->GetEndParent();
@@ -582,7 +582,7 @@ nsHTMLEditRules::WillDoAction(Selection* aSelection,
if (!aSelection) {
return NS_OK;
}
NS_ENSURE_TRUE(aSelection->GetRangeCount(), NS_OK);
NS_ENSURE_TRUE(aSelection->RangeCount(), NS_OK);
nsRefPtr<nsRange> range = aSelection->GetRangeAt(0);
nsCOMPtr<nsINode> selStartNode = range->GetStartParent();
@@ -2427,7 +2427,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
// except table elements.
join = true;
uint32_t rangeCount = aSelection->GetRangeCount();
uint32_t rangeCount = aSelection->RangeCount();
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
nsRefPtr<nsRange> range = aSelection->GetRangeAt(rangeIdx);
@@ -6087,7 +6087,7 @@ nsHTMLEditRules::GetListActionNodes(nsCOMArray<nsIDOMNode> &outArrayOfNodes,
// is only in part of it. used by list item dialog.
if (aEntireList)
{
uint32_t rangeCount = selection->GetRangeCount();
uint32_t rangeCount = selection->RangeCount();
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
nsCOMPtr<nsIDOMNode> commonParent, parent, tmp;
@@ -7565,7 +7565,7 @@ nsHTMLEditRules::ReapplyCachedStyles()
NS_ENSURE_STATE(mHTMLEditor);
nsRefPtr<Selection> selection = mHTMLEditor->GetSelection();
MOZ_ASSERT(selection);
if (!selection->GetRangeCount()) {
if (!selection->RangeCount()) {
// Nothing to do
return NS_OK;
}
@@ -8225,7 +8225,7 @@ nsHTMLEditRules::SelectionEndpointInNode(nsINode* aNode, bool* aResult)
nsRefPtr<Selection> selection = mHTMLEditor->GetSelection();
NS_ENSURE_STATE(selection);
uint32_t rangeCount = selection->GetRangeCount();
uint32_t rangeCount = selection->RangeCount();
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
nsCOMPtr<nsIDOMNode> startParent, endParent;
+2 -2
View File
@@ -3299,7 +3299,7 @@ nsHTMLEditor::GetIsSelectionEditable(bool* aIsSelectionEditable)
// Per the editing spec as of June 2012: we have to have a selection whose
// start and end nodes are editable, and which share an ancestor editing
// host. (Bug 766387.)
*aIsSelectionEditable = selection->GetRangeCount() &&
*aIsSelectionEditable = selection->RangeCount() &&
selection->GetAnchorNode()->IsEditable() &&
selection->GetFocusNode()->IsEditable();
@@ -4571,7 +4571,7 @@ nsHTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
{
// loop thru the ranges in the selection
nsAutoString bgcolor; bgcolor.AssignLiteral("bgcolor");
uint32_t rangeCount = selection->GetRangeCount();
uint32_t rangeCount = selection->RangeCount();
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
nsCOMPtr<nsIDOMNode> cachedBlockParent = nullptr;
nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
+3 -3
View File
@@ -144,7 +144,7 @@ nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty,
NS_ENSURE_SUCCESS(res, res);
if (!cancel && !handled) {
// loop thru the ranges in the selection
uint32_t rangeCount = selection->GetRangeCount();
uint32_t rangeCount = selection->RangeCount();
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
@@ -1374,7 +1374,7 @@ nsresult nsHTMLEditor::RemoveInlinePropertyImpl(nsIAtom *aProperty, const nsAStr
if (!cancel && !handled)
{
// loop thru the ranges in the selection
uint32_t rangeCount = selection->GetRangeCount();
uint32_t rangeCount = selection->RangeCount();
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
if (aProperty == nsGkAtoms::name) {
@@ -1547,7 +1547,7 @@ nsHTMLEditor::RelativeFontChange( int32_t aSizeChange)
nsAutoTxnsConserveSelection dontSpazMySelection(this);
// loop thru the ranges in the selection
uint32_t rangeCount = selection->GetRangeCount();
uint32_t rangeCount = selection->RangeCount();
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
+1 -1
View File
@@ -55,7 +55,7 @@ nsSelectionState::SaveSelection(Selection* aSel)
{
MOZ_ASSERT(aSel);
int32_t arrayCount = mArray.Length();
int32_t rangeCount = aSel->GetRangeCount();
int32_t rangeCount = aSel->RangeCount();
// if we need more items in the array, new them
if (arrayCount < rangeCount) {
+1 -1
View File
@@ -2954,7 +2954,7 @@ nsHTMLEditor::GetNextSelectedCell(nsIDOMRange **aRange, nsIDOMElement **aCell)
nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
int32_t rangeCount = selection->GetRangeCount();
int32_t rangeCount = selection->RangeCount();
// Don't even try if index exceeds range count
if (mSelectedCellIndex >= rangeCount)
@@ -1354,7 +1354,7 @@ mozInlineSpellChecker::DoSpellCheckSelection(mozInlineSpellWordUtil& aWordUtil,
// elements inside the selection
nsTArray<nsRefPtr<nsRange>> ranges;
int32_t count = aSpellCheckSelection->GetRangeCount();
int32_t count = aSpellCheckSelection->RangeCount();
for (int32_t idx = 0; idx < count; idx++) {
nsRange *range = aSpellCheckSelection->GetRangeAt(idx);
@@ -1448,7 +1448,7 @@ nsresult mozInlineSpellChecker::DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
// see if the selection has any ranges, if not, then we can optimize checking
// range inclusion later (we have no ranges when we are initially checking or
// when there are no misspelled words yet).
int32_t originalRangeCount = aSpellCheckSelection->GetRangeCount();
int32_t originalRangeCount = aSpellCheckSelection->RangeCount();
// set the starting DOM position to be the beginning of our range
{
@@ -1650,7 +1650,7 @@ mozInlineSpellChecker::ResumeCheck(mozInlineSpellStatus* aStatus)
rv = mSpellCheck->GetCurrentDictionary(currentDictionary);
if (NS_FAILED(rv)) {
// no active dictionary
int32_t count = spellCheckSelection->GetRangeCount();
int32_t count = spellCheckSelection->RangeCount();
for (int32_t index = count - 1; index >= 0; index--) {
nsRange *checkRange = spellCheckSelection->GetRangeAt(index);
if (checkRange) {
@@ -1721,7 +1721,7 @@ mozInlineSpellChecker::CleanupRangesInSelection(Selection *aSelection)
if (!aSelection)
return NS_ERROR_FAILURE;
int32_t count = aSelection->GetRangeCount();
int32_t count = aSelection->RangeCount();
for (int32_t index = 0; index < count; index++)
{
+18 -6
View File
@@ -138,14 +138,18 @@ public:
sink->Close();
RefPtr<ID2D1BitmapBrush> brush;
rt->CreateBitmapBrush(mOldSurfBitmap, D2D1::BitmapBrushProperties(), D2D1::BrushProperties(), byRef(brush));
HRESULT hr = rt->CreateBitmapBrush(mOldSurfBitmap, D2D1::BitmapBrushProperties(), D2D1::BrushProperties(), byRef(brush));
if (FAILED(hr)) {
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "[D2D] CreateBitmapBrush failure " << hexa(hr);
return;
}
rt->FillGeometry(invClippedArea, brush);
}
private:
DrawTargetD2D *mDT;
DrawTargetD2D *mDT;
// If we have an operator unbound by the source, this will contain a bitmap
// with the old dest surface data.
@@ -309,7 +313,12 @@ DrawTargetD2D::GetBitmapForSurface(SourceSurface *aSurface,
D2D1_BITMAP_PROPERTIES props =
D2D1::BitmapProperties(D2DPixelFormat(srcSurf->GetFormat()));
mRT->CreateBitmap(D2D1::SizeU(UINT32(sourceRect.width), UINT32(sourceRect.height)), data, stride, props, byRef(bitmap));
HRESULT hr = mRT->CreateBitmap(D2D1::SizeU(UINT32(sourceRect.width), UINT32(sourceRect.height)), data, stride, props, byRef(bitmap));
if (FAILED(hr)) {
IntSize size(sourceRect.width, sourceRect.height);
gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(size))) << "[D2D] 1CreateBitmap failure " << size << " Code: " << hexa(hr);
return nullptr;
}
// subtract the integer part leaving the fractional part
aSource.x -= (uint32_t)aSource.x;
@@ -2419,14 +2428,17 @@ DrawTargetD2D::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
}
break;
}
mRT->CreateBitmapBrush(bitmap,
HRESULT hr = mRT->CreateBitmapBrush(bitmap,
D2D1::BitmapBrushProperties(D2DExtend(pat->mExtendMode),
D2DExtend(pat->mExtendMode),
D2DFilter(pat->mFilter)),
D2D1::BrushProperties(aAlpha, D2DMatrix(mat)),
byRef(bmBrush));
if (FAILED(hr)) {
gfxCriticalError() << "[D2D] 1CreateBitmapBrush failure: " << hexa(hr);
return nullptr;
}
return bmBrush.forget();
}
+8 -2
View File
@@ -841,7 +841,7 @@ DrawTargetD2D1::Init(const IntSize &aSize, SurfaceFormat aFormat)
hr = mDC->CreateBitmap(D2DIntSize(aSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(mTempBitmap));
if (FAILED(hr)) {
gfxCriticalError() << "[D2D1.1] failed to create new TempBitmap " << aSize << " Code: " << hexa(hr);
gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize))) << "[D2D1.1] failed to create new TempBitmap " << aSize << " Code: " << hexa(hr);
return false;
}
@@ -1020,7 +1020,13 @@ DrawTargetD2D1::FinalizeDrawing(CompositionOp aOp, const Pattern &aPattern)
}
RefPtr<ID2D1Bitmap> tmpBitmap;
mDC->CreateBitmap(D2DIntSize(mSize), D2D1::BitmapProperties(D2DPixelFormat(mFormat)), byRef(tmpBitmap));
HRESULT hr = mDC->CreateBitmap(D2DIntSize(mSize), D2D1::BitmapProperties(D2DPixelFormat(mFormat)), byRef(tmpBitmap));
if (FAILED(hr)) {
gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(mSize))) << "[D2D1.1] 5CreateBitmap failure " << mSize << " Code: " << hexa(hr);
// For now, crash in this scenario; this should happen because tmpBitmap is
// null and CopyFromBitmap call below dereferences it.
// return;
}
// This flush is important since the copy method will not know about the context drawing to the surface.
// We also need to pop all the clips to make sure any drawn content will have made it to the final bitmap.
+1 -1
View File
@@ -60,7 +60,7 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
'sha256.c',
]
if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] == 'Linux':
if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] in ('Linux', 'Android'):
USE_LIBS += [
'mozsandbox',
]
@@ -6,6 +6,9 @@
#include <errno.h>
#include <fcntl.h>
#if defined(OS_MACOSX)
#include <sched.h>
#endif
#include <stddef.h>
#include <unistd.h>
#include <sys/types.h>
@@ -724,9 +727,39 @@ bool Channel::ChannelImpl::ProcessOutgoingMessages() {
msg->file_descriptor_set()->CommitAll();
#endif
if (bytes_written < 0 && errno != EAGAIN) {
CHROMIUM_LOG(ERROR) << "pipe error: " << strerror(errno);
return false;
if (bytes_written < 0) {
switch (errno) {
case EAGAIN:
// Not an error; the sendmsg would have blocked, so return to the
// event loop and try again later.
break;
#if defined(OS_MACOSX)
// (Note: this comment is copied from https://crrev.com/86c3d9ef4fdf6;
// see also bug 1142693 comment #73.)
//
// On OS X if sendmsg() is trying to send fds between processes and
// there isn't enough room in the output buffer to send the fd
// structure over atomically then EMSGSIZE is returned.
//
// EMSGSIZE presents a problem since the system APIs can only call us
// when there's room in the socket buffer and not when there is
// "enough" room.
//
// The current behavior is to return to the event loop when EMSGSIZE
// is received and hopefull service another FD. This is however still
// technically a busy wait since the event loop will call us right
// back until the receiver has read enough data to allow passing the
// FD over atomically.
case EMSGSIZE:
// Because this is likely to result in a busy-wait, we'll try to make
// it easier for the receiver to make progress.
sched_yield();
break;
#endif
default:
CHROMIUM_LOG(ERROR) << "pipe error: " << strerror(errno);
return false;
}
}
if (static_cast<size_t>(bytes_written) != amt_to_write) {
+15 -1
View File
@@ -54,7 +54,11 @@
"Goanna:MozillaRntimeMain", __VA_ARGS__)) \
: (void)0 )
#endif
# ifdef MOZ_CONTENT_SANDBOX
# include "mozilla/Sandbox.h"
# endif
#endif // MOZ_WIDGET_GONK
#ifdef MOZ_NUWA_PROCESS
#include <binder/ProcessState.h>
@@ -155,6 +159,16 @@ content_process_main(int argc, char* argv[])
}
#endif
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
// This has to happen while we're still single-threaded, and on
// B2G that means before the Android Binder library is
// initialized. Additional special handling is needed for Nuwa:
// the Nuwa process itself needs to be unsandboxed, and the same
// single-threadedness condition applies to its children; see also
// AfterNuwaFork().
mozilla::SandboxEarlyInit(XRE_GetProcessType(), isNuwa);
#endif
#ifdef MOZ_WIDGET_GONK
// This creates a ThreadPool for binder ipc. A ThreadPool is necessary to
// receive binder calls, though not necessary to send binder calls.
+12 -5
View File
@@ -736,7 +736,6 @@ class HashTableEntry
void removeLive() { MOZ_ASSERT(isLive()); keyHash = sRemovedKey; mem.addr()->~T(); }
bool isLive() const { return isLiveHash(keyHash); }
void setCollision() { MOZ_ASSERT(isLive()); keyHash |= sCollisionBit; }
void setCollision(HashNumber bit) { MOZ_ASSERT(isLive()); keyHash |= bit; }
void unsetCollision() { keyHash &= ~sCollisionBit; }
bool hasCollision() const { return keyHash & sCollisionBit; }
bool matchHash(HashNumber hn) { return (keyHash & ~sCollisionBit) == hn; }
@@ -1030,6 +1029,8 @@ class HashTable : private AllocPolicy
#ifdef JS_DEBUG
uint64_t mutationCount;
mutable bool mEntered;
// Note that some updates to these stats are not thread-safe. See the
// comment on the three-argument overloading of HashTable::lookup().
mutable struct Stats
{
uint32_t searches; // total number of table searches
@@ -1227,7 +1228,12 @@ class HashTable : private AllocPolicy
return HashPolicy::match(HashPolicy::getKey(e.get()), l);
}
Entry& lookup(const Lookup& l, HashNumber keyHash, unsigned collisionBit) const
// Warning: in order for readonlyThreadsafeLookup() to be safe this
// function must not modify the table in any way when |collisionBit| is 0.
// (The use of the METER() macro to increment stats violates this
// restriction but we will live with that for now because it's enabled so
// rarely.)
Entry &lookup(const Lookup &l, HashNumber keyHash, unsigned collisionBit) const
{
MOZ_ASSERT(isLiveHash(keyHash));
MOZ_ASSERT(!(keyHash & sCollisionBit));
@@ -1257,12 +1263,13 @@ class HashTable : private AllocPolicy
// Save the first removed entry pointer so we can recycle later.
Entry* firstRemoved = nullptr;
while(true) {
while (true) {
if (MOZ_UNLIKELY(entry->isRemoved())) {
if (!firstRemoved)
firstRemoved = entry;
} else {
entry->setCollision(collisionBit);
if (collisionBit == sCollisionBit)
entry->setCollision();
}
METER(stats.steps++);
@@ -1308,7 +1315,7 @@ class HashTable : private AllocPolicy
// Collision: double hash.
DoubleHash dh = hash2(keyHash);
while(true) {
while (true) {
MOZ_ASSERT(!entry->isRemoved());
entry->setCollision();
+29 -16
View File
@@ -96,6 +96,10 @@ const char js_with_str[] = "with";
// which create a small number of atoms.
static const uint32_t JS_STRING_HASH_COUNT = 64;
AtomSet::Ptr js::FrozenAtomSet::readonlyThreadsafeLookup(const AtomSet::Lookup &l) const {
return mSet->readonlyThreadsafeLookup(l);
}
struct CommonNameInfo
{
const char* str;
@@ -109,6 +113,9 @@ JSRuntime::initializeAtoms(JSContext* cx)
if (!atoms_ || !atoms_->init(JS_STRING_HASH_COUNT))
return false;
// |permanentAtoms| hasn't been created yet.
MOZ_ASSERT(!permanentAtoms);
if (parentRuntime) {
staticStrings = parentRuntime->staticStrings;
commonNames = parentRuntime->commonNames;
@@ -118,10 +125,6 @@ JSRuntime::initializeAtoms(JSContext* cx)
return true;
}
permanentAtoms = cx->new_<AtomSet>();
if (!permanentAtoms || !permanentAtoms->init(JS_STRING_HASH_COUNT))
return false;
staticStrings = cx->new_<StaticStrings>();
if (!staticStrings || !staticStrings->init(cx))
return false;
@@ -220,8 +223,8 @@ js::MarkPermanentAtoms(JSTracer* trc)
rt->staticStrings->trace(trc);
if (rt->permanentAtoms) {
for (AtomSet::Enum e(*rt->permanentAtoms); !e.empty(); e.popFront()) {
const AtomStateEntry& entry = e.front();
for (FrozenAtomSet::Range r(rt->permanentAtoms->all()); !r.empty(); r.popFront()) {
const AtomStateEntry &entry = r.front();
JSAtom* atom = entry.asPtr();
MarkPermanentAtom(trc, atom, "permanent_table");
@@ -263,21 +266,22 @@ JSRuntime::sweepAtoms()
}
bool
JSRuntime::transformToPermanentAtoms()
JSRuntime::transformToPermanentAtoms(JSContext *cx)
{
MOZ_ASSERT(!parentRuntime);
// All static strings were created as permanent atoms, now move the contents
// of the atoms table into permanentAtoms and mark each as permanent.
MOZ_ASSERT(permanentAtoms && permanentAtoms->empty());
MOZ_ASSERT(!permanentAtoms);
permanentAtoms = cx->new_<FrozenAtomSet>(atoms_); // takes ownership of atoms_
AtomSet* temp = atoms_;
atoms_ = permanentAtoms;
permanentAtoms = temp;
atoms_ = cx->new_<AtomSet>();
if (!atoms_ || !atoms_->init(JS_STRING_HASH_COUNT))
return false;
for (AtomSet::Enum e(*permanentAtoms); !e.empty(); e.popFront()) {
AtomStateEntry entry = e.front();
for (FrozenAtomSet::Range r(permanentAtoms->all()); !r.empty(); r.popFront()) {
AtomStateEntry entry = r.front();
JSAtom* atom = entry.asPtr();
atom->morphIntoPermanentAtom();
}
@@ -295,6 +299,7 @@ AtomIsInterned(JSContext* cx, JSAtom* atom)
AtomHasher::Lookup lookup(atom);
/* Likewise, permanent strings are considered to be interned. */
MOZ_ASSERT(cx->isPermanentAtomsInitialized());
AtomSet::Ptr p = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
if (p)
return true;
@@ -319,9 +324,16 @@ AtomizeAndCopyChars(ExclusiveContext* cx, const CharT* tbchars, size_t length, I
AtomHasher::Lookup lookup(tbchars, length);
AtomSet::Ptr pp = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
if (pp)
return pp->asPtr();
// Note: when this function is called while the permanent atoms table is
// being initialized (in initializeAtoms()), |permanentAtoms| is not yet
// initialized so this lookup is always skipped. Only once
// transformToPermanentAtoms() is called does |permanentAtoms| get
// initialized and then this lookup will go ahead.
if (cx->isPermanentAtomsInitialized()) {
AtomSet::Ptr pp = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
if (pp)
return pp->asPtr();
}
AutoLockForExclusiveAccess lock(cx);
@@ -376,6 +388,7 @@ js::AtomizeString(ExclusiveContext* cx, JSString* str,
AtomHasher::Lookup lookup(&atom);
/* Likewise, permanent atoms are always interned. */
MOZ_ASSERT(cx->isPermanentAtomsInitialized());
AtomSet::Ptr p = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
if (p)
return &atom;
+24
View File
@@ -117,6 +117,30 @@ struct AtomHasher
typedef HashSet<AtomStateEntry, AtomHasher, SystemAllocPolicy> AtomSet;
// This class is a wrapper for AtomSet that is used to ensure the AtomSet is
// not modified. It should only expose read-only methods from AtomSet.
// Note however that the atoms within the table can be marked during GC.
class FrozenAtomSet
{
AtomSet *mSet;
public:
// This constructor takes ownership of the passed-in AtomSet.
explicit FrozenAtomSet(AtomSet *set) { mSet = set; }
~FrozenAtomSet() { js_delete(mSet); }
AtomSet::Ptr readonlyThreadsafeLookup(const AtomSet::Lookup &l) const;
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
return mSet->sizeOfIncludingThis(mallocSizeOf);
}
typedef AtomSet::Range Range;
AtomSet::Range all() const { return mSet->all(); }
};
class PropertyName;
} /* namespace js */
+1 -1
View File
@@ -126,7 +126,7 @@ js::NewContext(JSRuntime* rt, size_t stackChunkSize)
ok = rt->initSelfHosting(cx);
if (ok && !rt->parentRuntime)
ok = rt->transformToPermanentAtoms();
ok = rt->transformToPermanentAtoms(cx);
JS_EndRequest(cx);

Some files were not shown because too many files have changed in this diff Show More