merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-01-15 11:46:47 +01:00
commit a1d46b7914
324 changed files with 5320 additions and 2547 deletions

View File

@ -34,6 +34,7 @@
#include "nsITreeBoxObject.h"
#include "nsITreeColumns.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/HTMLLabelElement.h"
using namespace mozilla;
@ -41,6 +42,16 @@ using namespace mozilla;
// nsCoreUtils
////////////////////////////////////////////////////////////////////////////////
bool
nsCoreUtils::IsLabelWithControl(nsIContent* aContent)
{
dom::HTMLLabelElement* label = dom::HTMLLabelElement::FromContent(aContent);
if (label && label->GetControl())
return true;
return false;
}
bool
nsCoreUtils::HasClickListener(nsIContent *aContent)
{

View File

@ -28,6 +28,11 @@ class nsIWidget;
class nsCoreUtils
{
public:
/**
* Return true if the given node is a label of a control.
*/
static bool IsLabelWithControl(nsIContent *aContent);
/**
* Return true if the given node has registered click, mousedown or mouseup
* event listeners.

View File

@ -115,13 +115,14 @@ LinkableAccessible::Value(nsString& aValue)
uint8_t
LinkableAccessible::ActionCount()
{
bool isLink, isOnclick;
ActionWalk(&isLink, &isOnclick);
return (isLink || isOnclick) ? 1 : 0;
bool isLink, isOnclick, isLabelWithControl;
ActionWalk(&isLink, &isOnclick, &isLabelWithControl);
return (isLink || isOnclick || isLabelWithControl) ? 1 : 0;
}
Accessible*
LinkableAccessible::ActionWalk(bool* aIsLink, bool* aIsOnclick)
LinkableAccessible::ActionWalk(bool* aIsLink, bool* aIsOnclick,
bool* aIsLabelWithControl)
{
if (aIsOnclick) {
*aIsOnclick = false;
@ -129,6 +130,9 @@ LinkableAccessible::ActionWalk(bool* aIsLink, bool* aIsOnclick)
if (aIsLink) {
*aIsLink = false;
}
if (aIsLabelWithControl) {
*aIsLabelWithControl = false;
}
if (nsCoreUtils::HasClickListener(mContent)) {
if (aIsOnclick) {
@ -155,6 +159,13 @@ LinkableAccessible::ActionWalk(bool* aIsLink, bool* aIsOnclick)
}
return walkUpAcc;
}
if (nsCoreUtils::IsLabelWithControl(walkUpAcc->GetContent())) {
if (aIsLabelWithControl) {
*aIsLabelWithControl = true;
}
return walkUpAcc;
}
}
return nullptr;
}
@ -166,11 +177,11 @@ LinkableAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName)
// Action 0 (default action): Jump to link
if (aIndex == eAction_Jump) {
bool isOnclick, isLink;
ActionWalk(&isLink, &isOnclick);
bool isOnclick, isLink, isLabelWithControl;
ActionWalk(&isLink, &isOnclick, &isLabelWithControl);
if (isLink) {
aName.AssignLiteral("jump");
} else if (isOnclick) {
} else if (isOnclick || isLabelWithControl) {
aName.AssignLiteral("click");
}
}

View File

@ -76,7 +76,8 @@ public:
// ActionAccessible helpers
Accessible* ActionWalk(bool* aIsLink = nullptr,
bool* aIsOnclick = nullptr);
bool* aIsOnclick = nullptr,
bool* aIsLabelWithControl = nullptr);
// HyperLinkAccessible
virtual already_AddRefed<nsIURI> AnchorURIAt(uint32_t aAnchorIndex) override;

View File

@ -75,6 +75,32 @@ HTMLLabelAccessible::RelationByType(RelationType aType)
return rel;
}
uint8_t
HTMLLabelAccessible::ActionCount()
{
return nsCoreUtils::IsLabelWithControl(mContent) ? 1 : 0;
}
void
HTMLLabelAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName)
{
if (aIndex == 0) {
if (nsCoreUtils::IsLabelWithControl(mContent))
aName.AssignLiteral("click");
}
}
bool
HTMLLabelAccessible::DoAction(uint8_t aIndex)
{
if (aIndex != 0)
return false;
DoCommand();
return true;
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLOuputAccessible
////////////////////////////////////////////////////////////////////////////////

View File

@ -62,6 +62,11 @@ public:
// Accessible
virtual Relation RelationByType(RelationType aType) override;
// ActionAccessible
virtual uint8_t ActionCount() override;
virtual void ActionNameAt(uint8_t aIndex, nsAString& aName) override;
virtual bool DoAction(uint8_t aIndex) override;
protected:
virtual ~HTMLLabelAccessible() {}
virtual ENameValueFlag NativeName(nsString& aName) override;

View File

@ -39,11 +39,19 @@
ID: "onclick_img",
actionName: "click",
events: CLICK_EVENTS
},
{
ID: "label1",
actionName: "click",
events: CLICK_EVENTS
}
];
testActions(actionsArray);
is(getAccessible("label1").firstChild.actionCount, 1, "label text should have 1 action");
getAccessible("onclick_img").takeFocus();
is(getAccessible("link1").actionCount, 1, "links should have one action");
is(getAccessible("link2").actionCount, 1, "link with onclick handler should have 1 action");
@ -87,5 +95,13 @@
<a id="link1" href="www">linkable textleaf accessible</a>
<div id="link2" onclick="">linkable textleaf accessible</div>
<div>
<label for="TextBox_t2" id="label1">
<span>Explicit</span>
</label>
<input name="in2" id="TextBox_t2" type="text" maxlength="17">
</div>
</body>
</html>

View File

@ -60,6 +60,11 @@
actionName: "press",
events: CLICK_EVENTS
},
{
ID: "name_entry_label",
actionName: "click",
events: CLICK_EVENTS
},
{
ID: "labelWithPopup",
actionName: "click",
@ -72,6 +77,8 @@
}*/
];
is(getAccessible("name_entry_label").firstChild.actionCount, 1, "label text should have 1 action");
testActions(actionsArray);
}
@ -125,6 +132,10 @@
<label id="labelWithPopup" value="file name"
popup="fileContext"
tabindex="0"/>
<hbox>
<label id="name_entry_label" value="Name" control="name_entry"/>
<textbox id="name_entry"/>
</hbox>
</vbox>
</hbox>
</window>

View File

@ -252,7 +252,9 @@ ReserveFileDescriptors(FdArray& aReservedFds)
MOZ_CRASH("ProcLoader error: failed to reserve a magic file descriptor.");
}
aReservedFds.append(target);
if (!aReservedFds.append(target)) {
MOZ_CRASH("Failed to append to aReservedFds");
}
if (fd == target) {
// No need to call dup2(). We already occupy the desired file descriptor.

View File

@ -10,6 +10,7 @@ var Cc = Components.classes;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/NotificationDB.jsm");
Cu.import("resource:///modules/RecentWindow.jsm");
Cu.import("resource:///modules/UserContextUI.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
@ -4059,24 +4060,7 @@ function updateUserContextUIIndicator(browser)
let label = document.getElementById("userContext-label");
let userContextId = browser.getAttribute("usercontextid");
hbox.setAttribute("usercontextid", userContextId);
switch (userContextId) {
case "1":
label.value = gBrowserBundle.GetStringFromName("usercontext.personal.label");
break;
case "2":
label.value = gBrowserBundle.GetStringFromName("usercontext.work.label");
break;
case "3":
label.value = gBrowserBundle.GetStringFromName("usercontext.banking.label");
break;
case "4":
label.value = gBrowserBundle.GetStringFromName("usercontext.shopping.label");
break;
// Display the context IDs for values outside the pre-defined range.
// Used for debugging, no localization necessary.
default:
label.value = "Context " + userContextId;
}
label.value = UserContextUI.getUserContextLabel(userContextId);
}
/**

View File

@ -758,7 +758,7 @@
if (this.mBrowser.userTypedClear > 0 ||
((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) &&
aLocation.spec != "about:blank") ||
aFlags && Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) {
aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) {
this.mBrowser.userTypedValue = null;
}

View File

@ -417,7 +417,7 @@ skip-if = os == "linux" || os == "mac" # No tabs in titlebar on linux
# Disabled on OS X because of bug 967917
[browser_tabfocus.js]
[browser_tabkeynavigation.js]
skip-if = e10s
skip-if = (os == "mac" && !e10s)
[browser_tabopen_reflows.js]
[browser_tabs_close_beforeunload.js]
support-files =

View File

@ -42,23 +42,19 @@ function test() {
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated");
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true },
browser1.contentWindow);
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true });
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+Tab on Tab1");
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true },
browser2.contentWindow);
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true });
is(gBrowser.selectedTab, tab3,
"Tab3 should be activated by pressing Ctrl+Tab on Tab2");
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true },
browser3.contentWindow);
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true });
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+Shift+Tab on Tab3");
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true },
browser2.contentWindow);
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true });
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated by pressing Ctrl+Shift+Tab on Tab2");
@ -67,23 +63,19 @@ function test() {
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated");
EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true },
browser1.contentWindow);
EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true });
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+PageDown on Tab1");
EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true },
browser2.contentWindow);
EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true });
is(gBrowser.selectedTab, tab3,
"Tab3 should be activated by pressing Ctrl+PageDown on Tab2");
EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true },
browser3.contentWindow);
EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true });
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+PageUp on Tab3");
EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true },
browser2.contentWindow);
EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true });
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated by pressing Ctrl+PageUp on Tab2");
@ -98,23 +90,19 @@ function test() {
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated");
EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true },
browser1.contentWindow);
EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true });
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+" + advanceKey + " on Tab1");
EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true },
browser2.contentWindow);
EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true });
is(gBrowser.selectedTab, tab3,
"Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2");
EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true },
browser3.contentWindow);
EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true });
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3");
EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true },
browser2.contentWindow);
EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true });
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2");
}
@ -125,15 +113,13 @@ function test() {
is(gBrowser.tabContainer.selectedIndex, 2,
"Tab2 index should be 2");
EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true, shiftKey: true },
browser2.contentWindow);
EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true, shiftKey: true });
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated after Ctrl+Shift+PageDown");
is(gBrowser.tabContainer.selectedIndex, 3,
"Tab2 index should be 1 after Ctrl+Shift+PageDown");
EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true, shiftKey: true },
browser2.contentWindow);
EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true, shiftKey: true });
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated after Ctrl+Shift+PageUp");
is(gBrowser.tabContainer.selectedIndex, 2,
@ -153,45 +139,38 @@ function test() {
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated");
EventUtils.synthesizeKey(advanceKey, { metaKey: true },
browser1.contentWindow);
EventUtils.synthesizeKey(advanceKey, { metaKey: true });
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+" + advanceKey + " on Tab1");
EventUtils.synthesizeKey(advanceKey, { metaKey: true },
browser2.contentWindow);
todo_is(gBrowser.selectedTab, tab3,
"Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2");
EventUtils.synthesizeKey(advanceKey, { metaKey: true });
is(gBrowser.selectedTab, tab3,
"Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2");
if (gBrowser.selectedTab != tab3) {
EventUtils.synthesizeKey(reverseKey, { metaKey: true },
browser3.contentWindow);
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3");
}
EventUtils.synthesizeKey(reverseKey, { metaKey: true });
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3");
EventUtils.synthesizeKey(reverseKey, { metaKey: true },
browser2.contentWindow);
todo_is(gBrowser.selectedTab, tab1,
"Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2");
EventUtils.synthesizeKey(reverseKey, { metaKey: true });
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2");
} else {
gBrowser.selectedTab = tab2;
EventUtils.synthesizeKey("VK_F4", { type: "keydown", ctrlKey: true },
browser2.contentWindow);
EventUtils.synthesizeKey("VK_F4", { type: "keydown", ctrlKey: true });
isnot(gBrowser.selectedTab, tab2,
"Tab2 should be closed by pressing Ctrl+F4 on Tab2");
is(gBrowser.tabs.length, 3,
"The count of tabs should be 3 since tab2 should be closed");
"The count of tabs should be 3 since tab2 should be closed");
let activeWindow =
gBrowser.getBrowserForTab(gBrowser.selectedTab).contentWindow;
// NOTE: keypress event shouldn't be fired since the keydown event should
// be consumed by tab2.
EventUtils.synthesizeKey("VK_F4", { type: "keyup", ctrlKey: true },
activeWindow);
is(gBrowser.tabs.length, 3,
"The count of tabs should be 3 since renaming key events shouldn't close other tabs");
EventUtils.synthesizeKey("VK_F4", { type: "keyup", ctrlKey: true });
is(gBrowser.tabs.length, 3,
"The count of tabs should be 3 since renaming key events shouldn't close other tabs");
}
gBrowser.selectedTab = tab3;

View File

@ -15,30 +15,22 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
"@mozilla.org/browser/aboutnewtab-service;1",
"nsIAboutNewTabService");
XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
"resource://gre/modules/Deprecated.jsm");
const DepecationURL = "https://bugzilla.mozilla.org/show_bug.cgi?id=1204983#c89";
this.NewTabURL = {
get: function() {
Deprecated.warning("NewTabURL.get is deprecated, please query aboutNewTabService.newTabURL", DepecationURL);
return aboutNewTabService.newTabURL;
},
get overridden() {
Deprecated.warning("NewTabURL.overridden is deprecated, please query aboutNewTabService.overridden", DepecationURL);
return aboutNewTabService.overridden;
},
override: function(newURL) {
Deprecated.warning("NewTabURL.override is deprecated, please set aboutNewTabService.newTabURL", DepecationURL);
aboutNewTabService.newTabURL = newURL;
},
reset: function() {
Deprecated.warning("NewTabURL.reset is deprecated, please use aboutNewTabService.resetNewTabURL()", DepecationURL);
aboutNewTabService.resetNewTabURL();
}
};

View File

@ -2974,9 +2974,6 @@ var DefaultBrowserCheck = {
#ifdef E10S_TESTING_ONLY
var E10SUINotification = {
// Increase this number each time we want to roll out an
// e10s testing period to Nightly users.
CURRENT_NOTICE_COUNT: 4,
CURRENT_PROMPT_PREF: "browser.displayedE10SPrompt.1",
PREVIOUS_PROMPT_PREF: "browser.displayedE10SPrompt",
@ -3007,20 +3004,7 @@ var E10SUINotification = {
return;
}
if (Services.appinfo.browserTabsRemoteAutostart) {
if (this.forcedOn) {
return;
}
let notice = 0;
try {
notice = Services.prefs.getIntPref("browser.displayedE10SNotice");
} catch(e) {}
let activationNoticeShown = notice >= this.CURRENT_NOTICE_COUNT;
if (!activationNoticeShown) {
this._showE10sActivatedNotice();
}
} else {
if (!Services.appinfo.browserTabsRemoteAutostart) {
let displayFeedbackRequest = false;
try {
displayFeedbackRequest = Services.prefs.getBoolPref("browser.requestE10sFeedback");
@ -3032,10 +3016,6 @@ var E10SUINotification = {
return;
}
// The user has just voluntarily disabled e10s. Subtract one from displayedE10SNotice
// so that the next time e10s is activated (either by the user or forced by us), they
// can see the notice again.
Services.prefs.setIntPref("browser.displayedE10SNotice", this.CURRENT_NOTICE_COUNT - 1);
Services.prefs.clearUserPref("browser.requestE10sFeedback");
let url = Services.urlFormatter.formatURLPref("app.feedback.baseURL");
@ -3084,32 +3064,6 @@ var E10SUINotification = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
_showE10sActivatedNotice: function() {
let win = RecentWindow.getMostRecentBrowserWindow();
if (!win)
return;
Services.prefs.setIntPref("browser.displayedE10SNotice", this.CURRENT_NOTICE_COUNT);
let nb = win.document.getElementById("high-priority-global-notificationbox");
let message = win.gNavigatorBundle.getFormattedString(
"e10s.postActivationInfobar.message",
[gBrandBundle.GetStringFromName("brandShortName")]
);
let buttons = [
{
label: win.gNavigatorBundle.getString("e10s.postActivationInfobar.learnMore.label"),
accessKey: win.gNavigatorBundle.getString("e10s.postActivationInfobar.learnMore.accesskey"),
callback: function () {
win.openUILinkIn("https://wiki.mozilla.org/Electrolysis", "tab");
}
}
];
nb.appendNotification(message, "e10s-activated-noticed",
null, nb.PRIORITY_WARNING_MEDIUM, buttons);
},
_showE10SPrompt: function BG__showE10SPrompt() {
let win = RecentWindow.getMostRecentBrowserWindow();
if (!win)

View File

@ -6,6 +6,8 @@
const nsICookie = Components.interfaces.nsICookie;
Components.utils.import("resource://gre/modules/PluralForm.jsm");
Components.utils.import("resource://gre/modules/Services.jsm")
Components.utils.import("resource:///modules/UserContextUI.jsm");
var gCookiesWindow = {
_cm : Components.classes["@mozilla.org/cookiemanager;1"]
@ -29,6 +31,10 @@ var gCookiesWindow = {
this._populateList(true);
document.getElementById("filter").focus();
if (!Services.prefs.getBoolPref("privacy.userContext.enabled")) {
document.getElementById("userContextRow").hidden = true;
}
},
uninit: function () {
@ -453,16 +459,17 @@ var gCookiesWindow = {
_makeCookieObject: function (aStrippedHost, aCookie) {
var host = aCookie.host;
var formattedHost = host.charAt(0) == "." ? host.substring(1, host.length) : host;
var c = { name : aCookie.name,
value : aCookie.value,
isDomain : aCookie.isDomain,
host : aCookie.host,
rawHost : aStrippedHost,
path : aCookie.path,
isSecure : aCookie.isSecure,
expires : aCookie.expires,
level : 1,
container : false };
var c = { name : aCookie.name,
value : aCookie.value,
isDomain : aCookie.isDomain,
host : aCookie.host,
rawHost : aStrippedHost,
path : aCookie.path,
isSecure : aCookie.isSecure,
expires : aCookie.expires,
level : 1,
container : false,
originAttributes: aCookie.originAttributes };
return c;
},
@ -500,7 +507,7 @@ var gCookiesWindow = {
_updateCookieData: function (aItem) {
var seln = this._view.selection;
var ids = ["name", "value", "host", "path", "isSecure", "expires"];
var ids = ["name", "value", "host", "path", "isSecure", "expires", "userContext"];
var properties;
if (aItem && !aItem.container && seln.count > 0) {
@ -509,17 +516,20 @@ var gCookiesWindow = {
isDomain: aItem.isDomain ? this._bundle.getString("domainColon")
: this._bundle.getString("hostColon"),
isSecure: aItem.isSecure ? this._bundle.getString("forSecureOnly")
: this._bundle.getString("forAnyConnection") };
for (var i = 0; i < ids.length; ++i)
: this._bundle.getString("forAnyConnection"),
userContext: UserContextUI.getUserContextLabel(aItem.originAttributes.userContextId) };
for (var i = 0; i < ids.length; ++i) {
document.getElementById(ids[i]).disabled = false;
}
}
else {
var noneSelected = this._bundle.getString("noCookieSelected");
properties = { name: noneSelected, value: noneSelected, host: noneSelected,
path: noneSelected, expires: noneSelected,
isSecure: noneSelected };
for (i = 0; i < ids.length; ++i)
isSecure: noneSelected, userContext: noneSelected };
for (i = 0; i < ids.length; ++i) {
document.getElementById(ids[i]).disabled = true;
}
}
for (var property in properties)
document.getElementById(property).value = properties[property];

View File

@ -85,6 +85,10 @@
<hbox pack="end"><label id="expiresLabel" control="expires" value="&props.expires.label;"/></hbox>
<textbox id="expires" readonly="true" class="plain"/>
</row>
<row align="center" id="userContextRow">
<hbox pack="end"><label id="userContextLabel" control="userContext" value="&props.container.label;"/></hbox>
<textbox id="userContext" readonly="true" class="plain"/>
</row>
</rows>
</grid>
</hbox>

View File

@ -746,9 +746,6 @@ appMenuRemoteTabs.mobilePromo.ios = Firefox for iOS
# e10s.offerPopup.enableAndRestart.accesskey
# e10s.offerPopup.noThanks.label
# e10s.offerPopup.noThanks.accesskey
# e10s.postActivationInfobar.message
# e10s.postActivationInfobar.learnMore.label
# e10s.postActivationInfobar.learnMore.accesskey
# e10s.accessibilityNotice.mainMessage
# e10s.accessibilityNotice.enableAndRestart.label
# e10s.accessibilityNotice.enableAndRestart.accesskey
@ -763,9 +760,6 @@ e10s.offerPopup.enableAndRestart.label = Enable and Restart
e10s.offerPopup.enableAndRestart.accesskey = E
e10s.offerPopup.noThanks.label = No, thanks
e10s.offerPopup.noThanks.accesskey = N
e10s.postActivationInfobar.message = You're now helping to test multi-process in %S! Please report problems you find.
e10s.postActivationInfobar.learnMore.label = Learn More
e10s.postActivationInfobar.learnMore.accesskey = L
e10s.accessibilityNotice.mainMessage2 = Accessibility support is partially disabled due to compatibility issues with new %S features.
e10s.accessibilityNotice.acceptButton.label = OK
e10s.accessibilityNotice.acceptButton.accesskey = O

View File

@ -21,6 +21,7 @@
<!ENTITY props.path.label "Path:">
<!ENTITY props.secure.label "Send For:">
<!ENTITY props.expires.label "Expires:">
<!ENTITY props.container.label "Container:">
<!ENTITY window.title "Cookies">
<!ENTITY windowClose.key "w">

View File

@ -0,0 +1,32 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
this.EXPORTED_SYMBOLS = ["UserContextUI"];
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm")
XPCOMUtils.defineLazyGetter(this, "gBrowserBundle", function() {
return Services.strings.createBundle("chrome://browser/locale/browser.properties");
});
this.UserContextUI = {
getUserContextLabel(userContextId) {
switch (userContextId) {
// No UserContext:
case 0: return "";
case 1: return gBrowserBundle.GetStringFromName("usercontext.personal.label");
case 2: return gBrowserBundle.GetStringFromName("usercontext.work.label");
case 3: return gBrowserBundle.GetStringFromName("usercontext.shopping.label");
case 4: return gBrowserBundle.GetStringFromName("usercontext.banking.label");
// Display the context IDs for values outside the pre-defined range.
// Used for debugging, no localization necessary.
default: return "Context " + userContextId;
}
}
}

View File

@ -43,6 +43,7 @@ EXTRA_JS_MODULES += [
'Social.jsm',
'TabGroupsMigrator.jsm',
'TransientPrefs.jsm',
'UserContextUI.jsm',
'WebappManager.jsm',
'webrtcUI.jsm',
]

View File

@ -364,13 +364,25 @@ BasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
}
NS_IMETHODIMP
BasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
BasePrincipal::EnsureCSP(nsIDOMDocument* aDocument,
nsIContentSecurityPolicy** aCSP)
{
if (mCSP) {
return NS_ERROR_ALREADY_INITIALIZED;
// if there is a CSP already associated with this principal
// then just return that - do not overwrite it!!!
NS_IF_ADDREF(*aCSP = mCSP);
return NS_OK;
}
mCSP = aCsp;
nsresult rv = NS_OK;
mCSP = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Store the request context for violation reports
rv = aDocument ? mCSP->SetRequestContext(aDocument, nullptr)
: mCSP->SetRequestContext(nullptr, this);
NS_ENSURE_SUCCESS(rv, rv);
NS_IF_ADDREF(*aCSP = mCSP);
return NS_OK;
}
@ -382,12 +394,25 @@ BasePrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP)
}
NS_IMETHODIMP
BasePrincipal::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP)
BasePrincipal::EnsurePreloadCSP(nsIDOMDocument* aDocument,
nsIContentSecurityPolicy** aPreloadCSP)
{
if (mPreloadCSP) {
return NS_ERROR_ALREADY_INITIALIZED;
// if there is a speculative CSP already associated with this principal
// then just return that - do not overwrite it!!!
NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
return NS_OK;
}
mPreloadCSP = aPreloadCSP;
nsresult rv = NS_OK;
mPreloadCSP = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Store the request context for violation reports
rv = aDocument ? mPreloadCSP->SetRequestContext(aDocument, nullptr)
: mPreloadCSP->SetRequestContext(nullptr, this);
NS_ENSURE_SUCCESS(rv, rv);
NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
return NS_OK;
}

View File

@ -202,9 +202,9 @@ public:
NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval) final;
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) final;
NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
NS_IMETHOD EnsureCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
NS_IMETHOD SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP) override;
NS_IMETHOD EnsurePreloadCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
NS_IMETHOD GetCspJSON(nsAString& outCSPinJSON) override;
NS_IMETHOD GetIsNullPrincipal(bool* aResult) override;
NS_IMETHOD GetIsCodebasePrincipal(bool* aResult) override;

View File

@ -15,12 +15,13 @@ struct JSPrincipals;
interface nsIURI;
interface nsIContentSecurityPolicy;
interface nsIDOMDocument;
[ptr] native JSContext(JSContext);
[ptr] native JSPrincipals(JSPrincipals);
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
[scriptable, builtinclass, uuid(188fc4a2-3157-4956-a7a2-d674991770da)]
[scriptable, builtinclass, uuid(d0391e86-1ad7-4ab0-bb7c-14d6d9967369)]
interface nsIPrincipal : nsISerializable
{
/**
@ -133,12 +134,19 @@ interface nsIPrincipal : nsISerializable
/**
* A Content Security Policy associated with this principal.
*
* Please note that if a csp was already set on the
* principal, then it should not be destroyed! Instead, the
* current csp should be quried and extended by
* calling AppendPolicy() on it.
* Use this function to query the associated CSP with this principal.
*/
[noscript] attribute nsIContentSecurityPolicy csp;
[noscript] readonly attribute nsIContentSecurityPolicy csp;
/*
* Use this function to query a CSP associated with this principal.
* If no CSP is associated with this principal then one is created
* internally and setRequestContext is called on the CSP using aDocument.
*
* Please note if aDocument is null, then setRequestContext on the
* CSP object is called using the current principal.
*/
[noscript] nsIContentSecurityPolicy ensureCSP(in nsIDOMDocument aDocument);
/**
* A speculative Content Security Policy associated with this
@ -147,13 +155,19 @@ interface nsIPrincipal : nsISerializable
*
* If you want to query the CSP associated with that principal,
* then this is *not* what you want. Instead query 'csp'.
*
* Please note that if a preloadCSP was already set on the
* principal, then it should not be destroyed! Instead, the
* current preloadCSP should be quried and extended by
* calling AppendPolicy() on it.
*/
[noscript] attribute nsIContentSecurityPolicy preloadCsp;
[noscript] readonly attribute nsIContentSecurityPolicy preloadCsp;
/*
* Use this function to query a speculative CSP associated with this
* principal. If no speculative CSP is associated with this principal
* then one is created internally and setRequestContext is called on
* the CSP using aDocument.
*
* Please note if aDocument is null, then setRequestContext on the
* speculative CSP object is called using the current principal.
*/
[noscript] nsIContentSecurityPolicy ensurePreloadCSP(in nsIDOMDocument aDocument);
/**
* The CSP of the principal in JSON notation.

View File

@ -398,19 +398,14 @@ nsPrincipal::Read(nsIObjectInputStream* aStream)
rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports));
NS_ENSURE_SUCCESS(rv, rv);
// This may be null.
nsCOMPtr<nsIContentSecurityPolicy> csp = do_QueryInterface(supports, &rv);
rv = Init(codebase, attrs);
NS_ENSURE_SUCCESS(rv, rv);
rv = SetCsp(csp);
NS_ENSURE_SUCCESS(rv, rv);
// need to link in the CSP context here (link in the URI of the protected
// resource).
if (csp) {
csp->SetRequestContext(nullptr, this);
mCSP = do_QueryInterface(supports, &rv);
// make sure setRequestContext is called after Init(),
// to make sure the principals URI been initalized.
if (mCSP) {
mCSP->SetRequestContext(nullptr, this);
}
SetDomain(domain);

View File

@ -70,7 +70,8 @@ nsSystemPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
}
NS_IMETHODIMP
nsSystemPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
nsSystemPrincipal::EnsureCSP(nsIDOMDocument* aDocument,
nsIContentSecurityPolicy** aCSP)
{
// CSP on a system principal makes no sense
return NS_OK;
@ -84,7 +85,8 @@ nsSystemPrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP)
}
NS_IMETHODIMP
nsSystemPrincipal::SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP)
nsSystemPrincipal::EnsurePreloadCSP(nsIDOMDocument* aDocument,
nsIContentSecurityPolicy** aPreloadCSP)
{
// CSP on a system principal makes no sense
return NS_OK;

View File

@ -30,9 +30,9 @@ public:
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
NS_IMETHOD EnsureCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
NS_IMETHOD SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP) override;
NS_IMETHOD EnsurePreloadCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
nsresult GetOriginInternal(nsACString& aOrigin) override;

View File

@ -1187,7 +1187,7 @@ Animation::EffectEnd() const
return StickyTimeDuration(0);
}
return mEffect->Timing().mDelay
return mEffect->SpecifiedTiming().mDelay
+ mEffect->GetComputedTiming().mActiveDuration;
}

View File

@ -14,6 +14,7 @@
namespace mozilla {
namespace dom {
class AnimationEffectTimingReadOnly;
struct ComputedTimingProperties;
class AnimationEffectReadOnly : public nsISupports,
@ -30,9 +31,9 @@ public:
nsISupports* GetParentObject() const { return mParent; }
virtual void GetComputedTimingAsDict(ComputedTimingProperties& aRetVal) const
{
}
virtual already_AddRefed<AnimationEffectTimingReadOnly> Timing() const = 0;
virtual void GetComputedTimingAsDict(ComputedTimingProperties& aRetVal) const = 0;
protected:
virtual ~AnimationEffectReadOnly() = default;

View File

@ -0,0 +1,59 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "mozilla/dom/AnimationEffectTimingReadOnly.h"
#include "mozilla/dom/AnimationEffectTimingReadOnlyBinding.h"
namespace mozilla {
TimingParams&
TimingParams::operator=(const dom::AnimationEffectTimingProperties& aRhs)
{
mDuration = aRhs.mDuration;
mDelay = TimeDuration::FromMilliseconds(aRhs.mDelay);
mIterations = aRhs.mIterations;
mDirection = aRhs.mDirection;
mFill = aRhs.mFill;
return *this;
}
bool
TimingParams::operator==(const TimingParams& aOther) const
{
bool durationEqual;
if (mDuration.IsUnrestrictedDouble()) {
durationEqual = aOther.mDuration.IsUnrestrictedDouble() &&
(mDuration.GetAsUnrestrictedDouble() ==
aOther.mDuration.GetAsUnrestrictedDouble());
} else {
// We consider all string values and uninitialized values as meaning "auto".
// Since mDuration is either a string or uninitialized, we consider it equal
// if aOther.mDuration is also either a string or uninitialized.
durationEqual = !aOther.mDuration.IsUnrestrictedDouble();
}
return durationEqual &&
mDelay == aOther.mDelay &&
mIterations == aOther.mIterations &&
mDirection == aOther.mDirection &&
mFill == aOther.mFill;
}
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationEffectTimingReadOnly, mParent)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AnimationEffectTimingReadOnly, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AnimationEffectTimingReadOnly, Release)
JSObject*
AnimationEffectTimingReadOnly::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return AnimationEffectTimingReadOnlyBinding::Wrap(aCx, this, aGivenProto);
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,89 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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_dom_AnimationEffectTimingReadOnly_h
#define mozilla_dom_AnimationEffectTimingReadOnly_h
#include "js/TypeDecls.h"
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/UnionTypes.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
// X11 has a #define for None
#ifdef None
#undef None
#endif
#include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for FillMode
// and PlaybackDirection
namespace mozilla {
struct TimingParams
{
// The unitialized state of mDuration represents "auto".
// Bug 1237173: We will replace this with Maybe<TimeDuration>.
dom::OwningUnrestrictedDoubleOrString mDuration;
TimeDuration mDelay; // Initializes to zero
double mIterations = 1.0; // Can be NaN, negative, +/-Infinity
dom::PlaybackDirection mDirection = dom::PlaybackDirection::Normal;
dom::FillMode mFill = dom::FillMode::Auto;
TimingParams& operator=(const dom::AnimationEffectTimingProperties& aRhs);
bool operator==(const TimingParams& aOther) const;
bool operator!=(const TimingParams& aOther) const
{
return !(*this == aOther);
}
};
namespace dom {
class AnimationEffectTimingReadOnly : public nsWrapperCache
{
public:
AnimationEffectTimingReadOnly() = default;
explicit AnimationEffectTimingReadOnly(const TimingParams& aTiming)
: mTiming(aTiming) { }
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnimationEffectTimingReadOnly)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AnimationEffectTimingReadOnly)
protected:
virtual ~AnimationEffectTimingReadOnly() = default;
public:
nsISupports* GetParentObject() const { return mParent; }
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
double Delay() const { return mTiming.mDelay.ToMilliseconds(); }
double EndDelay() const { return 0.0; }
FillMode Fill() const { return mTiming.mFill; }
double IterationStart() const { return 0.0; }
double Iterations() const { return mTiming.mIterations; }
void GetDuration(OwningUnrestrictedDoubleOrString& aRetVal) const
{
aRetVal = mTiming.mDuration;
}
PlaybackDirection Direction() const { return mTiming.mDirection; }
void GetEasing(nsString& aRetVal) const { aRetVal.AssignLiteral("linear"); }
const TimingParams& AsTimingParams() const { return mTiming; }
void SetTimingParams(const TimingParams& aTiming) { mTiming = aTiming; }
protected:
nsCOMPtr<nsISupports> mParent;
TimingParams mTiming;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_AnimationEffectTimingReadOnly_h

View File

@ -50,4 +50,4 @@ private:
} // namespace mozilla
#endif // mozilla_dom_AnimationEffectReadOnly_h
#endif // mozilla_ComputedTimingFunction_h

View File

@ -6,7 +6,6 @@
#include "mozilla/dom/KeyframeEffect.h"
#include "mozilla/dom/AnimationEffectReadOnlyBinding.h"
#include "mozilla/dom/KeyframeEffectBinding.h"
#include "mozilla/dom/PropertyIndexedKeyframesBinding.h"
#include "mozilla/AnimationUtils.h"
@ -24,32 +23,19 @@
namespace mozilla {
bool
AnimationTiming::FillsForwards() const
{
return mFillMode == dom::FillMode::Both ||
mFillMode == dom::FillMode::Forwards;
}
bool
AnimationTiming::FillsBackwards() const
{
return mFillMode == dom::FillMode::Both ||
mFillMode == dom::FillMode::Backwards;
}
// Helper functions for generating a ComputedTimingProperties dictionary
static void
GetComputedTimingDictionary(const ComputedTiming& aComputedTiming,
const Nullable<TimeDuration>& aLocalTime,
const AnimationTiming& aTiming,
const TimingParams& aTiming,
dom::ComputedTimingProperties& aRetVal)
{
// AnimationEffectTimingProperties
aRetVal.mDelay = aTiming.mDelay.ToMilliseconds();
aRetVal.mFill = aTiming.mFillMode;
aRetVal.mIterations = aTiming.mIterationCount;
aRetVal.mDuration.SetAsUnrestrictedDouble() = aTiming.mIterationDuration.ToMilliseconds();
aRetVal.mFill = aComputedTiming.mFill;
aRetVal.mIterations = aComputedTiming.mIterations;
aRetVal.mDuration.SetAsUnrestrictedDouble() =
aComputedTiming.mDuration.ToMilliseconds();
aRetVal.mDirection = aTiming.mDirection;
// ComputedTimingProperties
@ -89,14 +75,15 @@ KeyframeEffectReadOnly::KeyframeEffectReadOnly(
nsIDocument* aDocument,
Element* aTarget,
nsCSSPseudoElements::Type aPseudoType,
const AnimationTiming& aTiming)
const TimingParams& aTiming)
: AnimationEffectReadOnly(aDocument)
, mTarget(aTarget)
, mTiming(aTiming)
, mPseudoType(aPseudoType)
, mInEffectOnLastAnimationTimingUpdate(false)
{
MOZ_ASSERT(aTarget, "null animation target is not yet supported");
mTiming = new AnimationEffectTimingReadOnly(aTiming);
}
JSObject*
@ -118,13 +105,20 @@ KeyframeEffectReadOnly::Composite() const
return CompositeOperation::Replace;
}
void
KeyframeEffectReadOnly::SetTiming(const AnimationTiming& aTiming)
already_AddRefed<AnimationEffectTimingReadOnly>
KeyframeEffectReadOnly::Timing() const
{
if (mTiming == aTiming) {
RefPtr<AnimationEffectTimingReadOnly> temp(mTiming);
return temp.forget();
}
void
KeyframeEffectReadOnly::SetSpecifiedTiming(const TimingParams& aTiming)
{
if (mTiming->AsTimingParams() == aTiming) {
return;
}
mTiming = aTiming;
mTiming->SetTimingParams(aTiming);
if (mAnimation) {
mAnimation->NotifyEffectTimingUpdated();
}
@ -205,31 +199,36 @@ void
KeyframeEffectReadOnly::GetComputedTimingAsDict(ComputedTimingProperties& aRetVal) const
{
const Nullable<TimeDuration> currentTime = GetLocalTime();
GetComputedTimingDictionary(GetComputedTimingAt(currentTime, mTiming),
GetComputedTimingDictionary(GetComputedTimingAt(currentTime,
SpecifiedTiming()),
currentTime,
mTiming,
SpecifiedTiming(),
aRetVal);
}
ComputedTiming
KeyframeEffectReadOnly::GetComputedTimingAt(
const Nullable<TimeDuration>& aLocalTime,
const AnimationTiming& aTiming)
const TimingParams& aTiming)
{
const TimeDuration zeroDuration;
// Currently we expect negative durations to be picked up during CSS
// parsing but when we start receiving timing parameters from other sources
// we will need to clamp negative durations here.
// For now, if we're hitting this it probably means we're overflowing
// integer arithmetic in mozilla::TimeStamp.
MOZ_ASSERT(aTiming.mIterationDuration >= zeroDuration,
"Expecting iteration duration >= 0");
const StickyTimeDuration zeroDuration;
// Always return the same object to benefit from return-value optimization.
ComputedTiming result;
result.mActiveDuration = ActiveDuration(aTiming);
if (aTiming.mDuration.IsUnrestrictedDouble()) {
double durationMs = aTiming.mDuration.GetAsUnrestrictedDouble();
if (!IsNaN(durationMs) && durationMs >= 0.0f) {
result.mDuration = StickyTimeDuration::FromMilliseconds(durationMs);
}
}
result.mIterations = IsNaN(aTiming.mIterations) || aTiming.mIterations < 0.0f ?
1.0f :
aTiming.mIterations;
result.mActiveDuration = ActiveDuration(result.mDuration, result.mIterations);
result.mFill = aTiming.mFill == dom::FillMode::Auto ?
dom::FillMode::None :
aTiming.mFill;
// The default constructor for ComputedTiming sets all other members to
// values consistent with an animation that has not been sampled.
@ -247,7 +246,7 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
StickyTimeDuration activeTime;
if (localTime >= aTiming.mDelay + result.mActiveDuration) {
result.mPhase = ComputedTiming::AnimationPhase::After;
if (!aTiming.FillsForwards()) {
if (!result.FillsForwards()) {
// The animation isn't active or filling at this time.
result.mProgress.SetNull();
return result;
@ -255,12 +254,11 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
activeTime = result.mActiveDuration;
// Note that infinity == floor(infinity) so this will also be true when we
// have finished an infinitely repeating animation of zero duration.
isEndOfFinalIteration =
aTiming.mIterationCount != 0.0 &&
aTiming.mIterationCount == floor(aTiming.mIterationCount);
isEndOfFinalIteration = result.mIterations != 0.0 &&
result.mIterations == floor(result.mIterations);
} else if (localTime < aTiming.mDelay) {
result.mPhase = ComputedTiming::AnimationPhase::Before;
if (!aTiming.FillsBackwards()) {
if (!result.FillsBackwards()) {
// The animation isn't active or filling at this time.
result.mProgress.SetNull();
return result;
@ -275,19 +273,19 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
// Get the position within the current iteration.
StickyTimeDuration iterationTime;
if (aTiming.mIterationDuration != zeroDuration) {
if (result.mDuration != zeroDuration) {
iterationTime = isEndOfFinalIteration
? StickyTimeDuration(aTiming.mIterationDuration)
: activeTime % aTiming.mIterationDuration;
? result.mDuration
: activeTime % result.mDuration;
} /* else, iterationTime is zero */
// Determine the 0-based index of the current iteration.
if (isEndOfFinalIteration) {
result.mCurrentIteration =
aTiming.mIterationCount == NS_IEEEPositiveInfinity()
IsInfinite(result.mIterations) // Positive Infinity?
? UINT64_MAX // In GetComputedTimingDictionary(), we will convert this
// into Infinity.
: static_cast<uint64_t>(aTiming.mIterationCount) - 1;
: static_cast<uint64_t>(result.mIterations) - 1;
} else if (activeTime == zeroDuration) {
// If the active time is zero we're either in the first iteration
// (including filling backwards) or we have finished an animation with an
@ -295,11 +293,11 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
// the exact end of an iteration since we deal with that above).
result.mCurrentIteration =
result.mPhase == ComputedTiming::AnimationPhase::After
? static_cast<uint64_t>(aTiming.mIterationCount) // floor
? static_cast<uint64_t>(result.mIterations) // floor
: 0;
} else {
result.mCurrentIteration =
static_cast<uint64_t>(activeTime / aTiming.mIterationDuration); // floor
static_cast<uint64_t>(activeTime / result.mDuration); // floor
}
// Normalize the iteration time into a fraction of the iteration duration.
@ -308,15 +306,15 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
} else if (result.mPhase == ComputedTiming::AnimationPhase::After) {
double progress = isEndOfFinalIteration
? 1.0
: fmod(aTiming.mIterationCount, 1.0f);
: fmod(result.mIterations, 1.0);
result.mProgress.SetValue(progress);
} else {
// We are in the active phase so the iteration duration can't be zero.
MOZ_ASSERT(aTiming.mIterationDuration != zeroDuration,
MOZ_ASSERT(result.mDuration != zeroDuration,
"In the active phase of a zero-duration animation?");
double progress = aTiming.mIterationDuration == TimeDuration::Forever()
double progress = result.mDuration == StickyTimeDuration::Forever()
? 0.0
: iterationTime / aTiming.mIterationDuration;
: iterationTime / result.mDuration;
result.mProgress.SetValue(progress);
}
@ -345,19 +343,19 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
}
StickyTimeDuration
KeyframeEffectReadOnly::ActiveDuration(const AnimationTiming& aTiming)
KeyframeEffectReadOnly::ActiveDuration(const StickyTimeDuration& aIterationDuration,
double aIterationCount)
{
if (aTiming.mIterationCount == mozilla::PositiveInfinity<float>()) {
if (IsInfinite(aIterationCount)) {
// An animation that repeats forever has an infinite active duration
// unless its iteration duration is zero, in which case it has a zero
// active duration.
const StickyTimeDuration zeroDuration;
return aTiming.mIterationDuration == zeroDuration
? zeroDuration
: StickyTimeDuration::Forever();
return aIterationDuration == zeroDuration ?
zeroDuration :
StickyTimeDuration::Forever();
}
return StickyTimeDuration(
aTiming.mIterationDuration.MultDouble(aTiming.mIterationCount));
return aIterationDuration.MultDouble(aIterationCount);
}
// https://w3c.github.io/web-animations/#in-play
@ -641,53 +639,19 @@ DumpAnimationProperties(nsTArray<AnimationProperty>& aAnimationProperties)
}
#endif
// Extract an iteration duration from an UnrestrictedDoubleOrXXX object.
template <typename T>
static TimeDuration
GetIterationDuration(const T& aDuration) {
// Always return the same object to benefit from return-value optimization.
TimeDuration result;
if (aDuration.IsUnrestrictedDouble()) {
double durationMs = aDuration.GetAsUnrestrictedDouble();
if (!IsNaN(durationMs) && durationMs >= 0.0f) {
result = TimeDuration::FromMilliseconds(durationMs);
}
}
// else, aDuration should be zero
return result;
}
/* static */ AnimationTiming
/* static */ TimingParams
KeyframeEffectReadOnly::ConvertKeyframeEffectOptions(
const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions)
{
AnimationTiming animationTiming;
TimingParams timing;
if (aOptions.IsKeyframeEffectOptions()) {
const KeyframeEffectOptions& opt = aOptions.GetAsKeyframeEffectOptions();
animationTiming.mIterationDuration = GetIterationDuration(opt.mDuration);
animationTiming.mDelay = TimeDuration::FromMilliseconds(opt.mDelay);
// FIXME: Covert mIterationCount to a valid value.
// Bug 1214536 should revise this and keep the original value, so
// AnimationTimingEffectReadOnly can get the original iterations.
animationTiming.mIterationCount = (IsNaN(opt.mIterations) ||
opt.mIterations < 0.0f) ?
1.0f :
opt.mIterations;
animationTiming.mDirection = opt.mDirection;
// FIXME: We should store original value.
animationTiming.mFillMode = (opt.mFill == FillMode::Auto) ?
FillMode::None :
opt.mFill;
timing = aOptions.GetAsKeyframeEffectOptions();
} else {
animationTiming.mIterationDuration = GetIterationDuration(aOptions);
animationTiming.mDelay = TimeDuration(0);
animationTiming.mIterationCount = 1.0f;
animationTiming.mDirection = PlaybackDirection::Normal;
animationTiming.mFillMode = FillMode::None;
timing.mDuration.SetAsUnrestrictedDouble() =
aOptions.GetAsUnrestrictedDouble();
}
return animationTiming;
return timing;
}
/**
@ -1723,7 +1687,7 @@ KeyframeEffectReadOnly::Constructor(
return nullptr;
}
AnimationTiming timing = ConvertKeyframeEffectOptions(aOptions);
TimingParams timing = ConvertKeyframeEffectOptions(aOptions);
InfallibleTArray<AnimationProperty> animationProperties;
BuildAnimationPropertyList(aGlobal.Context(), aTarget, aFrames,

View File

@ -15,14 +15,17 @@
#include "mozilla/Attributes.h"
#include "mozilla/ComputedTimingFunction.h" // ComputedTimingFunction
#include "mozilla/LayerAnimationInfo.h" // LayerAnimations::kRecords
#include "mozilla/OwningNonNull.h" // OwningNonNull<...>
#include "mozilla/StickyTimeDuration.h"
#include "mozilla/StyleAnimationValue.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/dom/AnimationEffectReadOnly.h"
#include "mozilla/dom/AnimationEffectTimingReadOnly.h" // TimingParams
#include "mozilla/dom/Element.h"
#include "mozilla/dom/KeyframeBinding.h"
#include "mozilla/dom/Nullable.h"
struct JSContext;
class nsCSSPropertySet;
class nsIContent;
@ -36,41 +39,11 @@ struct AnimationCollection;
class AnimValuesStyleRule;
namespace dom {
struct ComputedTimingProperties;
class UnrestrictedDoubleOrKeyframeEffectOptions;
enum class IterationCompositeOperation : uint32_t;
enum class CompositeOperation : uint32_t;
}
/**
* Input timing parameters.
*
* Eventually this will represent all the input timing parameters specified
* by content but for now it encapsulates just the subset of those
* parameters passed to GetPositionInIteration.
*/
struct AnimationTiming
{
TimeDuration mIterationDuration;
TimeDuration mDelay;
float mIterationCount; // mozilla::PositiveInfinity<float>() means infinite
dom::PlaybackDirection mDirection;
dom::FillMode mFillMode;
bool FillsForwards() const;
bool FillsBackwards() const;
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);
}
};
/**
* Stores the results of calculating the timing properties of an animation
* at a given sample time.
@ -88,6 +61,25 @@ struct ComputedTiming
Nullable<double> mProgress;
// Zero-based iteration index (meaningless if mProgress is null).
uint64_t mCurrentIteration = 0;
// Unlike TimingParams::mIterations, this value is
// guaranteed to be in the range [0, Infinity].
double mIterations = 1.0;
StickyTimeDuration mDuration;
// This is the computed fill mode so it is never auto
dom::FillMode mFill = dom::FillMode::None;
bool FillsForwards() const {
MOZ_ASSERT(mFill != dom::FillMode::Auto,
"mFill should not be Auto in ComputedTiming.");
return mFill == dom::FillMode::Both ||
mFill == dom::FillMode::Forwards;
}
bool FillsBackwards() const {
MOZ_ASSERT(mFill != dom::FillMode::Auto,
"mFill should not be Auto in ComputedTiming.");
return mFill == dom::FillMode::Both ||
mFill == dom::FillMode::Backwards;
}
enum class AnimationPhase {
Null, // Not sampled (null sample time)
@ -178,7 +170,7 @@ public:
KeyframeEffectReadOnly(nsIDocument* aDocument,
Element* aTarget,
nsCSSPseudoElements::Type aPseudoType,
const AnimationTiming& aTiming);
const TimingParams& aTiming);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(KeyframeEffectReadOnly,
@ -227,9 +219,13 @@ public:
aRetVal.AssignLiteral("distribute");
}
const AnimationTiming& Timing() const { return mTiming; }
AnimationTiming& Timing() { return mTiming; }
void SetTiming(const AnimationTiming& aTiming);
already_AddRefed<AnimationEffectTimingReadOnly> Timing() const override;
const TimingParams& SpecifiedTiming() const
{
return mTiming->AsTimingParams();
}
void SetSpecifiedTiming(const TimingParams& aTiming);
void NotifyAnimationTimingUpdated();
Nullable<TimeDuration> GetLocalTime() const;
@ -246,22 +242,25 @@ public:
// (because it is not currently active and is not filling at this time).
static ComputedTiming
GetComputedTimingAt(const Nullable<TimeDuration>& aLocalTime,
const AnimationTiming& aTiming);
const TimingParams& aTiming);
// Shortcut for that gets the computed timing using the current local time as
// calculated from the timeline time.
ComputedTiming
GetComputedTiming(const AnimationTiming* aTiming = nullptr) const
GetComputedTiming(const TimingParams* aTiming = nullptr) const
{
return GetComputedTimingAt(GetLocalTime(), aTiming ? *aTiming : mTiming);
return GetComputedTimingAt(GetLocalTime(),
aTiming ? *aTiming : SpecifiedTiming());
}
void
GetComputedTimingAsDict(ComputedTimingProperties& aRetVal) const override;
// Return the duration of the active interval for the given timing parameters.
// Return the duration of the active interval for the given duration and
// iteration count.
static StickyTimeDuration
ActiveDuration(const AnimationTiming& aTiming);
ActiveDuration(const StickyTimeDuration& aIterationDuration,
double aIterationCount);
bool IsInPlay() const;
bool IsCurrent() const;
@ -334,7 +333,7 @@ protected:
// owning Animation's timing.
void UpdateTargetRegistration();
static AnimationTiming ConvertKeyframeEffectOptions(
static TimingParams ConvertKeyframeEffectOptions(
const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions);
static void BuildAnimationPropertyList(
@ -347,7 +346,7 @@ protected:
nsCOMPtr<Element> mTarget;
RefPtr<Animation> mAnimation;
AnimationTiming mTiming;
OwningNonNull<AnimationEffectTimingReadOnly> mTiming;
nsCSSPseudoElements::Type mPseudoType;
InfallibleTArray<AnimationProperty> mProperties;

View File

@ -10,6 +10,7 @@ MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
EXPORTS.mozilla.dom += [
'Animation.h',
'AnimationEffectReadOnly.h',
'AnimationEffectTimingReadOnly.h',
'AnimationTimeline.h',
'DocumentTimeline.h',
'KeyframeEffect.h',
@ -29,6 +30,7 @@ EXPORTS.mozilla += [
UNIFIED_SOURCES += [
'Animation.cpp',
'AnimationEffectReadOnly.cpp',
'AnimationEffectTimingReadOnly.cpp',
'AnimationTimeline.cpp',
'AnimationUtils.cpp',
'AnimValuesStyleRule.cpp',

View File

@ -344,7 +344,7 @@ TextInputProcessor::PrepareKeyboardEventForComposition(
aKeyboardEvent =
aOptionalArgc && aDOMKeyEvent ?
aDOMKeyEvent->GetInternalNSEvent()->AsKeyboardEvent() : nullptr;
aDOMKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent() : nullptr;
if (!aKeyboardEvent || aOptionalArgc < 2) {
aKeyFlags = 0;
}
@ -769,7 +769,7 @@ TextInputProcessor::Keydown(nsIDOMKeyEvent* aDOMKeyEvent,
return NS_ERROR_INVALID_ARG;
}
WidgetKeyboardEvent* originalKeyEvent =
aDOMKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
aDOMKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent();
if (NS_WARN_IF(!originalKeyEvent)) {
return NS_ERROR_INVALID_ARG;
}
@ -875,7 +875,7 @@ TextInputProcessor::Keyup(nsIDOMKeyEvent* aDOMKeyEvent,
return NS_ERROR_INVALID_ARG;
}
WidgetKeyboardEvent* originalKeyEvent =
aDOMKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
aDOMKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent();
if (NS_WARN_IF(!originalKeyEvent)) {
return NS_ERROR_INVALID_ARG;
}

View File

@ -1561,7 +1561,7 @@ WebSocketImpl::Init(JSContext* aCx,
// to reflect that upgrade. Please note that we can not upgrade from ws:
// to wss: before performing content policy checks because CSP needs to
// send reports in case the scheme is about to be upgraded.
if (!mSecure && originDoc && originDoc->GetUpgradeInsecureRequests()) {
if (!mSecure && originDoc && originDoc->GetUpgradeInsecureRequests(false)) {
// let's use the old specification before the upgrade for logging
NS_ConvertUTF8toUTF16 reportSpec(mURI);

View File

@ -116,8 +116,8 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
nsContentPolicyType externalType =
nsContentUtils::InternalContentPolicyTypeToExternal(contentType);
nsContentPolicyType externalTypeOrScript =
nsContentUtils::InternalContentPolicyTypeToExternalOrScript(contentType);
nsContentPolicyType externalTypeOrMCBInternal =
nsContentUtils::InternalContentPolicyTypeToExternalOrMCBInternal(contentType);
nsContentPolicyType externalTypeOrCSPInternal =
nsContentUtils::InternalContentPolicyTypeToExternalOrCSPInternal(contentType);
@ -140,11 +140,13 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
/* check the appropriate policy */
// Send the internal content policy type to the mixed content blocker
// which needs to know about TYPE_INTERNAL_WORKER,
// TYPE_INTERNAL_SHARED_WORKER and TYPE_INTERNAL_SERVICE_WORKER.
// TYPE_INTERNAL_SHARED_WORKER and TYPE_INTERNAL_SERVICE_WORKER
// and also preloads: TYPE_INTERNAL_SCRIPT_PRELOAD,
// TYPE_INTERNAL_IMAGE_PRELOAD, TYPE_INTERNAL_STYLESHEET_PRELOAD
bool isMixedContentBlocker = mixedContentBlocker == entries[i];
nsContentPolicyType type = externalType;
if (isMixedContentBlocker) {
type = externalTypeOrScript;
type = externalTypeOrMCBInternal;
}
// Send the internal content policy type for CSP which needs to
// know about preloads and workers, in particular:

View File

@ -4955,13 +4955,13 @@ nsContentUtils::GetAccelKeyCandidates(nsIDOMKeyEvent* aDOMKeyEvent,
NS_PRECONDITION(aCandidates.IsEmpty(), "aCandidates must be empty");
nsAutoString eventType;
aDOMKeyEvent->GetType(eventType);
aDOMKeyEvent->AsEvent()->GetType(eventType);
// Don't process if aDOMKeyEvent is not a keypress event.
if (!eventType.EqualsLiteral("keypress"))
return;
WidgetKeyboardEvent* nativeKeyEvent =
aDOMKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
aDOMKeyEvent->AsEvent()->GetInternalNSEvent()->AsKeyboardEvent();
if (nativeKeyEvent) {
NS_ASSERTION(nativeKeyEvent->mClass == eKeyboardEventClass,
"wrong type of native event");
@ -7991,7 +7991,7 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType)
/* static */
nsContentPolicyType
nsContentUtils::InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType aType)
nsContentUtils::InternalContentPolicyTypeToExternalOrMCBInternal(nsContentPolicyType aType)
{
switch (aType) {
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
@ -8001,7 +8001,7 @@ nsContentUtils::InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType
return aType;
default:
return InternalContentPolicyTypeToExternal(aType);
return InternalContentPolicyTypeToExternalOrPreload(aType);
}
}

View File

@ -986,16 +986,18 @@ public:
static nsContentPolicyType InternalContentPolicyTypeToExternal(nsContentPolicyType aType);
/**
* Map internal content policy types to external ones or script types:
* Map internal content policy types to external ones or script types or preload types:
* * TYPE_INTERNAL_SCRIPT
* * TYPE_INTERNAL_WORKER
* * TYPE_INTERNAL_SHARED_WORKER
* * TYPE_INTERNAL_SERVICE_WORKER
*
* * TYPE_INTERNAL_SCRIPT_PRELOAD
* * TYPE_INTERNAL_IMAGE_PRELOAD
* * TYPE_INTERNAL_STYLESHEET_PRELOAD
*
* Note: DO NOT call this function unless you know what you're doing!
*/
static nsContentPolicyType InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType aType);
static nsContentPolicyType InternalContentPolicyTypeToExternalOrMCBInternal(nsContentPolicyType aType);
/**
* Map internal content policy types to external ones or preload types:

View File

@ -2550,12 +2550,12 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
treeItem->GetSameTypeParent(getter_AddRefs(sameTypeParent));
if (sameTypeParent) {
mUpgradeInsecureRequests =
sameTypeParent->GetDocument()->GetUpgradeInsecureRequests();
sameTypeParent->GetDocument()->GetUpgradeInsecureRequests(false);
// if the parent document makes use of upgrade-insecure-requests
// then subdocument preloads should always be upgraded.
mUpgradeInsecurePreloads =
mUpgradeInsecureRequests ||
sameTypeParent->GetDocument()->GetUpgradeInsecurePreloads();
sameTypeParent->GetDocument()->GetUpgradeInsecureRequests(true);
}
}
@ -2785,19 +2785,8 @@ nsDocument::InitCSP(nsIChannel* aChannel)
}
}
csp = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
if (NS_FAILED(rv)) {
MOZ_LOG(gCspPRLog, LogLevel::Debug, ("Failed to create CSP object: %x", rv));
return rv;
}
// used as a "self" identifier for the CSP.
nsCOMPtr<nsIURI> selfURI;
aChannel->GetURI(getter_AddRefs(selfURI));
// Store the request context for violation reports
csp->SetRequestContext(this, nullptr);
rv = principal->EnsureCSP(this, getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
// ----- if the doc is an app and we want a default CSP, apply it.
if (applyAppDefaultCSP) {
@ -2847,14 +2836,7 @@ nsDocument::InitCSP(nsIChannel* aChannel)
aChannel->Cancel(NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION);
}
}
rv = principal->SetCsp(csp);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_LOG(gCspPRLog, LogLevel::Debug,
("Inserted CSP into principal %p", principal));
ApplySettingsFromCSP(false);
return NS_OK;
}

View File

@ -321,19 +321,14 @@ public:
* of the document's ancestors up to the toplevel document makes use
* of the CSP directive 'upgrade-insecure-requests'.
*/
bool GetUpgradeInsecureRequests() const
bool GetUpgradeInsecureRequests(bool aPreload) const
{
if (aPreload) {
return mUpgradeInsecurePreloads;
}
return mUpgradeInsecureRequests;
}
/**
* Same as GetUpgradeInsecureRequests() but *only* for preloads.
*/
bool GetUpgradeInsecurePreloads() const
{
return mUpgradeInsecurePreloads;
}
/**
* Set the principal responsible for this document.
*/

View File

@ -646,6 +646,21 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// sheets. If the script comes from the network stream, cheat for
// performance reasons and avoid a trip through the event loop.
if (aElement->GetParserCreated() == FROM_PARSER_NETWORK) {
// Attempt to compile script off-thread first -- it reduces locking of
// the main thread for long time.
if (NumberOfProcessors() > 1 &&
AttemptAsyncScriptCompile(request) == NS_OK) {
NS_ASSERTION(request->mProgress == nsScriptLoadRequest::Progress_Compiling,
"Request should be off-thread compiling now.");
NS_ASSERTION(!mParserBlockingRequest,
"There can be only one parser-blocking script at a time");
NS_ASSERTION(mXSLTRequests.isEmpty(),
"Parser-blocking scripts and XSLT scripts in the same doc!");
mParserBlockingRequest = request;
return true;
}
// And process a request if off-thread compilation heuristics think that
// non-async way will be faster.
return ProcessRequest(request) == NS_ERROR_HTMLPARSER_BLOCK;
}
// Otherwise, we've got a document.written script, make a trip through
@ -1791,7 +1806,7 @@ nsScriptLoadHandler::TryDecodeRawData(const uint8_t* aData,
haveRead += dstLen;
MOZ_ASSERT(haveRead <= capacity, "mDecoder produced more data than expected");
mBuffer.resizeUninitialized(haveRead);
MOZ_ALWAYS_TRUE(mBuffer.resizeUninitialized(haveRead));
return NS_OK;
}

View File

@ -3240,7 +3240,7 @@ class CGConstructorEnabled(CGAbstractMethod):
conditions = []
iface = self.descriptor.interface
if not iface.isExposedInWindow():
if not iface.isExposedOnMainThread():
exposedInWindowCheck = dedent(
"""
MOZ_ASSERT(!NS_IsMainThread(), "Why did we even get called?");
@ -3259,7 +3259,7 @@ class CGConstructorEnabled(CGAbstractMethod):
}
""", workerCondition=workerCondition.define())
exposedInWorkerCheck = CGGeneric(exposedInWorkerCheck)
if iface.isExposedInWindow():
if iface.isExposedOnMainThread():
exposedInWorkerCheck = CGIfWrapper(exposedInWorkerCheck,
"!NS_IsMainThread()")
body.append(exposedInWorkerCheck)

View File

@ -501,6 +501,10 @@ class IDLExposureMixins():
def isExposedInWindow(self):
return 'Window' in self.exposureSet
def isExposedOnMainThread(self):
return (self.isExposedInWindow() or
self.isExposedInSystemGlobals())
def isExposedInAnyWorker(self):
return len(self.getWorkerExposureSet()) > 0

View File

@ -122,10 +122,10 @@ WebGL2Context::VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
void
WebGL2Context::VertexAttribI4iv(GLuint index, size_t length, const GLint* v)
{
if (!ValidateAttribIndex(index, "vertexAttribI4iv"))
if (!ValidateAttribArraySetter("vertexAttribI4iv", 4, length))
return;
if (!ValidateAttribArraySetter("vertexAttribI4iv", 4, length))
if (!ValidateAttribIndex(index, "vertexAttribI4iv"))
return;
mVertexAttribType[index] = LOCAL_GL_INT;
@ -183,7 +183,7 @@ WebGL2Context::VertexAttribI4uiv(GLuint index, size_t length, const GLuint* v)
if (IsContextLost())
return;
if (!ValidateAttribIndex(index, "vertexAttribI4uiv"))
if (!ValidateAttribArraySetter("vertexAttribI4uiv", 4, length))
return;
if (!ValidateAttribIndex(index, "vertexAttribI4uiv"))

View File

@ -448,8 +448,8 @@ WebGLContext::ValidateAttribArraySetter(const char* name, uint32_t setterElemSiz
return false;
if (arrayLength < setterElemSize) {
ErrorInvalidOperation("%s: Array must have >= %d elements.", name,
setterElemSize);
ErrorInvalidValue("%s: Array must have >= %d elements.", name,
setterElemSize);
return false;
}

View File

@ -584,7 +584,7 @@ IMEStateManager::OnMouseButtonEventInEditor(nsPresContext* aPresContext,
}
WidgetMouseEvent* internalEvent =
aMouseEvent->GetInternalNSEvent()->AsMouseEvent();
aMouseEvent->AsEvent()->GetInternalNSEvent()->AsMouseEvent();
if (NS_WARN_IF(!internalEvent)) {
MOZ_LOG(sISMLog, LogLevel::Debug,
("ISM: IMEStateManager::OnMouseButtonEventInEditor(), "
@ -597,7 +597,7 @@ IMEStateManager::OnMouseButtonEventInEditor(nsPresContext* aPresContext,
if (MOZ_LOG_TEST(sISMLog, LogLevel::Info)) {
nsAutoString eventType;
aMouseEvent->GetType(eventType);
aMouseEvent->AsEvent()->GetType(eventType);
MOZ_LOG(sISMLog, LogLevel::Info,
("ISM: IMEStateManager::OnMouseButtonEventInEditor(), "
"mouse event (type=%s, button=%d) is %s",
@ -630,7 +630,7 @@ IMEStateManager::OnClickInEditor(nsPresContext* aPresContext,
NS_ENSURE_TRUE_VOID(widget);
bool isTrusted;
nsresult rv = aMouseEvent->GetIsTrusted(&isTrusted);
nsresult rv = aMouseEvent->AsEvent()->GetIsTrusted(&isTrusted);
NS_ENSURE_SUCCESS_VOID(rv);
if (!isTrusted) {
MOZ_LOG(sISMLog, LogLevel::Debug,

View File

@ -346,6 +346,12 @@ UIEvent::IsChar() const
return keyEvent ? keyEvent->isChar : false;
}
mozilla::dom::Event*
UIEvent::AsEvent(void)
{
return this;
}
NS_IMETHODIMP
UIEvent::DuplicatePrivateData()
{

View File

@ -88,7 +88,7 @@ class InternalRequest final
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalRequest)
explicit InternalRequest()
InternalRequest()
: mMethod("GET")
, mHeaders(new InternalHeaders(HeadersGuardEnum::None))
, mContentPolicyType(nsIContentPolicy::TYPE_FETCH)
@ -113,6 +113,36 @@ public:
{
}
InternalRequest(const nsACString& aURL,
const nsACString& aMethod,
already_AddRefed<InternalHeaders> aHeaders,
RequestMode aMode,
RequestRedirect aRequestRedirect,
RequestCredentials aRequestCredentials,
const nsAString& aReferrer,
nsContentPolicyType aContentPolicyType)
: mMethod(aMethod)
, mURL(aURL)
, mHeaders(aHeaders)
, mContentPolicyType(aContentPolicyType)
, mReferrer(aReferrer)
, mMode(aMode)
, mCredentialsMode(aRequestCredentials)
, mResponseTainting(LoadTainting::Basic)
, mCacheMode(RequestCache::Default)
, mRedirectMode(aRequestRedirect)
, mAuthenticationFlag(false)
, mForceOriginHeader(false)
, mPreserveContentCodings(false)
// FIXME See the above comment in the default constructor.
, mSameOriginDataURL(true)
, mSkipServiceWorker(false)
, mSynchronous(false)
, mUnsafeRequest(false)
, mUseURLCredentials(false)
{
}
already_AddRefed<InternalRequest> Clone();
void

View File

@ -331,7 +331,7 @@ DarwinGamepadService::InputValueChanged(IOHIDValueRef value)
const int numButtons = gamepad.numButtons();
for (unsigned b = 0; b < ArrayLength(newState); b++) {
if (newState[b] != oldState[b]) {
NewButtonEvent(i, numButtons - 4 + b, newState[b]);
NewButtonEvent(gamepad.mSuperIndex, numButtons - 4 + b, newState[b]);
}
}
gamepad.setDpadState(newState);
@ -339,7 +339,7 @@ DarwinGamepadService::InputValueChanged(IOHIDValueRef value)
double d = IOHIDValueGetIntegerValue(value);
double v = 2.0f * (d - axis->min) /
(double)(axis->max - axis->min) - 1.0f;
NewAxisMoveEvent(i, axis->id, v);
NewAxisMoveEvent(gamepad.mSuperIndex, axis->id, v);
} else if (const Button* button = gamepad.lookupButton(element)) {
int iv = IOHIDValueGetIntegerValue(value);
bool pressed = iv != 0;
@ -350,7 +350,7 @@ DarwinGamepadService::InputValueChanged(IOHIDValueRef value)
} else {
v = pressed ? 1.0 : 0.0;
}
NewButtonEvent(i, button->id, pressed, v);
NewButtonEvent(gamepad.mSuperIndex, button->id, pressed, v);
}
return;
}

View File

@ -90,6 +90,7 @@ class nsGeolocationRequest final
const GeoPositionCallback& aCallback,
const GeoPositionErrorCallback& aErrorCallback,
PositionOptions* aOptions,
uint8_t aProtocolType,
bool aWatchPositionRequest = false,
int32_t aWatchId = 0);
void Shutdown();
@ -120,6 +121,7 @@ class nsGeolocationRequest final
int32_t mWatchId;
bool mShutdown;
nsCOMPtr<nsIContentPermissionRequester> mRequester;
uint8_t mProtocolType;
};
static PositionOptions*
@ -354,6 +356,7 @@ nsGeolocationRequest::nsGeolocationRequest(Geolocation* aLocator,
const GeoPositionCallback& aCallback,
const GeoPositionErrorCallback& aErrorCallback,
PositionOptions* aOptions,
uint8_t aProtocolType,
bool aWatchPositionRequest,
int32_t aWatchId)
: mIsWatchPositionRequest(aWatchPositionRequest),
@ -362,7 +365,8 @@ nsGeolocationRequest::nsGeolocationRequest(Geolocation* aLocator,
mOptions(aOptions),
mLocator(aLocator),
mWatchId(aWatchId),
mShutdown(false)
mShutdown(false),
mProtocolType(aProtocolType)
{
nsCOMPtr<nsIDOMWindow> win = do_QueryReferent(mLocator->GetOwner());
if (win) {
@ -453,6 +457,13 @@ nsGeolocationRequest::GetElement(nsIDOMElement * *aRequestingElement)
NS_IMETHODIMP
nsGeolocationRequest::Cancel()
{
if (mRequester) {
// Record the number of denied requests for regular web content.
// This method is only called when the user explicitly denies the request,
// and is not called when the page is simply unloaded, or similar.
Telemetry::Accumulate(Telemetry::GEOLOCATION_REQUEST_GRANTED, mProtocolType);
}
if (mLocator->ClearPendingRequest(this)) {
return NS_OK;
}
@ -466,6 +477,11 @@ nsGeolocationRequest::Allow(JS::HandleValue aChoices)
{
MOZ_ASSERT(aChoices.isUndefined());
if (mRequester) {
// Record the number of granted requests for regular web content.
Telemetry::Accumulate(Telemetry::GEOLOCATION_REQUEST_GRANTED, mProtocolType + 10);
}
if (mLocator->ClearPendingRequest(this)) {
return NS_OK;
}
@ -1193,7 +1209,8 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Geolocation,
mPendingRequests)
Geolocation::Geolocation()
: mLastWatchId(0)
: mProtocolType(ProtocolType::OTHER)
, mLastWatchId(0)
{
}
@ -1234,6 +1251,24 @@ Geolocation::Init(nsIDOMWindow* aContentDom)
/* wants untrusted */ false);
}
nsCOMPtr<nsIURI> uri;
nsresult rv = mPrincipal->GetURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
bool isHttp;
rv = uri->SchemeIs("http", &isHttp);
NS_ENSURE_SUCCESS(rv, rv);
bool isHttps;
rv = uri->SchemeIs("https", &isHttps);
NS_ENSURE_SUCCESS(rv, rv);
// Store the protocol to send via telemetry later.
if (isHttp) {
mProtocolType = ProtocolType::HTTP;
} else if (isHttps) {
mProtocolType = ProtocolType::HTTPS;
}
}
// If no aContentDom was passed into us, we are being used
@ -1494,11 +1529,13 @@ Geolocation::GetCurrentPosition(GeoPositionCallback& callback,
return NS_ERROR_NOT_AVAILABLE;
}
RefPtr<nsGeolocationRequest> request = new nsGeolocationRequest(this,
callback,
errorCallback,
options,
false);
// Count the number of requests per protocol/scheme.
Telemetry::Accumulate(Telemetry::GEOLOCATION_GETCURRENTPOSITION_SECURE_ORIGIN,
static_cast<uint8_t>(mProtocolType));
RefPtr<nsGeolocationRequest> request =
new nsGeolocationRequest(this, callback, errorCallback, options,
static_cast<uint8_t>(mProtocolType), false);
if (!sGeoEnabled) {
nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(false, request);
@ -1583,15 +1620,16 @@ Geolocation::WatchPosition(GeoPositionCallback& aCallback,
return NS_ERROR_NOT_AVAILABLE;
}
// Count the number of requests per protocol/scheme.
Telemetry::Accumulate(Telemetry::GEOLOCATION_WATCHPOSITION_SECURE_ORIGIN,
static_cast<uint8_t>(mProtocolType));
// The watch ID:
*aRv = mLastWatchId++;
RefPtr<nsGeolocationRequest> request = new nsGeolocationRequest(this,
aCallback,
aErrorCallback,
aOptions,
true,
*aRv);
RefPtr<nsGeolocationRequest> request =
new nsGeolocationRequest(this, aCallback, aErrorCallback, aOptions,
static_cast<uint8_t>(mProtocolType), true, *aRv);
if (!sGeoEnabled) {
GPSLOG("request allow event");

View File

@ -218,6 +218,12 @@ private:
// where the content was loaded from
nsCOMPtr<nsIPrincipal> mPrincipal;
// the protocols we want to measure
enum class ProtocolType: uint8_t { OTHER, HTTP, HTTPS };
// the protocol used to load the content
ProtocolType mProtocolType;
// owning back pointer.
RefPtr<nsGeolocationService> mService;

View File

@ -1746,7 +1746,7 @@ HTMLFormElement::GetActionURL(nsIURI** aActionURL,
bool isHttpScheme = false;
rv = actionURL->SchemeIs("http", &isHttpScheme);
NS_ENSURE_SUCCESS(rv, rv);
if (isHttpScheme && document->GetUpgradeInsecureRequests()) {
if (isHttpScheme && document->GetUpgradeInsecureRequests(false)) {
// let's use the old specification before the upgrade for logging
nsAutoCString spec;
rv = actionURL->GetSpec(spec);

View File

@ -129,26 +129,13 @@ HTMLMetaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIPrincipal* principal = aDocument->NodePrincipal();
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = principal->GetCsp(getter_AddRefs(csp));
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDocument);
rv = principal->EnsureCSP(domDoc, getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
// Multiple CSPs (delivered through either header of meta tag) need to be
// joined together, see:
// https://w3c.github.io/webappsec/specs/content-security-policy/#delivery-html-meta-element
if (!csp) {
csp = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Store the request context so CSP can resolve 'self'
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDocument);
rv = csp->SetRequestContext(domDoc, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
// set the new CSP
rv = principal->SetCsp(csp);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = csp->AppendPolicy(content,
false, // csp via meta tag can not be report only
true); // delivered through the meta tag

View File

@ -343,12 +343,7 @@ HTMLSharedObjectElement::GetCapabilities() const
{
uint32_t capabilities = eSupportPlugins | eAllowPluginSkipChannel;
if (mNodeInfo->Equals(nsGkAtoms::embed)) {
capabilities |= eSupportSVG | eSupportImages;
}
// If this is a rewritten youtube flash embed, add documents to capabilities
// so that we can render HTML5 if possible.
if (mRewrittenYoutubeEmbed) {
capabilities |= eSupportDocuments;
capabilities |= eSupportSVG | eSupportImages | eSupportDocuments;
}
return capabilities;

View File

@ -3,7 +3,7 @@
* 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 "nsIDOMEvent.idl"
#include "nsISupports.idl"
/**
* Animation events are defined in:
@ -11,8 +11,9 @@
* http://dev.w3.org/csswg/css3-animations/#animation-events-
*/
[builtinclass, uuid(772c7069-3f7d-42cf-97ab-b32f1c0b83da)]
interface nsIDOMAnimationEvent : nsIDOMEvent {
[builtinclass, uuid(ce6d1db3-53b8-4ade-9baa-70f4947200a2)]
interface nsIDOMAnimationEvent : nsISupports
{
readonly attribute DOMString animationName;
readonly attribute float elapsedTime;
readonly attribute DOMString pseudoElement;

View File

@ -3,7 +3,7 @@
* 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 "nsIDOMEvent.idl"
#include "nsISupports.idl"
/**
* The nsIDOMBeforeUnloadEvent interface is the interface for events
@ -15,8 +15,8 @@
*
*/
[builtinclass, uuid(96abf41b-32a8-4ff6-a0d6-4ade4ddebf89)]
interface nsIDOMBeforeUnloadEvent : nsIDOMEvent
[builtinclass, uuid(26c83933-a5a4-455e-8c46-69fa24dfa991)]
interface nsIDOMBeforeUnloadEvent : nsISupports
{
/**
* Attribute used to pass back a return value from a beforeunload

View File

@ -4,12 +4,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "domstubs.idl"
#include "nsIDOMEvent.idl"
#include "nsISupports.idl"
interface nsIDOMDataTransfer;
[builtinclass, uuid(4ef84980-52c2-425c-b41a-2ee75ec5d497)]
interface nsIDOMClipboardEvent : nsIDOMEvent
[builtinclass, uuid(b54d6144-3980-4895-83c7-82f158bc1cf5)]
interface nsIDOMClipboardEvent : nsISupports
{
readonly attribute nsIDOMDataTransfer clipboardData;

View File

@ -3,10 +3,10 @@
* 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 "nsIDOMEvent.idl"
#include "nsISupports.idl"
[builtinclass, uuid(7efbe68a-811a-4159-801c-226948cfd08f)]
interface nsIDOMCommandEvent : nsIDOMEvent
[builtinclass, uuid(73a50e55-3eaa-4a38-a588-9b68a6d65032)]
interface nsIDOMCommandEvent : nsISupports
{
readonly attribute DOMString command;

View File

@ -3,11 +3,11 @@
* 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 "nsIDOMEvent.idl"
#include "nsISupports.idl"
#include "nsIVariant.idl"
[builtinclass, uuid(31ceb43e-5f49-43bf-9a18-3b60a535c814)]
interface nsIDOMDataContainerEvent : nsIDOMEvent
[builtinclass, uuid(a9f1f528-d106-4fea-8663-2d7f64b627a9)]
interface nsIDOMDataContainerEvent : nsISupports
{
/**
* Return the data associated with the given key.

View File

@ -3,7 +3,8 @@
* 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 "nsIDOMEvent.idl"
#include "nsISupports.idl"
#include "nsIDOMWindow.idl"
/**
* The nsIDOMMessageEvent interface is used for server-sent events and for
@ -12,8 +13,8 @@
* For more information on this interface, please see
* http://www.whatwg.org/specs/web-apps/current-work/#messageevent
*/
[builtinclass, uuid(4408a2f5-614f-40a3-8786-e16bd3f74e32)]
interface nsIDOMMessageEvent : nsIDOMEvent
[builtinclass, uuid(5d57bc56-30cf-4839-9e98-17f940120ec0)]
interface nsIDOMMessageEvent : nsISupports
{
/**
* Custom string data associated with this event.

View File

@ -3,10 +3,11 @@
* 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 "nsIDOMEvent.idl"
#include "nsISupports.idl"
#include "nsIDOMNode.idl"
[builtinclass, uuid(df7e4cd9-e41f-4c8e-a764-2e3191d2f463)]
interface nsIDOMMutationEvent : nsIDOMEvent
[builtinclass, uuid(30c9997f-bc4c-4890-b890-febb6ae3051b)]
interface nsIDOMMutationEvent : nsISupports
{
const unsigned short MODIFICATION = 1;
const unsigned short ADDITION = 2;

View File

@ -3,7 +3,9 @@
* 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 "nsIDOMEvent.idl"
#include "nsISupports.idl"
#include "nsIDOMClientRectList.idl"
#include "nsIDOMClientRect.idl"
interface nsIDOMPaintRequestList;
@ -12,8 +14,8 @@ interface nsIDOMPaintRequestList;
* event, which fires at a window when painting has happened in
* that window.
*/
[builtinclass, uuid(550f660c-65a5-4e17-b828-3dbec7c44304)]
interface nsIDOMNotifyPaintEvent : nsIDOMEvent
[builtinclass, uuid(63f573a0-3e4e-474b-a0c2-bb4ca93febaa)]
interface nsIDOMNotifyPaintEvent : nsISupports
{
/**
* Get a list of rectangles which are affected. The rectangles are in CSS pixels

View File

@ -3,7 +3,7 @@
* 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 "nsIDOMEvent.idl"
#include "nsISupports.idl"
/**
* Transition events are defined in:
@ -11,8 +11,8 @@
* http://dev.w3.org/csswg/css3-transitions/#transition-events-
*/
[builtinclass, uuid(acb69403-0dcb-4db0-9ffc-8a22cc56c4eb)]
interface nsIDOMTransitionEvent : nsIDOMEvent {
[builtinclass, uuid(ee3499bf-0f14-4bb6-829c-19ad24fd4a85)]
interface nsIDOMTransitionEvent : nsISupports {
readonly attribute DOMString propertyName;
readonly attribute float elapsedTime;
readonly attribute DOMString pseudoElement;

View File

@ -3,7 +3,8 @@
* 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 "nsIDOMEvent.idl"
#include "nsISupports.idl"
#include "nsIDOMWindow.idl"
/**
* The nsIDOMUIEvent interface is the datatype for all UI events in the
@ -13,8 +14,18 @@
* http://www.w3.org/TR/DOM-Level-2-Events/
*/
[builtinclass, uuid(db058d10-1db9-4cf9-bb4c-483c304a137f)]
interface nsIDOMUIEvent : nsIDOMEvent
%{C++
namespace mozilla {
namespace dom {
class Event;
}
}
%}
[ptr] native EventPtr(mozilla::dom::Event);
[builtinclass, uuid(75996b57-51f0-4c9c-aaaa-e35eaf347b66)]
interface nsIDOMUIEvent : nsISupports
{
readonly attribute nsIDOMWindow view;
readonly attribute long detail;
@ -38,4 +49,6 @@ interface nsIDOMUIEvent : nsIDOMEvent
attribute boolean cancelBubble;
readonly attribute boolean isChar;
[notxpcom, nostdcall] EventPtr AsEvent();
};

View File

@ -651,30 +651,34 @@ GeckoMediaPluginServiceParent::UnloadPlugins()
NS_LITERAL_CSTRING("Starting to unload plugins"));
#endif
nsTArray<RefPtr<GMPParent>> plugins;
{
MutexAutoLock lock(mMutex);
LOGD(("%s::%s plugins:%u including async:%u", __CLASS__, __FUNCTION__,
mPlugins.Length(), mAsyncShutdownPlugins.Length()));
// Move all plugins references to a local array. This way mMutex won't be
// locked when calling CloseActive (to avoid inter-locking).
plugins = Move(mPlugins);
}
LOGD(("%s::%s plugins:%u including async:%u", __CLASS__, __FUNCTION__,
plugins.Length(), mAsyncShutdownPlugins.Length()));
#ifdef DEBUG
for (const auto& plugin : mPlugins) {
LOGD(("%s::%s plugin: '%s'", __CLASS__, __FUNCTION__,
plugin->GetDisplayName().get()));
}
for (const auto& plugin : mAsyncShutdownPlugins) {
LOGD(("%s::%s async plugin: '%s'", __CLASS__, __FUNCTION__,
plugin->GetDisplayName().get()));
}
for (const auto& plugin : plugins) {
LOGD(("%s::%s plugin: '%s'", __CLASS__, __FUNCTION__,
plugin->GetDisplayName().get()));
}
for (const auto& plugin : mAsyncShutdownPlugins) {
LOGD(("%s::%s async plugin: '%s'", __CLASS__, __FUNCTION__,
plugin->GetDisplayName().get()));
}
#endif
// Note: CloseActive may be async; it could actually finish
// shutting down when all the plugins have unloaded.
for (size_t i = 0; i < mPlugins.Length(); i++) {
// Note: CloseActive may be async; it could actually finish
// shutting down when all the plugins have unloaded.
for (const auto& plugin : plugins) {
#ifdef MOZ_CRASHREPORTER
SetAsyncShutdownPluginState(mPlugins[i], 'S',
NS_LITERAL_CSTRING("CloseActive"));
SetAsyncShutdownPluginState(plugin, 'S',
NS_LITERAL_CSTRING("CloseActive"));
#endif
mPlugins[i]->CloseActive(true);
}
mPlugins.Clear();
plugin->CloseActive(true);
}
#ifdef MOZ_CRASHREPORTER
@ -1061,6 +1065,13 @@ GeckoMediaPluginServiceParent::RemoveOnGMPThread(const nsAString& aDirectory,
}
if (aDeleteFromDisk && !inUse) {
// Ensure the GMP dir and all files in it are writable, so we have
// permission to delete them.
directory->SetPermissions(0700);
DirectoryEnumerator iter(directory, DirectoryEnumerator::FilesAndDirs);
for (nsCOMPtr<nsIFile> dirEntry; (dirEntry = iter.Next()) != nullptr;) {
dirEntry->SetPermissions(0700);
}
if (NS_SUCCEEDED(directory->Remove(true))) {
mPluginsWaitingForDeletion.RemoveElement(aDirectory);
NS_DispatchToMainThread(new NotifyObserversTask("gmp-directory-deleted",

View File

@ -17,6 +17,7 @@
#include <media/IOMX.h>
#include <utils/List.h>
#include <media/stagefright/OMXCodec.h>
#include <cutils/properties.h>
extern mozilla::LogModule* GetPDMLog();
@ -43,6 +44,13 @@ bool IsSoftwareCodec(const char* aComponentName) {
return (str.Find(NS_LITERAL_CSTRING("OMX.google.")) == -1 ? false : true);
}
bool IsInEmulator()
{
char propQemu[PROPERTY_VALUE_MAX];
property_get("ro.kernel.qemu", propQemu, "");
return !strncmp(propQemu, "1", 1);
}
class GonkOmxObserver : public BnOMXObserver {
public:
void onMessage(const omx_message& aMsg)
@ -289,7 +297,10 @@ GonkBufferData::GetPlatformMediaData()
return nullptr;
}
MOZ_RELEASE_ASSERT(mTextureClientRecycleHandler);
if (!mTextureClientRecycleHandler) {
// There is no GraphicBuffer, it should fallback to normal YUV420 VideoData.
return nullptr;
}
VideoInfo info;
info.mDisplay = mGonkPlatformLayer->GetTrackInfo()->GetAsVideoInfo()->mDisplay;
@ -520,35 +531,39 @@ GonkOmxPlatformLayer::InitOmxToStateLoaded(const TrackInfo* aInfo)
return OMX_ErrorUndefined;
}
bool useHardwareCodecOnly = false;
// H264 and H263 has different profiles, software codec doesn't support high profile.
// So we use hardware codec only.
if (!IsInEmulator() &&
(mInfo->mMimeType.EqualsLiteral("video/avc") ||
mInfo->mMimeType.EqualsLiteral("video/mp4") ||
mInfo->mMimeType.EqualsLiteral("video/mp4v-es") ||
mInfo->mMimeType.EqualsLiteral("video/3gp"))) {
useHardwareCodecOnly = true;
}
LOG("find componenet for mime type %s", mInfo->mMimeType.Data());
// In Gonk, the software component name has prefix "OMX.google". It needs to
// have a way to use hardware codec first.
android::Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
const char* swcomponent = nullptr;
nsTArray<const char*> components;
OMXCodec::findMatchingCodecs(mInfo->mMimeType.Data(),
0,
nullptr,
0,
&matchingCodecs);
for (uint32_t i = 0; i < matchingCodecs.size(); i++) {
const char* componentName = matchingCodecs.itemAt(i).mName.string();
if (IsSoftwareCodec(componentName)) {
swcomponent = componentName;
} else {
// Try to use hardware codec first.
if (LoadComponent(componentName)) {
mUsingHardwareCodec = true;
return OMX_ErrorNone;
}
LOG("failed to load component %s", componentName);
}
components.AppendElement(matchingCodecs.itemAt(i).mName.string());
}
// TODO: in android ICS, the software codec is allocated in mediaserver by
// default, it may be necessary to allocate it in local process.
//
// fallback to sw codec
if (swcomponent && LoadComponent(swcomponent)) {
return OMX_ErrorNone;
for (auto name : components) {
if (IsSoftwareCodec(name) && useHardwareCodecOnly) {
continue;
}
if (LoadComponent(name)) {
return OMX_ErrorNone;
}
}
LOG("no component is loaded");

View File

@ -23,6 +23,8 @@ extern mozilla::LogModule* GetPDMLog();
return; \
} \
// There should be a better way to calculate it.
#define MIN_VIDEO_INPUT_BUFFER_SIZE 64 * 1024
namespace mozilla {
@ -60,11 +62,52 @@ void GetPortIndex(nsTArray<uint32_t>& aPortIndex) {
aPortIndex.AppendElement(1);
}
template<class T> void
InitOmxParameter(T* aParam)
{
PodZero(aParam);
aParam->nSize = sizeof(T);
aParam->nVersion.s.nVersionMajor = 1;
}
// A helper class to retrieve AudioData or VideoData.
class MediaDataHelper {
protected:
virtual ~MediaDataHelper() {}
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDataHelper)
MediaDataHelper(const TrackInfo* aTrackInfo,
layers::ImageContainer* aImageContainer,
OmxPromiseLayer* aOmxLayer);
already_AddRefed<MediaData> GetMediaData(BufferData* aBufferData, bool& aPlatformDepenentData);
protected:
already_AddRefed<AudioData> CreateAudioData(BufferData* aBufferData);
already_AddRefed<VideoData> CreateYUV420VideoData(BufferData* aBufferData);
const TrackInfo* mTrackInfo;
OMX_PARAM_PORTDEFINITIONTYPE mOutputPortDef;
// audio output
MediaQueue<AudioData> mAudioQueue;
AudioCompactor mAudioCompactor;
// video output
RefPtr<layers::ImageContainer> mImageContainer;
};
OmxDataDecoder::OmxDataDecoder(const TrackInfo& aTrackInfo,
MediaDataDecoderCallback* aCallback,
layers::ImageContainer* aImageContainer)
: mMonitor("OmxDataDecoder")
, mOmxTaskQueue(CreateMediaDecodeTaskQueue())
, mImageContainer(aImageContainer)
, mWatchManager(this, mOmxTaskQueue)
, mOmxState(OMX_STATETYPE::OMX_StateInvalid, "OmxDataDecoder::mOmxState")
, mTrackInfo(aTrackInfo.Clone())
@ -72,7 +115,6 @@ OmxDataDecoder::OmxDataDecoder(const TrackInfo& aTrackInfo,
, mShuttingDown(false)
, mCheckingInputExhausted(false)
, mPortSettingsChanged(-1, "OmxDataDecoder::mPortSettingsChanged")
, mAudioCompactor(mAudioQueue)
, mCallback(aCallback)
{
LOG("(%p)", this);
@ -272,6 +314,7 @@ OmxDataDecoder::DoAsyncShutdown()
self->mOmxLayer->Shutdown();
self->mWatchManager.Shutdown();
self->mOmxLayer = nullptr;
self->mMediaDataHelper = nullptr;
MonitorAutoLock lock(self->mMonitor);
self->mShuttingDown = false;
@ -281,6 +324,7 @@ OmxDataDecoder::DoAsyncShutdown()
self->mOmxLayer->Shutdown();
self->mWatchManager.Shutdown();
self->mOmxLayer = nullptr;
self->mMediaDataHelper = nullptr;
MonitorAutoLock lock(self->mMonitor);
self->mShuttingDown = false;
@ -288,80 +332,6 @@ OmxDataDecoder::DoAsyncShutdown()
});
}
void
OmxDataDecoder::OutputAudio(BufferData* aBufferData)
{
// TODO: it'd be better to move these code to BufferData::GetPlatformMediaData() or
// some kind of abstract layer.
MOZ_ASSERT(mOmxTaskQueue->IsCurrentThreadIn());
OMX_BUFFERHEADERTYPE* buf = aBufferData->mBuffer;
AudioInfo* info = mTrackInfo->GetAsAudioInfo();
if (buf->nFilledLen) {
uint64_t offset = 0;
uint32_t frames = buf->nFilledLen / (2 * info->mChannels);
if (aBufferData->mRawData) {
offset = aBufferData->mRawData->mOffset;
}
typedef AudioCompactor::NativeCopy OmxCopy;
mAudioCompactor.Push(offset,
buf->nTimeStamp,
info->mRate,
frames,
info->mChannels,
OmxCopy(buf->pBuffer + buf->nOffset,
buf->nFilledLen,
info->mChannels));
RefPtr<AudioData> audio = mAudioQueue.PopFront();
mCallback->Output(audio);
}
aBufferData->mStatus = BufferData::BufferStatus::FREE;
}
void
OmxDataDecoder::OutputVideo(BufferData* aBufferData)
{
MOZ_ASSERT(mOmxTaskQueue->IsCurrentThreadIn());
RefPtr<MediaData> data = aBufferData->GetPlatformMediaData();
MOZ_RELEASE_ASSERT(data);
VideoData* video(data->As<VideoData>());
if (aBufferData->mRawData) {
video->mTime = aBufferData->mRawData->mTime;
video->mTimecode = aBufferData->mRawData->mTimecode;
video->mOffset = aBufferData->mRawData->mOffset;
video->mDuration = aBufferData->mRawData->mDuration;
video->mKeyframe = aBufferData->mRawData->mKeyframe;
}
aBufferData->mStatus = BufferData::BufferStatus::OMX_CLIENT_OUTPUT;
// TextureClient's recycle callback is called when reference count of
// TextureClient becomes 1. In most cases, the last reference count is held
// by ITextureClientRecycleAllocator.
// And then promise will be resolved in the callback.
// TODO:
// Because it is gonk specific behaviour, it needs to find a way to
// proper abstracting it.
MOZ_RELEASE_ASSERT(aBufferData->mPromise.IsEmpty());
RefPtr<OmxBufferPromise> p = aBufferData->mPromise.Ensure(__func__);
RefPtr<OmxDataDecoder> self = this;
RefPtr<BufferData> buffer = aBufferData;
p->Then(mOmxTaskQueue, __func__,
[self, buffer] () {
MOZ_RELEASE_ASSERT(buffer->mStatus == BufferData::BufferStatus::OMX_CLIENT_OUTPUT);
buffer->mStatus = BufferData::BufferStatus::FREE;
self->FillAndEmptyBuffers();
},
[buffer] () {
MOZ_RELEASE_ASSERT(buffer->mStatus == BufferData::BufferStatus::OMX_CLIENT_OUTPUT);
buffer->mStatus = BufferData::BufferStatus::FREE;
});
mCallback->Output(video);
}
void
OmxDataDecoder::FillBufferDone(BufferData* aData)
{
@ -383,17 +353,53 @@ OmxDataDecoder::FillBufferDone(BufferData* aData)
EndOfStream();
aData->mStatus = BufferData::BufferStatus::FREE;
} else {
if (mTrackInfo->IsAudio()) {
OutputAudio(aData);
} else if (mTrackInfo->IsVideo()) {
OutputVideo(aData);
} else {
MOZ_ASSERT(0);
}
Output(aData);
FillAndEmptyBuffers();
}
}
void
OmxDataDecoder::Output(BufferData* aData)
{
if (!mMediaDataHelper) {
mMediaDataHelper = new MediaDataHelper(mTrackInfo.get(), mImageContainer, mOmxLayer);
}
bool isPlatformData = false;
RefPtr<MediaData> data = mMediaDataHelper->GetMediaData(aData, isPlatformData);
if (!data) {
aData->mStatus = BufferData::BufferStatus::FREE;
return;
}
if (isPlatformData) {
// If the MediaData is platform dependnet data, it's mostly a kind of
// limited resource, for example, GraphicBuffer on Gonk. So we use promise
// to notify when the resource is free.
aData->mStatus = BufferData::BufferStatus::OMX_CLIENT_OUTPUT;
MOZ_RELEASE_ASSERT(aData->mPromise.IsEmpty());
RefPtr<OmxBufferPromise> p = aData->mPromise.Ensure(__func__);
RefPtr<OmxDataDecoder> self = this;
RefPtr<BufferData> buffer = aData;
p->Then(mOmxTaskQueue, __func__,
[self, buffer] () {
MOZ_RELEASE_ASSERT(buffer->mStatus == BufferData::BufferStatus::OMX_CLIENT_OUTPUT);
buffer->mStatus = BufferData::BufferStatus::FREE;
self->FillAndEmptyBuffers();
},
[buffer] () {
MOZ_RELEASE_ASSERT(buffer->mStatus == BufferData::BufferStatus::OMX_CLIENT_OUTPUT);
buffer->mStatus = BufferData::BufferStatus::FREE;
});
} else {
aData->mStatus = BufferData::BufferStatus::FREE;
}
mCallback->Output(data);
}
void
OmxDataDecoder::FillBufferFailure(OmxBufferFailureHolder aFailureHolder)
{
@ -515,6 +521,7 @@ OmxDataDecoder::FindAvailableBuffer(OMX_DIRTYPE aType)
if (buf->mStatus == BufferData::BufferStatus::FREE) {
return buf;
}
LOG("buffer is owned by %d, type %d", buf->mStatus, aType);
}
return nullptr;
@ -689,6 +696,10 @@ OmxDataDecoder::ConfigVideoCodec()
if (def.eDir == OMX_DirInput) {
def.format.video.eCompressionFormat = codetype;
def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
if (def.nBufferSize < MIN_VIDEO_INPUT_BUFFER_SIZE) {
def.nBufferSize = videoInfo->mImage.width * videoInfo->mImage.height;
LOG("Change input buffer size to %d", def.nBufferSize);
}
} else {
def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
}
@ -749,15 +760,19 @@ OmxDataDecoder::Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2)
switch (aEvent) {
case OMX_EventPortSettingsChanged:
{
// According to spec: "To prevent the loss of any input data, the
// component issuing the OMX_EventPortSettingsChanged event on its input
// port should buffer all input port data that arrives between the
// emission of the OMX_EventPortSettingsChanged event and the arrival of
// the command to disable the input port."
//
// So client needs to disable port and reallocate buffers.
MOZ_ASSERT(mPortSettingsChanged == -1);
mPortSettingsChanged = aData1;
// Don't always disable port. See bug 1235340.
if (aData2 == 0 ||
aData2 == OMX_IndexParamPortDefinition) {
// According to spec: "To prevent the loss of any input data, the
// component issuing the OMX_EventPortSettingsChanged event on its input
// port should buffer all input port data that arrives between the
// emission of the OMX_EventPortSettingsChanged event and the arrival of
// the command to disable the input port."
//
// So client needs to disable port and reallocate buffers.
MOZ_ASSERT(mPortSettingsChanged == -1);
mPortSettingsChanged = aData1;
}
LOG("Got OMX_EventPortSettingsChanged event");
break;
}
@ -772,14 +787,6 @@ OmxDataDecoder::Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2)
return true;
}
template<class T> void
OmxDataDecoder::InitOmxParameter(T* aParam)
{
PodZero(aParam);
aParam->nSize = sizeof(T);
aParam->nVersion.s.nVersionMajor = 1;
}
bool
OmxDataDecoder::BuffersCanBeReleased(OMX_DIRTYPE aType)
{
@ -975,4 +982,150 @@ void OmxDataDecoder::FlushFailure(OmxCommandFailureHolder aFailureHolder)
mMonitor.Notify();
}
MediaDataHelper::MediaDataHelper(const TrackInfo* aTrackInfo,
layers::ImageContainer* aImageContainer,
OmxPromiseLayer* aOmxLayer)
: mTrackInfo(aTrackInfo)
, mAudioCompactor(mAudioQueue)
, mImageContainer(aImageContainer)
{
// Get latest port definition.
nsTArray<uint32_t> ports;
GetPortIndex(ports);
for (auto idx : ports) {
InitOmxParameter(&mOutputPortDef);
mOutputPortDef.nPortIndex = idx;
aOmxLayer->GetParameter(OMX_IndexParamPortDefinition, &mOutputPortDef, sizeof(mOutputPortDef));
if (mOutputPortDef.eDir == OMX_DirOutput) {
break;
}
}
}
already_AddRefed<MediaData>
MediaDataHelper::GetMediaData(BufferData* aBufferData, bool& aPlatformDepenentData)
{
aPlatformDepenentData = false;
RefPtr<MediaData> data;
if (mTrackInfo->IsAudio()) {
if (!aBufferData->mBuffer->nFilledLen) {
return nullptr;
}
data = CreateAudioData(aBufferData);
} else if (mTrackInfo->IsVideo()) {
data = aBufferData->GetPlatformMediaData();
if (data) {
aPlatformDepenentData = true;
} else {
if (!aBufferData->mBuffer->nFilledLen) {
return nullptr;
}
// Get YUV VideoData, it uses more CPU, in most cases, on software codec.
data = CreateYUV420VideoData(aBufferData);
}
// Update video time code, duration... from the raw data.
VideoData* video(data->As<VideoData>());
if (aBufferData->mRawData) {
video->mTime = aBufferData->mRawData->mTime;
video->mTimecode = aBufferData->mRawData->mTimecode;
video->mOffset = aBufferData->mRawData->mOffset;
video->mDuration = aBufferData->mRawData->mDuration;
video->mKeyframe = aBufferData->mRawData->mKeyframe;
}
}
return data.forget();
}
already_AddRefed<AudioData>
MediaDataHelper::CreateAudioData(BufferData* aBufferData)
{
RefPtr<AudioData> audio;
OMX_BUFFERHEADERTYPE* buf = aBufferData->mBuffer;
const AudioInfo* info = mTrackInfo->GetAsAudioInfo();
if (buf->nFilledLen) {
uint64_t offset = 0;
uint32_t frames = buf->nFilledLen / (2 * info->mChannels);
if (aBufferData->mRawData) {
offset = aBufferData->mRawData->mOffset;
}
typedef AudioCompactor::NativeCopy OmxCopy;
mAudioCompactor.Push(offset,
buf->nTimeStamp,
info->mRate,
frames,
info->mChannels,
OmxCopy(buf->pBuffer + buf->nOffset,
buf->nFilledLen,
info->mChannels));
audio = mAudioQueue.PopFront();
}
return audio.forget();
}
already_AddRefed<VideoData>
MediaDataHelper::CreateYUV420VideoData(BufferData* aBufferData)
{
uint8_t *yuv420p_buffer = (uint8_t *)aBufferData->mBuffer->pBuffer;
int32_t stride = mOutputPortDef.format.video.nStride;
int32_t slice_height = mOutputPortDef.format.video.nSliceHeight;
int32_t width = mTrackInfo->GetAsVideoInfo()->mImage.width;
int32_t height = mTrackInfo->GetAsVideoInfo()->mImage.height;
// TODO: convert other formats to YUV420.
if (mOutputPortDef.format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar) {
return nullptr;
}
size_t yuv420p_y_size = stride * slice_height;
size_t yuv420p_u_size = ((stride + 1) / 2) * ((slice_height + 1) / 2);
uint8_t *yuv420p_y = yuv420p_buffer;
uint8_t *yuv420p_u = yuv420p_y + yuv420p_y_size;
uint8_t *yuv420p_v = yuv420p_u + yuv420p_u_size;
VideoData::YCbCrBuffer b;
b.mPlanes[0].mData = yuv420p_y;
b.mPlanes[0].mWidth = width;
b.mPlanes[0].mHeight = height;
b.mPlanes[0].mStride = stride;
b.mPlanes[0].mOffset = 0;
b.mPlanes[0].mSkip = 0;
b.mPlanes[1].mData = yuv420p_u;
b.mPlanes[1].mWidth = (width + 1) / 2;
b.mPlanes[1].mHeight = (height + 1) / 2;
b.mPlanes[1].mStride = (stride + 1) / 2;
b.mPlanes[1].mOffset = 0;
b.mPlanes[1].mSkip = 0;
b.mPlanes[2].mData = yuv420p_v;
b.mPlanes[2].mWidth =(width + 1) / 2;
b.mPlanes[2].mHeight = (height + 1) / 2;
b.mPlanes[2].mStride = (stride + 1) / 2;
b.mPlanes[2].mOffset = 0;
b.mPlanes[2].mSkip = 0;
VideoInfo info;
info.mDisplay = mTrackInfo->GetAsVideoInfo()->mDisplay;
info.mImage = mTrackInfo->GetAsVideoInfo()->mImage;
RefPtr<VideoData> data = VideoData::Create(info,
mImageContainer,
0, // Filled later by caller.
0, // Filled later by caller.
1, // We don't know the duration.
b,
0, // Filled later by caller.
-1,
info.mImage);
LOG("YUV420 VideoData: disp width %d, height %d, pic width %d, height %d, time %ld",
info.mDisplay.width, info.mDisplay.height, info.mImage.width,
info.mImage.height, aBufferData->mBuffer->nTimeStamp);
return data.forget();
}
}

View File

@ -12,9 +12,13 @@
#include "OmxPromiseLayer.h"
#include "MediaInfo.h"
#include "AudioCompactor.h"
#include "OMX_Component.h"
#include "ImageContainer.h"
namespace mozilla {
class MediaDataHelper;
typedef OmxPromiseLayer::OmxCommandPromise OmxCommandPromise;
typedef OmxPromiseLayer::OmxBufferPromise OmxBufferPromise;
typedef OmxPromiseLayer::OmxBufferFailureHolder OmxBufferFailureHolder;
@ -110,9 +114,7 @@ protected:
// the port format is changed due to different codec specific.
void PortSettingsChanged();
void OutputAudio(BufferData* aBufferData);
void OutputVideo(BufferData* aBufferData);
void Output(BufferData* aData);
// Buffer can be released if its status is not OMX_COMPONENT or
// OMX_CLIENT_OUTPUT.
@ -136,8 +138,6 @@ protected:
BufferData* FindAvailableBuffer(OMX_DIRTYPE aType);
template<class T> void InitOmxParameter(T* aParam);
// aType could be OMX_DirMax for all types.
RefPtr<OmxPromiseLayer::OmxBufferPromise::AllPromiseType>
CollectBufferPromises(OMX_DIRTYPE aType);
@ -149,6 +149,8 @@ protected:
RefPtr<TaskQueue> mReaderTaskQueue;
RefPtr<layers::ImageContainer> mImageContainer;
WatchManager<OmxDataDecoder> mWatchManager;
// It is accessed in omx TaskQueue.
@ -185,12 +187,7 @@ protected:
BUFFERLIST mOutPortBuffers;
// For audio output.
// TODO: because this class is for both video and audio decoding, so there
// should be some kind of abstract things to these members.
MediaQueue<AudioData> mAudioQueue;
AudioCompactor mAudioCompactor;
RefPtr<MediaDataHelper> mMediaDataHelper;
MediaDataDecoderCallback* mCallback;
};

View File

@ -44,7 +44,12 @@ OmxDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
bool
OmxDecoderModule::SupportsMimeType(const nsACString& aMimeType) const
{
// TODO: it could be better to query the support mine types from OMX instead
// of hard coding.
return aMimeType.EqualsLiteral("audio/mp4a-latm") ||
aMimeType.EqualsLiteral("video/mp4v-es") ||
aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/3gp") ||
aMimeType.EqualsLiteral("video/avc");
}

View File

@ -119,7 +119,7 @@ already_AddRefed<MediaRawData>
OmxPromiseLayer::FindAndRemoveRawData(OMX_TICKS aTimecode)
{
for (auto raw : mRawDatas) {
if (raw->mTimecode == aTimecode) {
if (raw->mTime == aTimecode) {
mRawDatas.RemoveElement(raw);
return raw.forget();
}

View File

@ -25,7 +25,8 @@
#include "nsIContent.h"
#include "nsPluginInstanceOwner.h"
#include "nsWrapperCacheInlines.h"
#include "js/HashTable.h"
#include "js/GCHashTable.h"
#include "js/TracingAPI.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/plugins/PluginAsyncSurrogate.h"
@ -42,21 +43,33 @@ using namespace mozilla;
using mozilla::plugins::PluginScriptableObjectParent;
using mozilla::plugins::ParentNPObject;
struct JSObjWrapperHasher : public js::DefaultHasher<nsJSObjWrapperKey>
struct JSObjWrapperHasher
{
typedef nsJSObjWrapperKey Key;
typedef Key Lookup;
static uint32_t hash(const Lookup &l) {
return HashGeneric(l.mJSObj, l.mNpp);
return js::MovableCellHasher<JS::Heap<JSObject*>>::hash(l.mJSObj) ^
HashGeneric(l.mNpp);
}
static void rekey(Key &k, const Key& newKey) {
MOZ_ASSERT(k.mNpp == newKey.mNpp);
k.mJSObj = newKey.mJSObj;
static bool match(const Key& k, const Lookup &l) {
return js::MovableCellHasher<JS::Heap<JSObject*>>::match(k.mJSObj, l.mJSObj) &&
k.mNpp == l.mNpp;
}
};
namespace js {
template <>
struct DefaultGCPolicy<nsJSObjWrapper*> {
static void trace(JSTracer* trc, nsJSObjWrapper** wrapper, const char* name) {
MOZ_ASSERT(wrapper);
MOZ_ASSERT(*wrapper);
(*wrapper)->trace(trc);
}
};
} // namespace js
class NPObjWrapperHashEntry : public PLDHashEntryHdr
{
public:
@ -72,10 +85,10 @@ public:
// when a plugin is torn down in case there's a leak in the plugin (we
// don't want to leak the world just because a plugin leaks an
// NPObject).
typedef js::HashMap<nsJSObjWrapperKey,
nsJSObjWrapper*,
JSObjWrapperHasher,
js::SystemAllocPolicy> JSObjWrapperTable;
typedef js::GCHashMap<nsJSObjWrapperKey,
nsJSObjWrapper*,
JSObjWrapperHasher,
js::SystemAllocPolicy> JSObjWrapperTable;
static JSObjWrapperTable sJSObjWrappers;
// Whether it's safe to iterate sJSObjWrappers. Set to true when sJSObjWrappers
@ -278,20 +291,8 @@ OnWrapperDestroyed();
static void
TraceJSObjWrappers(JSTracer *trc, void *data)
{
if (!sJSObjWrappers.initialized()) {
return;
}
// Trace all JSObjects in the sJSObjWrappers table and rekey the entries if
// any of them moved.
for (JSObjWrapperTable::Enum e(sJSObjWrappers); !e.empty(); e.popFront()) {
nsJSObjWrapperKey key = e.front().key();
JS::UnsafeTraceRoot(trc, &key.mJSObj, "sJSObjWrappers key object");
nsJSObjWrapper *wrapper = e.front().value();
JS::TraceEdge(trc, &wrapper->mJSObj, "sJSObjWrappers wrapper object");
if (key != e.front().key()) {
e.rekeyFront(key);
}
if (sJSObjWrappers.initialized()) {
sJSObjWrappers.trace(trc);
}
}
@ -1079,33 +1080,6 @@ nsJSObjWrapper::NP_Construct(NPObject *npobj, const NPVariant *args,
return doInvoke(npobj, NPIdentifier_VOID, args, argCount, true, result);
}
/*
* This function is called during minor GCs for each key in the sJSObjWrappers
* table that has been moved.
*
* Note that the wrapper may be dead at this point, and even the table may have
* been finalized if all wrappers have died.
*/
static void
JSObjWrapperKeyMarkCallback(JSTracer *trc, JSObject *obj, void *data) {
NPP npp = static_cast<NPP>(data);
MOZ_ASSERT(sJSObjWrappersAccessible);
if (!sJSObjWrappers.initialized())
return;
JSObject *prior = obj;
nsJSObjWrapperKey oldKey(prior, npp);
JSObjWrapperTable::Ptr p = sJSObjWrappers.lookup(oldKey);
if (!p)
return;
js::UnsafeTraceManuallyBarrieredEdge(trc, &obj, "sJSObjWrappers key object");
nsJSObjWrapperKey newKey(obj, npp);
sJSObjWrappers.rekeyIfMoved(oldKey, newKey);
}
// Look up or create an NPObject that wraps the JSObject obj.
// static
@ -1191,16 +1165,12 @@ nsJSObjWrapper::GetNewOrUsed(NPP npp, JSContext *cx, JS::Handle<JSObject*> obj)
// Insert the new wrapper into the hashtable, rooting the JSObject. Its
// lifetime is now tied to that of the NPObject.
nsJSObjWrapperKey key(obj, npp);
if (!sJSObjWrappers.putNew(key, wrapper)) {
if (!sJSObjWrappers.putNew(nsJSObjWrapperKey(obj, npp), wrapper)) {
// Out of memory, free the wrapper we created.
_releaseobject(wrapper);
return nullptr;
}
// Add postbarrier for the hashtable key
JS_StoreObjectPostBarrierCallback(cx, JSObjWrapperKeyMarkCallback, obj, wrapper->mNpp);
return wrapper;
}

View File

@ -10,6 +10,7 @@
#include "npapi.h"
#include "npruntime.h"
#include "PLDHashTable.h"
#include "js/RootingAPI.h"
class nsJSNPRuntime
{
@ -33,7 +34,11 @@ public:
return !(*this == other);
}
JSObject * mJSObj;
void trace(JSTracer* trc) {
JS::TraceEdge(trc, &mJSObj, "nsJSObjWrapperKey");
}
JS::Heap<JSObject*> mJSObj;
const NPP mNpp;
};
@ -48,6 +53,10 @@ public:
JS::Handle<JSObject*> obj);
static bool HasOwnProperty(NPObject* npobj, NPIdentifier npid);
void trace(JSTracer* trc) {
JS::TraceEdge(trc, &mJSObj, "nsJSObjWrapper");
}
protected:
explicit nsJSObjWrapper(NPP npp);
~nsJSObjWrapper();

View File

@ -55,6 +55,7 @@ using mozilla::DefaultXDisplay;
#include "mozilla/MiscEvents.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/TextEvents.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/HTMLObjectElementBinding.h"
#include "mozilla/dom/TabChild.h"
#include "nsFrameSelection.h"

View File

@ -33,6 +33,7 @@
#include "nsCRT.h"
#include "nsIFile.h"
#include "nsIObserverService.h"
#include "nsIXULRuntime.h"
#include "nsNPAPIPlugin.h"
#include "nsPrintfCString.h"
#include "prsystem.h"
@ -679,7 +680,8 @@ PluginModuleParent::PluginModuleParent(bool aIsChrome, bool aAllowAsyncInit)
{
#if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK)
mIsStartingAsync = aAllowAsyncInit &&
Preferences::GetBool(kAsyncInitPref, false);
Preferences::GetBool(kAsyncInitPref, false) &&
!BrowserTabsRemoteAutostart();
#if defined(MOZ_CRASHREPORTER)
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AsyncPluginInit"),
mIsStartingAsync ?

View File

@ -80,6 +80,13 @@ PresentationRequest::WrapObject(JSContext* aCx,
already_AddRefed<Promise>
PresentationRequest::Start(ErrorResult& aRv)
{
return StartWithDevice(NullString(), aRv);
}
already_AddRefed<Promise>
PresentationRequest::StartWithDevice(const nsAString& aDeviceId,
ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
if (NS_WARN_IF(!global)) {
@ -124,7 +131,7 @@ PresentationRequest::Start(ErrorResult& aRv)
nsCOMPtr<nsIPresentationServiceCallback> callback =
new PresentationRequesterCallback(this, mUrl, id, promise);
rv = service->StartSession(mUrl, id, origin, callback);
rv = service->StartSession(mUrl, id, origin, aDeviceId, callback);
if (NS_WARN_IF(NS_FAILED(rv))) {
promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
}

View File

@ -33,6 +33,9 @@ public:
// WebIDL (public APIs)
already_AddRefed<Promise> Start(ErrorResult& aRv);
already_AddRefed<Promise> StartWithDevice(const nsAString& aDeviceId,
ErrorResult& aRv);
already_AddRefed<Promise> GetAvailability(ErrorResult& aRv);
IMPL_EVENT_HANDLER(connectionavailable);

View File

@ -384,6 +384,7 @@ NS_IMETHODIMP
PresentationService::StartSession(const nsAString& aUrl,
const nsAString& aSessionId,
const nsAString& aOrigin,
const nsAString& aDeviceId,
nsIPresentationServiceCallback* aCallback)
{
MOZ_ASSERT(NS_IsMainThread());
@ -396,20 +397,62 @@ PresentationService::StartSession(const nsAString& aUrl,
new PresentationControllingInfo(aUrl, aSessionId, aCallback);
mSessionInfo.Put(aSessionId, info);
// Pop up a prompt and ask user to select a device.
nsCOMPtr<nsIPresentationDevicePrompt> prompt =
do_GetService(PRESENTATION_DEVICE_PROMPT_CONTRACTID);
if (NS_WARN_IF(!prompt)) {
return info->ReplyError(NS_ERROR_DOM_OPERATION_ERR);
}
nsCOMPtr<nsIPresentationDeviceRequest> request =
new PresentationDeviceRequest(aUrl, aSessionId, aOrigin);
nsresult rv = prompt->PromptDeviceSelection(request);
if (aDeviceId.IsVoid()) {
// Pop up a prompt and ask user to select a device.
nsCOMPtr<nsIPresentationDevicePrompt> prompt =
do_GetService(PRESENTATION_DEVICE_PROMPT_CONTRACTID);
if (NS_WARN_IF(!prompt)) {
return info->ReplyError(NS_ERROR_DOM_OPERATION_ERR);
}
nsresult rv = prompt->PromptDeviceSelection(request);
if (NS_WARN_IF(NS_FAILED(rv))) {
return info->ReplyError(NS_ERROR_DOM_OPERATION_ERR);
}
return NS_OK;
}
// Find the designated device from available device list.
nsCOMPtr<nsIPresentationDeviceManager> deviceManager =
do_GetService(PRESENTATION_DEVICE_MANAGER_CONTRACTID);
if (NS_WARN_IF(!deviceManager)) {
return info->ReplyError(NS_ERROR_DOM_OPERATION_ERR);
}
nsCOMPtr<nsIArray> devices;
nsresult rv = deviceManager->GetAvailableDevices(getter_AddRefs(devices));
if (NS_WARN_IF(NS_FAILED(rv))) {
return info->ReplyError(NS_ERROR_DOM_OPERATION_ERR);
}
return NS_OK;
nsCOMPtr<nsISimpleEnumerator> enumerator;
rv = devices->Enumerate(getter_AddRefs(enumerator));
if (NS_WARN_IF(NS_FAILED(rv))) {
return info->ReplyError(NS_ERROR_DOM_OPERATION_ERR);
}
NS_ConvertUTF16toUTF8 utf8DeviceId(aDeviceId);
bool hasMore;
while(NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore){
nsCOMPtr<nsISupports> isupports;
rv = enumerator->GetNext(getter_AddRefs(isupports));
nsCOMPtr<nsIPresentationDevice> device(do_QueryInterface(isupports));
MOZ_ASSERT(device);
nsAutoCString id;
if (NS_SUCCEEDED(device->GetId(id)) && id.Equals(utf8DeviceId)) {
request->Select(device);
return NS_OK;
}
}
// Reject if designated device is not available.
return info->ReplyError(NS_ERROR_DOM_NOT_FOUND_ERR);
}
NS_IMETHODIMP

View File

@ -33,7 +33,7 @@ interface nsIPresentationServiceCallback : nsISupports
void notifyError(in nsresult error);
};
[scriptable, uuid(c177a13a-bf1a-48bf-8032-d415c3343c46)]
[scriptable, uuid(2e360359-c45c-4949-bf95-410242ce483f)]
interface nsIPresentationService : nsISupports
{
/*
@ -43,6 +43,8 @@ interface nsIPresentationService : nsISupports
* @param url: The url of presenting page.
* @param sessionId: An ID to identify presentation session.
* @param origin: The url of requesting page.
* @param deviceId: The specified device of handling this request, null string
for prompt device selection dialog.
* @param callback: Invoke the callback when the operation is completed.
* NotifySuccess() is called with |id| if a session is
* established successfully with the selected device.
@ -51,6 +53,7 @@ interface nsIPresentationService : nsISupports
void startSession(in DOMString url,
in DOMString sessionId,
in DOMString origin,
in DOMString deviceId,
in nsIPresentationServiceCallback callback);
/*

View File

@ -17,6 +17,7 @@ struct StartSessionRequest
nsString url;
nsString sessionId;
nsString origin;
nsString deviceId;
};
struct SendSessionMessageRequest

View File

@ -49,10 +49,13 @@ NS_IMETHODIMP
PresentationIPCService::StartSession(const nsAString& aUrl,
const nsAString& aSessionId,
const nsAString& aOrigin,
const nsAString& aDeviceId,
nsIPresentationServiceCallback* aCallback)
{
return SendRequest(aCallback,
StartSessionRequest(nsAutoString(aUrl), nsAutoString(aSessionId), nsAutoString(aOrigin)));
return SendRequest(aCallback, StartSessionRequest(nsAutoString(aUrl),
nsAutoString(aSessionId),
nsAutoString(aOrigin),
nsAutoString(aDeviceId)));
}
NS_IMETHODIMP

View File

@ -252,7 +252,7 @@ PresentationRequestParent::DoRequest(const StartSessionRequest& aRequest)
{
MOZ_ASSERT(mService);
return mService->StartSession(aRequest.url(), aRequest.sessionId(),
aRequest.origin(), this);
aRequest.origin(), aRequest.deviceId(), this);
}
nsresult

View File

@ -17,6 +17,8 @@ skip-if = toolkit == 'android' # Bug 1129785
skip-if = toolkit == 'android' # Bug 1129785
[test_presentation_sender_default_request.html]
skip-if = toolkit == 'android' # Bug 1129785
[test_presentation_sender_startWithDevice.html]
skip-if = toolkit == 'android' # Bug 1129785
[test_presentation_receiver_establish_connection_error.html]
skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android' || os == 'mac' || os == 'win' || buildapp == 'mulet') # Bug 1129785, Bug 1204709
[test_presentation_receiver_establish_connection_timeout.html]

View File

@ -0,0 +1,173 @@
<!DOCTYPE HTML>
<html>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<head>
<meta charset="utf-8">
<title>Test startWithDevice for B2G Presentation API at sender side</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1239242">Test startWithDevice for B2G Presentation API at sender side</a>
<script type="application/javascript;version=1.8">
'use strict';
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript.js'));
var request;
var connection;
function testSetup() {
return new Promise(function(aResolve, aReject) {
request = new PresentationRequest("http://example.com");
request.getAvailability().then(
function(aAvailability) {
aAvailability.onchange = function() {
aAvailability.onchange = null;
ok(aAvailability.value, "Device should be available.");
aResolve();
}
},
function(aError) {
ok(false, "Error occurred when getting availability: " + aError);
teardown();
aReject();
}
);
gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartConnectionWithDevice() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
gScript.removeMessageListener('device-prompt', devicePromptHandler);
ok(false, "Device prompt should not be triggered.");
teardown();
aReject();
});
gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
gScript.removeMessageListener('control-channel-established', controlChannelEstablishedHandler);
info("A control channel is established.");
gScript.sendAsyncMessage('trigger-control-channel-open');
});
gScript.addMessageListener('control-channel-opened', function controlChannelOpenedHandler(aReason) {
gScript.removeMessageListener('control-channel-opened', controlChannelOpenedHandler);
info("The control channel is opened.");
});
gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
info("The control channel is closed. " + aReason);
});
gScript.addMessageListener('offer-sent', function offerSentHandler(aIsValid) {
gScript.removeMessageListener('offer-sent', offerSentHandler);
ok(aIsValid, "A valid offer is sent out.");
gScript.sendAsyncMessage('trigger-incoming-transport');
});
gScript.addMessageListener('answer-received', function answerReceivedHandler() {
gScript.removeMessageListener('answer-received', answerReceivedHandler);
info("An answer is received.");
});
gScript.addMessageListener('data-transport-initialized', function dataTransportInitializedHandler() {
gScript.removeMessageListener('data-transport-initialized', dataTransportInitializedHandler);
info("Data transport channel is initialized.");
gScript.sendAsyncMessage('trigger-incoming-answer');
});
gScript.addMessageListener('data-transport-notification-enabled', function dataTransportNotificationEnabledHandler() {
gScript.removeMessageListener('data-transport-notification-enabled', dataTransportNotificationEnabledHandler);
info("Data notification is enabled for data transport channel.");
});
var connectionFromEvent;
request.onconnectionavailable = function(aEvent) {
request.onconnectionavailable = null;
connectionFromEvent = aEvent.connection;
ok(connectionFromEvent, "|connectionavailable| event is fired with a connection.");
if (connection) {
is(connection, connectionFromEvent, "The connection from promise and the one from |connectionavailable| event should be the same.");
aResolve();
}
};
request.startWithDevice('id').then(
function(aConnection) {
connection = aConnection;
ok(connection, "Connection should be available.");
ok(connection.id, "Connection ID should be set.");
is(connection.state, "connected", "Connection state at sender side should be connected by default.");
if (connectionFromEvent) {
is(connection, connectionFromEvent, "The connection from promise and the one from |connectionavailable| event should be the same.");
aResolve();
}
},
function(aError) {
ok(false, "Error occurred when establishing a connection: " + aError);
teardown();
aReject();
}
);
});
}
function testStartConnectionWithDeviceNotFoundError() {
return new Promise(function(aResolve, aReject) {
request.startWithDevice('').then(
function(aConnection) {
ok(false, "Should not establish connection to an unknown device");
teardown();
aReject();
},
function(aError) {
is(aError.name, 'NotFoundError', "Expect NotFoundError occurred when establishing a connection");
aResolve();
}
);
});
}
function teardown() {
gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
gScript.removeMessageListener('teardown-complete', teardownCompleteHandler);
gScript.destroy();
SimpleTest.finish();
});
gScript.sendAsyncMessage('teardown');
}
function runTests() {
ok(window.PresentationRequest, "PresentationRequest should be available.");
testSetup().
then(testStartConnectionWithDevice).
then(testStartConnectionWithDeviceNotFoundError).
then(teardown);
}
//SimpleTest.expectAssertions(0, 5);
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPermissions([
{type: 'presentation-device-manage', allow: true, context: document},
{type: 'presentation', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0]]},
runTests);
});
</script>
</body>
</html>

View File

@ -410,7 +410,9 @@ nsCSPContext::reportInlineViolation(nsContentPolicyType aContentType,
// use selfURI as the sourceFile
nsAutoCString sourceFile;
mSelfURI->GetSpec(sourceFile);
if (mSelfURI) {
mSelfURI->GetSpec(sourceFile);
}
nsAutoString codeSample(aContent);
// cap the length of the script sample at 40 chars
@ -591,6 +593,7 @@ nsCSPContext::SetRequestContext(nsIDOMDocument* aDOMDocument,
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDOMDocument);
mLoadingContext = do_GetWeakReference(doc);
mSelfURI = doc->GetDocumentURI();
mLoadingPrincipal = doc->NodePrincipal();
doc->GetReferrer(mReferrer);
mInnerWindowID = doc->InnerWindowID();
// the innerWindowID is not available for CSPs delivered through the
@ -668,6 +671,51 @@ nsCSPContext::logToConsole(const char16_t* aName,
aSeverityFlag, "CSP", mInnerWindowID);
}
/**
* Strip URI for reporting according to:
* http://www.w3.org/TR/CSP/#violation-reports
*
* @param aURI
* The uri to be stripped for reporting
* @param aProtectedResourcePrincipal
* The loadingPrincipal of the protected resource
* which is needed to enforce the SOP.
* @return ASCII serialization of the uri to be reported.
*/
void
StripURIForReporting(nsIURI* aURI,
nsIPrincipal* aProtectedResourcePrincipal,
nsACString& outStrippedURI)
{
// 1) If the origin of uri is a globally unique identifier (for example,
// aURI has a scheme of data, blob, or filesystem), then return the
// ASCII serialization of uris scheme.
bool isHttp =
(NS_SUCCEEDED(aURI->SchemeIs("http", &isHttp)) && isHttp) ||
(NS_SUCCEEDED(aURI->SchemeIs("https", &isHttp)) && isHttp);
if (!isHttp) {
// not strictly spec compliant, but what we really care about is
// http/https. If it's not http/https, then treat aURI as if
// it's a globally unique identifier and just return the scheme.
aURI->GetScheme(outStrippedURI);
return;
}
// 2) If the origin of uri is not the same as the origin of the protected
// resource, then return the ASCII serialization of uris origin.
bool sameOrigin =
NS_SUCCEEDED(aProtectedResourcePrincipal->CheckMayLoad(aURI, false, false));
if (!sameOrigin) {
// cross origin redirects also fall into this category, see:
// http://www.w3.org/TR/CSP/#violation-reports
aURI->GetPrePath(outStrippedURI);
return;
}
// 3) Return uri, with any fragment component removed.
aURI->GetSpecIgnoringRef(outStrippedURI);
}
/**
* Sends CSP violation reports to all sources listed under report-uri.
*
@ -714,15 +762,7 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
nsCOMPtr<nsIURI> uri = do_QueryInterface(aBlockedContentSource);
// could be a string or URI
if (uri) {
// aOriginalURI will only be *not* null in case of a redirect in which
// case aOriginalURI is the uri before the redirect.
if (aOriginalURI) {
// do not report anything else than the origin in case of a redirect, see:
// http://www.w3.org/TR/CSP/#violation-reports
uri->GetPrePath(reportBlockedURI);
} else {
uri->GetSpecIgnoringRef(reportBlockedURI);
}
StripURIForReporting(uri, mLoadingPrincipal, reportBlockedURI);
} else {
nsCOMPtr<nsISupportsCString> cstr = do_QueryInterface(aBlockedContentSource);
if (cstr) {
@ -739,7 +779,7 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
// document-uri
nsAutoCString reportDocumentURI;
mSelfURI->GetSpecIgnoringRef(reportDocumentURI);
StripURIForReporting(mSelfURI, mLoadingPrincipal, reportDocumentURI);
report.mCsp_report.mDocument_uri = NS_ConvertUTF8toUTF16(reportDocumentURI);
// original-policy

View File

@ -310,7 +310,7 @@ nsMixedContentBlocker::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
}
int16_t decision = REJECT_REQUEST;
rv = ShouldLoad(nsContentUtils::InternalContentPolicyTypeToExternalOrScript(contentPolicyType),
rv = ShouldLoad(nsContentUtils::InternalContentPolicyTypeToExternalOrMCBInternal(contentPolicyType),
newUri,
requestingLocation,
loadInfo->LoadingNode(),
@ -378,9 +378,11 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
// to them.
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternalOrScript(aContentType),
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternalOrMCBInternal(aContentType),
"We should only see external content policy types here.");
bool isPreload = nsContentUtils::IsPreloadType(aContentType);
// The content policy type that we receive may be an internal type for
// scripts. Let's remember if we have seen a worker type, and reset it to the
// external type in all cases right now.
@ -668,7 +670,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
bool isHttpScheme = false;
rv = aContentLocation->SchemeIs("http", &isHttpScheme);
NS_ENSURE_SUCCESS(rv, rv);
if (isHttpScheme && docShell->GetDocument()->GetUpgradeInsecureRequests()) {
if (isHttpScheme && docShell->GetDocument()->GetUpgradeInsecureRequests(isPreload)) {
*aDecision = ACCEPT;
return NS_OK;
}

View File

@ -2,13 +2,10 @@
<head>
<link rel='stylesheet' type='text/css'
href='/tests/dom/security/test/csp/file_CSP.sjs?testid=css_self&type=text/css' />
<link rel='stylesheet' type='text/css'
href='http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=css_examplecom&type=text/css' />
</head>
<body>
<img src="/tests/dom/security/test/csp/file_CSP.sjs?testid=img_self&type=img/png"> </img>
<img src="http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=img_examplecom&type=img/png"> </img>
<script src='/tests/dom/security/test/csp/file_CSP.sjs?testid=script_self&type=text/javascript'></script>
</body>

View File

@ -20,21 +20,15 @@ var path = "/tests/dom/security/test/csp/";
// true/false is the pass/fail result.
window.loads = {
css_self: {expected: true, verified: false},
css_examplecom: {expected: false, verified: false},
img_self: {expected: false, verified: false},
img_examplecom: {expected: false, verified: false},
script_self: {expected: true, verified: false},
};
window.violation_reports = {
css_self:
{expected: 0, expected_ro: 0}, /* totally fine */
css_examplecom:
{expected: 1, expected_ro: 0}, /* violates enforced CSP */
img_self:
{expected: 1, expected_ro: 0}, /* violates enforced CSP */
img_examplecom:
{expected: 1, expected_ro: 1}, /* violates both CSPs */
script_self:
{expected: 0, expected_ro: 1}, /* violates report-only */
};

View File

@ -57,7 +57,7 @@ function checkResults(reportStr) {
"http://mochi.test:8888/tests/dom/security/test/csp/file_report_for_import_server.sjs?report",
"Incorrect original-policy");
is(cspReport["blocked-uri"],
"http://example.com/tests/dom/security/test/csp/file_report_for_import_server.sjs?stylesheet",
"http://example.com",
"Incorrect blocked-uri");
// we do not always set the following fields

View File

@ -39,9 +39,9 @@ function makeReportHandler(testpath, message, expectedJSON) {
request.bodyInputStream,
request.bodyInputStream.available()));
dump("GOT REPORT:\n" + JSON.stringify(reportObj) + "\n");
dump("TESTPATH: " + testpath + "\n");
dump("EXPECTED: \n" + JSON.stringify(expectedJSON) + "\n\n");
// dump("GOT REPORT:\n" + JSON.stringify(reportObj) + "\n");
// dump("TESTPATH: " + testpath + "\n");
// dump("EXPECTED: \n" + JSON.stringify(expectedJSON) + "\n\n");
for (var i in expectedJSON)
do_check_eq(expectedJSON[i], reportObj['csp-report'][i]);
@ -132,7 +132,7 @@ function run_test() {
}
});
makeTest(2, {"blocked-uri": "http://blocked.test/foo.js"}, false,
makeTest(2, {"blocked-uri": "http://blocked.test"}, false,
function(csp) {
// shouldLoad creates and sends out the report here.
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT,
@ -172,4 +172,36 @@ function run_test() {
4);
}
});
// test that only the uri's scheme is reported for globally unique identifiers
makeTest(5, {"blocked-uri": "data"}, false,
function(csp) {
var base64data =
"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" +
"P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
// shouldLoad creates and sends out the report here.
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE,
NetUtil.newURI("data:image/png;base64," + base64data),
null, null, null, null);
});
// test that only the uri's scheme is reported for globally unique identifiers
makeTest(6, {"blocked-uri": "intent"}, false,
function(csp) {
// shouldLoad creates and sends out the report here.
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SUBDOCUMENT,
NetUtil.newURI("intent://mymaps.com/maps?um=1&ie=UTF-8&fb=1&sll"),
null, null, null, null);
});
// test fragment removal
var selfSpec = REPORT_SERVER_URI + ":" + REPORT_SERVER_PORT + "/foo/self/foo.js";
makeTest(7, {"blocked-uri": selfSpec}, false,
function(csp) {
var uri = NetUtil
// shouldLoad creates and sends out the report here.
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT,
NetUtil.newURI(selfSpec + "#bar"),
null, null, null, null);
});
}

View File

@ -70,6 +70,7 @@ skip-if = android_version == '18' # bug 1147994
[test_pointer-events-7.xhtml]
[test_scientific.html]
[test_selectSubString.xhtml]
[test_style_sheet.html]
[test_stroke-hit-testing.xhtml]
[test_stroke-linecap-hit-testing.xhtml]
[test_SVGLengthList-2.xhtml]

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<title>Test for Bug 1239128</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1239128">Mozilla Bug 1239128</a>
<p id="display"</p>
<svg>
<style>svg { fill: blue; }</style>
</svg>
<pre id="test">
<script class="testbody" type="application/javascript">
var style = document.querySelector("style");
var exceptionThrown = false;
try {
is(style.sheet.cssRules[0].cssText, "svg { fill: blue; }",
"Should get the fill: blue rule back");
} catch (e) {
exceptionThrown = true;
}
ok(!exceptionThrown, "Should be able to access data: <style> stylesheet");
</script>
</pre>

View File

@ -128,6 +128,8 @@ var interfaceNamesInGlobalScope =
{name: "Animation", release: false},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "AnimationEffectReadOnly", release: false},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "AnimationEffectTimingReadOnly", release: false},
// IMPORTANT: Do not change this list without review from a DOM peer!
"AnimationEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!

View File

@ -46,9 +46,8 @@ dictionary ComputedTimingProperties : AnimationEffectTimingProperties {
[Func="nsDocument::IsWebAnimationsEnabled"]
interface AnimationEffectReadOnly {
// Not yet implemented:
// readonly attribute AnimationEffectTimingReadOnly timing;
[Cached, Constant]
readonly attribute AnimationEffectTimingReadOnly timing;
[BinaryName="getComputedTimingAsDict"]
ComputedTimingProperties getComputedTiming();
};

View File

@ -0,0 +1,23 @@
/* -*- 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/.
*
* The origin of this IDL file is
* https://w3c.github.io/web-animations/#animationeffecttimingreadonly
*
* Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
[Func="nsDocument::IsWebAnimationsEnabled"]
interface AnimationEffectTimingReadOnly {
readonly attribute double delay;
readonly attribute double endDelay;
readonly attribute FillMode fill;
readonly attribute double iterationStart;
readonly attribute unrestricted double iterations;
readonly attribute (unrestricted double or DOMString) duration;
readonly attribute PlaybackDirection direction;
readonly attribute DOMString easing;
};

View File

@ -43,4 +43,24 @@ interface PresentationRequest : EventTarget {
* The event is fired for all connections that are created for the controller.
*/
attribute EventHandler onconnectionavailable;
/*
* A chrome page, or page which has presentation-device-manage permissiongs,
* uses startWithDevice() to start a new connection with specified device,
* and it will be returned with the promise. UA may show a prompt box with a
* list of available devices and ask the user to grant permission, choose a
* device, or cancel the operation.
*
* The promise is resolved when the presenting page is successfully loaded and
* the communication channel is established, i.e., the connection state is
* "connected".
*
* The promise may be rejected duo to one of the following reasons:
* - "OperationError": Unexpected error occurs.
* - "NotFoundError": No available device.
* - "NetworkError": Failed to establish the control channel or data channel.
* - "TimeoutError": Presenting page takes too long to load.
*/
[CheckAnyPermissions="presentation-device-manage", Throws]
Promise<PresentationConnection> startWithDevice(DOMString deviceId);
};

View File

@ -22,4 +22,5 @@ interface SVGStyleElement : SVGElement {
[SetterThrows]
attribute boolean scoped;
};
SVGStyleElement implements LinkStyle;

View File

@ -24,6 +24,7 @@ WEBIDL_FILES = [
'Animatable.webidl',
'Animation.webidl',
'AnimationEffectReadOnly.webidl',
'AnimationEffectTimingReadOnly.webidl',
'AnimationEvent.webidl',
'AnimationTimeline.webidl',
'AnonymousContent.webidl',

View File

@ -1185,13 +1185,6 @@ private:
MOZ_ASSERT(aWorkerPrivate->IsServiceWorker());
GlobalObject globalObj(aCx, aWorkerPrivate->GlobalScope()->GetWrapper());
NS_ConvertUTF8toUTF16 local(mSpec);
RequestOrUSVString requestInfo;
requestInfo.SetAsUSVString().Rebind(local.Data(), local.Length());
RootedDictionary<RequestInit> reqInit(aCx);
reqInit.mMethod.Construct(mMethod);
RefPtr<InternalHeaders> internalHeaders = new InternalHeaders(HeadersGuardEnum::Request);
MOZ_ASSERT(mHeaderNames.Length() == mHeaderValues.Length());
for (uint32_t i = 0; i < mHeaderNames.Length(); i++) {
@ -1203,35 +1196,30 @@ private:
}
}
RefPtr<Headers> headers = new Headers(globalObj.GetAsSupports(), internalHeaders);
reqInit.mHeaders.Construct();
reqInit.mHeaders.Value().SetAsHeaders() = headers;
reqInit.mMode.Construct(mRequestMode);
reqInit.mRedirect.Construct(mRequestRedirect);
reqInit.mCredentials.Construct(mRequestCredentials);
ErrorResult result;
RefPtr<Request> request = Request::Constructor(globalObj, requestInfo, reqInit, result);
internalHeaders->SetGuard(HeadersGuardEnum::Immutable, result);
if (NS_WARN_IF(result.Failed())) {
result.SuppressException();
return false;
}
RefPtr<InternalRequest> internalReq = new InternalRequest(mSpec,
mMethod,
internalHeaders.forget(),
mRequestMode,
mRequestRedirect,
mRequestCredentials,
NS_ConvertUTF8toUTF16(mReferrer),
mContentPolicyType);
internalReq->SetBody(mUploadStream);
// For Telemetry, note that this Request object was created by a Fetch event.
RefPtr<InternalRequest> internalReq = request->GetInternalRequest();
MOZ_ASSERT(internalReq);
internalReq->SetCreatedByFetchEvent();
internalReq->SetBody(mUploadStream);
internalReq->SetReferrer(NS_ConvertUTF8toUTF16(mReferrer));
request->SetContentPolicyType(mContentPolicyType);
request->GetInternalHeaders()->SetGuard(HeadersGuardEnum::Immutable, result);
if (NS_WARN_IF(result.Failed())) {
result.SuppressException();
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(globalObj.GetAsSupports());
if (NS_WARN_IF(!global)) {
return false;
}
RefPtr<Request> request = new Request(global, internalReq);
// TODO: remove conditional on http here once app protocol support is
// removed from service worker interception

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