merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-07-31 12:57:22 +02:00
commit 8457c6a69a
240 changed files with 5504 additions and 4947 deletions

View File

@ -989,8 +989,8 @@ pref("browser.autofocus", false);
// Enable wakelock
pref("dom.wakelock.enabled", true);
// Disable touch caret by default
pref("touchcaret.enabled", false);
// Enable touch caret by default
pref("touchcaret.enabled", true);
// Disable selection caret by default
pref("selectioncaret.enabled", false);

View File

@ -22,9 +22,6 @@ const Cu = Components.utils;
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
// Preloading the CSP jsm in this process early on.
Cu.import("resource://gre/modules/CSPUtils.jsm");
function debug(msg) {
log(msg);
}

View File

@ -490,8 +490,6 @@
@BINPATH@/components/formautofill.manifest
@BINPATH@/components/FormAutofillContentService.js
@BINPATH@/components/FormAutofillStartup.js
@BINPATH@/components/contentSecurityPolicy.manifest
@BINPATH@/components/contentSecurityPolicy.js
@BINPATH@/components/contentAreaDropListener.manifest
@BINPATH@/components/contentAreaDropListener.js
@BINPATH@/components/messageWakeupService.js

View File

@ -9,33 +9,17 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/Services.jsm");
const reporter = Cc["@mozilla.org/datareporting/service;1"]
.getService(Ci.nsISupports)
.wrappedJSObject
.healthReporter;
const policy = Cc["@mozilla.org/datareporting/service;1"]
.getService(Ci.nsISupports)
.wrappedJSObject
.policy;
const prefs = new Preferences("datareporting.healthreport.");
let healthReportWrapper = {
init: function () {
if (!reporter) {
healthReportWrapper.handleInitFailure();
return;
}
reporter.onInit().then(healthReportWrapper.refreshPayload,
healthReportWrapper.handleInitFailure);
let iframe = document.getElementById("remote-report");
iframe.addEventListener("load", healthReportWrapper.initRemotePage, false);
let report = this._getReportURI();
iframe.src = report.spec;
iframe.src = this._getReportURI().spec;
iframe.onload = () => {
MozSelfSupport.getHealthReportPayload().then(this.updatePayload,
this.handleInitFailure);
};
prefs.observe("uploadEnabled", this.updatePrefState, healthReportWrapper);
},
@ -48,36 +32,30 @@ let healthReportWrapper = {
return Services.io.newURI(url, null, null);
},
onOptIn: function () {
policy.recordHealthReportUploadEnabled(true,
"Health report page sent opt-in command.");
this.updatePrefState();
},
onOptOut: function () {
policy.recordHealthReportUploadEnabled(false,
"Health report page sent opt-out command.");
setDataSubmission: function (enabled) {
MozSelfSupport.healthReportDataSubmissionEnabled = enabled;
this.updatePrefState();
},
updatePrefState: function () {
try {
let prefs = {
enabled: policy.healthReportUploadEnabled,
}
this.injectData("prefs", prefs);
} catch (e) {
this.reportFailure(this.ERROR_PREFS_FAILED);
enabled: MozSelfSupport.healthReportDataSubmissionEnabled,
};
healthReportWrapper.injectData("prefs", prefs);
}
catch (ex) {
healthReportWrapper.reportFailure(healthReportWrapper.ERROR_PREFS_FAILED);
}
},
refreshPayload: function () {
reporter.collectAndObtainJSONPayload().then(healthReportWrapper.updatePayload,
healthReportWrapper.handlePayloadFailure);
MozSelfSupport.getHealthReportPayload().then(this.updatePayload,
this.handlePayloadFailure);
},
updatePayload: function (data) {
healthReportWrapper.injectData("payload", data);
updatePayload: function (payload) {
healthReportWrapper.injectData("payload", JSON.stringify(payload));
},
injectData: function (type, content) {
@ -99,10 +77,10 @@ let healthReportWrapper = {
handleRemoteCommand: function (evt) {
switch (evt.detail.command) {
case "DisableDataSubmission":
this.onOptOut();
this.setDataSubmission(false);
break;
case "EnableDataSubmission":
this.onOptIn();
this.setDataSubmission(true);
break;
case "RequestCurrentPrefs":
this.updatePrefState();

View File

@ -17,6 +17,7 @@ DIRS += [
'search',
'sessionstore',
'shell',
'selfsupport',
'sidebar',
'tabview',
'translation',

View File

@ -0,0 +1,74 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const policy = Cc["@mozilla.org/datareporting/service;1"]
.getService(Ci.nsISupports)
.wrappedJSObject
.policy;
XPCOMUtils.defineLazyGetter(this, "reporter", () => {
return Cc["@mozilla.org/datareporting/service;1"]
.getService(Ci.nsISupports)
.wrappedJSObject
.healthReporter;
});
function MozSelfSupportInterface() {
}
MozSelfSupportInterface.prototype = {
classDescription: "MozSelfSupport",
classID: Components.ID("{d30aae8b-f352-4de3-b936-bb9d875df0bb}"),
contractID: "@mozilla.org/mozselfsupport;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
Ci.nsIObserver]),
_window: null,
init: function (window) {
this._window = window;
// FIXME: Remove this hack after static attributes work for JS-implemented
// WebIDL (see bug 863952). For a detailed description of how this works,
// see the comment accompanying the init function of amInstallTrigger.js.
return window.MozSelfSupportImpl._create(this._window, this);
},
get healthReportDataSubmissionEnabled() {
return policy.healthReportUploadEnabled;
},
set healthReportDataSubmissionEnabled(enabled) {
let reason = "Self-support interface sent " +
(enabled ? "opt-in" : "opt-out") +
" command.";
policy.recordHealthReportUploadEnabled(enabled, reason);
},
getHealthReportPayload: function () {
return new this._window.Promise(function (aResolve, aReject) {
if (reporter) {
let resolvePayload = function () {
reporter.collectAndObtainJSONPayload(true).then(aResolve, aReject);
};
if (reporter.initialized) {
resolvePayload();
} else {
reporter.onInit().then(resolvePayload, aReject);
}
} else {
aReject(new Error("No reporter"));
}
}.bind(this));
},
}
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MozSelfSupportInterface]);

View File

@ -0,0 +1,4 @@
component {d30aae8b-f352-4de3-b936-bb9d875df0bb} SelfSupportService.js
contract @mozilla.org/mozselfsupport;1 {d30aae8b-f352-4de3-b936-bb9d875df0bb}
category JavaScript-global-privileged-property MozSelfSupport @mozilla.org/mozselfsupport;1

View File

@ -0,0 +1,10 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXTRA_COMPONENTS += [
'SelfSupportService.js',
'SelfSupportService.manifest',
]

View File

@ -452,8 +452,6 @@
@BINPATH@/components/formautofill.manifest
@BINPATH@/components/FormAutofillContentService.js
@BINPATH@/components/FormAutofillStartup.js
@BINPATH@/components/contentSecurityPolicy.manifest
@BINPATH@/components/contentSecurityPolicy.js
@BINPATH@/components/contentAreaDropListener.manifest
@BINPATH@/components/contentAreaDropListener.js
@BINPATH@/browser/components/BrowserProfileMigrators.manifest
@ -489,6 +487,8 @@
#endif
#ifdef MOZ_SERVICES_HEALTHREPORT
@BINPATH@/components/HealthReportComponents.manifest
@BINPATH@/browser/components/SelfSupportService.manifest
@BINPATH@/browser/components/SelfSupportService.js
#endif
#ifdef MOZ_SERVICES_SYNC
@BINPATH@/components/SyncComponents.manifest

View File

@ -60,6 +60,8 @@ http://127.0.0.1:80 privileged
http://127.0.0.1:8888 privileged
http://test:80 privileged
http://mochi.test:8888 privileged
http://test1.mochi.test:8888
http://test2.mochi.test:8888
http://example.org:80 privileged
http://test1.example.org:80 privileged
http://test2.example.org:80 privileged

View File

@ -530,10 +530,10 @@ nsPrincipal::Read(nsIObjectInputStream* aStream)
rv = SetCsp(csp);
NS_ENSURE_SUCCESS(rv, rv);
// need to link in the CSP context here (link in a reference to this
// nsIPrincipal and to the URI of the protected resource).
// need to link in the CSP context here (link in the URI of the protected
// resource).
if (csp) {
csp->SetRequestContext(codebase, nullptr, this, nullptr);
csp->SetRequestContext(codebase, nullptr, nullptr);
}
SetDomain(domain);

View File

@ -5094,6 +5094,9 @@ if test -n "$MOZ_APPLEMEDIA"; then
# hack in frameworks for fmp4 - see bug 1029974
# We load VideoToolbox and CoreMedia dynamically, so they don't appear here.
LDFLAGS="$LDFLAGS -framework AudioToolbox"
dnl Verify CoreMedia is available.
AC_CHECK_HEADER([CoreMedia/CoreMedia.h], [],
[AC_MSG_ERROR([MacOS X 10.7 SDK or later is required])])
fi
dnl ========================================================

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="host"></div>
<script>
var s = host.createShadowRoot();
s.innerHTML = '<input type="range" />';
</script>
</body>
</html>

View File

@ -151,3 +151,4 @@ load 942979.html
load 978646.html
load 1026714.html
pref(dom.webcomponents.enabled,true) load 1027461-1.html
pref(dom.webcomponents.enabled,true) load 1024428-1.html

View File

@ -151,7 +151,7 @@ interface nsIContentPolicy : nsISupports
const nsContentPolicyType TYPE_BEACON = 19;
/* When adding new content types, please update nsContentBlocker,
* NS_CP_ContentTypeName, contentSecurityPolicy.js, all nsIContentPolicy
* NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy
* implementations, and other things that are not listed here that are
* related to nsIContentPolicy. */

View File

@ -17,17 +17,10 @@ interface nsIPrincipal;
* one of these per document/principal.
*/
[scriptable, uuid(3e923bf6-a974-4f3b-91c4-b4fd48b37732)]
[scriptable, uuid(ee599622-99e3-491a-890e-6ee254bf1390)]
interface nsIContentSecurityPolicy : nsISerializable
{
/**
* Set to true when the CSP has been read in and parsed and is ready to
* enforce. This is a barrier for the nsDocument so it doesn't load any
* sub-content until either it knows that a CSP is ready or will not be used.
*/
readonly attribute boolean isInitialized;
/**
* Accessor method for a read-only string version of the policy at a given
* index.
@ -50,14 +43,11 @@ interface nsIContentSecurityPolicy : nsISerializable
* Parse and install a CSP policy.
* @param aPolicy
* String representation of the policy (e.g., header value)
* @param selfURI
* the URI of the protected document/principal
* @param reportOnly
* Should this policy affect content, script and style processing or
* just send reports if it is violated?
*/
void appendPolicy(in AString policyString, in nsIURI selfURI,
in boolean reportOnly);
void appendPolicy(in AString policyString, in boolean reportOnly);
/**
* Whether this policy allows in-page script.
@ -188,7 +178,6 @@ interface nsIContentSecurityPolicy : nsISerializable
*/
void setRequestContext(in nsIURI selfURI,
in nsIURI referrer,
in nsIPrincipal documentPrincipal,
in nsIChannel aChannel);
/**

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +0,0 @@
component {d1680bb4-1ac0-4772-9437-1188375e44f2} contentSecurityPolicy.js
contract @mozilla.org/contentsecuritypolicy;1 {d1680bb4-1ac0-4772-9437-1188375e44f2}

View File

@ -198,19 +198,10 @@ SOURCES += [
EXTRA_COMPONENTS += [
'contentAreaDropListener.js',
'contentAreaDropListener.manifest',
'contentSecurityPolicy.manifest',
'messageWakeupService.js',
'messageWakeupService.manifest',
]
EXTRA_PP_COMPONENTS += [
'contentSecurityPolicy.js',
]
EXTRA_JS_MODULES += [
'CSPUtils.jsm',
]
FAIL_ON_WARNINGS = True
MSVC_ENABLE_PGO = True

View File

@ -25,7 +25,6 @@
#include "nsIObjectOutputStream.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIPrincipal.h"
#include "nsIPropertyBag2.h"
#include "nsIStringStream.h"
#include "nsIUploadChannel.h"
@ -235,12 +234,6 @@ nsCSPContext::~nsCSPContext()
mShouldLoadCache.Clear();
}
NS_IMETHODIMP
nsCSPContext::GetIsInitialized(bool *outIsInitialized)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCSPContext::GetPolicy(uint32_t aIndex, nsAString& outStr)
{
@ -272,16 +265,11 @@ nsCSPContext::RemovePolicy(uint32_t aIndex)
NS_IMETHODIMP
nsCSPContext::AppendPolicy(const nsAString& aPolicyString,
nsIURI* aSelfURI,
bool aReportOnly)
{
CSPCONTEXTLOG(("nsCSPContext::AppendPolicy: %s",
NS_ConvertUTF16toUTF8(aPolicyString).get()));
if (aSelfURI) {
// aSelfURI will be disregarded since we will remove it with bug 991474
NS_WARNING("aSelfURI should be a nullptr in AppendPolicy and removed in bug 991474");
}
// Use the mSelfURI from setRequestContext, see bug 991474
NS_ASSERTION(mSelfURI, "mSelfURI required for AppendPolicy, but not set");
nsCSPPolicy* policy = nsCSPParser::parseContentSecurityPolicy(aPolicyString, mSelfURI, aReportOnly, mInnerWindowID);
@ -547,7 +535,6 @@ getInnerWindowID(nsIRequest* aRequest) {
NS_IMETHODIMP
nsCSPContext::SetRequestContext(nsIURI* aSelfURI,
nsIURI* aReferrer,
nsIPrincipal* aDocumentPrincipal,
nsIChannel* aChannel)
{
NS_PRECONDITION(aSelfURI || aChannel, "Need aSelfURI or aChannel to set the context properly");

View File

@ -28,7 +28,6 @@ using namespace mozilla;
/* Keeps track of whether or not CSP is enabled */
bool CSPService::sCSPEnabled = true;
bool CSPService::sNewBackendEnabled = true;
#ifdef PR_LOGGING
static PRLogModuleInfo* gCspPRLog;
@ -37,7 +36,6 @@ static PRLogModuleInfo* gCspPRLog;
CSPService::CSPService()
{
Preferences::AddBoolVarCache(&sCSPEnabled, "security.csp.enable");
Preferences::AddBoolVarCache(&sNewBackendEnabled, "security.csp.newbackend.enable");
#ifdef PR_LOGGING
if (!gCspPRLog)
@ -100,8 +98,9 @@ CSPService::ShouldLoad(uint32_t aContentType,
// These content types are not subject to CSP content policy checks:
// TYPE_CSP_REPORT, TYPE_REFRESH, TYPE_DOCUMENT
// (their mappings are null in contentSecurityPolicy.js)
// TYPE_CSP_REPORT -- csp can't block csp reports
// TYPE_REFRESH -- never passed to ShouldLoad (see nsIContentPolicy.idl)
// TYPE_DOCUMENT -- used for frame-ancestors
if (aContentType == nsIContentPolicy::TYPE_CSP_REPORT ||
aContentType == nsIContentPolicy::TYPE_REFRESH ||
aContentType == nsIContentPolicy::TYPE_DOCUMENT) {

View File

@ -26,7 +26,6 @@ public:
CSPService();
static bool sCSPEnabled;
static bool sNewBackendEnabled;
protected:
virtual ~CSPService();

View File

@ -2643,8 +2643,9 @@ nsDocument::SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages)
}
static nsresult
AppendCSPFromHeader(nsIContentSecurityPolicy* csp, const nsAString& aHeaderValue,
nsIURI* aSelfURI, bool aReportOnly)
AppendCSPFromHeader(nsIContentSecurityPolicy* csp,
const nsAString& aHeaderValue,
bool aReportOnly)
{
// Need to tokenize the header value since multiple headers could be
// concatenated into one comma-separated list of policies.
@ -2653,7 +2654,7 @@ AppendCSPFromHeader(nsIContentSecurityPolicy* csp, const nsAString& aHeaderValue
nsCharSeparatedTokenizer tokenizer(aHeaderValue, ',');
while (tokenizer.hasMoreTokens()) {
const nsSubstring& policy = tokenizer.nextToken();
rv = csp->AppendPolicy(policy, aSelfURI, aReportOnly);
rv = csp->AppendPolicy(policy, aReportOnly);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef PR_LOGGING
{
@ -2764,17 +2765,7 @@ nsDocument::InitCSP(nsIChannel* aChannel)
}
}
// Create new CSP object:
// * by default we are trying to use the new C++ implmentation
// * however, we still support XCSP headers during the transition phase
// and fall back to the JS implementation if we find an XCSP header.
if (CSPService::sNewBackendEnabled) {
csp = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
}
else {
csp = do_CreateInstance("@mozilla.org/contentsecuritypolicy;1", &rv);
}
csp = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
if (NS_FAILED(rv)) {
#ifdef PR_LOGGING
@ -2788,7 +2779,7 @@ nsDocument::InitCSP(nsIChannel* aChannel)
aChannel->GetURI(getter_AddRefs(selfURI));
// Store the request context for violation reports
csp->SetRequestContext(nullptr, nullptr, nullptr, aChannel);
csp->SetRequestContext(nullptr, nullptr, aChannel);
// ----- if the doc is an app and we want a default CSP, apply it.
if (applyAppDefaultCSP) {
@ -2802,24 +2793,24 @@ nsDocument::InitCSP(nsIChannel* aChannel)
}
if (appCSP) {
csp->AppendPolicy(appCSP, selfURI, false);
csp->AppendPolicy(appCSP, false);
}
}
// ----- if the doc is an app and specifies a CSP in its manifest, apply it.
if (applyAppManifestCSP) {
csp->AppendPolicy(appManifestCSP, selfURI, false);
csp->AppendPolicy(appManifestCSP, false);
}
// ----- if there's a full-strength CSP header, apply it.
if (!cspHeaderValue.IsEmpty()) {
rv = AppendCSPFromHeader(csp, cspHeaderValue, selfURI, false);
rv = AppendCSPFromHeader(csp, cspHeaderValue, false);
NS_ENSURE_SUCCESS(rv, rv);
}
// ----- if there's a report-only CSP header, apply it.
if (!cspROHeaderValue.IsEmpty()) {
rv = AppendCSPFromHeader(csp, cspROHeaderValue, selfURI, true);
rv = AppendCSPFromHeader(csp, cspROHeaderValue, true);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -4334,7 +4325,7 @@ void
nsIDocument::SetContainer(nsDocShell* aContainer)
{
if (aContainer) {
mDocumentContainer = aContainer->asWeakPtr();
mDocumentContainer = aContainer;
} else {
mDocumentContainer = WeakPtr<nsDocShell>();
}

View File

@ -108,16 +108,13 @@ nsresult runTest(uint32_t aExpectedPolicyCount, // this should be 0 for policies
// arguments can be nullptrs.
csp->SetRequestContext(selfURI,
nullptr, // nsIURI* aReferrer
nullptr, // nsIPrincipal* aDocumentPrincipal
dummyChannel);
NS_ENSURE_SUCCESS(rv, rv);
// append a policy
nsString policyStr;
policyStr.AssignASCII(aPolicy);
// Second argument in AppendPolicy needs to be a nullptr,
// because we are using the selfURI set in SetRequestingContext
rv = csp->AppendPolicy(policyStr, nullptr, false);
rv = csp->AppendPolicy(policyStr, false);
NS_ENSURE_SUCCESS(rv, rv);
// when executing fuzzy tests we do not care about the actual output

View File

@ -44,7 +44,7 @@
let appchan = SpecialPowers.Services.io.newChannel(gManifestURL, null, null);
try {
csp.setRequestContext(null, null, null, appchan);
csp.setRequestContext(null, null, appchan);
ok(true, "setRequestContext hasn't thown");
} catch(e) {
ok(false, "setRequestContext throws");

View File

@ -1,159 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import('resource://gre/modules/CSPUtils.jsm');
var ioService = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
var self = ioService.newURI("http://test1.example.com:80", null, null);
function testValidSRCsHostSourceWithSchemeAndPath() {
var csps = [
"http://test1.example.com",
"http://test1.example.com/",
"http://test1.example.com/path-1",
"http://test1.example.com/path-1/",
"http://test1.example.com/path-1/path_2/",
"http://test1.example.com/path-1/path_2/file.js",
"http://test1.example.com/path-1/path_2/file_1.js",
"http://test1.example.com/path-1/path_2/file-2.js",
"http://test1.example.com/path-1/path_2/f.js",
"http://test1.example.com/path-1/path_2/f.oo.js"
]
var obj;
var expected = "http://test1.example.com";
for (let i in csps) {
var src = csps[i];
obj = CSPSourceList.fromString(src, undefined, self);
dump("expected: " + expected + "\n");
dump("got: " + obj._sources[0] + "\n");
do_check_eq(1, obj._sources.length);
do_check_eq(obj._sources[0], expected);
}
}
function testValidSRCsRegularHost() {
var csps = [
"test1.example.com",
"test1.example.com/",
"test1.example.com/path-1",
"test1.example.com/path-1/",
"test1.example.com/path-1/path_2/",
"test1.example.com/path-1/path_2/file.js",
"test1.example.com/path-1/path_2/file_1.js",
"test1.example.com/path-1/path_2/file-2.js",
"test1.example.com/path-1/path_2/f.js",
"test1.example.com/path-1/path_2/f.oo.js"
]
var obj;
var expected = "http://test1.example.com";
for (let i in csps) {
var src = csps[i];
obj = CSPSourceList.fromString(src, undefined, self);
do_check_eq(1, obj._sources.length);
do_check_eq(obj._sources[0], expected);
}
}
function testValidSRCsWildCardHost() {
var csps = [
"*.example.com",
"*.example.com/",
"*.example.com/path-1",
"*.example.com/path-1/",
"*.example.com/path-1/path_2/",
"*.example.com/path-1/path_2/file.js",
"*.example.com/path-1/path_2/file_1.js",
"*.example.com/path-1/path_2/file-2.js",
"*.example.com/path-1/path_2/f.js",
"*.example.com/path-1/path_2/f.oo.js"
]
var obj;
var expected = "http://*.example.com";
for (let i in csps) {
var src = csps[i];
obj = CSPSourceList.fromString(src, undefined, self);
do_check_eq(1, obj._sources.length);
do_check_eq(obj._sources[0], expected);
}
}
function testValidSRCsRegularPort() {
var csps = [
"test1.example.com:80",
"test1.example.com:80/",
"test1.example.com:80/path-1",
"test1.example.com:80/path-1/",
"test1.example.com:80/path-1/path_2",
"test1.example.com:80/path-1/path_2/",
"test1.example.com:80/path-1/path_2/file.js",
"test1.example.com:80/path-1/path_2/f.ile.js"
]
var obj;
var expected = "http://test1.example.com";
for (let i in csps) {
var src = csps[i];
obj = CSPSourceList.fromString(src, undefined, self);
do_check_eq(1, obj._sources.length);
do_check_eq(obj._sources[0], expected);
}
}
function testValidSRCsWildCardPort() {
var csps = [
"test1.example.com:*",
"test1.example.com:*/",
"test1.example.com:*/path-1",
"test1.example.com:*/path-1/",
"test1.example.com:*/path-1/path_2",
"test1.example.com:*/path-1/path_2/",
"test1.example.com:*/path-1/path_2/file.js",
"test1.example.com:*/path-1/path_2/f.ile.js"
]
var obj;
var expected = "http://test1.example.com:*";
for (let i in csps) {
var src = csps[i];
obj = CSPSourceList.fromString(src, undefined, self);
do_check_eq(1, obj._sources.length);
do_check_eq(obj._sources[0], expected);
}
}
function testInvalidSRCs() {
var csps = [
"test1.example.com:88path-1/",
"test1.example.com:80.js",
"test1.example.com:*.js",
"test1.example.com:*."
]
var obj;
var expected = [];
for (let i in csps) {
var src = csps[i];
obj = CSPSourceList.fromString(src, undefined, self);
do_check_eq(0, obj._sources.length);
}
}
function run_test() {
testValidSRCsHostSourceWithSchemeAndPath();
testValidSRCsRegularHost();
testValidSRCsWildCardHost();
testValidSRCsRegularPort();
testValidSRCsWildCardPort();
testInvalidSRCs();
do_test_finished();
}

View File

@ -75,11 +75,11 @@ function makeTest(id, expectedJSON, useReportOnlyPolicy, callback) {
dump("Created test " + id + " : " + policy + "\n\n");
// make the reports seem authentic by "binding" them to a channel.
csp.setRequestContext(selfuri, null, null, selfchan);
csp.setRequestContext(selfuri, null, selfchan);
// Load up the policy
// set as report-only if that's the case
csp.appendPolicy(policy, selfuri, useReportOnlyPolicy);
csp.appendPolicy(policy, useReportOnlyPolicy);
// prime the report server
var handler = makeReportHandler("/test" + id, "Test " + id, expectedJSON);

View File

@ -1,879 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
//load('CSPUtils.jsm');
Cu.import('resource://gre/modules/CSPUtils.jsm');
Cu.import('resource://gre/modules/NetUtil.jsm');
var httpServer = new HttpServer();
httpServer.start(-1);
const POLICY_FROM_URI = "default-src 'self'; img-src *";
const POLICY_PORT = httpServer.identity.primaryPort;
const POLICY_URI = "http://localhost:" + POLICY_PORT + "/policy";
const POLICY_URI_RELATIVE = "/policy";
//converts string to nsIURI
function URI(uriString) {
var ioService = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
return ioService.newURI(uriString, null, null);
}
// helper to assert that an array has the given value somewhere.
function do_check_in_array(arr, val, stack) {
if (!stack)
stack = Components.stack.caller;
var text = val + " in [" + arr.join(",") + "]";
for(var i in arr) {
//dump(".......... " + i + "> " + arr[i] + "\n");
if(arr[i] == val) {
//succeed
++_passedChecks;
dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " +
stack.lineNumber + "] " + text + "\n");
return;
}
}
do_throw(text, stack);
}
// helper to assert that an object or array must have a given key
function do_check_has_key(foo, key, stack) {
if (!stack)
stack = Components.stack.caller;
var keys = [];
for (let k in foo) { keys.push(k); }
var text = key + " in [" + keys.join(",") + "]";
for (var x in foo) {
if (x == key) {
//succeed
++_passedChecks;
dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " +
stack.lineNumber + "] " + text + "\n");
return;
}
}
do_throw(text, stack);
}
// helper to use .equals on stuff
function do_check_equivalent(foo, bar, stack) {
if (!stack)
stack = Components.stack.caller;
var text = foo + ".equals(" + bar + ")";
if(foo.equals && foo.equals(bar)) {
++_passedChecks;
dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " +
stack.lineNumber + "] " + text + "\n");
return;
}
do_throw(text, stack);
}
var tests = [];
function test(fcn) {
tests.push(fcn);
}
test(
function test_CSPHost_fromstring() {
var h;
h = CSPHost.fromString("*");
do_check_neq(null, h); // "* lone wildcard should work"
h = CSPHost.fromString("foo.bar");
do_check_neq(null, h); // "standard tuple failed"
h = CSPHost.fromString("*.bar");
do_check_neq(null, h); // "wildcard failed"
h = CSPHost.fromString("foo.*.bar");
do_check_eq(null, h); // "wildcard in wrong place worked"
h = CSPHost.fromString("com");
do_check_neq(null, h); // "lone symbol should not fail"
h = CSPHost.fromString("f00b4r.com");
do_check_neq(null, h); // "Numbers in hosts should work"
h = CSPHost.fromString("foo-bar.com");
do_check_neq(null, h); // "dashes in hosts should work"
h = CSPHost.fromString("foo!bar.com");
do_check_eq(null, h); // "special chars in hosts should fail"
h = CSPHost.fromString("{app-url-is-uid}");
do_check_neq(null, h); // "Packaged apps URLs failed"
});
test(
function test_CSPHost_clone() {
h = CSPHost.fromString("*.a.b.c");
h2 = h.clone();
for(var i in h._segments) {
// "cloned segments should match"
do_check_eq(h._segments[i], h2._segments[i]);
}
});
test(
function test_CSPHost_permits() {
var h = CSPHost.fromString("*.b.c");
var h2 = CSPHost.fromString("a.b.c");
do_check_true( h.permits(h2)); //"CSPHost *.b.c should allow CSPHost a.b.c"
do_check_true( h.permits("a.b.c")); //"CSPHost *.b.c should allow string a.b.c"
do_check_false(h.permits("b.c")); //"CSPHost *.b.c should not allow string b.c"
do_check_false(h.permits("a.a.c")); //"CSPHost *.b.c should not allow string a.a.c"
do_check_false(h2.permits(h)); //"CSPHost a.b.c should not allow CSPHost *.b.c"
do_check_false(h2.permits("b.c")); //"CSPHost a.b.c should not allow string b.c"
do_check_true( h2.permits("a.b.c")); //"CSPHost a.b.c should allow string a.b.c"
});
///////////////////// Test the Source object //////////////////////
test(
function test_CSPSource_fromString() {
// can't do these tests because "self" is not defined.
//"basic source should not be null.");
do_check_neq(null, CSPSource.fromString("a.com", undefined, "http://abc.com"));
//"ldh characters should all work for host.");
do_check_neq(null, CSPSource.fromString("a2-c.com", undefined, "https://a.com"));
//"wildcard should work in first token for host.");
do_check_neq(null, CSPSource.fromString("*.a.com", undefined, "http://abc.com"));
//print(" --- Ignore the following two errors if they print ---");
//"wildcard should not work in non-first token for host.");
do_check_eq(null, CSPSource.fromString("x.*.a.com", undefined, "http://a.com"));
//"funny characters (#) should not work for host.");
do_check_eq(null, CSPSource.fromString("a#2-c.com", undefined, "http://a.com"));
//print(" --- Stop ignoring errors that print ---\n");
//"failed to parse host with port.");
do_check_neq(null, CSPSource.create("a.com:23", undefined, "http://a.com"));
//"failed to parse host with scheme.");
do_check_neq(null, CSPSource.create("https://a.com", undefined, "http://a.com"));
//"failed to parse host with scheme and port.");
do_check_neq(null, CSPSource.create("https://a.com:200", undefined, "http://a.com"));
//Check to make sure we don't match multiple instances with regex
do_check_eq(null, CSPSource.create("http://foo.com:bar.com:23"));
//Port parsing should work for all schemes
do_check_neq(null, CSPSource.create("data:"));
do_check_neq(null, CSPSource.create("javascript:"));
//"app:// URLs should work, including the {} characters.");
do_check_neq(null, CSPSource.fromString("{app-host-is-uid}", undefined, "app://{app-host-is-uid}"));
});
test(
function test_CSPSource_fromString_withSelf() {
var src;
src = CSPSource.create("a.com", undefined, "https://foobar.com:443");
//"src should inherit port *
do_check_true(src.permits("https://a.com:443"));
//"src should inherit and require https scheme
do_check_false(src.permits("http://a.com"));
//"src should inherit scheme 'https'"
do_check_true(src.permits("https://a.com"));
src = CSPSource.create("http://a.com", undefined, "https://foobar.com:443");
//"src should inherit and require http scheme"
do_check_false(src.permits("https://a.com"));
//"src should inherit scheme 'http'"
do_check_true(src.permits("http://a.com"));
//"src should inherit port and scheme from parent"
//"src should inherit default port for 'http'"
do_check_true(src.permits("http://a.com:80"));
src = CSPSource.create("'self'", undefined, "https://foobar.com:443");
//"src should inherit port *
do_check_true(src.permits("https://foobar.com:443"));
//"src should inherit and require https scheme
do_check_false(src.permits("http://foobar.com"));
//"src should inherit scheme 'https'"
do_check_true(src.permits("https://foobar.com"));
//"src should reject other hosts"
do_check_false(src.permits("https://a.com"));
src = CSPSource.create("javascript:", undefined, "https://foobar.com:443");
//"hostless schemes should be parseable."
var aUri = NetUtil.newURI("javascript:alert('foo');");
do_check_true(src.permits(aUri));
//"src should reject other hosts"
do_check_false(src.permits("https://a.com"));
//"nothing else should be allowed"
do_check_false(src.permits("https://foobar.com"));
src = CSPSource.create("{app-host-is-uid}", undefined, "app://{app-host-is-uid}");
//"src should inherit and require 'app' scheme"
do_check_false(src.permits("https://{app-host-is-uid}"));
//"src should inherit scheme 'app'"
do_check_true(src.permits("app://{app-host-is-uid}"));
});
///////////////////// Test the source list //////////////////////
test(
function test_CSPSourceList_fromString() {
var sd = CSPSourceList.fromString("'none'");
//"'none' -- should parse"
do_check_neq(null,sd);
// "'none' should be a zero-length list"
do_check_eq(0, sd._sources.length);
do_check_true(sd.isNone());
sd = CSPSourceList.fromString("*");
//"'*' should be a zero-length list"
do_check_eq(0, sd._sources.length);
//print(" --- Ignore the following three errors if they print ---");
//"funny char in host"
do_check_true(CSPSourceList.fromString("f!oo.bar").isNone());
//"funny char in scheme"
do_check_true(CSPSourceList.fromString("ht!ps://f-oo.bar").isNone());
//"funny char in port"
do_check_true(CSPSourceList.fromString("https://f-oo.bar:3f").isNone());
//print(" --- Stop ignoring errors that print ---\n");
});
test(
function test_CSPSourceList_fromString_twohost() {
var str = "foo.bar:21 https://ras.bar";
var parsed = "http://foo.bar:21 https://ras.bar";
var sd = CSPSourceList.fromString(str, undefined, URI("http://self.com:80"));
//"two-host list should parse"
do_check_neq(null,sd);
//"two-host list should parse to two hosts"
do_check_eq(2, sd._sources.length);
//"two-host list should contain original data"
do_check_eq(parsed, sd.toString());
});
test(
function test_CSPSourceList_permits() {
var nullSourceList = CSPSourceList.fromString("'none'");
var simpleSourceList = CSPSourceList.fromString("a.com", undefined, URI("http://self.com"));
var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88",
undefined,
URI("http://self.com:88"));
var allSourceList = CSPSourceList.fromString("*");
var allAndMoreSourceList = CSPSourceList.fromString("* https://bar.com 'none'");
var wildcardHostSourceList = CSPSourceList.fromString("*.foo.com",
undefined, URI("http://self.com"));
var allDoubledHostSourceList = CSPSourceList.fromString("**");
var allGarbageHostSourceList = CSPSourceList.fromString("*a");
//'none' should permit none."
do_check_false( nullSourceList.permits("http://a.com"));
//a.com should permit a.com"
do_check_true( simpleSourceList.permits("http://a.com"));
//wrong host"
do_check_false( simpleSourceList.permits("http://b.com"));
//double list permits http://bar.com:88"
do_check_true( doubleSourceList.permits("http://bar.com:88"));
//double list permits https://bar.com:88"
do_check_false( doubleSourceList.permits("https://bar.com:88"));
//double list does not permit http://bar.com:443"
do_check_false( doubleSourceList.permits("http://bar.com:443"));
//"double list permits https://foo.com:88" (should not inherit port)
do_check_false( doubleSourceList.permits("https://foo.com:88"));
//"double list does not permit foo.com on http"
do_check_false( doubleSourceList.permits("http://foo.com"));
//"* does not permit specific host"
do_check_true( allSourceList.permits("http://x.com:23"));
//"* does not permit a long host with no port"
do_check_true( allSourceList.permits("http://a.b.c.d.e.f.g.h.i.j.k.l.x.com"));
//* short circuts parsing
do_check_true(allAndMoreSourceList.permits("http://a.com"));
//"** permits all"
do_check_false(allDoubledHostSourceList.permits("http://barbaz.com"));
//"*a permits all"
do_check_false(allGarbageHostSourceList.permits("http://barbaz.com"));
//"*.foo.com does not permit somerandom.foo.com"
do_check_true(wildcardHostSourceList.permits("http://somerandom.foo.com"));
//"*.foo.com permits all"
do_check_false(wildcardHostSourceList.permits("http://barbaz.com"));
});
//////////////// TEST CSP REP SPEC COMPLIANT PARSER ////////////
test(
function test_CSPRep_fromString() {
var cspr;
var cspr_allowval;
var SD = CSPRep.SRC_DIRECTIVES;
var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC, SD.SCRIPT_SRC, SD.FONT_SRC,
SD.OBJECT_SRC, SD.FRAME_SRC, SD.CONNECT_SRC];
// check default policy "default-src *"
cspr = CSPRep.fromString("default-src *", URI("http://self.com:80"));
// "DEFAULT_SRC directive is missing when specified in fromString"
do_check_has_key(cspr._directives, SD.DEFAULT_SRC);
for(var x in DEFAULTS) {
// each of these should be equivalent to DEFAULT_SRC
//DEFAULTS[x] + " does not use default rule."
do_check_true(cspr.permits("http://bar.com", DEFAULTS[x]));
}
});
test(
function test_CSPRep_fromString_oneDir() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES;
var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.IMG_SRC,
SD.FRAME_SRC, SD.CONNECT_SRC];
// check one-directive policies
cspr = CSPRep.fromString("default-src bar.com; script-src https://foo.com",
URI("http://self.com"));
for(var x in DEFAULTS) {
//DEFAULTS[x] + " does not use default rule."
do_check_false(cspr.permits("http://bar.com:22", DEFAULTS[x]));
//DEFAULTS[x] + " does not use default rule."
do_check_true(cspr.permits("http://bar.com:80", DEFAULTS[x]));
//DEFAULTS[x] + " does not use default rule."
do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x]));
//DEFAULTS[x] + " does not use default rule."
do_check_false(cspr.permits("https://foo.com", DEFAULTS[x]));
}
//"script-src false positive in policy.
do_check_false(cspr.permits("http://bar.com:22", SD.SCRIPT_SRC));
//"script-src false negative in policy.
do_check_true(cspr.permits("https://foo.com:443", SD.SCRIPT_SRC));
});
test(
function test_CSPRep_fromString_twoDir() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES;
var DEFAULTS = [SD.STYLE_SRC, SD.MEDIA_SRC, SD.FRAME_SRC,
SD.CONNECT_SRC];
// check two-directive policies
var polstr = "default-src allow.com; " +
"script-src https://foo.com; " +
"img-src bar.com:*";
cspr = CSPRep.fromString(polstr, URI("http://self.com"));
for(var x in DEFAULTS) {
do_check_true(cspr.permits("http://allow.com", DEFAULTS[x]));
//DEFAULTS[x] + " does not use default rule.
do_check_false(cspr.permits("https://foo.com:400", DEFAULTS[x]));
//DEFAULTS[x] + " does not use default rule.
do_check_false(cspr.permits("http://bar.com:400", DEFAULTS[x]));
//DEFAULTS[x] + " does not use default rule.
}
//"img-src does not use default rule.
do_check_false(cspr.permits("http://allow.com:22", SD.IMG_SRC));
//"img-src does not use default rule.
do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC));
//"img-src does not use default rule.
do_check_true(cspr.permits("http://bar.com:88", SD.IMG_SRC));
//"script-src does not use default rule.
do_check_false(cspr.permits("http://allow.com:22", SD.SCRIPT_SRC));
//"script-src does not use default rule.
do_check_true(cspr.permits("https://foo.com:443", SD.SCRIPT_SRC));
//"script-src does not use default rule.
do_check_false(cspr.permits("http://bar.com:400", SD.SCRIPT_SRC));
});
test(function test_CSPRep_fromString_withself() {
var cspr;
var self = "https://self.com:34";
var SD = CSPRep.SRC_DIRECTIVES;
// check one-directive policies
cspr = CSPRep.fromString("default-src 'self'; script-src 'self' https://*:*",
URI(self));
//"img-src does not enforce default rule, 'self'.
do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC));
//"img-src does not allow self
do_check_true(cspr.permits(self, SD.IMG_SRC));
//"script-src is too relaxed
do_check_false(cspr.permits("http://evil.com", SD.SCRIPT_SRC));
//"script-src should allow self
do_check_true(cspr.permits(self, SD.SCRIPT_SRC));
//"script-src is too strict on host/port
do_check_true(cspr.permits("https://evil.com:100", SD.SCRIPT_SRC));
});
//////////////// TEST FRAME ANCESTOR DEFAULTS /////////////////
// (see bug 555068)
test(function test_FrameAncestor_defaults() {
var cspr;
var self = "http://self.com:34";
var SD = CSPRep.SRC_DIRECTIVES;
cspr = CSPRep.fromString("default-src 'none'", URI(self));
//"frame-ancestors should default to * not 'default-src' value"
do_check_true(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("https://self.com:34", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("http://self.com", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS));
cspr = CSPRep.fromString("default-src 'none'; frame-ancestors 'self'", URI(self));
//"frame-ancestors should only allow self"
do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS));
do_check_false(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS));
do_check_false(cspr.permits("https://self.com:34", SD.FRAME_ANCESTORS));
do_check_false(cspr.permits("http://self.com", SD.FRAME_ANCESTORS));
do_check_false(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS));
});
test(function test_FrameAncestor_TLD_defaultPorts() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES;
var self = "http://self"; //TLD only, no .com or anything.
cspr = CSPRep.fromString("default-src 'self'; frame-ancestors 'self' http://foo:80 bar:80 http://three", URI(self));
//"frame-ancestors should default to * not 'allow' value"
do_check_true(cspr.permits("http://self", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("http://self:80", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("http://foo", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("http://foo:80", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("http://bar", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("http://three:80", SD.FRAME_ANCESTORS));
do_check_false(cspr.permits("https://foo:400", SD.FRAME_ANCESTORS));
do_check_false(cspr.permits("https://self:34", SD.FRAME_ANCESTORS));
do_check_false(cspr.permits("https://bar", SD.FRAME_ANCESTORS));
do_check_false(cspr.permits("http://three:81", SD.FRAME_ANCESTORS));
do_check_false(cspr.permits("https://three:81", SD.FRAME_ANCESTORS));
});
test(function test_FrameAncestor_ignores_userpass_bug779918() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES;
var self = "http://self.com/bar";
var testPolicy = "default-src 'self'; frame-ancestors 'self'";
cspr = CSPRep.fromString(testPolicy, URI(self));
// wrapped in URI() because of source parsing
do_check_true(cspr.permits(URI("http://username:password@self.com/foo"), SD.FRAME_ANCESTORS));
do_check_true(cspr.permits(URI("http://other:pass1@self.com/foo"), SD.FRAME_ANCESTORS));
do_check_true(cspr.permits(URI("http://self.com:80/foo"), SD.FRAME_ANCESTORS));
do_check_true(cspr.permits(URI("http://self.com/foo"), SD.FRAME_ANCESTORS));
// construct fake ancestry with CSP applied to the child.
// [aChildUri] -> [aParentUri] -> (root/top)
// and then test "permitsAncestry" on the child/self docshell.
function testPermits(aChildUri, aParentUri, aContentType) {
let cspObj = Cc["@mozilla.org/contentsecuritypolicy;1"]
.createInstance(Ci.nsIContentSecurityPolicy);
cspObj.appendPolicy(testPolicy, aChildUri, false);
let docshellparent = Cc["@mozilla.org/docshell;1"]
.createInstance(Ci.nsIDocShell);
let docshellchild = Cc["@mozilla.org/docshell;1"]
.createInstance(Ci.nsIDocShell);
docshellparent.setCurrentURI(aParentUri);
docshellchild.setCurrentURI(aChildUri);
docshellparent.addChild(docshellchild);
return cspObj.permitsAncestry(docshellchild);
};
// check parent without userpass
do_check_true(testPermits(URI("http://username:password@self.com/foo"),
URI("http://self.com/bar")));
do_check_true(testPermits(URI("http://user1:pass1@self.com/foo"),
URI("http://self.com/bar")));
do_check_true(testPermits(URI("http://self.com/foo"),
URI("http://self.com/bar")));
// check parent with userpass
do_check_true(testPermits(URI("http://username:password@self.com/foo"),
URI("http://username:password@self.com/bar")));
do_check_true(testPermits(URI("http://user1:pass1@self.com/foo"),
URI("http://username:password@self.com/bar")));
do_check_true(testPermits(URI("http://self.com/foo"),
URI("http://username:password@self.com/bar")));
});
test(function test_CSP_ReportURI_parsing() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES;
var self = "http://self.com:34";
var parsedURIs = [];
var uri_valid_absolute = self + "/report.py";
var uri_other_host_absolute = "http://foo.org:34/report.py";
var uri_valid_relative = "/report.py";
var uri_valid_relative_expanded = self + uri_valid_relative;
var uri_valid_relative2 = "foo/bar/report.py";
var uri_valid_relative2_expanded = self + "/" + uri_valid_relative2;
var uri_invalid_relative = "javascript:alert(1)";
var uri_other_scheme_absolute = "https://self.com/report.py";
var uri_other_scheme_and_host_absolute = "https://foo.com/report.py";
cspr = CSPRep.fromString("default-src *; report-uri " + uri_valid_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, uri_valid_absolute);
do_check_eq(parsedURIs.length, 1);
cspr = CSPRep.fromString("default-src *; report-uri " + uri_other_host_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, uri_other_host_absolute);
do_check_eq(parsedURIs.length, 1); // the empty string is in there.
cspr = CSPRep.fromString("default-src *; report-uri " + uri_invalid_relative, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, "");
do_check_eq(parsedURIs.length, 1);
cspr = CSPRep.fromString("default-src *; report-uri " + uri_valid_relative, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, uri_valid_relative_expanded);
do_check_eq(parsedURIs.length, 1);
cspr = CSPRep.fromString("default-src *; report-uri " + uri_valid_relative2, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
dump(parsedURIs.length);
do_check_in_array(parsedURIs, uri_valid_relative2_expanded);
do_check_eq(parsedURIs.length, 1);
// make sure cross-scheme reporting works
cspr = CSPRep.fromString("default-src *; report-uri " + uri_other_scheme_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
dump(parsedURIs.length);
do_check_in_array(parsedURIs, uri_other_scheme_absolute);
do_check_eq(parsedURIs.length, 1);
// make sure cross-scheme, cross-host reporting works
cspr = CSPRep.fromString("default-src *; report-uri " + uri_other_scheme_and_host_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
dump(parsedURIs.length);
do_check_in_array(parsedURIs, uri_other_scheme_and_host_absolute);
do_check_eq(parsedURIs.length, 1);
// combination!
cspr = CSPRep.fromString("default-src *; report-uri " +
uri_valid_relative2 + " " +
uri_valid_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, uri_valid_relative2_expanded);
do_check_in_array(parsedURIs, uri_valid_absolute);
do_check_eq(parsedURIs.length, 2);
cspr = CSPRep.fromString("default-src *; report-uri " +
uri_valid_relative2 + " " +
uri_other_host_absolute + " " +
uri_valid_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, uri_valid_relative2_expanded);
do_check_in_array(parsedURIs, uri_other_host_absolute);
do_check_in_array(parsedURIs, uri_valid_absolute);
do_check_eq(parsedURIs.length, 3);
});
test(
function test_bug634778_duplicateDirective_Detection() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES;
var self = "http://self.com:34";
var firstDomain = "http://first.com";
var secondDomain = "http://second.com";
var thirdDomain = "http://third.com";
// check for duplicate "default-src" directives
// Spec says first directive persists (subsequent re-statement is
// ignored)
cspr = CSPRep.fromString("default-src " + self + "; default-src " +
firstDomain, URI(self));
do_check_true(cspr.permits(self, SD.DEFAULT_SRC));
do_check_false(cspr.permits(firstDomain, SD.DEFAULT_SRC));
// check for duplicate report-uri directives
cspr = CSPRep.fromString("default-src *; report-uri " + self + "/report.py; report-uri "
+ firstDomain + "/report.py", URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, self + "/report.py");
do_check_eq(parsedURIs.length, 1);
// check for three directives with duplicates
cspr = CSPRep.fromString("img-src " + firstDomain + "; default-src " + self
+ "; img-src " + secondDomain, URI(self));
do_check_true(cspr.permits(firstDomain, SD.IMG_SRC));
do_check_false(cspr.permits(secondDomain, SD.IMG_SRC));
do_check_true(cspr.permits(self, SD.DEFAULT_SRC));
// check for three directives with duplicates
cspr = CSPRep.fromString("img-src " + firstDomain + "; default-src " + self
+ "; img-src " + secondDomain, URI(self));
do_check_true(cspr.permits(firstDomain, SD.IMG_SRC));
do_check_false(cspr.permits(secondDomain, SD.IMG_SRC));
// check for three directives with duplicates
cspr = CSPRep.fromString("default-src " + self + "; img-src " + firstDomain
+ "; img-src " + secondDomain, URI(self));
do_check_true(cspr.permits(firstDomain, SD.IMG_SRC));
do_check_false(cspr.permits(secondDomain, SD.IMG_SRC));
// check for four directives with duplicates
cspr = CSPRep.fromString("default-src " + self + "; img-src " + firstDomain
+ "; img-src " + secondDomain + "; img-src "
+ thirdDomain, URI(self));
do_check_true(cspr.permits(firstDomain, SD.IMG_SRC));
do_check_false(cspr.permits(secondDomain, SD.IMG_SRC));
do_check_false(cspr.permits(thirdDomain, SD.IMG_SRC));
// check for four directives with two duplicates
cspr = CSPRep.fromString("default-src " + self + "; style-src "
+ firstDomain + "; media-src " + firstDomain
+ "; media-src " + secondDomain + "; style-src "
+ thirdDomain, URI(self));
do_check_true(cspr.permits(self, SD.DEFAULT_SRC));
do_check_true(cspr.permits(firstDomain, SD.STYLE_SRC));
do_check_true(cspr.permits(firstDomain, SD.MEDIA_SRC));
do_check_false(cspr.permits(secondDomain, SD.MEDIA_SRC));
do_check_false(cspr.permits(thirdDomain, SD.STYLE_SRC));
});
test(
function test_bug672961_withNonstandardSelfPort() {
/**
* When a protected document has a non-standard port, other host names
* listed as sources should inherit the scheme of the protected document
* but NOT the port. Other hosts should use the default port for the
* inherited scheme. For example, since 443 is default for HTTPS:
*
* Document with CSP: https://foobar.com:4443
* Transmitted policy:
* "default-src 'self' a.com"
* Explicit policy:
* "default-src https://foobar.com:4443 https://a.com:443"
*
* This test examines scheme and nonstandard port inheritance.
*/
var src;
src = CSPSource.create("a.com", undefined, "https://foobar.com:4443");
//"src should inherit and require https scheme
do_check_false(src.permits("http://a.com"));
//"src should inherit scheme 'https'"
do_check_true(src.permits("https://a.com"));
//"src should get default port
do_check_true(src.permits("https://a.com:443"));
src = CSPSource.create("http://a.com", undefined, "https://foobar.com:4443");
//"src should require http scheme"
do_check_false(src.permits("https://a.com"));
//"src should keep scheme 'http'"
do_check_true(src.permits("http://a.com"));
//"src should inherit default port for 'http'"
do_check_true(src.permits("http://a.com:80"));
src = CSPSource.create("'self'", undefined, "https://foobar.com:4443");
//"src should inherit nonstandard port from self
do_check_true(src.permits("https://foobar.com:4443"));
do_check_false(src.permits("https://foobar.com"));
do_check_false(src.permits("https://foobar.com:443"));
//"src should inherit and require https scheme from self
do_check_false(src.permits("http://foobar.com:4443"));
do_check_false(src.permits("http://foobar.com"));
});
test(
function test_bug634773_noneAndStarAreDifferent() {
/**
* Bug 634773 is that default-src * and default-src 'none' end up "equal" via
* CSPSourceList.prototype.equals(), which is wrong. This tests that
* doesn't happen.
*/
var p_none = CSPSourceList.fromString("'none'", undefined, "http://foo.com", false);
var p_all = CSPSourceList.fromString("*", undefined, "http://foo.com", false);
var p_one = CSPSourceList.fromString("bar.com", undefined, "http://foo.com", false);
do_check_false(p_none.equals(p_all));
do_check_false(p_none.equals(p_one));
do_check_false(p_all.equals(p_none));
do_check_false(p_all.equals(p_one));
do_check_true(p_all.permits("http://bar.com"));
do_check_true(p_one.permits("http://bar.com"));
do_check_false(p_none.permits("http://bar.com"));
});
test(
function test_bug764937_defaultSrcMissing() {
var cspObj = Cc["@mozilla.org/contentsecuritypolicy;1"]
.createInstance(Ci.nsIContentSecurityPolicy);
var selfURI = URI("http://self.com/");
function testPermits(cspObj, aUri, aContentType) {
return cspObj.shouldLoad(aContentType, aUri, null, null, null, null)
== Ci.nsIContentPolicy.ACCEPT;
};
const policy = "script-src 'self'";
cspObj.appendPolicy(policy, selfURI, false);
// Spec-Compliant policy default-src defaults to *.
// This means all images are allowed, and only 'self'
// script is allowed.
do_check_true(testPermits(cspObj,
URI("http://bar.com/foo.png"),
Ci.nsIContentPolicy.TYPE_IMAGE));
do_check_true(testPermits(cspObj,
URI("http://self.com/foo.png"),
Ci.nsIContentPolicy.TYPE_IMAGE));
do_check_true(testPermits(cspObj,
URI("http://self.com/foo.js"),
Ci.nsIContentPolicy.TYPE_SCRIPT));
do_check_false(testPermits(cspObj,
URI("http://bar.com/foo.js"),
Ci.nsIContentPolicy.TYPE_SCRIPT));
});
test(function test_equals_does_case_insensitive_comparison() {
// NOTE: For scheme, host and keyword-host:
// (1) compare the same lower-case in two distinct objects
// (2) compare upper-case with lower-case inputs
// to test case insensitivity.
// CSPSource equals ignores case
var upperCaseHost = "http://FOO.COM";
var lowerCaseHost = "http://foo.com";
var src1 = CSPSource.fromString(lowerCaseHost);
var src2 = CSPSource.fromString(lowerCaseHost);
do_check_true(src1.equals(src2))
var src3 = CSPSource.fromString(upperCaseHost);
do_check_true(src1.equals(src3))
// CSPHost equals ignores case
var upperCaseScheme = "HTTP";
var lowerCaseScheme = "http";
src1 = CSPHost.fromString(lowerCaseScheme);
src2 = CSPHost.fromString(lowerCaseScheme);
do_check_true(src1.equals(src2));
src3 = CSPHost.fromString(upperCaseScheme);
do_check_true(src1.equals(src3));
// CSPSourceList equals (mainly for testing keywords)
var upperCaseKeywords = "'SELF'";
var lowerCaseKeywords = "'self'";
src1 = CSPSourceList.fromString(lowerCaseKeywords);
src2 = CSPSourceList.fromString(lowerCaseKeywords);
do_check_true(src1.equals(src2))
src3 = CSPSourceList.fromString(upperCaseKeywords);
do_check_true(src1.equals(src3))
});
test(function test_csp_permits_case_insensitive() {
var cspr;
var SD = CSPRep.SRC_DIRECTIVES;
// checks directives can be case-insensitive
var selfHost = "http://self.com";
var testPolicy1 = "DEFAULT-src 'self';";
cspr = CSPRep.fromString(testPolicy1, URI(selfHost));
do_check_true(cspr.permits(URI("http://self.com"), SD.DEFAULT_SRC));
// checks hosts can be case-insensitive
var testPolicy2 = "default-src 'self' http://FOO.COM";
cspr = CSPRep.fromString(testPolicy2, URI(selfHost));
do_check_true(cspr.permits(URI("http://foo.com"), SD.DEFAULT_SRC));
// checks schemes can be case-insensitive
var testPolicy3 = "default-src 'self' HTTP://foo.com";
cspr = CSPRep.fromString(testPolicy3, URI(selfHost));
do_check_true(cspr.permits(URI("http://foo.com"), SD.DEFAULT_SRC));
// checks keywords can be case-insensitive
var testPolicy4 = "default-src 'NONE'";
cspr = CSPRep.fromString(testPolicy4, URI(selfHost));
do_check_false(cspr.permits(URI("http://foo.com"), SD.DEFAULT_SRC));
});
/*
test(function test_CSPRep_fromPolicyURI_failswhenmixed() {
var cspr;
var self = "http://localhost:" + POLICY_PORT;
var closed_policy = CSPRep.fromString("default-src 'none'");
var my_uri_policy = "policy-uri " + POLICY_URI;
//print(" --- Ignore the following two errors if they print ---");
cspr = CSPRep.fromString("default-src *; " + my_uri_policy, URI(self));
//"Parsing should fail when 'policy-uri' is mixed with default-src directive"
do_check_equivalent(cspr, closed_policy);
cspr = CSPRep.fromString("img-src 'self'; " + my_uri_policy, URI(self));
//"Parsing should fail when 'policy-uri' is mixed with other directives"
do_check_equivalent(cspr, closed_policy);
//print(" --- Stop ignoring errors that print ---\n");
});
*/
// TODO: test reporting
// TODO: test refinements (?)
// TODO: test 'eval' and 'inline' keywords
function run_test() {
function policyresponder(request,response) {
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "text/csp", false);
response.bodyOutputStream.write(POLICY_FROM_URI, POLICY_FROM_URI.length);
}
//server.registerDirectory("/", nsILocalFileForBasePath);
httpServer.registerPathHandler("/policy", policyresponder);
for(let i in tests) {
add_task(tests[i]);
}
do_register_cleanup(function () {
//teardown
httpServer.stop(function() { });
});
run_next_test();
}

View File

@ -22,7 +22,6 @@ support-files =
[test_bug553888.js]
[test_bug737966.js]
[test_csputils.js]
[test_cspreports.js]
[test_error_codes.js]
run-sequentially = Hardcoded 4444 port.
@ -32,4 +31,3 @@ skip-if = os == 'mac'
[test_xhr_document.js]
[test_xhr_standalone.js]
[test_xmlserializer.js]
[test_csp_ignores_path.js]

View File

@ -930,6 +930,18 @@ nsTextInputListener::EditAction()
return NS_OK;
}
NS_IMETHODIMP
nsTextInputListener::BeforeEditAction()
{
return NS_OK;
}
NS_IMETHODIMP
nsTextInputListener::CancelEditAction()
{
return NS_OK;
}
// END nsIEditorObserver
@ -1042,7 +1054,7 @@ public:
PrepareEditorEvent(nsTextEditorState &aState,
nsIContent *aOwnerContent,
const nsAString &aCurrentValue)
: mState(aState.asWeakPtr())
: mState(&aState)
, mOwnerContent(aOwnerContent)
, mCurrentValue(aCurrentValue)
{

View File

@ -248,6 +248,17 @@ MediaDecoderReader::RequestAudioData()
!AudioQueue().IsFinished()) {
if (!DecodeAudioData()) {
AudioQueue().Finish();
break;
}
// AudioQueue size is still zero, post a task to try again. Don't spin
// waiting in this while loop since it somehow prevents audio EOS from
// coming in gstreamer 1.x when there is still video buffer waiting to be
// consumed. (|mVideoSinkBufferCount| > 0)
if (AudioQueue().GetSize() == 0 && mTaskQueue) {
RefPtr<nsIRunnable> task(NS_NewRunnableMethod(
this, &MediaDecoderReader::RequestAudioData));
mTaskQueue->Dispatch(task.forget());
return;
}
}
if (AudioQueue().GetSize() > 0) {

View File

@ -211,27 +211,34 @@ public:
}
// Decode thread.
virtual MediaDataDecoder* CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
MediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE {
BlankVideoDataCreator* decoder = new BlankVideoDataCreator(
virtual already_AddRefed<MediaDataDecoder>
CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
MediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE {
BlankVideoDataCreator* creator = new BlankVideoDataCreator(
aConfig.display_width, aConfig.display_height, aImageContainer);
return new BlankMediaDataDecoder<BlankVideoDataCreator>(decoder,
aVideoTaskQueue,
aCallback);
nsRefPtr<MediaDataDecoder> decoder =
new BlankMediaDataDecoder<BlankVideoDataCreator>(creator,
aVideoTaskQueue,
aCallback);
return decoder.forget();
}
// Decode thread.
virtual MediaDataDecoder* CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE {
BlankAudioDataCreator* decoder = new BlankAudioDataCreator(
virtual already_AddRefed<MediaDataDecoder>
CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE {
BlankAudioDataCreator* creator = new BlankAudioDataCreator(
aConfig.channel_count, aConfig.samples_per_second);
return new BlankMediaDataDecoder<BlankAudioDataCreator>(decoder,
aAudioTaskQueue,
aCallback);
nsRefPtr<MediaDataDecoder> decoder =
new BlankMediaDataDecoder<BlankAudioDataCreator>(creator,
aAudioTaskQueue,
aCallback);
return decoder.forget();
}
};

View File

@ -125,10 +125,10 @@ private:
}
// The platform decoder.
RefPtr<MediaDataDecoder> mDecoder;
nsRefPtr<MediaDataDecoder> mDecoder;
// TaskQueue on which decoder can choose to decode.
// Only non-null up until the decoder is created.
RefPtr<MediaTaskQueue> mTaskQueue;
nsRefPtr<MediaTaskQueue> mTaskQueue;
// Callback that receives output and error notifications from the decoder.
nsAutoPtr<DecoderCallback> mCallback;
// Monitor that protects all non-threadsafe state; the primitives

View File

@ -93,11 +93,12 @@ public:
// Returns nullptr if the decoder can't be created.
// It is safe to store a reference to aConfig.
// Called on decode thread.
virtual MediaDataDecoder* CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
MediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) = 0;
virtual already_AddRefed<MediaDataDecoder>
CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
MediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) = 0;
// Creates an AAC decoder with the specified properties.
// Asynchronous decoding of audio should be done in runnables dispatched to
@ -109,9 +110,10 @@ public:
// COINIT_MULTITHREADED.
// It is safe to store a reference to aConfig.
// Called on decode thread.
virtual MediaDataDecoder* CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) = 0;
virtual already_AddRefed<MediaDataDecoder>
CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) = 0;
virtual ~PlatformDecoderModule() {}

View File

@ -66,22 +66,26 @@ AppleDecoderModule::Shutdown()
return NS_OK;
}
MediaDataDecoder*
already_AddRefed<MediaDataDecoder>
AppleDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
mozilla::layers::LayersBackend aLayersBackend,
mozilla::layers::ImageContainer* aImageContainer,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
MediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback)
{
return new AppleVTDecoder(aConfig, aVideoTaskQueue, aCallback, aImageContainer);
nsRefPtr<MediaDataDecoder> decoder =
new AppleVTDecoder(aConfig, aVideoTaskQueue, aCallback, aImageContainer);
return decoder.forget();
}
MediaDataDecoder*
already_AddRefed<MediaDataDecoder>
AppleDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
{
return new AppleATDecoder(aConfig, aAudioTaskQueue, aCallback);
nsRefPtr<MediaDataDecoder> decoder =
new AppleATDecoder(aConfig, aAudioTaskQueue, aCallback);
return decoder.forget();
}
} // namespace mozilla

View File

@ -25,18 +25,18 @@ public:
virtual nsresult Shutdown() MOZ_OVERRIDE;
// Decode thread.
virtual MediaDataDecoder*
virtual already_AddRefed<MediaDataDecoder>
CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
mozilla::layers::LayersBackend aLayersBackend,
mozilla::layers::ImageContainer* aImageContainer,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
MediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
// Decode thread.
virtual MediaDataDecoder* CreateAACDecoder(
const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
virtual already_AddRefed<MediaDataDecoder>
CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
static void Init();
private:

View File

@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "EMEDecoderModule.h"
#include "mtransport/runnable_utils.h"
#include "mozIGeckoMediaPluginService.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
@ -193,7 +192,7 @@ EMEDecoderModule::Shutdown()
return NS_OK;
}
MediaDataDecoder*
already_AddRefed<MediaDataDecoder>
EMEDecoderModule::CreateH264Decoder(const VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
@ -203,24 +202,25 @@ EMEDecoderModule::CreateH264Decoder(const VideoDecoderConfig& aConfig,
if (mCDMDecodesVideo) {
NS_WARNING("Support for CDM that decodes video not yet supported");
return nullptr;
} else {
nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateH264Decoder(aConfig,
aLayersBackend,
aImageContainer,
aVideoTaskQueue,
aCallback));
if (!decoder) {
return nullptr;
}
return new EMEDecryptor(decoder,
aCallback,
mTaskQueue,
mProxy);
}
nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateH264Decoder(aConfig,
aLayersBackend,
aImageContainer,
aVideoTaskQueue,
aCallback));
if (!decoder) {
return nullptr;
}
nsRefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(decoder,
aCallback,
mTaskQueue,
mProxy));
return emeDecoder.forget();
}
MediaDataDecoder*
already_AddRefed<MediaDataDecoder>
EMEDecoderModule::CreateAACDecoder(const AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
@ -228,19 +228,20 @@ EMEDecoderModule::CreateAACDecoder(const AudioDecoderConfig& aConfig,
if (mCDMDecodesAudio) {
NS_WARNING("Support for CDM that decodes audio not yet supported");
return nullptr;
} else {
nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateAACDecoder(aConfig,
aAudioTaskQueue,
aCallback));
if (!decoder) {
return nullptr;
}
return new EMEDecryptor(decoder,
aCallback,
mTaskQueue,
mProxy);
}
nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateAACDecoder(aConfig,
aAudioTaskQueue,
aCallback));
if (!decoder) {
return nullptr;
}
nsRefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(decoder,
aCallback,
mTaskQueue,
mProxy));
return emeDecoder.forget();
}
} // namespace mozilla

View File

@ -33,7 +33,7 @@ public:
virtual nsresult Shutdown() MOZ_OVERRIDE;
// Decode thread.
virtual MediaDataDecoder*
virtual already_AddRefed<MediaDataDecoder>
CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
@ -41,10 +41,10 @@ public:
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
// Decode thread.
virtual MediaDataDecoder* CreateAACDecoder(
const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
virtual already_AddRefed<MediaDataDecoder>
CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
private:
nsRefPtr<CDMProxy> mProxy;

View File

@ -25,23 +25,27 @@ public:
virtual nsresult Shutdown() MOZ_OVERRIDE { return NS_OK; }
virtual MediaDataDecoder* CreateH264Decoder(
const mp4_demuxer::VideoDecoderConfig& aConfig,
mozilla::layers::LayersBackend aLayersBackend,
mozilla::layers::ImageContainer* aImageContainer,
MediaTaskQueue* aVideoTaskQueue, MediaDataDecoderCallback* aCallback)
MOZ_OVERRIDE
virtual already_AddRefed<MediaDataDecoder>
CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
MediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE
{
return new FFmpegH264Decoder<V>(aVideoTaskQueue, aCallback, aConfig,
aImageContainer);
nsRefPtr<MediaDataDecoder> decoder =
new FFmpegH264Decoder<V>(aVideoTaskQueue, aCallback, aConfig,
aImageContainer);
return decoder.forget();
}
virtual MediaDataDecoder* CreateAACDecoder(
const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue, MediaDataDecoderCallback* aCallback)
MOZ_OVERRIDE
virtual already_AddRefed<MediaDataDecoder>
CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE
{
return new FFmpegAACDecoder<V>(aAudioTaskQueue, aCallback, aConfig);
nsRefPtr<MediaDataDecoder> decoder =
new FFmpegAACDecoder<V>(aAudioTaskQueue, aCallback, aConfig);
return decoder.forget();
}
};

View File

@ -63,29 +63,33 @@ WMFDecoderModule::Shutdown()
return NS_OK;
}
MediaDataDecoder*
already_AddRefed<MediaDataDecoder>
WMFDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
mozilla::layers::LayersBackend aLayersBackend,
mozilla::layers::ImageContainer* aImageContainer,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
MediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback)
{
return new WMFMediaDataDecoder(new WMFVideoMFTManager(aConfig,
aLayersBackend,
aImageContainer,
sDXVAEnabled),
aVideoTaskQueue,
aCallback);
nsRefPtr<MediaDataDecoder> decoder =
new WMFMediaDataDecoder(new WMFVideoMFTManager(aConfig,
aLayersBackend,
aImageContainer,
sDXVAEnabled),
aVideoTaskQueue,
aCallback);
return decoder.forget();
}
MediaDataDecoder*
already_AddRefed<MediaDataDecoder>
WMFDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
{
return new WMFMediaDataDecoder(new WMFAudioMFTManager(aConfig),
aAudioTaskQueue,
aCallback);
nsRefPtr<MediaDataDecoder> decoder =
new WMFMediaDataDecoder(new WMFAudioMFTManager(aConfig),
aAudioTaskQueue,
aCallback);
return decoder.forget();
}
} // namespace mozilla

View File

@ -25,18 +25,18 @@ public:
virtual nsresult Shutdown() MOZ_OVERRIDE;
// Decode thread.
virtual MediaDataDecoder*
virtual already_AddRefed<MediaDataDecoder>
CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
mozilla::layers::LayersBackend aLayersBackend,
mozilla::layers::ImageContainer* aImageContainer,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
MediaTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
// Decode thread.
virtual MediaDataDecoder* CreateAACDecoder(
const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
virtual already_AddRefed<MediaDataDecoder>
CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
MediaTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
static void Init();
private:

View File

@ -271,5 +271,12 @@ GMPChild::RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor)
return true;
}
bool
GMPChild::RecvCrashPluginNow()
{
abort();
return true;
}
} // namespace gmp
} // namespace mozilla

View File

@ -47,6 +47,8 @@ private:
virtual bool DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor) MOZ_OVERRIDE;
virtual bool RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor) MOZ_OVERRIDE;
virtual bool RecvCrashPluginNow() MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual void ProcessingError(Result aWhat) MOZ_OVERRIDE;

View File

@ -101,6 +101,14 @@ GMPParent::Init(GeckoMediaPluginService *aService, nsIFile* aPluginDir)
return ReadGMPMetaData();
}
void
GMPParent::Crash()
{
if (mState != GMPStateNotLoaded) {
unused << SendCrashPluginNow();
}
}
nsresult
GMPParent::LoadProcess()
{

View File

@ -62,6 +62,8 @@ public:
nsresult Init(GeckoMediaPluginService *aService, nsIFile* aPluginDir);
nsresult CloneFrom(const GMPParent* aOther);
void Crash();
nsresult LoadProcess();
// Called internally to close this if we don't need it

View File

@ -9,6 +9,7 @@
#include "GMPVideoDecoderParent.h"
#include "nsIObserverService.h"
#include "GeckoChildProcessHost.h"
#include "mozilla/Preferences.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/SyncRunnable.h"
#include "nsXPCOMPrivate.h"
@ -145,6 +146,11 @@ GeckoMediaPluginService::Init()
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false)));
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false)));
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs) {
prefs->AddObserver("media.gmp.plugin.crash", this, false);
}
// Kick off scanning for plugins
nsCOMPtr<nsIThread> thread;
unused << GetThread(getter_AddRefs(thread));
@ -155,7 +161,26 @@ GeckoMediaPluginService::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aSomeData)
{
if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic)) {
if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
nsCOMPtr<nsIPrefBranch> branch( do_QueryInterface(aSubject) );
if (branch) {
bool crashNow = false;
if (NS_LITERAL_STRING("media.gmp.plugin.crash").Equals(aSomeData)) {
branch->GetBoolPref("media.gmp.plugin.crash", &crashNow);
}
if (crashNow) {
nsCOMPtr<nsIThread> gmpThread;
{
MutexAutoLock lock(mMutex);
gmpThread = mGMPThread;
}
if (gmpThread) {
gmpThread->Dispatch(WrapRunnable(this, &GeckoMediaPluginService::CrashPlugins),
NS_DISPATCH_NORMAL);
}
}
}
} else if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic)) {
nsCOMPtr<nsIThread> gmpThread;
{
MutexAutoLock lock(mMutex);
@ -340,6 +365,17 @@ GeckoMediaPluginService::UnloadPlugins()
mPlugins.Clear();
}
void
GeckoMediaPluginService::CrashPlugins()
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
MutexAutoLock lock(mMutex);
for (uint32_t i = 0; i < mPlugins.Length(); i++) {
mPlugins[i]->Crash();
}
}
void
GeckoMediaPluginService::LoadFromEnvironment()
{

View File

@ -44,6 +44,7 @@ private:
const nsTArray<nsCString>& aTags);
void UnloadPlugins();
void CrashPlugins();
void LoadFromEnvironment();
void ProcessPossiblePlugin(nsIFile* aDir);

View File

@ -27,6 +27,8 @@ child:
async PGMPDecryptor();
async PGMPVideoDecoder();
async PGMPVideoEncoder();
async CrashPluginNow();
};
} // namespace gmp

View File

@ -630,9 +630,11 @@ bool GStreamerReader::DecodeAudioData()
}
int64_t timestamp = GST_BUFFER_TIMESTAMP(buffer);
timestamp = gst_segment_to_stream_time(&mAudioSegment,
GST_FORMAT_TIME, timestamp);
{
ReentrantMonitorAutoEnter mon(mGstThreadsMonitor);
timestamp = gst_segment_to_stream_time(&mAudioSegment,
GST_FORMAT_TIME, timestamp);
}
timestamp = GST_TIME_AS_USECONDS(timestamp);
int64_t offset = GST_BUFFER_OFFSET(buffer);

View File

@ -72,7 +72,7 @@ AudioListener::SetOrientation(double aX, double aY, double aZ,
void
AudioListener::RegisterPannerNode(PannerNode* aPannerNode)
{
mPanners.AppendElement(aPannerNode->asWeakPtr());
mPanners.AppendElement(aPannerNode);
// Let the panner node know about our parameters
aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_POSITION, mPosition);

View File

@ -700,7 +700,7 @@ SpeechRecognition::Start(const Optional<NonNull<DOMMediaStream>>& aStream, Error
mRecognitionService = do_GetService(speechRecognitionServiceCID.get(), &rv);
NS_ENSURE_SUCCESS_VOID(rv);
rv = mRecognitionService->Initialize(this->asWeakPtr());
rv = mRecognitionService->Initialize(this);
NS_ENSURE_SUCCESS_VOID(rv);
MediaStreamConstraints constraints;

View File

@ -48,6 +48,7 @@ public:
int32_t aModType) const MOZ_OVERRIDE;
// nsSVGElement overrides
virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
@ -65,8 +66,6 @@ public:
virtual bool IsTransformable() MOZ_OVERRIDE { return true; }
protected:
// nsSVGElement overrides
nsAutoPtr<nsSVGAnimatedTransformList> mTransforms;
// XXX maybe move this to property table, to save space on un-animated elems?
@ -77,4 +76,3 @@ protected:
} // namespace mozilla
#endif // SVGTransformableElement_h

View File

@ -242,12 +242,4 @@ public:
sSVGAnimatedRectTearoffTable;
};
namespace mozilla {
template<>
struct HasDangerousPublicDestructor<nsSVGViewBox>
{
static const bool value = true;
};
}
#endif // __NS_SVGVIEWBOX_H__

View File

@ -1466,6 +1466,7 @@ Navigator::GetBattery(ErrorResult& aRv)
/* static */ already_AddRefed<Promise>
Navigator::GetDataStores(nsPIDOMWindow* aWindow,
const nsAString& aName,
const nsAString& aOwner,
ErrorResult& aRv)
{
if (!aWindow || !aWindow->GetDocShell()) {
@ -1480,16 +1481,18 @@ Navigator::GetDataStores(nsPIDOMWindow* aWindow,
}
nsCOMPtr<nsISupports> promise;
aRv = service->GetDataStores(aWindow, aName, getter_AddRefs(promise));
aRv = service->GetDataStores(aWindow, aName, aOwner, getter_AddRefs(promise));
nsRefPtr<Promise> p = static_cast<Promise*>(promise.get());
return p.forget();
}
already_AddRefed<Promise>
Navigator::GetDataStores(const nsAString& aName, ErrorResult& aRv)
Navigator::GetDataStores(const nsAString& aName,
const nsAString& aOwner,
ErrorResult& aRv)
{
return GetDataStores(mWindow, aName, aRv);
return GetDataStores(mWindow, aName, aOwner, aRv);
}
already_AddRefed<Promise>

View File

@ -161,13 +161,15 @@ public:
static already_AddRefed<Promise> GetDataStores(nsPIDOMWindow* aWindow,
const nsAString& aName,
const nsAString& aOwner,
ErrorResult& aRv);
already_AddRefed<Promise> GetDataStores(const nsAString &aName,
already_AddRefed<Promise> GetDataStores(const nsAString& aName,
const nsAString& aOwner,
ErrorResult& aRv);
// Feature Detection API
already_AddRefed<Promise> GetFeature(const nsAString &aName,
already_AddRefed<Promise> GetFeature(const nsAString& aName,
ErrorResult& aRv);
bool Vibrate(uint32_t aDuration);

View File

@ -40,6 +40,21 @@ WebGLFramebuffer::WebGLFramebuffer(WebGLContext* context)
mColorAttachments[0].mAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0;
}
WebGLFramebuffer::Attachment::Attachment(GLenum aAttachmentPoint)
: mAttachmentPoint(aAttachmentPoint)
, mNeedsFinalize(false)
{}
WebGLFramebuffer::Attachment::~Attachment()
{}
void
WebGLFramebuffer::Attachment::Reset()
{
mTexturePtr = nullptr;
mRenderbufferPtr = nullptr;
}
bool
WebGLFramebuffer::Attachment::IsDeleteRequested() const
{

View File

@ -26,8 +26,11 @@ class WebGLFramebuffer MOZ_FINAL
, public WebGLRefCountedObject<WebGLFramebuffer>
, public LinkedListElement<WebGLFramebuffer>
, public WebGLContextBoundObject
, public SupportsWeakPtr<WebGLFramebuffer>
{
public:
MOZ_DECLARE_REFCOUNTED_TYPENAME(WebGLFramebuffer)
WebGLFramebuffer(WebGLContext* context);
struct Attachment
@ -40,10 +43,8 @@ public:
GLint mTexImageLevel;
mutable bool mNeedsFinalize;
Attachment(GLenum aAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0)
: mAttachmentPoint(aAttachmentPoint)
, mNeedsFinalize(false)
{}
Attachment(GLenum aAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0);
~Attachment();
bool IsDefined() const {
return Texture() || Renderbuffer();
@ -79,10 +80,7 @@ public:
bool HasUninitializedImageData() const;
void SetImageDataStatus(WebGLImageDataStatus x);
void Reset() {
mTexturePtr = nullptr;
mRenderbufferPtr = nullptr;
}
void Reset();
const WebGLRectangleObject& RectangleObject() const;

View File

@ -11,20 +11,6 @@
using namespace mozilla;
WebGLFramebufferAttachable::AttachmentPoint*
WebGLFramebufferAttachable::Contains(const WebGLFramebuffer* fb, GLenum attachment)
{
AttachmentPoint* first = mAttachmentPoints.begin();
AttachmentPoint* last = mAttachmentPoints.end();
for (; first != last; ++first) {
if (first->mFB == fb && first->mAttachment == attachment)
return first;
}
return nullptr;
}
void
WebGLFramebufferAttachable::AttachTo(WebGLFramebuffer* fb, GLenum attachment)
{
@ -32,10 +18,10 @@ WebGLFramebufferAttachable::AttachTo(WebGLFramebuffer* fb, GLenum attachment)
if (!fb)
return;
if (Contains(fb, attachment))
if (mAttachmentPoints.Contains(AttachmentPoint(fb, attachment)))
return; // Already attached. Ignore.
mAttachmentPoints.append(AttachmentPoint(fb, attachment));
mAttachmentPoints.AppendElement(AttachmentPoint(fb, attachment));
}
void
@ -45,20 +31,21 @@ WebGLFramebufferAttachable::DetachFrom(WebGLFramebuffer* fb, GLenum attachment)
if (!fb)
return;
AttachmentPoint* point = Contains(fb, attachment);
if (!point) {
const size_t i = mAttachmentPoints.IndexOf(AttachmentPoint(fb, attachment));
if (i == mAttachmentPoints.NoIndex) {
MOZ_ASSERT(false, "Is not attached to FB");
return;
}
mAttachmentPoints.erase(point);
mAttachmentPoints.RemoveElementAt(i);
}
void
WebGLFramebufferAttachable::NotifyFBsStatusChanged()
{
AttachmentPoint* first = mAttachmentPoints.begin();
AttachmentPoint* last = mAttachmentPoints.end();
for ( ; first != last; ++first)
first->mFB->NotifyAttachableChanged();
for (size_t i = 0; i < mAttachmentPoints.Length(); ++i) {
MOZ_ASSERT(mAttachmentPoints[i].mFB,
"Unexpected null pointer; seems that a WebGLFramebuffer forgot to call DetachFrom before dying");
mAttachmentPoints[i].mFB->NotifyAttachableChanged();
}
}

View File

@ -7,12 +7,12 @@
#define WEBGLFRAMEBUFFERATTACHABLE_H_
#include "GLDefs.h"
#include "mozilla/Vector.h"
#include "nsTArray.h"
#include "mozilla/WeakPtr.h"
#include "WebGLFramebuffer.h"
namespace mozilla {
class WebGLFramebuffer;
class WebGLFramebufferAttachable
{
struct AttachmentPoint
@ -22,13 +22,15 @@ class WebGLFramebufferAttachable
, mAttachment(attachment)
{}
const WebGLFramebuffer* mFB;
WeakPtr<const WebGLFramebuffer> mFB;
GLenum mAttachment;
bool operator==(const AttachmentPoint& o) const {
return mFB == o.mFB && mAttachment == o.mAttachment;
}
};
Vector<AttachmentPoint> mAttachmentPoints;
AttachmentPoint* Contains(const WebGLFramebuffer* fb, GLenum attachment);
nsTArray<AttachmentPoint> mAttachmentPoints;
public:

View File

@ -322,7 +322,7 @@ private:
// Returns mResult as an ArrayBufferView, or an error
virtual void Resolve() MOZ_OVERRIDE
{
TypedArrayCreator<Uint8Array> ret(mResult);
TypedArrayCreator<ArrayBuffer> ret(mResult);
mResultPromise->MaybeResolve(ret);
}
};
@ -987,7 +987,7 @@ private:
{
if (mSign) {
// Return the computed MAC
TypedArrayCreator<Uint8Array> ret(mResult);
TypedArrayCreator<ArrayBuffer> ret(mResult);
mResultPromise->MaybeResolve(ret);
} else {
// Compare the MAC to the provided signature
@ -1116,7 +1116,7 @@ private:
virtual void Resolve() MOZ_OVERRIDE
{
if (mSign) {
TypedArrayCreator<Uint8Array> ret(mSignature);
TypedArrayCreator<ArrayBuffer> ret(mSignature);
mResultPromise->MaybeResolve(ret);
} else {
mResultPromise->MaybeResolve(mVerified);
@ -1745,7 +1745,7 @@ private:
return;
}
TypedArrayCreator<Uint8Array> ret(mResult);
TypedArrayCreator<ArrayBuffer> ret(mResult);
mResultPromise->MaybeResolve(ret);
}
};

View File

@ -1807,3 +1807,15 @@ TestArray.addTest(
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Test that we return ArrayBuffers not ArrayBufferViews",
function() {
var that = this;
crypto.subtle.digest("SHA-256", tv.sha256.data)
.then(complete(that, function (x) {
return x instanceof ArrayBuffer;
}), error(that));
}
);

View File

@ -3,14 +3,14 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var util = {
// Compare the contents of two ArrayBufferViews
// Compare the contents of two ArrayBuffer(View)s
memcmp: function util_memcmp(x, y) {
if (!x || !y) { return false; }
var xb = new Uint8Array(x);
var yb = new Uint8Array(y);
if (x.byteLength !== y.byteLength) { return false; }
var xb = new Uint8Array(x.buffer, x.byteOffset, x.byteLength);
var yb = new Uint8Array(y.buffer, y.byteOffset, y.byteLength);
for (var i=0; i<xb.byteLength; ++i) {
if (xb[i] !== yb[i]) {
return false;

View File

@ -322,16 +322,18 @@ class MOZ_STACK_CLASS GetDataStoreInfosData
{
public:
GetDataStoreInfosData(nsClassHashtable<nsStringHashKey, HashApp>& aAccessStores,
const nsAString& aName, uint32_t aAppId,
nsTArray<DataStoreInfo>& aStores)
const nsAString& aName, const nsAString& aManifestURL,
uint32_t aAppId, nsTArray<DataStoreInfo>& aStores)
: mAccessStores(aAccessStores)
, mName(aName)
, mManifestURL(aManifestURL)
, mAppId(aAppId)
, mStores(aStores)
{}
nsClassHashtable<nsStringHashKey, HashApp>& mAccessStores;
nsString mName;
nsString mManifestURL;
uint32_t mAppId;
nsTArray<DataStoreInfo>& mStores;
};
@ -354,6 +356,11 @@ GetDataStoreInfosEnumerator(const uint32_t& aAppId,
return PL_DHASH_NEXT;
}
if (!data->mManifestURL.IsEmpty() &&
!data->mManifestURL.Equals(aInfo->mManifestURL)) {
return PL_DHASH_NEXT;
}
DataStoreInfo* accessInfo = nullptr;
if (!apps->Get(data->mAppId, &accessInfo)) {
return PL_DHASH_NEXT;
@ -873,6 +880,7 @@ DataStoreService::InstallAccessDataStore(uint32_t aAppId,
NS_IMETHODIMP
DataStoreService::GetDataStores(nsIDOMWindow* aWindow,
const nsAString& aName,
const nsAString& aOwner,
nsISupports** aDataStores)
{
// FIXME This will be a thread-safe method.
@ -909,7 +917,7 @@ DataStoreService::GetDataStores(nsIDOMWindow* aWindow,
return NS_OK;
}
rv = GetDataStoreInfos(aName, appId, principal, stores);
rv = GetDataStoreInfos(aName, aOwner, appId, principal, stores);
if (NS_FAILED(rv)) {
RejectPromise(window, promise, rv);
promise.forget(aDataStores);
@ -924,6 +932,7 @@ DataStoreService::GetDataStores(nsIDOMWindow* aWindow,
nsTArray<DataStoreSetting> array;
if (!contentChild->SendDataStoreGetStores(nsAutoString(aName),
nsAutoString(aOwner),
IPC::Principal(principal),
&array)) {
RejectPromise(window, promise, NS_ERROR_FAILURE);
@ -1048,6 +1057,7 @@ DataStoreService::GetDataStoresResolve(nsPIDOMWindow* aWindow,
// name and available for this 'aAppId'.
nsresult
DataStoreService::GetDataStoreInfos(const nsAString& aName,
const nsAString& aOwner,
uint32_t aAppId,
nsIPrincipal* aPrincipal,
nsTArray<DataStoreInfo>& aStores)
@ -1083,13 +1093,14 @@ DataStoreService::GetDataStoreInfos(const nsAString& aName,
}
DataStoreInfo* info = nullptr;
if (apps->Get(aAppId, &info)) {
if (apps->Get(aAppId, &info) &&
(aOwner.IsEmpty() || aOwner.Equals(info->mManifestURL))) {
DataStoreInfo* owned = aStores.AppendElement();
owned->Init(info->mName, info->mOriginURL, info->mManifestURL, false,
info->mEnabled);
}
GetDataStoreInfosData data(mAccessStores, aName, aAppId, aStores);
GetDataStoreInfosData data(mAccessStores, aName, aOwner, aAppId, aStores);
apps->EnumerateRead(GetDataStoreInfosEnumerator, &data);
return NS_OK;
}
@ -1336,6 +1347,7 @@ DataStoreService::RemoveCounter(uint32_t aId)
nsresult
DataStoreService::GetDataStoresFromIPC(const nsAString& aName,
const nsAString& aOwner,
nsIPrincipal* aPrincipal,
nsTArray<DataStoreSetting>* aValue)
{
@ -1349,7 +1361,7 @@ DataStoreService::GetDataStoresFromIPC(const nsAString& aName,
}
nsTArray<DataStoreInfo> stores;
rv = GetDataStoreInfos(aName, appId, aPrincipal, stores);
rv = GetDataStoreInfos(aName, aOwner, appId, aPrincipal, stores);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

View File

@ -53,6 +53,7 @@ public:
nsresult GenerateUUID(nsAString& aID);
nsresult GetDataStoresFromIPC(const nsAString& aName,
const nsAString& aOwner,
nsIPrincipal* aPrincipal,
nsTArray<DataStoreSetting>* aValue);
@ -83,8 +84,8 @@ private:
void GetDataStoresResolve(nsPIDOMWindow* aWindow, Promise* aPromise,
const nsTArray<DataStoreInfo>& aStores);
nsresult GetDataStoreInfos(const nsAString& aName, uint32_t aAppId,
nsIPrincipal* aPrincipal,
nsresult GetDataStoreInfos(const nsAString& aName, const nsAString& aOwner,
uint32_t aAppId, nsIPrincipal* aPrincipal,
nsTArray<DataStoreInfo>& aStores);
void DeleteDataStores(uint32_t aAppId);

View File

@ -8,7 +8,7 @@
interface nsIDOMWindow;
interface nsIPrincipal;
[scriptable, uuid(43a731b9-0b5d-400a-8711-8c912c3c3572)]
[scriptable, uuid(9b59c49a-0cd7-11e4-b096-74d02b97e723)]
interface nsIDataStoreService : nsISupports
{
void installDataStore(in unsigned long appId,
@ -24,7 +24,8 @@ interface nsIDataStoreService : nsISupports
in boolean readOnly);
nsISupports getDataStores(in nsIDOMWindow window,
in DOMString name);
in DOMString name,
in DOMString owner);
boolean checkPermission(in nsIPrincipal principal);
};

View File

@ -6,6 +6,8 @@
<body>
<script type="application/javascript;version=1.7">
var gHostedManifestURL = 'http://test/tests/dom/datastore/tests/file_app.sjs?testToken=file_app_install.html';
function is(a, b, msg) {
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
}
@ -22,19 +24,68 @@
alert('DONE');
}
navigator.getDataStores('foo').then(function(stores) {
is(stores.length, 1, "getDataStores('foo') returns 1 element");
is(stores[0].name, 'foo', 'The dataStore.name is foo');
ok(stores[0].owner, 'The dataStore.owner exists');
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
var tests = [
// Get datastore with name 'foo'
function() {
navigator.getDataStores('foo').then(function(stores) {
is(stores.length, 1, "getDataStores('foo') returns 1 element");
is(stores[0].name, 'foo', 'The dataStore.name is foo');
ok(stores[0].owner, 'The dataStore.owner exists');
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
runTest();
}, cbError);
},
navigator.getDataStores('bar').then(function(stores) {
is(stores.length, 1, "getDataStores('bar') returns 1 element");
is(stores[0].name, 'bar', 'The dataStore.name is bar');
ok(stores[0].owner, 'The dataStore.owner exists');
is(stores[0].readOnly, false, 'The dataStore bar is in readonly');
// Get datastore with name 'bar'
function() {
navigator.getDataStores('bar').then(function(stores) {
is(stores.length, 1, "getDataStores('bar') returns 1 element");
is(stores[0].name, 'bar', 'The dataStore.name is bar');
ok(stores[0].owner, 'The dataStore.owner exists');
is(stores[0].readOnly, false, 'The dataStore bar is in readonly');
runTest();
}, cbError);
},
// Get datastore with name 'foo' and a specified owner
function() {
navigator.getDataStores('foo', gHostedManifestURL).then(function(stores) {
is(stores.length, 1, "getDataStores('foo','" + gHostedManifestURL +
"') returns 1 element");
is(stores[0].name, 'foo', 'The dataStore.name is foo');
ok(stores[0].owner, 'The dataStore.owner exists');
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
runTest();
}, cbError);
},
// Get datastore with name 'foo' and an arbitrary non-existent owner
function() {
navigator.getDataStores('foo', 'non-existent').then(function(stores) {
is(stores.length, 0, "getDataStores('foo','non-existent') returns 0 element");
runTest();
}, cbError);
},
// Get datastore with an arbitrary non-existent name
function() {
navigator.getDataStores('non-existent').then(function(stores) {
is(stores.length, 0, "getDataStores('non-existent') returns 0 element");
runTest();
}, cbError);
},
];
function runTest() {
if (!tests.length) {
finish();
}, cbError);
}, cbError);
return;
}
var test = tests.shift();
test();
}
runTest();
</script>
</html>

View File

@ -296,6 +296,20 @@ static uint32_t CountNewlinesInNativeLength(nsIContent* aContent,
}
#endif
/* static */ uint32_t
ContentEventHandler::GetNativeTextLength(nsIContent* aContent,
uint32_t aStartOffset,
uint32_t aEndOffset)
{
MOZ_ASSERT(aEndOffset >= aStartOffset,
"aEndOffset must be equals or larger than aStartOffset");
if (aStartOffset == aEndOffset) {
return 0;
}
return GetTextLength(aContent, LINE_BREAK_TYPE_NATIVE, aEndOffset) -
GetTextLength(aContent, LINE_BREAK_TYPE_NATIVE, aStartOffset);
}
/* static */ uint32_t
ContentEventHandler::GetNativeTextLength(nsIContent* aContent,
uint32_t aMaxLength)

View File

@ -85,6 +85,12 @@ public:
nsRange* aRange,
uint32_t* aOffset,
LineBreakType aLineBreakType);
// Computes the native text length between aStartOffset and aEndOffset of
// aContent. Currently, this method supports only text node or br element
// for aContent.
static uint32_t GetNativeTextLength(nsIContent* aContent,
uint32_t aStartOffset,
uint32_t aEndOffset);
// Get the native text length of a content node excluding any children
static uint32_t GetNativeTextLength(nsIContent* aContent,
uint32_t aMaxLength = UINT32_MAX);

View File

@ -25,7 +25,6 @@
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/InternalMutationEvent.h"
#include "mozilla/ipc/MessageChannel.h"
#include "mozilla/MiscEvents.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/TextEvents.h"

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,8 @@
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIDocShell.h" // XXX Why does only this need to be included here?
#include "nsIEditor.h"
#include "nsIEditorObserver.h"
#include "nsIReflowObserver.h"
#include "nsISelectionListener.h"
#include "nsIScrollObserver.h"
@ -29,11 +31,12 @@ class EventStateManager;
// IMEContentObserver notifies widget of any text and selection changes
// in the currently focused editor
class IMEContentObserver MOZ_FINAL : public nsISelectionListener,
public nsStubMutationObserver,
public nsIReflowObserver,
public nsIScrollObserver,
public nsSupportsWeakReference
class IMEContentObserver MOZ_FINAL : public nsISelectionListener
, public nsStubMutationObserver
, public nsIReflowObserver
, public nsIScrollObserver
, public nsSupportsWeakReference
, public nsIEditorObserver
{
public:
IMEContentObserver();
@ -41,7 +44,9 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IMEContentObserver,
nsISelectionListener)
NS_DECL_NSIEDITOROBSERVER
NS_DECL_NSISELECTIONLISTENER
NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATAWILLCHANGE
NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
@ -72,22 +77,148 @@ public:
nsresult GetSelectionAndRoot(nsISelection** aSelection,
nsIContent** aRoot) const;
struct TextChangeData
{
// mStartOffset is the start offset of modified or removed text in
// original content and inserted text in new content.
uint32_t mStartOffset;
// mRemovalEndOffset is the end offset of modified or removed text in
// original content. If the value is same as mStartOffset, no text hasn't
// been removed yet.
uint32_t mRemovedEndOffset;
// mAddedEndOffset is the end offset of inserted text or same as
// mStartOffset if just removed. The vlaue is offset in the new content.
uint32_t mAddedEndOffset;
bool mCausedOnlyByComposition;
bool mStored;
TextChangeData()
: mStartOffset(0)
, mRemovedEndOffset(0)
, mAddedEndOffset(0)
, mCausedOnlyByComposition(false)
, mStored(false)
{
}
TextChangeData(uint32_t aStartOffset,
uint32_t aRemovedEndOffset,
uint32_t aAddedEndOffset,
bool aCausedByComposition)
: mStartOffset(aStartOffset)
, mRemovedEndOffset(aRemovedEndOffset)
, mAddedEndOffset(aAddedEndOffset)
, mCausedOnlyByComposition(aCausedByComposition)
, mStored(true)
{
MOZ_ASSERT(aRemovedEndOffset >= aStartOffset,
"removed end offset must not be smaller than start offset");
MOZ_ASSERT(aAddedEndOffset >= aStartOffset,
"added end offset must not be smaller than start offset");
}
// Positive if text is added. Negative if text is removed.
int64_t Difference() const
{
return mAddedEndOffset - mRemovedEndOffset;
}
};
private:
~IMEContentObserver() {}
void MaybeNotifyIMEOfTextChange(const TextChangeData& aTextChangeData);
void MaybeNotifyIMEOfSelectionChange(bool aCausedByComposition);
void MaybeNotifyIMEOfPositionChange();
void NotifyContentAdded(nsINode* aContainer, int32_t aStart, int32_t aEnd);
void ObserveEditableNode();
/**
* UnregisterObservers() unresiters all listeners and observers.
* @param aPostEvent When true, DOM event will be posted to the thread.
* Otherwise, dispatched when safe.
*/
void UnregisterObservers(bool aPostEvent);
void StoreTextChangeData(const TextChangeData& aTextChangeData);
void FlushMergeableNotifications();
#ifdef DEBUG
void TestMergingTextChangeData();
#endif
nsCOMPtr<nsIWidget> mWidget;
nsCOMPtr<nsISelection> mSelection;
nsCOMPtr<nsIContent> mRootContent;
nsCOMPtr<nsINode> mEditableNode;
nsCOMPtr<nsIDocShell> mDocShell;
nsCOMPtr<nsIEditor> mEditor;
/**
* FlatTextCache stores flat text length from start of the content to
* mNodeOffset of mContainerNode.
*/
struct FlatTextCache
{
// mContainerNode and mNodeOffset represent a point in DOM tree. E.g.,
// if mContainerNode is a div element, mNodeOffset is index of its child.
nsCOMPtr<nsINode> mContainerNode;
int32_t mNodeOffset;
// Length of flat text generated from contents between the start of content
// and a child node whose index is mNodeOffset of mContainerNode.
uint32_t mFlatTextLength;
FlatTextCache()
: mNodeOffset(0)
, mFlatTextLength(0)
{
}
void Clear()
{
mContainerNode = nullptr;
mNodeOffset = 0;
mFlatTextLength = 0;
}
void Cache(nsINode* aContainer, int32_t aNodeOffset,
uint32_t aFlatTextLength)
{
MOZ_ASSERT(aContainer, "aContainer must not be null");
MOZ_ASSERT(
aNodeOffset <= static_cast<int32_t>(aContainer->GetChildCount()),
"aNodeOffset must be same as or less than the count of children");
mContainerNode = aContainer;
mNodeOffset = aNodeOffset;
mFlatTextLength = aFlatTextLength;
}
bool Match(nsINode* aContainer, int32_t aNodeOffset) const
{
return aContainer == mContainerNode && aNodeOffset == mNodeOffset;
}
};
// mEndOfAddedTextCache caches text length from the start of content to
// the end of the last added content only while an edit action is being
// handled by the editor and no other mutation (e.g., removing node)
// occur.
FlatTextCache mEndOfAddedTextCache;
// mStartOfRemovingTextRangeCache caches text length from the start of content
// to the start of the last removed content only while an edit action is being
// handled by the editor and no other mutation (e.g., adding node) occur.
FlatTextCache mStartOfRemovingTextRangeCache;
TextChangeData mTextChangeData;
EventStateManager* mESM;
nsIMEUpdatePreference mUpdatePreference;
uint32_t mPreAttrChangeLength;
int64_t mPreCharacterDataChangeLength;
bool mIsEditorInTransaction;
bool mIsSelectionChangeEventPending;
bool mSelectionChangeCausedOnlyByComposition;
bool mIsPositionChangeEventPending;
};
} // namespace mozilla

View File

@ -14,10 +14,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=375008
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=375008">Mozilla Bug 375008</a>
<p id="display"></p>
<div id="content">
<div>
<input id='witness'>
</div>
<div id='not-focusable'>
<!-- Disabled elements -->
<button hidden disabled>foo</button>
@ -52,6 +48,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=375008
<option hidden>foo</option>
</div>
<div>
<input id='witness'>
</div>
</div>
<pre id="test">
<script type="application/javascript">

View File

@ -2290,6 +2290,7 @@ ContentParent::RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel,
bool
ContentParent::RecvDataStoreGetStores(
const nsString& aName,
const nsString& aOwner,
const IPC::Principal& aPrincipal,
InfallibleTArray<DataStoreSetting>* aValue)
{
@ -2298,7 +2299,7 @@ ContentParent::RecvDataStoreGetStores(
return false;
}
nsresult rv = service->GetDataStoresFromIPC(aName, aPrincipal, aValue);
nsresult rv = service->GetDataStoresFromIPC(aName, aOwner, aPrincipal, aValue);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}

View File

@ -577,6 +577,7 @@ private:
virtual bool RecvDataStoreGetStores(
const nsString& aName,
const nsString& aOwner,
const IPC::Principal& aPrincipal,
InfallibleTArray<DataStoreSetting>* aValue) MOZ_OVERRIDE;

View File

@ -603,7 +603,7 @@ parent:
async AudioChannelChangedNotification();
async AudioChannelChangeDefVolChannel(int32_t aChannel, bool aHidden);
sync DataStoreGetStores(nsString aName, Principal aPrincipal)
sync DataStoreGetStores(nsString aName, nsString aOwner, Principal aPrincipal)
returns (DataStoreSetting[] dataStores);
async FilePathUpdateNotify(nsString aType,

View File

@ -19,7 +19,6 @@ const BrowserElementIsPreloaded = true;
Cu.import("resource://gre/modules/AppsServiceChild.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
Cu.import("resource://gre/modules/CSPUtils.jsm");
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/Geometry.jsm");
@ -70,7 +69,7 @@ const BrowserElementIsPreloaded = true;
Cc["@mozilla.org/thread-manager;1"].getService(Ci["nsIThreadManager"]);
Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci["nsIAppStartup"]);
Cc["@mozilla.org/uriloader;1"].getService(Ci["nsIURILoader"]);
Cc["@mozilla.org/contentsecuritypolicy;1"].createInstance(Ci["nsIContentSecurityPolicy"]);
Cc["@mozilla.org/cspcontext;1"].createInstance(Ci["nsIContentSecurityPolicy"]);
/* Applications Specific Helper */
try {

View File

@ -23,6 +23,7 @@
#include "nsIDocument.h"
#include "nsISupportsPrimitives.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIIDNService.h"
#include "nsNetUtil.h"
#include "mozilla/Types.h"
#include "mozilla/PeerIdentity.h"
@ -100,6 +101,59 @@ using dom::OwningBooleanOrMediaTrackConstraints;
using dom::SupportedAudioConstraints;
using dom::SupportedVideoConstraints;
static bool
HostHasPermission(nsIURI &docURI)
{
nsAdoptingCString hostName;
docURI.GetAsciiHost(hostName); //normalize UTF8 to ASCII equivalent
nsAdoptingCString domainWhiteList =
Preferences::GetCString("media.getusermedia.screensharing.allowed_domains");
domainWhiteList.StripWhitespace();
if (domainWhiteList.IsEmpty() || hostName.IsEmpty()) {
return false;
}
nsresult rv;
// Get UTF8 to ASCII domain name normalization service
nsCOMPtr<nsIIDNService> idnService
= do_GetService("@mozilla.org/network/idn-service;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
PRUint32 begin = 0;
PRUint32 end = 0;
nsCString domainName;
/*
Test each domain name in the comma separated list
after converting from UTF8 to ASCII. Each domain
must match exactly: no wildcards are used.
*/
do {
end = domainWhiteList.FindChar(',', begin);
if (end == (PRUint32)-1) {
// Last or only domain name in the comma separated list
end = domainWhiteList.Length();
}
rv = idnService->ConvertUTF8toACE(Substring(domainWhiteList, begin, end - begin),
domainName);
if (NS_SUCCEEDED(rv)) {
if (hostName.EqualsIgnoreCase(domainName.Data(), domainName.Length())) {
return true;
}
} else {
NS_WARNING("Failed to convert UTF-8 host to ASCII");
}
begin = end + 1;
} while (end < domainWhiteList.Length());
return false;
}
ErrorCallbackRunnable::ErrorCallbackRunnable(
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aSuccess,
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError,
@ -1488,12 +1542,20 @@ MediaManager::GetUserMedia(bool aPrivileged,
onError.forget(), windowID, listener, mPrefs);
}
// deny screensharing request if support is disabled
if (c.mVideo.IsMediaTrackConstraints() &&
!Preferences::GetBool("media.getusermedia.screensharing.enabled", false)) {
nsIURI* docURI = aWindow->GetDocumentURI();
if (c.mVideo.IsMediaTrackConstraints()) {
auto& tc = c.mVideo.GetAsMediaTrackConstraints();
if (tc.mMediaSource != dom::MediaSourceEnum::Camera && tc.mMediaSource != dom::MediaSourceEnum::Browser) {
return runnable->Denied(NS_LITERAL_STRING("PERMISSION_DENIED"));
// deny screensharing request if support is disabled
if (tc.mMediaSource != dom::MediaSourceEnum::Camera) {
if (!Preferences::GetBool("media.getusermedia.screensharing.enabled", false)) {
return runnable->Denied(NS_LITERAL_STRING("PERMISSION_DENIED"));
}
/* Deny screensharing if the requesting document is not from a host
on the whitelist. */
if (!HostHasPermission(*docURI)) {
return runnable->Denied(NS_LITERAL_STRING("PERMISSION_DENIED"));
}
}
}
@ -1510,7 +1572,6 @@ MediaManager::GetUserMedia(bool aPrivileged,
return NS_OK;
}
#endif
nsIURI* docURI = aWindow->GetDocumentURI();
bool isLoop = false;
nsCOMPtr<nsIURI> loopURI;

View File

@ -60,15 +60,21 @@ var globalPasted = false;
function pasteArea()
{
var pasteArea = document.getElementById("paste-selection-area");
var pasteAreaRect = pasteArea.getBoundingClientRect();
var pasteAreaCenterX = pasteAreaRect.left + pasteAreaRect.width/2;
var pasteAreaCenterY = pasteAreaRect.top + pasteAreaRect.height/2;
var util = SpecialPowers.getDOMWindowUtils(window);
pasteArea.focus();
synthesizeMouse(pasteArea, 8, 8, { button: 1 });
util.sendMouseEventToWindow("mousedown", pasteAreaCenterX, pasteAreaCenterY, 1, 1, 0, true);
util.sendMouseEventToWindow("mouseup", pasteAreaCenterX, pasteAreaCenterY, 1, 1, 0, true);
var usesMouseButtonPaste = SpecialPowers.getBoolPref("middlemouse.paste");
if (usesMouseButtonPaste) {
// The data transfer should contain the selection data when the selection clipboard is supported,
// not the global clipboard data.
var expectedText = supportsSelectionClipboard ? "COPY TEXT" : "CLIPBOARD";
is(document.getElementById("paste-selection-area").value, expectedText, "data pasted properly from selection");
is(document.getElementById("paste-selection-area").value, expectedText, "In pasteArea(): data pasted properly from selection");
ok(selectionPasted, "selection event fired");
}
else {
@ -92,7 +98,7 @@ function pastedSelection(event)
ok(navigator.platform.indexOf("Mac") == -1 && navigator.platform.indexOf("Win") == -1, "middle click enabled on right platforms");
var expectedText = supportsSelectionClipboard ? "COPY TEXT" : "CLIPBOARD";
is(event.clipboardData.getData("text/plain"), expectedText, "data pasted properly from selection");
is(event.clipboardData.getData("text/plain"), expectedText, "In pastedSelection(): data pasted properly from selection");
selectionPasted = true;
}

View File

@ -0,0 +1,41 @@
/* 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 MozSelfSupport interface allows external Mozilla support sites such as
* FHR and SUMO to access data and control settings that are not otherwise
* exposed to external content.
*
* At the moment, this is a ChromeOnly interface, but the plan is to allow
* specific Mozilla domains to access it directly.
*/
[ChromeOnly,
JSImplementation="@mozilla.org/mozselfsupport;1"]
interface MozSelfSupportImpl
{
/**
* Controls whether uploading FHR data is allowed.
*/
attribute boolean healthReportDataSubmissionEnabled;
/**
* Retrieves the FHR payload object, which is of the form:
*
* {
* version: Number,
* clientID: String,
* clientIDVersion: Number,
* thisPingDate: String,
* geckoAppInfo: Object,
* data: Object
* }
*
* Refer to the getJSONPayload function in healthreporter.jsm for more
* information.
*
* @return Promise<Object>
* Resolved when the FHR payload data has been collected.
*/
Promise getHealthReportPayload();
};

View File

@ -123,7 +123,7 @@ Navigator implements NavigatorBattery;
[NoInterfaceObject]
interface NavigatorDataStore {
[Throws, NewObject, Func="Navigator::HasDataStoreSupport"]
Promise getDataStores(DOMString name);
Promise getDataStores(DOMString name, optional DOMString? owner = null);
};
Navigator implements NavigatorDataStore;

View File

@ -260,6 +260,7 @@ WEBIDL_FILES = [
'MozMobileMessageManager.webidl',
'MozNamedAttrMap.webidl',
'MozPowerManager.webidl',
'MozSelfSupport.webidl',
'MozTimeManager.webidl',
'MozWakeLock.webidl',
'MutationEvent.webidl',

View File

@ -248,6 +248,9 @@ WifiCertService::Shutdown()
mRequestThread->Shutdown();
mRequestThread = nullptr;
}
mListener = nullptr;
return NS_OK;
}

View File

@ -239,11 +239,16 @@ WifiProxyService::Shutdown()
mEventThreadList[i].mThread = nullptr;
}
}
mEventThreadList.Clear();
if (mControlThread) {
mControlThread->Shutdown();
mControlThread = nullptr;
}
mListener = nullptr;
return NS_OK;
}

View File

@ -1780,6 +1780,7 @@ function WifiWorker() {
}).bind(this));
Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
Services.obs.addObserver(this, "xpcom-shutdown", false);
this.wantScanResults = [];
@ -2433,6 +2434,7 @@ WifiWorker.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWorkerHolder,
Ci.nsIWifi,
Ci.nsIObserver,
Ci.nsISettingsServiceCallback]),
disconnectedByWifi: false,
@ -3504,22 +3506,28 @@ WifiWorker.prototype = {
// nsIObserver implementation
observe: function observe(subject, topic, data) {
// Note that this function gets called for any and all settings changes,
// so we need to carefully check if we have the one we're interested in.
// The string we're interested in will be a JSON string that looks like:
// {"key":"wifi.enabled","value":"true"}.
if (topic !== kMozSettingsChangedObserverTopic) {
return;
}
switch (topic) {
case kMozSettingsChangedObserverTopic:
// The string we're interested in will be a JSON string that looks like:
// {"key":"wifi.enabled","value":"true"}.
let setting = JSON.parse(data);
// To avoid WifiWorker setting the wifi again, don't need to deal with
// the "mozsettings-changed" event fired from internal setting.
if (setting.message && setting.message === "fromInternalSetting") {
return;
}
let setting = JSON.parse(data);
// To avoid WifiWorker setting the wifi again, don't need to deal with
// the "mozsettings-changed" event fired from internal setting.
if (setting.message && setting.message === "fromInternalSetting") {
return;
}
this.handle(setting.key, setting.value);
this.handle(setting.key, setting.value);
break;
case "xpcom-shutdown":
let wifiService = Cc["@mozilla.org/wifi/service;1"].getService(Ci.nsIWifiProxyService);
wifiService.shutdown();
let wifiCertService = Cc["@mozilla.org/wifi/certservice;1"].getService(Ci.nsIWifiCertService);
wifiCertService.shutdown();
break;
}
},
handle: function handle(aName, aResult) {

View File

@ -206,15 +206,18 @@ class NavigatorGetDataStoresRunnable MOZ_FINAL : public WorkerMainThreadRunnable
{
nsRefPtr<PromiseWorkerProxy> mPromiseWorkerProxy;
const nsString mName;
const nsString mOwner;
ErrorResult& mRv;
public:
NavigatorGetDataStoresRunnable(WorkerPrivate* aWorkerPrivate,
Promise* aWorkerPromise,
const nsAString& aName,
const nsAString& aOwner,
ErrorResult& aRv)
: WorkerMainThreadRunnable(aWorkerPrivate)
, mName(aName)
, mOwner(aOwner)
, mRv(aRv)
{
MOZ_ASSERT(aWorkerPrivate);
@ -246,7 +249,8 @@ protected:
return false;
}
nsRefPtr<Promise> promise = Navigator::GetDataStores(window, mName, mRv);
nsRefPtr<Promise> promise =
Navigator::GetDataStores(window, mName, mOwner, mRv);
promise->AppendNativeHandler(mPromiseWorkerProxy);
return true;
}
@ -255,6 +259,7 @@ protected:
already_AddRefed<Promise>
WorkerNavigator::GetDataStores(JSContext* aCx,
const nsAString& aName,
const nsAString& aOwner,
ErrorResult& aRv)
{
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
@ -267,7 +272,7 @@ WorkerNavigator::GetDataStores(JSContext* aCx,
}
nsRefPtr<NavigatorGetDataStoresRunnable> runnable =
new NavigatorGetDataStoresRunnable(workerPrivate, promise, aName, aRv);
new NavigatorGetDataStoresRunnable(workerPrivate, promise, aName, aOwner, aRv);
runnable->Dispatch(aCx);
return promise.forget();

View File

@ -110,6 +110,7 @@ public:
already_AddRefed<Promise> GetDataStores(JSContext* aCx,
const nsAString& aName,
const nsAString& aOwner,
ErrorResult& aRv);
};

View File

@ -896,6 +896,7 @@ nsEditor::BeginPlaceHolderTransaction(nsIAtom *aName)
NS_PRECONDITION(mPlaceHolderBatch >= 0, "negative placeholder batch count!");
if (!mPlaceHolderBatch)
{
NotifyEditorObservers(eNotifyEditorObserversOfBefore);
// time to turn on the batch
BeginUpdateViewBatch();
mPlaceHolderTxn = nullptr;
@ -978,8 +979,10 @@ nsEditor::EndPlaceHolderTransaction()
// notify editor observers of action but if composing, it's done by
// text event handler.
if (!mComposition) {
NotifyEditorObservers();
NotifyEditorObservers(eNotifyEditorObserversOfEnd);
}
} else {
NotifyEditorObservers(eNotifyEditorObserversOfCancel);
}
}
mPlaceHolderBatch--;
@ -1854,17 +1857,35 @@ private:
bool mIsComposing;
};
void nsEditor::NotifyEditorObservers(void)
void
nsEditor::NotifyEditorObservers(NotificationForEditorObservers aNotification)
{
for (int32_t i = 0; i < mEditorObservers.Count(); i++) {
mEditorObservers[i]->EditAction();
}
switch (aNotification) {
case eNotifyEditorObserversOfEnd:
for (int32_t i = 0; i < mEditorObservers.Count(); i++) {
mEditorObservers[i]->EditAction();
}
if (!mDispatchInputEvent) {
return;
}
if (!mDispatchInputEvent) {
return;
}
FireInputEvent();
FireInputEvent();
break;
case eNotifyEditorObserversOfBefore:
for (int32_t i = 0; i < mEditorObservers.Count(); i++) {
mEditorObservers[i]->BeforeEditAction();
}
break;
case eNotifyEditorObserversOfCancel:
for (int32_t i = 0; i < mEditorObservers.Count(); i++) {
mEditorObservers[i]->CancelEditAction();
}
break;
default:
MOZ_CRASH("Handle all notifications here");
break;
}
}
void
@ -2076,7 +2097,7 @@ nsEditor::EndIMEComposition()
mComposition = nullptr;
// notify editor observers of action
NotifyEditorObservers();
NotifyEditorObservers(eNotifyEditorObserversOfEnd);
}

View File

@ -178,7 +178,13 @@ public:
already_AddRefed<nsIDocument> GetDocument();
already_AddRefed<nsIPresShell> GetPresShell();
already_AddRefed<nsIWidget> GetWidget();
void NotifyEditorObservers();
enum NotificationForEditorObservers
{
eNotifyEditorObserversOfEnd,
eNotifyEditorObserversOfBefore,
eNotifyEditorObserversOfCancel
};
void NotifyEditorObservers(NotificationForEditorObservers aNotification);
/* ------------ nsIEditor methods -------------- */
NS_DECL_NSIEDITOR

View File

@ -865,6 +865,8 @@ nsPlaintextEditor::UpdateIMEComposition(nsIDOMEvent* aDOMTextEvent)
nsresult rv = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(rv, rv);
NotifyEditorObservers(eNotifyEditorObserversOfBefore);
nsRefPtr<nsCaret> caretP = ps->GetCaret();
{
@ -885,7 +887,7 @@ nsPlaintextEditor::UpdateIMEComposition(nsIDOMEvent* aDOMTextEvent)
// notified at followed compositionend event.
// NOTE: We must notify after the auto batch will be gone.
if (IsIMEComposing()) {
NotifyEditorObservers();
NotifyEditorObservers(eNotifyEditorObserversOfEnd);
}
return rv;
@ -1100,6 +1102,8 @@ nsPlaintextEditor::Undo(uint32_t aCount)
ForceCompositionEnd();
NotifyEditorObservers(eNotifyEditorObserversOfBefore);
nsAutoRules beginRulesSniffing(this, EditAction::undo, nsIEditor::eNone);
nsTextRulesInfo ruleInfo(EditAction::undo);
@ -1112,8 +1116,8 @@ nsPlaintextEditor::Undo(uint32_t aCount)
result = nsEditor::Undo(aCount);
result = mRules->DidDoAction(selection, &ruleInfo, result);
}
NotifyEditorObservers();
NotifyEditorObservers(eNotifyEditorObserversOfEnd);
return result;
}
@ -1127,6 +1131,8 @@ nsPlaintextEditor::Redo(uint32_t aCount)
ForceCompositionEnd();
NotifyEditorObservers(eNotifyEditorObserversOfBefore);
nsAutoRules beginRulesSniffing(this, EditAction::redo, nsIEditor::eNone);
nsTextRulesInfo ruleInfo(EditAction::redo);
@ -1139,8 +1145,8 @@ nsPlaintextEditor::Redo(uint32_t aCount)
result = nsEditor::Redo(aCount);
result = mRules->DidDoAction(selection, &ruleInfo, result);
}
NotifyEditorObservers();
NotifyEditorObservers(eNotifyEditorObserversOfEnd);
return result;
}

View File

@ -9,7 +9,7 @@
Editor Observer interface to outside world
*/
[scriptable, uuid(e52a09fd-d33a-4f85-be0a-fbd348f0fa27)]
[scriptable, uuid(f3ee57a6-890c-4ce0-a584-8a84bba0292e)]
/**
* A generic editor observer interface.
@ -23,4 +23,14 @@ interface nsIEditorObserver : nsISupports {
* Called after the editor completes a user action.
*/
void EditAction();
/**
* Called when editor starts to handle a user action. I.e., This must be
* called before the first DOM change.
*/
void BeforeEditAction();
/**
* Called after BeforeEditAction() is called but EditorAction() won't be
* called.
*/
void CancelEditAction();
};

View File

@ -95,6 +95,9 @@ RotatedBuffer::DrawBufferQuadrant(gfx::DrawTarget* aTarget,
gfx::Point quadrantTranslation(quadrantRect.x, quadrantRect.y);
MOZ_ASSERT(aSource != BUFFER_BOTH);
RefPtr<SourceSurface> snapshot = GetSourceSurface(aSource);
// direct2d is much slower when using OP_SOURCE so use OP_OVER and
// (maybe) a clear instead. Normally we need to draw in a single operation
// (to avoid flickering) but direct2d is ok since it defers rendering.
@ -102,19 +105,11 @@ RotatedBuffer::DrawBufferQuadrant(gfx::DrawTarget* aTarget,
// cases.
if (aTarget->GetBackendType() == BackendType::DIRECT2D && aOperator == CompositionOp::OP_SOURCE) {
aOperator = CompositionOp::OP_OVER;
if (mDTBuffer->GetFormat() == SurfaceFormat::B8G8R8A8) {
if (snapshot->GetFormat() == SurfaceFormat::B8G8R8A8) {
aTarget->ClearRect(ToRect(fillRect));
}
}
RefPtr<gfx::SourceSurface> snapshot;
if (aSource == BUFFER_BLACK) {
snapshot = mDTBuffer->Snapshot();
} else {
MOZ_ASSERT(aSource == BUFFER_WHITE);
snapshot = mDTBufferOnWhite->Snapshot();
}
if (aOperator == CompositionOp::OP_SOURCE) {
// OP_SOURCE is unbounded in Azure, and we really don't want that behaviour here.
// We also can't do a ClearRect+FillRect since we need the drawing to happen
@ -181,6 +176,21 @@ RotatedBuffer::DrawBufferWithRotation(gfx::DrawTarget *aTarget, ContextSource aS
DrawBufferQuadrant(aTarget, RIGHT, BOTTOM, aSource, aOpacity, aOperator,aMask, aMaskTransform);
}
TemporaryRef<SourceSurface>
SourceRotatedBuffer::GetSourceSurface(ContextSource aSource) const
{
RefPtr<SourceSurface> surf;
if (aSource == BUFFER_BLACK) {
surf = mSource;
} else {
MOZ_ASSERT(aSource == BUFFER_WHITE);
surf = mSourceOnWhite;
}
MOZ_ASSERT(surf);
return surf;
}
/* static */ bool
RotatedContentBuffer::IsClippingCheap(DrawTarget* aTarget, const nsIntRegion& aRegion)
{
@ -737,6 +747,19 @@ RotatedContentBuffer::BorrowDrawTargetForPainting(PaintState& aPaintState,
return result;
}
TemporaryRef<SourceSurface>
RotatedContentBuffer::GetSourceSurface(ContextSource aSource) const
{
MOZ_ASSERT(mDTBuffer);
if (aSource == BUFFER_BLACK) {
return mDTBuffer->Snapshot();
} else {
MOZ_ASSERT(mDTBufferOnWhite);
MOZ_ASSERT(aSource == BUFFER_WHITE);
return mDTBufferOnWhite->Snapshot();
}
}
}
}

View File

@ -52,12 +52,9 @@ class RotatedBuffer {
public:
typedef gfxContentType ContentType;
RotatedBuffer(gfx::DrawTarget* aDTBuffer, gfx::DrawTarget* aDTBufferOnWhite,
const nsIntRect& aBufferRect,
RotatedBuffer(const nsIntRect& aBufferRect,
const nsIntPoint& aBufferRotation)
: mDTBuffer(aDTBuffer)
, mDTBufferOnWhite(aDTBufferOnWhite)
, mBufferRect(aBufferRect)
: mBufferRect(aBufferRect)
, mBufferRotation(aBufferRotation)
, mDidSelfCopy(false)
{ }
@ -89,8 +86,10 @@ public:
const nsIntRect& BufferRect() const { return mBufferRect; }
const nsIntPoint& BufferRotation() const { return mBufferRotation; }
virtual bool HaveBuffer() const { return mDTBuffer; }
virtual bool HaveBufferOnWhite() const { return mDTBufferOnWhite; }
virtual bool HaveBuffer() const = 0;
virtual bool HaveBufferOnWhite() const = 0;
virtual TemporaryRef<gfx::SourceSurface> GetSourceSurface(ContextSource aSource) const = 0;
protected:
@ -116,8 +115,6 @@ protected:
gfx::SourceSurface* aMask,
const gfx::Matrix* aMaskTransform) const;
RefPtr<gfx::DrawTarget> mDTBuffer;
RefPtr<gfx::DrawTarget> mDTBufferOnWhite;
/** The area of the ThebesLayer that is covered by the buffer as a whole */
nsIntRect mBufferRect;
/**
@ -136,6 +133,27 @@ protected:
bool mDidSelfCopy;
};
class SourceRotatedBuffer : public RotatedBuffer
{
public:
SourceRotatedBuffer(gfx::SourceSurface* aSource, gfx::SourceSurface* aSourceOnWhite,
const nsIntRect& aBufferRect,
const nsIntPoint& aBufferRotation)
: RotatedBuffer(aBufferRect, aBufferRotation)
, mSource(aSource)
, mSourceOnWhite(aSourceOnWhite)
{ }
virtual TemporaryRef<gfx::SourceSurface> GetSourceSurface(ContextSource aSource) const;
virtual bool HaveBuffer() const { return !!mSource; }
virtual bool HaveBufferOnWhite() const { return !!mSourceOnWhite; }
private:
RefPtr<gfx::SourceSurface> mSource;
RefPtr<gfx::SourceSurface> mSourceOnWhite;
};
// Mixin class for classes which need logic for loaning out a draw target.
// See comments on BorrowDrawTargetForQuadrantUpdate.
class BorrowDrawTarget
@ -308,6 +326,8 @@ public:
gfx::DrawTarget* GetDTBuffer() { return mDTBuffer; }
gfx::DrawTarget* GetDTBufferOnWhite() { return mDTBufferOnWhite; }
virtual TemporaryRef<gfx::SourceSurface> GetSourceSurface(ContextSource aSource) const;
/**
* Complete the drawing operation. The region to draw must have been
* drawn before this is called. The contents of the buffer are drawn
@ -398,6 +418,9 @@ protected:
*/
virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) {}
RefPtr<gfx::DrawTarget> mDTBuffer;
RefPtr<gfx::DrawTarget> mDTBufferOnWhite;
/**
* These members are only set transiently. They're used to map mDTBuffer
* when we're using surfaces that require explicit map/unmap. Only one

View File

@ -54,6 +54,12 @@ DIBTextureClient::Unlock()
{
MOZ_ASSERT(mIsLocked, "Unlocked called while the texture is not locked!");
if (mDrawTarget) {
if (mReadbackSink) {
RefPtr<SourceSurface> snapshot = mDrawTarget->Snapshot();
RefPtr<DataSourceSurface> dataSurf = snapshot->GetDataSurface();
mReadbackSink->ProcessReadback(dataSurf);
}
mDrawTarget->Flush();
mDrawTarget = nullptr;
}

View File

@ -1026,7 +1026,9 @@ APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint, bool* aOutInOverscroll
bool inOverscrolledApzc = false;
for (AsyncPanZoomController* apzc = mRootApzc; apzc; apzc = apzc->GetPrevSibling()) {
target = GetAPZCAtPoint(apzc, point, &inOverscrolledApzc);
if (target) {
// If we hit an overscrolled APZC, 'target' will be nullptr but it's still
// a hit so we don't search further siblings.
if (target || inOverscrolledApzc) {
break;
}
}

View File

@ -15,6 +15,8 @@
#include "nsISupportsUtils.h" // for NS_ADDREF, NS_RELEASE
#include "nsRegion.h" // for nsIntRegion
#include "nsTArray.h" // for nsAutoTArray
#include "ReadbackProcessor.h"
#include "ClientThebesLayer.h"
namespace mozilla {
namespace layers {
@ -55,13 +57,20 @@ public:
nsAutoTArray<Layer*, 12> children;
SortChildrenBy3DZOrder(children);
ReadbackProcessor readback;
readback.BuildUpdates(this);
for (uint32_t i = 0; i < children.Length(); i++) {
Layer* child = children.ElementAt(i);
if (child->GetEffectiveVisibleRegion().IsEmpty()) {
continue;
}
ToClientLayer(child)->RenderLayer();
if (child->GetType() != TYPE_THEBES) {
ToClientLayer(child)->RenderLayer();
} else {
static_cast<ClientThebesLayer*>(child)->RenderLayer(&readback);
}
if (!ClientManager()->GetRepeatTransaction() &&
!child->GetInvalidRegion().IsEmpty()) {

View File

@ -21,6 +21,7 @@
#include "mozilla/layers/LayerTransactionChild.h"
#include "mozilla/layers/TextureClientPool.h" // for TextureClientPool
#include "mozilla/layers/SimpleTextureClientPool.h" // for SimpleTextureClientPool
#include "ClientReadbackLayer.h" // for ClientReadbackLayer
#include "nsAString.h"
#include "nsIWidget.h" // for nsIWidget
#include "nsIWidgetListener.h"
@ -116,6 +117,13 @@ ClientLayerManager::Mutated(Layer* aLayer)
mForwarder->Mutated(Hold(aLayer));
}
already_AddRefed<ReadbackLayer>
ClientLayerManager::CreateReadbackLayer()
{
nsRefPtr<ReadbackLayer> layer = new ClientReadbackLayer(this);
return layer.forget();
}
void
ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
{

View File

@ -88,6 +88,7 @@ public:
virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
virtual already_AddRefed<ImageLayer> CreateImageLayer();
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer();
virtual already_AddRefed<ColorLayer> CreateColorLayer();
virtual already_AddRefed<RefLayer> CreateRefLayer();

View File

@ -0,0 +1,33 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_CLIENTREADBACKLAYER_H
#define GFX_CLIENTREADBACKLAYER_H
#include "ClientLayerManager.h"
#include "ReadbackLayer.h"
namespace mozilla {
namespace layers {
class ClientReadbackLayer :
public ReadbackLayer,
public ClientLayer
{
public:
ClientReadbackLayer(ClientLayerManager *aManager)
: ReadbackLayer(aManager, nullptr)
{
mImplData = static_cast<ClientLayer*>(this);
}
virtual Layer* AsLayer() { return this; }
virtual void RenderLayer() {}
};
} /* layers */
} /* mozilla */
#endif /* GFX_CLIENTREADBACKLAYER_H */

View File

@ -24,6 +24,7 @@
#include "nsISupportsImpl.h" // for Layer::AddRef, etc
#include "nsRect.h" // for nsIntRect
#include "gfx2DGlue.h"
#include "ReadbackProcessor.h"
namespace mozilla {
namespace layers {
@ -104,7 +105,7 @@ ClientThebesLayer::PaintThebes()
}
void
ClientThebesLayer::RenderLayer()
ClientThebesLayer::RenderLayer(ReadbackProcessor *aReadback)
{
if (GetMaskLayer()) {
ToClientLayer(GetMaskLayer())->RenderLayer();
@ -120,9 +121,16 @@ ClientThebesLayer::RenderLayer()
MOZ_ASSERT(mContentClient->GetForwarder());
}
nsTArray<ReadbackProcessor::Update> readbackUpdates;
nsIntRegion readbackRegion;
if (aReadback && UsedForReadback()) {
aReadback->GetThebesLayerUpdates(this, &readbackUpdates);
}
IntPoint origin(mVisibleRegion.GetBounds().x, mVisibleRegion.GetBounds().y);
mContentClient->BeginPaint();
PaintThebes();
mContentClient->EndPaint();
mContentClient->EndPaint(&readbackUpdates);
}
bool

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