merge mozilla-inbound to mozilla-central a=merge

--HG--
rename : toolkit/devtools/server/actors/styleeditor.js => devtools/server/actors/styleeditor.js
rename : toolkit/devtools/server/actors/stylesheets.js => devtools/server/actors/stylesheets.js
rename : toolkit/devtools/gcli/commands/screenshot.js => devtools/shared/gcli/commands/screenshot.js
This commit is contained in:
Carsten "Tomcat" Book 2015-09-22 12:35:13 +02:00
commit 651a168616
321 changed files with 3490 additions and 2052 deletions

View File

@ -1348,12 +1348,12 @@ DocAccessible::ProcessInvalidationList()
// Alter the tree according to aria-owns (seize the trees).
for (uint32_t idx = 0; idx < mARIAOwnsInvalidationList.Length(); idx++) {
Accessible* owner = mARIAOwnsInvalidationList[idx].mOwner;
if (owner->IsDefunct()) { // eventually died until we've got here
if (!owner->IsInDocument()) { // eventually died before we've got here
continue;
}
Accessible* child = GetAccessible(mARIAOwnsInvalidationList[idx].mChild);
if (!child) {
if (!child || !child->IsInDocument()) {
continue;
}

View File

@ -954,7 +954,7 @@ pref("devtools.debugger.unix-domain-socket", "/data/local/debugger-socket");
// falling back to Skia/software for smaller canvases
#ifdef MOZ_WIDGET_GONK
pref("gfx.canvas.azure.backends", "skia");
pref("gfx.canvas.azure.accelerated", true);
pref("gfx.canvas.azure.accelerated", false);
#endif
// Turn on dynamic cache size for Skia

View File

@ -45,7 +45,7 @@ var tests = [
let loopDoc = document.getElementById("loop-notification-panel").children[0].contentDocument;
yield waitForConditionPromise(() => {
return loopDoc.readyState == 'complete';
}, "Loop notification panel document should be fully loaded.");
}, "Loop notification panel document should be fully loaded.", 50);
let gettingStartedButton = loopDoc.getElementById("fte-button");
ok(gettingStartedButton, "Getting Started button should be found");

View File

@ -164,7 +164,7 @@ this.ContentLinkHandler = {
}
// Security says okay, now ask content policy
if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE,
if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE,
uri, targetDoc.documentURIObject,
aLink, aLink.type, null)
!= Ci.nsIContentPolicy.ACCEPT)

View File

@ -79,7 +79,7 @@ function _imageFromURI(doc, uri, privateMode, callback) {
null, // aLoadingPrincipal
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_IMAGE);
Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE);
try {
channel.QueryInterface(Ci.nsIPrivateBrowsingChannel);
channel.setPrivate(privateMode);

View File

@ -54,9 +54,6 @@ menuitem[cmd="cmd_clearhistory"][disabled] {
list-style-image: url("moz-icon://stock/gtk-clear?size=menu&state=disabled");
}
.searchbar-search-button-container {
-moz-box-align: center;
}
@ -88,15 +85,14 @@ menuitem[cmd="cmd_clearhistory"][disabled] {
}
.search-panel-current-engine {
border-bottom: 1px solid #ccc;
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
}
.search-panel-header {
font-weight: normal;
background-color: rgb(245, 245, 245);
border-top: 1px solid #ccc;
border-top: 1px solid rgba(0, 0, 0, 0.2);
padding: 3px 5px;
color: #666;
color: MenuText;
}
.search-panel-tree[collapsed=true] + .search-panel-header {
@ -113,12 +109,12 @@ menuitem[cmd="cmd_clearhistory"][disabled] {
}
.search-panel-input-value {
color: black;
color: Highlight;
}
.search-panel-one-offs {
margin: 0 -1px !important;
border-top: 1px solid #ccc;
border-top: 1px solid rgba(0, 0, 0, 0.2);
}
.searchbar-engine-one-off-item {
@ -130,14 +126,14 @@ menuitem[cmd="cmd_clearhistory"][disabled] {
margin: 0 0;
padding: 0 0;
background: none;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAYAAAABxvaqAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gofECQNNVW2/AAAABBJREFUGFdjOHPmzH8GehEA/KpKg9YTf4AAAAAASUVORK5CYII=');
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAYAAAABxvaqAAAABmJLR0QA/wD/AP+gvaeTAAAAFElEQVQI12NgYGAwZmJgYGCgBwEAHpIAXs+dj/cAAAAASUVORK5CYII=');
background-repeat: no-repeat;
background-position: right center;
}
.searchbar-engine-one-off-item:not(.last-row) {
box-sizing: content-box;
border-bottom: 1px solid #ccc;
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
}
.searchbar-engine-one-off-item.last-of-row {
@ -178,7 +174,7 @@ menuitem[cmd="cmd_clearhistory"][disabled] {
}
.addengine-item:first-of-type {
border-top: 1px solid #ccc;
border-top: 1px solid rgba(0, 0, 0, 0.2);
}
.addengine-item[selected] {
@ -231,13 +227,15 @@ menuitem[cmd="cmd_clearhistory"][disabled] {
.search-setting-button {
-moz-appearance: none;
background-color: Menu;
border: none;
border-top: 1px solid #ccc;
border-top: 1px solid rgba(0, 0, 0, 0.2);
margin: 0;
min-height: 32px;
}
.search-setting-button[selected] {
background-color: #d3d3d3;
background-color: Highlight;
color: HighlightText;
border-top-color: #bdbebe;
}

View File

@ -455,7 +455,7 @@ var OldStyleSheetActor = protocol.ActorClass({
}
let options = {
policy: Ci.nsIContentPolicy.TYPE_STYLESHEET,
policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET,
window: this.window,
charset: this._getCSSCharset()
};

View File

@ -606,7 +606,7 @@ var StyleSheetActor = protocol.ActorClass({
let options = {
loadFromCache: true,
policy: Ci.nsIContentPolicy.TYPE_STYLESHEET,
policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET,
window: this.window,
charset: this._getCSSCharset()
};
@ -692,7 +692,7 @@ var StyleSheetActor = protocol.ActorClass({
url = normalize(url, this.href);
let options = {
loadFromCache: false,
policy: Ci.nsIContentPolicy.TYPE_STYLESHEET,
policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET,
window: this.window
};
let map = fetch(url, options)
@ -1020,7 +1020,7 @@ var OriginalSourceActor = protocol.ActorClass({
return promise.resolve(content);
}
let options = {
policy: Ci.nsIContentPolicy.TYPE_STYLESHEET,
policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET,
window: this.window
};
return fetch(this.url, options).then(({content}) => {

View File

@ -357,7 +357,7 @@ function saveToClipboard(context, reply) {
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_IMAGE);
Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE);
const input = channel.open();
const imgTools = Cc["@mozilla.org/image/tools;1"]
.getService(Ci.imgITools);

View File

@ -13922,8 +13922,55 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNavigate,
return NS_OK;
}
namespace {
class FetchEventDispatcher final : public nsIFetchEventDispatcher
{
public:
FetchEventDispatcher(nsIInterceptedChannel* aChannel,
nsIRunnable* aContinueRunnable)
: mChannel(aChannel)
, mContinueRunnable(aContinueRunnable)
{
}
NS_DECL_ISUPPORTS
NS_DECL_NSIFETCHEVENTDISPATCHER
private:
~FetchEventDispatcher()
{
}
nsCOMPtr<nsIInterceptedChannel> mChannel;
nsCOMPtr<nsIRunnable> mContinueRunnable;
};
NS_IMPL_ISUPPORTS(FetchEventDispatcher, nsIFetchEventDispatcher)
NS_IMETHODIMP
nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
FetchEventDispatcher::Dispatch()
{
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
if (!swm) {
mChannel->Cancel(NS_ERROR_INTERCEPTION_FAILED);
return NS_OK;
}
ErrorResult error;
swm->DispatchPreparedFetchEvent(mChannel, mContinueRunnable, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
return NS_OK;
}
}
NS_IMETHODIMP
nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel,
nsIFetchEventDispatcher** aFetchDispatcher)
{
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
if (!swm) {
@ -13949,11 +13996,17 @@ nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
OriginAttributes attrs(GetAppId(), GetIsInBrowserElement());
ErrorResult error;
swm->DispatchFetchEvent(attrs, doc, aChannel, isReload, error);
nsCOMPtr<nsIRunnable> runnable =
swm->PrepareFetchEvent(attrs, doc, aChannel, isReload, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
MOZ_ASSERT(runnable);
nsRefPtr<FetchEventDispatcher> dispatcher =
new FetchEventDispatcher(aChannel, runnable);
dispatcher.forget(aFetchDispatcher);
return NS_OK;
}

View File

@ -1744,9 +1744,8 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
}
if (GetParent()) {
nsINode* p = mParent;
mParent = nullptr;
NS_RELEASE(p);
nsRefPtr<nsINode> p;
p.swap(mParent);
} else {
mParent = nullptr;
}

View File

@ -13,6 +13,7 @@
#include "nsISupports.h"
#include "nsXPCOM.h"
#include "nsContentPolicyUtils.h"
#include "mozilla/dom/nsCSPService.h"
#include "nsContentPolicy.h"
#include "nsIURI.h"
#include "nsIDocShell.h"
@ -123,9 +124,15 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
nsContentPolicyType externalTypeOrScript =
nsContentUtils::InternalContentPolicyTypeToExternalOrScript(contentType);
nsContentPolicyType externalTypeOrPreload =
nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(contentType);
nsCOMPtr<nsIContentPolicy> mixedContentBlocker =
do_GetService(NS_MIXEDCONTENTBLOCKER_CONTRACTID);
nsCOMPtr<nsIContentPolicy> cspService =
do_GetService(CSPSERVICE_CONTRACTID);
/*
* Enumerate mPolicies and ask each of them, taking the logical AND of
* their permissions.
@ -144,6 +151,15 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
if (isMixedContentBlocker) {
type = externalTypeOrScript;
}
// Send the internal content policy type for CSP which needs to
// know about preloads, in particular:
// * TYPE_INTERNAL_SCRIPT_PRELOAD
// * TYPE_INTERNAL_IMAGE_PRELOAD
// * TYPE_INTERNAL_STYLESHEET_PRELOAD
bool isCSP = cspService == entries[i];
if (isCSP) {
type = externalTypeOrPreload;
}
rv = (entries[i]->*policyMethod)(type, contentLocation,
requestingLocation, requestingContext,
mimeType, extra, requestPrincipal,

View File

@ -92,41 +92,46 @@ inline const char *
NS_CP_ContentTypeName(uint32_t contentType)
{
switch (contentType) {
CASE_RETURN( TYPE_OTHER );
CASE_RETURN( TYPE_SCRIPT );
CASE_RETURN( TYPE_IMAGE );
CASE_RETURN( TYPE_STYLESHEET );
CASE_RETURN( TYPE_OBJECT );
CASE_RETURN( TYPE_DOCUMENT );
CASE_RETURN( TYPE_SUBDOCUMENT );
CASE_RETURN( TYPE_REFRESH );
CASE_RETURN( TYPE_XBL );
CASE_RETURN( TYPE_PING );
CASE_RETURN( TYPE_XMLHTTPREQUEST );
CASE_RETURN( TYPE_OBJECT_SUBREQUEST );
CASE_RETURN( TYPE_DTD );
CASE_RETURN( TYPE_FONT );
CASE_RETURN( TYPE_MEDIA );
CASE_RETURN( TYPE_WEBSOCKET );
CASE_RETURN( TYPE_CSP_REPORT );
CASE_RETURN( TYPE_XSLT );
CASE_RETURN( TYPE_BEACON );
CASE_RETURN( TYPE_FETCH );
CASE_RETURN( TYPE_IMAGESET );
CASE_RETURN( TYPE_WEB_MANIFEST );
CASE_RETURN( TYPE_INTERNAL_SCRIPT );
CASE_RETURN( TYPE_INTERNAL_WORKER );
CASE_RETURN( TYPE_INTERNAL_SHARED_WORKER );
CASE_RETURN( TYPE_INTERNAL_EMBED );
CASE_RETURN( TYPE_INTERNAL_OBJECT );
CASE_RETURN( TYPE_INTERNAL_FRAME );
CASE_RETURN( TYPE_INTERNAL_IFRAME );
CASE_RETURN( TYPE_INTERNAL_AUDIO );
CASE_RETURN( TYPE_INTERNAL_VIDEO );
CASE_RETURN( TYPE_INTERNAL_TRACK );
CASE_RETURN( TYPE_INTERNAL_XMLHTTPREQUEST );
CASE_RETURN( TYPE_INTERNAL_EVENTSOURCE );
CASE_RETURN( TYPE_INTERNAL_SERVICE_WORKER );
CASE_RETURN( TYPE_OTHER );
CASE_RETURN( TYPE_SCRIPT );
CASE_RETURN( TYPE_IMAGE );
CASE_RETURN( TYPE_STYLESHEET );
CASE_RETURN( TYPE_OBJECT );
CASE_RETURN( TYPE_DOCUMENT );
CASE_RETURN( TYPE_SUBDOCUMENT );
CASE_RETURN( TYPE_REFRESH );
CASE_RETURN( TYPE_XBL );
CASE_RETURN( TYPE_PING );
CASE_RETURN( TYPE_XMLHTTPREQUEST );
CASE_RETURN( TYPE_OBJECT_SUBREQUEST );
CASE_RETURN( TYPE_DTD );
CASE_RETURN( TYPE_FONT );
CASE_RETURN( TYPE_MEDIA );
CASE_RETURN( TYPE_WEBSOCKET );
CASE_RETURN( TYPE_CSP_REPORT );
CASE_RETURN( TYPE_XSLT );
CASE_RETURN( TYPE_BEACON );
CASE_RETURN( TYPE_FETCH );
CASE_RETURN( TYPE_IMAGESET );
CASE_RETURN( TYPE_WEB_MANIFEST );
CASE_RETURN( TYPE_INTERNAL_SCRIPT );
CASE_RETURN( TYPE_INTERNAL_WORKER );
CASE_RETURN( TYPE_INTERNAL_SHARED_WORKER );
CASE_RETURN( TYPE_INTERNAL_EMBED );
CASE_RETURN( TYPE_INTERNAL_OBJECT );
CASE_RETURN( TYPE_INTERNAL_FRAME );
CASE_RETURN( TYPE_INTERNAL_IFRAME );
CASE_RETURN( TYPE_INTERNAL_AUDIO );
CASE_RETURN( TYPE_INTERNAL_VIDEO );
CASE_RETURN( TYPE_INTERNAL_TRACK );
CASE_RETURN( TYPE_INTERNAL_XMLHTTPREQUEST );
CASE_RETURN( TYPE_INTERNAL_EVENTSOURCE );
CASE_RETURN( TYPE_INTERNAL_SERVICE_WORKER );
CASE_RETURN( TYPE_INTERNAL_SCRIPT_PRELOAD );
CASE_RETURN( TYPE_INTERNAL_IMAGE );
CASE_RETURN( TYPE_INTERNAL_IMAGE_PRELOAD );
CASE_RETURN( TYPE_INTERNAL_STYLESHEET );
CASE_RETURN( TYPE_INTERNAL_STYLESHEET_PRELOAD );
default:
return "<Unknown Type>";
}

View File

@ -7959,6 +7959,7 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType)
{
switch (aType) {
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
case nsIContentPolicy::TYPE_INTERNAL_WORKER:
case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
@ -7981,6 +7982,14 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType)
case nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE:
return nsIContentPolicy::TYPE_XMLHTTPREQUEST;
case nsIContentPolicy::TYPE_INTERNAL_IMAGE:
case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD:
return nsIContentPolicy::TYPE_IMAGE;
case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET:
case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD:
return nsIContentPolicy::TYPE_STYLESHEET;
default:
return aType;
}
@ -8002,6 +8011,17 @@ nsContentUtils::InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType
}
}
/* static */
nsContentPolicyType
nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(nsContentPolicyType aType)
{
if (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD) {
return aType;
}
return InternalContentPolicyTypeToExternal(aType);
}
nsresult
nsContentUtils::SetFetchReferrerURIWithPolicy(nsIPrincipal* aPrincipal,
@ -8133,28 +8153,17 @@ nsContentUtils::InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
access = std::min(StorageAccess::eSessionScoped, access);
}
// If the caller is chrome privileged, then it is allowed to access any
// storage it likes, no matter whether the storage for that window/principal
// would normally be permitted.
if (IsSystemPrincipal(SubjectPrincipal())) {
return access;
}
if (!SubjectPrincipal()->Subsumes(aPrincipal)) {
NS_WARNING("A principal is attempting to access storage for a principal "
"which it doesn't subsume!");
return StorageAccess::eDeny;
}
// About URIs are allowed to access storage, even if they don't have chrome
// privileges. If this is not desired, than the consumer will have to
// implement their own restriction functionality.
nsCOMPtr<nsIURI> uri;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aPrincipal->GetURI(getter_AddRefs(uri))));
bool isAbout = false;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(uri->SchemeIs("about", &isAbout)));
if (isAbout) {
return access;
nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
if (NS_SUCCEEDED(rv) && uri) {
bool isAbout = false;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(uri->SchemeIs("about", &isAbout)));
if (isAbout) {
return access;
}
}
nsCOMPtr<nsIPermissionManager> permissionManager =

View File

@ -624,7 +624,7 @@ public:
* @param aContext the context the image is loaded in (eg an element)
* @param aLoadingDocument the document we belong to
* @param aLoadingPrincipal the principal doing the load
* @param [aContentPolicyType=nsIContentPolicy::TYPE_IMAGE] (Optional)
* @param [aContentPolicyType=nsIContentPolicy::TYPE_INTERNAL_IMAGE] (Optional)
* The CP content type to use
* @param aImageBlockingStatus the nsIContentPolicy blocking status for this
* image. This will be set even if a security check fails for the
@ -640,7 +640,7 @@ public:
nsIDocument* aLoadingDocument,
nsIPrincipal* aLoadingPrincipal,
int16_t* aImageBlockingStatus = nullptr,
uint32_t aContentPolicyType = nsIContentPolicy::TYPE_IMAGE);
uint32_t aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE);
/**
* Returns true if objects in aDocument shouldn't initiate image loads.
@ -660,7 +660,7 @@ public:
* creation
* @param aObserver the observer for the image load
* @param aLoadFlags the load flags to use. See nsIRequest
* @param [aContentPolicyType=nsIContentPolicy::TYPE_IMAGE] (Optional)
* @param [aContentPolicyType=nsIContentPolicy::TYPE_INTERNAL_IMAGE] (Optional)
* The CP content type to use
* @return the imgIRequest for the image load
*/
@ -673,7 +673,7 @@ public:
int32_t aLoadFlags,
const nsAString& initiatorType,
imgRequestProxy** aRequest,
uint32_t aContentPolicyType = nsIContentPolicy::TYPE_IMAGE);
uint32_t aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE);
/**
* Obtain an image loader that respects the given document/channel's privacy status.
@ -965,6 +965,16 @@ public:
*/
static nsContentPolicyType InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType aType);
/**
* Map internal content policy types to external ones or preload types:
* * TYPE_INTERNAL_SCRIPT_PRELOAD
* * TYPE_INTERNAL_IMAGE_PRELOAD
* * TYPE_INTERNAL_STYLESHEET_PRELOAD
*
* Note: DO NOT call this function unless you know what you're doing!
*/
static nsContentPolicyType InternalContentPolicyTypeToExternalOrPreload(nsContentPolicyType aType);
/**
* Quick helper to determine whether there are any mutation listeners
* of a given type that apply to this content or any of its ancestors.

View File

@ -9739,7 +9739,8 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
int16_t blockingStatus;
if (nsContentUtils::IsImageInCache(uri, static_cast<nsIDocument *>(this)) ||
!nsContentUtils::CanLoadImage(uri, static_cast<nsIDocument *>(this),
this, NodePrincipal(), &blockingStatus)) {
this, NodePrincipal(), &blockingStatus,
nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD)) {
return;
}
@ -9769,7 +9770,8 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
nullptr, // no observer
loadFlags,
NS_LITERAL_STRING("img"),
getter_AddRefs(request));
getter_AddRefs(request),
nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD);
// Pin image-reference to avoid evicting it from the img-cache before
// the "real" load occurs. Unpinned in DispatchContentLoadedEvents and
@ -9883,7 +9885,7 @@ nsDocument::PreloadStyle(nsIURI* uri, const nsAString& charset,
nsCOMPtr<nsICSSLoaderObserver> obs = new StubCSSLoaderObserver();
// Charset names are always ASCII.
CSSLoader()->LoadSheet(uri, NodePrincipal(),
CSSLoader()->LoadSheet(uri, true, NodePrincipal(),
NS_LossyConvertUTF16toASCII(charset),
obs,
Element::StringToCORSMode(aCrossOriginAttr),

View File

@ -20,7 +20,7 @@ interface nsIPrincipal;
* by launching a dialog to prompt the user for something).
*/
[scriptable,uuid(ce321216-c404-40a7-a711-d80454ec6b76)]
[scriptable,uuid(caad4f1f-d047-46ac-ae9d-dc598e4fb91b)]
interface nsIContentPolicy : nsIContentPolicyBase
{
/**

View File

@ -24,7 +24,7 @@ typedef unsigned long nsContentPolicyType;
* by launching a dialog to prompt the user for something).
*/
[scriptable,uuid(8527ae0d-0c43-4413-bc46-85c0bcb66876)]
[scriptable,uuid(17418187-d86f-48dd-92d1-238838df0a4e)]
interface nsIContentPolicyBase : nsISupports
{
/**
@ -280,6 +280,47 @@ interface nsIContentPolicyBase : nsISupports
*/
const nsContentPolicyType TYPE_INTERNAL_SERVICE_WORKER = 35;
/**
* Indicates an internal constant for *preloaded* scripts
* loaded through script elements.
*
* This will be mapped to TYPE_SCRIPT before being passed
* to content policy implementations.
*/
const nsContentPolicyType TYPE_INTERNAL_SCRIPT_PRELOAD = 36;
/**
* Indicates an internal constant for normal images.
*
* This will be mapped to TYPE_IMAGE before being passed
* to content policy implementations.
*/
const nsContentPolicyType TYPE_INTERNAL_IMAGE = 37;
/**
* Indicates an internal constant for *preloaded* images.
*
* This will be mapped to TYPE_IMAGE before being passed
* to content policy implementations.
*/
const nsContentPolicyType TYPE_INTERNAL_IMAGE_PRELOAD = 38;
/**
* Indicates an internal constant for normal stylesheets.
*
* This will be mapped to TYPE_STYLESHEET before being passed
* to content policy implementations.
*/
const nsContentPolicyType TYPE_INTERNAL_STYLESHEET = 39;
/**
* Indicates an internal constant for *preloaded* stylesheets.
*
* This will be mapped to TYPE_STYLESHEET before being passed
* to content policy implementations.
*/
const nsContentPolicyType TYPE_INTERNAL_STYLESHEET_PRELOAD = 40;
/* When adding new content types, please update nsContentBlocker,
* NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy
* implementations, the static_assert in dom/cache/DBSchema.cpp,

View File

@ -589,7 +589,7 @@ nsImageLoadingContent::PolicyTypeForLoad(ImageLoadType aImageLoadType)
MOZ_ASSERT(aImageLoadType == eImageLoadType_Normal,
"Unknown ImageLoadType type in PolicyTypeForLoad");
return nsIContentPolicy::TYPE_IMAGE;
return nsIContentPolicy::TYPE_INTERNAL_IMAGE;
}
int32_t

View File

@ -1530,7 +1530,7 @@ nsObjectLoadingContent::CheckProcessPolicy(int16_t *aContentPolicy)
int32_t objectType;
switch (mType) {
case eType_Image:
objectType = nsIContentPolicy::TYPE_IMAGE;
objectType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
break;
case eType_Document:
objectType = nsIContentPolicy::TYPE_DOCUMENT;

View File

@ -10,6 +10,7 @@
#include "nsScriptLoader.h"
#include "prsystem.h"
#include "jsapi.h"
#include "jsfriendapi.h"
#include "xpcpublic.h"
@ -223,10 +224,15 @@ nsresult
nsScriptLoader::CheckContentPolicy(nsIDocument* aDocument,
nsISupports *aContext,
nsIURI *aURI,
const nsAString &aType)
const nsAString &aType,
bool aIsPreLoad)
{
nsContentPolicyType contentPolicyType = aIsPreLoad
? nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD
: nsIContentPolicy::TYPE_INTERNAL_SCRIPT;
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_SCRIPT,
nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
aURI,
aDocument->NodePrincipal(),
aContext,
@ -249,7 +255,8 @@ nsresult
nsScriptLoader::ShouldLoadScript(nsIDocument* aDocument,
nsISupports* aContext,
nsIURI* aURI,
const nsAString &aType)
const nsAString &aType,
bool aIsPreLoad)
{
// Check that the containing page is allowed to load this URI.
nsresult rv = nsContentUtils::GetSecurityManager()->
@ -259,7 +266,7 @@ nsScriptLoader::ShouldLoadScript(nsIDocument* aDocument,
NS_ENSURE_SUCCESS(rv, rv);
// After the security manager, the content-policy stuff gets a veto
rv = CheckContentPolicy(aDocument, aContext, aURI, aType);
rv = CheckContentPolicy(aDocument, aContext, aURI, aType, aIsPreLoad);
if (NS_FAILED(rv)) {
return rv;
}
@ -274,7 +281,7 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
nsISupports *context = aRequest->mElement.get()
? static_cast<nsISupports *>(aRequest->mElement.get())
: static_cast<nsISupports *>(mDocument);
nsresult rv = ShouldLoadScript(mDocument, context, aRequest->mURI, aType);
nsresult rv = ShouldLoadScript(mDocument, context, aRequest->mURI, aType, aRequest->IsPreload());
if (NS_FAILED(rv)) {
return rv;
}
@ -296,12 +303,16 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
return NS_OK;
}
nsContentPolicyType contentPolicyType = aRequest->IsPreload()
? nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD
: nsIContentPolicy::TYPE_INTERNAL_SCRIPT;
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel),
aRequest->mURI,
mDocument,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_INTERNAL_SCRIPT,
contentPolicyType,
loadGroup,
prompter,
nsIRequest::LOAD_NORMAL |
@ -530,7 +541,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
if (elementCharset.Equals(preloadCharset) &&
ourCORSMode == request->mCORSMode &&
ourRefPolicy == request->mReferrerPolicy) {
rv = CheckContentPolicy(mDocument, aElement, request->mURI, type);
rv = CheckContentPolicy(mDocument, aElement, request->mURI, type, false);
NS_ENSURE_SUCCESS(rv, false);
} else {
// Drop the preload
@ -587,7 +598,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// loop gets a chance to spin.
// KVKV TODO: Instead of processing immediately, try off-thread-parsing
// it and only schedule a ProcessRequest if that fails.
// it and only schedule a pending ProcessRequest if that fails.
ProcessPendingRequestsAsync();
} else {
mLoadingAsyncRequests.AppendElement(request);
@ -636,6 +647,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
}
return true;
}
if (request->IsDoneLoading() && ReadyToExecuteScripts()) {
// The request has already been loaded and there are no pending style
// sheets. If the script comes from the network stream, cheat for
@ -654,6 +666,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
ProcessPendingRequestsAsync();
return true;
}
// The script hasn't loaded yet or there's a style sheet blocking it.
// The script will be run when it loads or the style sheet loads.
NS_ASSERTION(!mParserBlockingRequest,
@ -752,6 +765,23 @@ nsScriptLoader::ProcessOffThreadRequest(nsScriptLoadRequest* aRequest)
{
MOZ_ASSERT(aRequest->mProgress == nsScriptLoadRequest::Progress_Compiling);
aRequest->mProgress = nsScriptLoadRequest::Progress_DoneCompiling;
if (aRequest == mParserBlockingRequest) {
if (!ReadyToExecuteScripts()) {
// If not ready to execute scripts, schedule an async call to
// ProcessPendingRequests to handle it.
ProcessPendingRequestsAsync();
return NS_OK;
}
// Same logic as in top of ProcessPendingRequests.
mParserBlockingRequest = nullptr;
UnblockParser(aRequest);
ProcessRequest(aRequest);
mDocument->UnblockOnload(false);
ContinueParserAsync(aRequest);
return NS_OK;
}
nsresult rv = ProcessRequest(aRequest);
mDocument->UnblockOnload(false);
return rv;
@ -800,9 +830,10 @@ OffThreadScriptLoaderCallback(void *aToken, void *aCallbackData)
}
nsresult
nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest)
nsScriptLoader::AttemptAsyncScriptCompile(nsScriptLoadRequest* aRequest)
{
if (!aRequest->mElement->GetScriptAsync() || aRequest->mIsInline) {
// Don't off-thread compile inline scripts.
if (aRequest->mIsInline) {
return NS_ERROR_FAILURE;
}
@ -843,7 +874,8 @@ nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest)
}
nsresult
nsScriptLoader::CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest)
nsScriptLoader::CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest,
bool* oCompiledOffThread)
{
NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
"Processing requests when running scripts is unsafe.");
@ -852,8 +884,11 @@ nsScriptLoader::CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest)
NS_ASSERTION(!aRequest->InCompilingStage(),
"Candidate for off-thread compile is already in compiling stage.");
nsresult rv = AttemptAsyncScriptParse(aRequest);
nsresult rv = AttemptAsyncScriptCompile(aRequest);
if (rv != NS_ERROR_FAILURE) {
if (oCompiledOffThread && rv == NS_OK) {
*oCompiledOffThread = true;
}
return rv;
}
@ -1144,8 +1179,12 @@ nsScriptLoader::ProcessPendingRequests()
mParserBlockingRequest->IsReadyToRun() &&
ReadyToExecuteScripts()) {
request.swap(mParserBlockingRequest);
bool offThreadCompiled = request->mProgress == nsScriptLoadRequest::Progress_DoneCompiling;
UnblockParser(request);
ProcessRequest(request);
if (offThreadCompiled) {
mDocument->UnblockOnload(false);
}
ContinueParserAsync(request);
}
@ -1549,6 +1588,23 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
// Mark this as loaded
aRequest->mProgress = nsScriptLoadRequest::Progress_DoneLoading;
// If this is currently blocking the parser, attempt to compile it off-main-thread.
if (aRequest == mParserBlockingRequest && (PR_GetNumberOfProcessors() > 1)) {
nsresult rv = AttemptAsyncScriptCompile(aRequest);
if (rv == NS_OK) {
NS_ASSERTION(aRequest->mProgress == nsScriptLoadRequest::Progress_Compiling,
"Request should be off-thread compiling now.");
return NS_OK;
}
// If off-thread compile errored, return the error.
if (rv != NS_ERROR_FAILURE) {
return rv;
}
// If off-thread compile was rejected, continue with regular processing.
}
// And if it's async, move it to the loaded list. aRequest->mIsAsync really
// _should_ be in a list, but the consequences if it's not are bad enough we
// want to avoid trying to move it if it's not.

View File

@ -354,7 +354,8 @@ public:
static nsresult ShouldLoadScript(nsIDocument* aDocument,
nsISupports* aContext,
nsIURI* aURI,
const nsAString &aType);
const nsAString &aType,
bool aIsPreLoad);
/**
* Starts deferring deferred scripts and puts them in the mDeferredRequests
@ -435,7 +436,8 @@ private:
static nsresult CheckContentPolicy(nsIDocument* aDocument,
nsISupports *aContext,
nsIURI *aURI,
const nsAString &aType);
const nsAString &aType,
bool aIsPreLoad);
/**
* Start a load for aRequest's URI.
@ -468,9 +470,10 @@ private:
return mEnabled && !mBlockerCount;
}
nsresult AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest);
nsresult AttemptAsyncScriptCompile(nsScriptLoadRequest* aRequest);
nsresult ProcessRequest(nsScriptLoadRequest* aRequest);
nsresult CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest);
nsresult CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest,
bool* oCompiledOffThread=nullptr);
void FireScriptAvailable(nsresult aResult,
nsScriptLoadRequest* aRequest);
void FireScriptEvaluated(nsresult aResult,

View File

@ -275,7 +275,12 @@ static_assert(nsIContentPolicy::TYPE_INVALID == 0 &&
nsIContentPolicy::TYPE_INTERNAL_TRACK == 32 &&
nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST == 33 &&
nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE == 34 &&
nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER == 35,
nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER == 35 &&
nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD == 36 &&
nsIContentPolicy::TYPE_INTERNAL_IMAGE == 37 &&
nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD == 38 &&
nsIContentPolicy::TYPE_INTERNAL_STYLESHEET == 39 &&
nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD == 40,
"nsContentPolicyType values are as expected");
namespace {

View File

@ -1408,6 +1408,7 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
mTarget = Factory::CreateDrawTargetSkiaWithGrContext(glue->GetGrContext(), size, format);
if (mTarget) {
AddDemotableContext(this);
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
} else {
printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n");
mode = RenderingMode::SoftwareBackendMode;

View File

@ -161,18 +161,8 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt5);
case WebGLExtensionID::WEBGL_debug_renderer_info:
{
bool isEnabled = true;
return Preferences::GetBool("webgl.enable-debug-renderer-info", false);
#ifdef RELEASE_BUILD
// Keep this disabled on Release and Beta for now. (see bug 1171228)
isEnabled = false;
#endif
if (Preferences::GetBool("webgl.disable-debug-renderer-info", false))
isEnabled = false;
return isEnabled;
}
case WebGLExtensionID::WEBGL_depth_texture:
// WEBGL_depth_texture supports DEPTH_STENCIL textures
if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil))

View File

@ -2,11 +2,6 @@
<html>
<script>
var Cu = parent.Components.utils;
Cu.import("resource://gre/modules/AppConstants.jsm");
// This gives us `AppConstants` in the global scope.
// We need this because we only expose debug_renderer_info #ifndef MOZ_RELEASE_BUILD.
// This should match AppConstants.RELEASE_BUILD.
// This file has the portion of the test_webgl_renderer_info chrome mochitest
// that has to run as non-chrome to check that this WebGL extension is not exposed to content
@ -23,21 +18,18 @@ function ok(res, msg) {
function messageListener(e) {
// This is how the chrome test tells us to start running -- we have to wait for this
// message to avoid running before it's set up its event handler.
if (e.data == "run") {
run();
if (e.data.run) {
var canBeUnprivileged = e.data.canBeUnprivileged;
run(canBeUnprivileged);
}
}
window.addEventListener("message", messageListener, true);
function run() {
function run(canBeUnprivileged) {
const UNMASKED_VENDOR_WEBGL = 0x9245;
const UNMASKED_RENDERER_WEBGL = 0x9246;
var shouldHaveRendererInfo = false;
if (!AppConstants.RELEASE_BUILD)
shouldHaveRendererInfo = true;
var canvas = document.createElement("canvas");
var gl = canvas.getContext("experimental-webgl");
@ -51,7 +43,7 @@ function run() {
+ " WEBGL_debug_renderer_info extension");
var exts = gl.getSupportedExtensions();
if (shouldHaveRendererInfo) {
if (canBeUnprivileged) {
ok(exts.indexOf("WEBGL_debug_renderer_info") != -1,
"WEBGL_debug_renderer_info should be listed by getSupportedExtensions in"
+ " non-chrome contexts on non-RELEASE_BUILDs");

View File

@ -17,6 +17,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=666446
const UNMASKED_VENDOR_WEBGL = 0x9245;
const UNMASKED_RENDERER_WEBGL = 0x9246;
var Cu = parent.Components.utils;
Cu.import("resource://gre/modules/AppConstants.jsm");
// This gives us `AppConstants` in the global scope.
// We need this because we only expose debug_renderer_info #ifndef MOZ_RELEASE_BUILD.
// This should match AppConstants.RELEASE_BUILD.
const canBeUnprivileged = !AppConstants.RELEASE_BUILD;
function isNonEmptyString(s)
{
return s && (typeof s) == "string";
@ -67,7 +77,7 @@ function main()
// Now run the non-chrome code to verify the security of this WebGL chrome-only extension.
var iframe = document.createElement("iframe");
iframe.src = "chrome://mochitests/content/chrome/dom/canvas/test/chrome/nonchrome_webgl_debug_renderer_info.html";
iframe.src = "http://mochi.test:8888/chrome/dom/canvas/test/chrome/nonchrome_webgl_debug_renderer_info.html";
iframe.onload = function () {
@ -77,7 +87,9 @@ function main()
checkChromeCase(iframe.contentDocument.createElement("canvas"));
iframe.contentWindow.addEventListener("message", messageListener, false);
iframe.contentWindow.postMessage("run", "*");
iframe.contentWindow.postMessage({run: true,
canBeUnprivileged: canBeUnprivileged},
"*");
};
document.body.appendChild(iframe);

View File

@ -12,7 +12,7 @@ function AssertError(gl, expected, info) {
while (gl.getError()) {}
ok(actual == expected,
'For ' + info + ', expected 0x' + expected.toString(16) + ', got 0x'
'For ' + info + ', expected GL error 0x' + expected.toString(16) + ', got 0x'
+ actual.toString(16));
}
@ -23,17 +23,20 @@ var VENDOR_OVERRIDE = 'overridden vendor';
function TestExt() {
var ext = gl.getExtension('WEBGL_debug_renderer_info');
ok(ext, 'Should have access to \'WEBGL_debug_renderer_info\'.');
ok(ext, 'When pref enabled: Should have access to \'WEBGL_debug_renderer_info\'.');
AssertError(gl, 0, 'start of test');
var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
AssertError(gl, 0, 'UNMASKED_RENDERER_WEBGL');
ok(renderer,
'UNMASKED_RENDERER_WEBGL value should not be empty, was \'' + renderer + '\'');
'When pref enabled: UNMASKED_RENDERER_WEBGL value should not be empty, was \''
+ renderer + '\'');
var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);
AssertError(gl, 0, 'UNMASKED_VENDOR_WEBGL');
ok(vendor, 'UNMASKED_VENDOR_WEBGL value should not be empty, was \'' + vendor + '\'');
ok(vendor,
'When pref enabled: UNMASKED_VENDOR_WEBGL value should not be empty, was \''
+ vendor + '\'');
var prefArrArr = [
['webgl.renderer-string-override', RENDERER_OVERRIDE],
@ -45,23 +48,23 @@ function TestExt() {
function TestOverrides() {
var ext = gl.getExtension('WEBGL_debug_renderer_info');
ok(ext, 'Should have access to \'WEBGL_debug_renderer_info\'.');
ok(ext, 'When overrides set: Should have access to \'WEBGL_debug_renderer_info\'.');
AssertError(gl, 0, 'start of test');
var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
AssertError(gl, 0, 'UNMASKED_RENDERER_WEBGL');
ok(renderer == RENDERER_OVERRIDE,
'UNMASKED_RENDERER_WEBGL value should be \'' + RENDERER_OVERRIDE + '\', was \''
+ renderer + '\'');
'When overrides set: UNMASKED_RENDERER_WEBGL value should be \'' + RENDERER_OVERRIDE
+ '\', was \'' + renderer + '\'');
var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);
AssertError(gl, 0, 'UNMASKED_VENDOR_WEBGL');
ok(vendor == VENDOR_OVERRIDE,
'UNMASKED_VENDOR_WEBGL value should be \'' + VENDOR_OVERRIDE + '\', was \'' + vendor
+ '\'');
'When overrides set: UNMASKED_VENDOR_WEBGL value should be \'' + VENDOR_OVERRIDE
+ '\', was \'' + vendor + '\'');
var prefArrArr = [
['webgl.disable-debug-renderer-info', true],
['webgl.enable-debug-renderer-info', false],
];
var prefEnv = {'set': prefArrArr};
SpecialPowers.pushPrefEnv(prefEnv, TestDisable);
@ -69,7 +72,8 @@ function TestOverrides() {
function TestDisable() {
var ext = gl.getExtension('WEBGL_debug_renderer_info');
ok(!ext, 'Should not have access to \'WEBGL_debug_renderer_info\'.');
ok(!ext,
'When pref disabled: Should not have access to \'WEBGL_debug_renderer_info\'.');
ok(true, 'Test complete.');
SimpleTest.finish();
@ -87,7 +91,7 @@ function TestDisable() {
SimpleTest.waitForExplicitFinish();
var prefArrArr = [
['webgl.disable-debug-renderer-info', false],
['webgl.enable-debug-renderer-info', true],
];
var prefEnv = {'set': prefArrArr};
SpecialPowers.pushPrefEnv(prefEnv, TestExt);

View File

@ -116,6 +116,7 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte
context = RequestContext::Internal;
break;
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
context = RequestContext::Script;
break;
@ -125,10 +126,12 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte
case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
context = RequestContext::Sharedworker;
break;
case nsIContentPolicy::TYPE_IMAGE:
case nsIContentPolicy::TYPE_INTERNAL_IMAGE:
case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD:
context = RequestContext::Image;
break;
case nsIContentPolicy::TYPE_STYLESHEET:
case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET:
case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD:
context = RequestContext::Style;
break;
case nsIContentPolicy::TYPE_INTERNAL_OBJECT:

View File

@ -43,7 +43,7 @@ namespace dom {
* frame | TYPE_INTERNAL_FRAME
* hyperlink |
* iframe | TYPE_INTERNAL_IFRAME
* image | TYPE_IMAGE
* image | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD
* imageset | TYPE_IMAGESET
* import | Not supported by Gecko
* internal | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER
@ -53,10 +53,10 @@ namespace dom {
* ping | TYPE_PING
* plugin | TYPE_OBJECT_SUBREQUEST
* prefetch |
* script | TYPE_INTERNAL_SCRIPT
* script | TYPE_INTERNAL_SCRIPT, TYPE_INTERNAL_SCRIPT_PRELOAD
* sharedworker | TYPE_INTERNAL_SHARED_WORKER
* subresource | Not supported by Gecko
* style | TYPE_STYLESHEET
* style | TYPE_INTERNAL_STYLESHEET, TYPE_INTERNAL_STYLESHEET_PRELOAD
* track | TYPE_INTERNAL_TRACK
* video | TYPE_INTERNAL_VIDEO
* worker | TYPE_INTERNAL_WORKER

View File

@ -27,7 +27,6 @@
// If the pref is true, the antanna will be always available.
#define DOM_FM_ANTENNA_INTERNAL_PREF "dom.fmradio.antenna.internal"
using namespace mozilla::hal;
using mozilla::Preferences;
BEGIN_FMRADIO_NAMESPACE
@ -106,7 +105,7 @@ private:
NS_IMPL_ISUPPORTS_INHERITED0(FMRadioRequest, DOMRequest)
FMRadio::FMRadio()
: mHeadphoneState(SWITCH_STATE_OFF)
: mHeadphoneState(hal::SWITCH_STATE_OFF)
, mRdsGroupMask(0)
, mAudioChannelAgentEnabled(false)
, mHasInternalAntenna(false)
@ -131,8 +130,8 @@ FMRadio::Init(nsPIDOMWindow *aWindow)
if (mHasInternalAntenna) {
LOG("We have an internal antenna.");
} else {
mHeadphoneState = GetCurrentSwitchState(SWITCH_HEADPHONES);
RegisterSwitchObserver(SWITCH_HEADPHONES, this);
mHeadphoneState = hal::GetCurrentSwitchState(hal::SWITCH_HEADPHONES);
hal::RegisterSwitchObserver(hal::SWITCH_HEADPHONES, this);
}
nsCOMPtr<nsIAudioChannelAgent> audioChannelAgent =
@ -155,7 +154,7 @@ FMRadio::Shutdown()
IFMRadioService::Singleton()->RemoveObserver(this);
if (!mHasInternalAntenna) {
UnregisterSwitchObserver(SWITCH_HEADPHONES, this);
hal::UnregisterSwitchObserver(hal::SWITCH_HEADPHONES, this);
}
mIsShutdown = true;
@ -168,7 +167,7 @@ FMRadio::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
}
void
FMRadio::Notify(const SwitchEvent& aEvent)
FMRadio::Notify(const hal::SwitchEvent& aEvent)
{
MOZ_ASSERT(!mHasInternalAntenna);
@ -241,8 +240,8 @@ FMRadio::RdsEnabled()
bool
FMRadio::AntennaAvailable() const
{
return mHasInternalAntenna ? true : (mHeadphoneState != SWITCH_STATE_OFF) &&
(mHeadphoneState != SWITCH_STATE_UNKNOWN);
return mHasInternalAntenna ? true : (mHeadphoneState != hal::SWITCH_STATE_OFF) &&
(mHeadphoneState != hal::SWITCH_STATE_UNKNOWN);
}
Nullable<double>
@ -387,7 +386,7 @@ FMRadio::SeekUp()
}
nsRefPtr<FMRadioRequest> r = new FMRadioRequest(win, this);
IFMRadioService::Singleton()->Seek(FM_RADIO_SEEK_DIRECTION_UP, r);
IFMRadioService::Singleton()->Seek(hal::FM_RADIO_SEEK_DIRECTION_UP, r);
return r.forget();
}
@ -401,7 +400,7 @@ FMRadio::SeekDown()
}
nsRefPtr<FMRadioRequest> r = new FMRadioRequest(win, this);
IFMRadioService::Singleton()->Seek(FM_RADIO_SEEK_DIRECTION_DOWN, r);
IFMRadioService::Singleton()->Seek(hal::FM_RADIO_SEEK_DIRECTION_DOWN, r);
return r.forget();
}

View File

@ -33,7 +33,6 @@
#define DOM_PARSED_RDS_GROUPS ((0x2 << 30) | (0x3 << 4) | (0x3 << 0))
using namespace mozilla::hal;
using mozilla::Preferences;
BEGIN_FMRADIO_NAMESPACE
@ -78,9 +77,9 @@ FMRadioService::FMRadioService()
memset(mTempRadiotext, 0, sizeof(mTempRadiotext));
// Read power state and frequency from Hal.
mEnabled = IsFMRadioOn();
mEnabled = hal::IsFMRadioOn();
if (mEnabled) {
mPendingFrequencyInKHz = GetFMRadioFrequency();
mPendingFrequencyInKHz = hal::GetFMRadioFrequency();
SetState(Enabled);
}
@ -133,54 +132,34 @@ FMRadioService::FMRadioService()
NS_WARNING("Failed to add settings change observer!");
}
RegisterFMRadioObserver(this);
RegisterFMRadioRDSObserver(this);
hal::RegisterFMRadioObserver(this);
hal::RegisterFMRadioRDSObserver(this);
}
FMRadioService::~FMRadioService()
{
UnregisterFMRadioRDSObserver(this);
UnregisterFMRadioObserver(this);
hal::UnregisterFMRadioRDSObserver(this);
hal::UnregisterFMRadioObserver(this);
}
class EnableRunnable final : public nsRunnable
void
FMRadioService::EnableFMRadio()
{
public:
EnableRunnable(uint32_t aUpperLimit, uint32_t aLowerLimit, uint32_t aSpaceType, uint32_t aPreemphasis)
: mUpperLimit(aUpperLimit)
, mLowerLimit(aLowerLimit)
, mSpaceType(aSpaceType)
, mPreemphasis(aPreemphasis)
{
hal::FMRadioSettings info;
info.upperLimit() = mUpperBoundInKHz;
info.lowerLimit() = mLowerBoundInKHz;
info.spaceType() = mChannelWidthInKHz;
info.preEmphasis() = mPreemphasis;
hal::EnableFMRadio(info);
if (!mTuneThread) {
// hal::FMRadioSeek and hal::SetFMRadioFrequency run on this thread. These
// call ioctls that can stall the main thread, so we run them here.
mTuneThread = new LazyIdleThread(
TUNE_THREAD_TIMEOUT_MS, NS_LITERAL_CSTRING("FM Tuning"));
}
NS_IMETHOD Run()
{
FMRadioSettings info;
info.upperLimit() = mUpperLimit;
info.lowerLimit() = mLowerLimit;
info.spaceType() = mSpaceType;
info.preEmphasis() = mPreemphasis;
EnableFMRadio(info);
FMRadioService* fmRadioService = FMRadioService::Singleton();
if (!fmRadioService->mTuneThread) {
// SeekRunnable and SetFrequencyRunnable run on this thread. These
// call ioctls that can stall the main thread, so we run them here.
fmRadioService->mTuneThread = new LazyIdleThread(
TUNE_THREAD_TIMEOUT_MS, NS_LITERAL_CSTRING("FM Tuning"));
}
return NS_OK;
}
private:
uint32_t mUpperLimit;
uint32_t mLowerLimit;
uint32_t mSpaceType;
uint32_t mPreemphasis;
};
}
/**
* Read the airplane-mode setting, if the airplane-mode is not enabled, we
@ -197,9 +176,9 @@ public:
NS_IMETHOD
Handle(const nsAString& aName, JS::Handle<JS::Value> aResult)
{
FMRadioService* fmRadioService = FMRadioService::Singleton();
nsRefPtr<FMRadioService> fmRadioService = FMRadioService::Singleton();
MOZ_ASSERT(mPendingRequest == fmRadioService->mPendingRequest);
fmRadioService->mHasReadAirplaneModeSetting = true;
if (!aResult.isBoolean()) {
@ -211,12 +190,11 @@ public:
fmRadioService->mAirplaneModeEnabled = aResult.toBoolean();
if (!fmRadioService->mAirplaneModeEnabled) {
EnableRunnable* runnable =
new EnableRunnable(fmRadioService->mUpperBoundInKHz,
fmRadioService->mLowerBoundInKHz,
fmRadioService->mChannelWidthInKHz,
fmRadioService->mPreemphasis);
NS_DispatchToMainThread(runnable);
NS_DispatchToMainThread(NS_NewRunnableFunction(
[fmRadioService] () -> void {
fmRadioService->EnableFMRadio();
}
));
} else {
// Airplane mode is enabled, set the state back to Disabled.
fmRadioService->TransitionState(ErrorResponse(
@ -247,80 +225,29 @@ private:
NS_IMPL_ISUPPORTS(ReadAirplaneModeSettingTask, nsISettingsServiceCallback)
class DisableRunnable final : public nsRunnable
void
FMRadioService::DisableFMRadio()
{
public:
DisableRunnable() { }
if (mTuneThread) {
mTuneThread->Shutdown();
mTuneThread = nullptr;
}
// Fix Bug 796733. DisableFMRadio should be called before
// SetFmRadioAudioEnabled to prevent the annoying beep sound.
hal::DisableFMRadio();
EnableAudio(false);
};
NS_IMETHOD Run()
{
FMRadioService* fmRadioService = FMRadioService::Singleton();
if (fmRadioService->mTuneThread) {
fmRadioService->mTuneThread->Shutdown();
fmRadioService->mTuneThread = nullptr;
void
FMRadioService::DispatchFMRadioEventToMainThread(enum FMRadioEventType aType)
{
nsRefPtr<FMRadioService> self = this;
NS_DispatchToMainThread(NS_NewRunnableFunction(
[self, aType] () -> void {
self->NotifyFMRadioEvent(aType);
}
// Fix Bug 796733. DisableFMRadio should be called before
// SetFmRadioAudioEnabled to prevent the annoying beep sound.
DisableFMRadio();
fmRadioService->EnableAudio(false);
return NS_OK;
}
};
class SetFrequencyRunnable final : public nsRunnable
{
public:
SetFrequencyRunnable(int32_t aFrequency)
: mFrequency(aFrequency) { }
NS_IMETHOD Run()
{
SetFMRadioFrequency(mFrequency);
return NS_OK;
}
private:
int32_t mFrequency;
};
class SeekRunnable final : public nsRunnable
{
public:
SeekRunnable(FMRadioSeekDirection aDirection) : mDirection(aDirection) { }
NS_IMETHOD Run()
{
switch (mDirection) {
case FM_RADIO_SEEK_DIRECTION_UP:
case FM_RADIO_SEEK_DIRECTION_DOWN:
FMRadioSeek(mDirection);
break;
default:
MOZ_CRASH();
}
return NS_OK;
}
private:
FMRadioSeekDirection mDirection;
};
class NotifyRunnable final : public nsRunnable
{
public:
NotifyRunnable(FMRadioEventType aType) : mType(aType) { }
NS_IMETHOD Run()
{
FMRadioService::Singleton()->NotifyFMRadioEvent(mType);
return NS_OK;
}
private:
FMRadioEventType mType;
};
));
}
void
FMRadioService::TransitionState(const FMRadioResponseType& aResponse,
@ -357,7 +284,7 @@ FMRadioService::RemoveObserver(FMRadioEventObserver* aObserver)
if (mObserverList.Length() == 0)
{
// Turning off the FM radio HW because observer list is empty.
if (IsFMRadioOn()) {
if (hal::IsFMRadioOn()) {
DoDisable();
}
}
@ -416,7 +343,7 @@ bool
FMRadioService::IsEnabled() const
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
return IsFMRadioOn();
return hal::IsFMRadioOn();
}
bool
@ -431,7 +358,7 @@ FMRadioService::GetFrequency() const
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
if (IsEnabled()) {
int32_t frequencyInKHz = GetFMRadioFrequency();
int32_t frequencyInKHz = hal::GetFMRadioFrequency();
return frequencyInKHz / 1000.0;
}
@ -583,10 +510,12 @@ FMRadioService::Enable(double aFrequencyInMHz,
return;
}
NS_DispatchToMainThread(new EnableRunnable(mUpperBoundInKHz,
mLowerBoundInKHz,
mChannelWidthInKHz,
mPreemphasis));
nsRefPtr<FMRadioService> self = this;
NS_DispatchToMainThread(NS_NewRunnableFunction(
[self] () -> void {
self->EnableFMRadio();
}
));
}
void
@ -665,8 +594,13 @@ FMRadioService::DoDisable()
// console.log("We will catch disabled event ");
// };
// we need to call hal::DisableFMRadio() asynchronously. Same reason for
// EnableRunnable and SetFrequencyRunnable.
NS_DispatchToMainThread(new DisableRunnable());
// EnableFMRadio and hal::SetFMRadioFrequency.
nsRefPtr<FMRadioService> self = this;
NS_DispatchToMainThread(NS_NewRunnableFunction(
[self] () -> void {
self->DisableFMRadio();
}
));
}
void
@ -693,7 +627,7 @@ FMRadioService::SetFrequency(double aFrequencyInMHz,
NS_DispatchToMainThread(aReplyRunnable);
return;
case Seeking:
CancelFMRadioSeek();
hal::CancelFMRadioSeek();
TransitionState(ErrorResponse(
NS_LITERAL_STRING("Seek action is cancelled")), Enabled);
break;
@ -710,15 +644,19 @@ FMRadioService::SetFrequency(double aFrequencyInMHz,
return;
}
mTuneThread->Dispatch(new SetFrequencyRunnable(roundedFrequency),
nsIThread::DISPATCH_NORMAL);
mTuneThread->Dispatch(
NS_NewRunnableFunction(
[roundedFrequency] () -> void {
hal::SetFMRadioFrequency(roundedFrequency);
}
), nsIThread::DISPATCH_NORMAL);
aReplyRunnable->SetReply(SuccessResponse());
NS_DispatchToMainThread(aReplyRunnable);
}
void
FMRadioService::Seek(FMRadioSeekDirection aDirection,
FMRadioService::Seek(hal::FMRadioSeekDirection aDirection,
FMRadioReplyRunnable* aReplyRunnable)
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
@ -752,7 +690,19 @@ FMRadioService::Seek(FMRadioSeekDirection aDirection,
SetState(Seeking);
mPendingRequest = aReplyRunnable;
mTuneThread->Dispatch(new SeekRunnable(aDirection), nsIThread::DISPATCH_NORMAL);
mTuneThread->Dispatch(
NS_NewRunnableFunction(
[aDirection] () -> void {
switch (aDirection) {
case hal::FM_RADIO_SEEK_DIRECTION_UP:
case hal::FM_RADIO_SEEK_DIRECTION_DOWN:
hal::FMRadioSeek(aDirection);
break;
default:
MOZ_CRASH();
}
}
), nsIThread::DISPATCH_NORMAL);
}
void
@ -770,7 +720,7 @@ FMRadioService::CancelSeek(FMRadioReplyRunnable* aReplyRunnable)
}
// Cancel the seek immediately to prevent it from completing.
CancelFMRadioSeek();
hal::CancelFMRadioSeek();
TransitionState(
ErrorResponse(NS_LITERAL_STRING("Seek action is cancelled")), Enabled);
@ -783,7 +733,7 @@ void
FMRadioService::SetRDSGroupMask(uint32_t aRDSGroupMask)
{
mRDSGroupMask = aRDSGroupMask;
if (IsFMRadioOn() && mRDSEnabled) {
if (hal::IsFMRadioOn() && mRDSEnabled) {
DebugOnly<bool> enabled = hal::EnableRDS(mRDSGroupMask | DOM_PARSED_RDS_GROUPS);
MOZ_ASSERT(enabled);
}
@ -795,7 +745,7 @@ FMRadioService::EnableRDS(FMRadioReplyRunnable* aReplyRunnable)
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
MOZ_ASSERT(aReplyRunnable);
if (IsFMRadioOn()) {
if (hal::IsFMRadioOn()) {
if (!hal::EnableRDS(mRDSGroupMask | DOM_PARSED_RDS_GROUPS)) {
aReplyRunnable->SetReply(
ErrorResponse(NS_LITERAL_STRING("Could not enable RDS")));
@ -808,7 +758,8 @@ FMRadioService::EnableRDS(FMRadioReplyRunnable* aReplyRunnable)
aReplyRunnable->SetReply(SuccessResponse());
NS_DispatchToMainThread(aReplyRunnable);
NS_DispatchToMainThread(new NotifyRunnable(RDSEnabledChanged));
DispatchFMRadioEventToMainThread(RDSEnabledChanged);
}
void
@ -817,7 +768,7 @@ FMRadioService::DisableRDS(FMRadioReplyRunnable* aReplyRunnable)
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
MOZ_ASSERT(aReplyRunnable);
if (IsFMRadioOn()) {
if (hal::IsFMRadioOn()) {
hal::DisableRDS();
}
@ -826,7 +777,8 @@ FMRadioService::DisableRDS(FMRadioReplyRunnable* aReplyRunnable)
if (mRDSEnabled) {
mRDSEnabled = false;
NS_DispatchToMainThread(new NotifyRunnable(RDSEnabledChanged));
DispatchFMRadioEventToMainThread(RDSEnabledChanged);
}
}
@ -873,11 +825,11 @@ FMRadioService::NotifyFMRadioEvent(FMRadioEventType aType)
}
void
FMRadioService::Notify(const FMRadioOperationInformation& aInfo)
FMRadioService::Notify(const hal::FMRadioOperationInformation& aInfo)
{
switch (aInfo.operation()) {
case FM_RADIO_OPERATION_ENABLE:
MOZ_ASSERT(IsFMRadioOn());
case hal::FM_RADIO_OPERATION_ENABLE:
MOZ_ASSERT(hal::IsFMRadioOn());
MOZ_ASSERT(mState == Disabling || mState == Enabling);
// If we're disabling, disable the radio right now.
@ -891,7 +843,7 @@ FMRadioService::Notify(const FMRadioOperationInformation& aInfo)
// To make sure the FM app will get the right frequency after the FM
// radio is enabled, we have to set the frequency first.
SetFMRadioFrequency(mPendingFrequencyInKHz);
hal::SetFMRadioFrequency(mPendingFrequencyInKHz);
// Bug 949855: enable audio after the FM radio HW is enabled, to make sure
// 'hw.fm.isAnalog' could be detected as |true| during first time launch.
@ -902,7 +854,7 @@ FMRadioService::Notify(const FMRadioOperationInformation& aInfo)
// Update the current frequency without sending the`FrequencyChanged`
// event, to make sure the FM app will get the right frequency when the
// `EnabledChange` event is sent.
mPendingFrequencyInKHz = GetFMRadioFrequency();
mPendingFrequencyInKHz = hal::GetFMRadioFrequency();
UpdatePowerState();
// The frequency was changed from '0' to some meaningful number, so we
@ -916,7 +868,7 @@ FMRadioService::Notify(const FMRadioOperationInformation& aInfo)
}
}
break;
case FM_RADIO_OPERATION_DISABLE:
case hal::FM_RADIO_OPERATION_DISABLE:
MOZ_ASSERT(mState == Disabling);
mPISet = false;
@ -926,7 +878,7 @@ FMRadioService::Notify(const FMRadioOperationInformation& aInfo)
TransitionState(SuccessResponse(), Disabled);
UpdatePowerState();
break;
case FM_RADIO_OPERATION_SEEK:
case hal::FM_RADIO_OPERATION_SEEK:
// Seek action might be cancelled by SetFrequency(), we need to check if
// the current state is Seeking.
@ -936,7 +888,7 @@ FMRadioService::Notify(const FMRadioOperationInformation& aInfo)
UpdateFrequency();
break;
case FM_RADIO_OPERATION_TUNE:
case hal::FM_RADIO_OPERATION_TUNE:
UpdateFrequency();
break;
default:
@ -1014,7 +966,7 @@ static const uint16_t sRDSToUnicodeMap[256] = {
};
void
FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup)
FMRadioService::Notify(const hal::FMRadioRDSGroup& aRDSGroup)
{
uint16_t blocks[4];
blocks[0] = aRDSGroup.blockA();
@ -1035,7 +987,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup)
memset(mTempRadiotext, 0, sizeof(mTempRadiotext));
}
mPISet = true;
NS_DispatchToMainThread(new NotifyRunnable(PIChanged));
DispatchFMRadioEventToMainThread(PIChanged);
}
mLastPI = blocks[0];
@ -1044,7 +997,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup)
if ((mPTY != pty && pty == mLastPTY) || !mPTYSet) {
mPTY = pty;
mPTYSet = true;
NS_DispatchToMainThread(new NotifyRunnable(PTYChanged));
DispatchFMRadioEventToMainThread(PTYChanged);
}
mLastPTY = pty;
@ -1075,7 +1029,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup)
MutexAutoLock lock(mRDSLock);
mPSNameSet = true;
memcpy(mPSName, mTempPSName, sizeof(mTempPSName));
NS_DispatchToMainThread(new NotifyRunnable(PSChanged));
DispatchFMRadioEventToMainThread(PSChanged);
}
break;
}
@ -1089,7 +1044,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup)
mRadiotextAB = textAB;
MutexAutoLock lock(mRDSLock);
memset(mRadiotext, 0, sizeof(mRadiotext));
NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged));
DispatchFMRadioEventToMainThread(RadiotextChanged);
}
// mRadiotextState is a bitmask that lets us ensure all segments
@ -1129,7 +1085,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup)
MutexAutoLock lock(mRDSLock);
mRadiotextSet = true;
memcpy(mRadiotext, mTempRadiotext, sizeof(mTempRadiotext));
NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged));
DispatchFMRadioEventToMainThread(RadiotextChanged);
break;
}
case 5: // 2b Radiotext
@ -1142,7 +1099,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup)
mRadiotextAB = textAB;
MutexAutoLock lock(mRDSLock);
memset(mRadiotext, 0, sizeof(mRadiotext));
NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged));
DispatchFMRadioEventToMainThread(RadiotextChanged);
}
if (!segmentAddr) {
@ -1177,7 +1135,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup)
MutexAutoLock lock(mRDSLock);
mRadiotextSet = true;
memcpy(mRadiotext, mTempRadiotext, sizeof(mTempRadiotext));
NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged));
DispatchFMRadioEventToMainThread(RadiotextChanged);
break;
}
case 31: // 15b Fast Tuning and Switching
@ -1187,7 +1146,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup)
break;
}
mPTY = pty;
NS_DispatchToMainThread(new NotifyRunnable(PTYChanged));
DispatchFMRadioEventToMainThread(PTYChanged);
break;
}
}
@ -1209,13 +1169,14 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup)
MutexAutoLock lock(mRDSLock);
mRDSGroup = newgroup;
mRDSGroupSet = true;
NS_DispatchToMainThread(new NotifyRunnable(NewRDSGroup));
DispatchFMRadioEventToMainThread(NewRDSGroup);
}
void
FMRadioService::UpdatePowerState()
{
bool enabled = IsFMRadioOn();
bool enabled = hal::IsFMRadioOn();
if (enabled != mEnabled) {
mEnabled = enabled;
NotifyFMRadioEvent(EnabledChanged);
@ -1225,7 +1186,7 @@ FMRadioService::UpdatePowerState()
void
FMRadioService::UpdateFrequency()
{
int32_t frequency = GetFMRadioFrequency();
int32_t frequency = hal::GetFMRadioFrequency();
if (mPendingFrequencyInKHz != frequency) {
mPendingFrequencyInKHz = frequency;
NotifyFMRadioEvent(FrequencyChanged);

View File

@ -196,6 +196,10 @@ public:
/* FMRadioRDSObserver */
void Notify(const hal::FMRadioRDSGroup& aRDSGroup) override;
void EnableFMRadio();
void DisableFMRadio();
void DispatchFMRadioEventToMainThread(enum FMRadioEventType aType);
NS_DECL_NSIOBSERVER
protected:

View File

@ -99,7 +99,7 @@ ImageListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
}
int16_t decision = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_IMAGE,
nsresult rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_INTERNAL_IMAGE,
channelURI,
channelPrincipal,
domWindow->GetFrameElementInternal(),

View File

@ -52,9 +52,6 @@ public:
// state.
virtual ReentrantMonitor& GetReentrantMonitor() = 0;
// Returns true if the decoder is shut down.
virtual bool IsShutdown() const = 0;
// A special version of the above for the ogg decoder that is allowed to be
// called cross-thread.
virtual bool IsOggDecoderShutdown() { return false; }
@ -93,6 +90,13 @@ public:
// Set the media as being seekable or not.
virtual void SetMediaSeekable(bool aMediaSeekable) = 0;
void DispatchSetMediaSeekable(bool aMediaSeekable)
{
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<bool>(
this, &AbstractMediaDecoder::SetMediaSeekable, aMediaSeekable);
NS_DispatchToMainThread(r);
}
virtual VideoFrameContainer* GetVideoFrameContainer() = 0;
virtual mozilla::layers::ImageContainer* GetImageContainer() = 0;

View File

@ -50,7 +50,7 @@ ResourceLoader.load = function(uri, doc) {
// the '2' identifies this as a script load
let ioChannel = ioService.newChannelFromURI2(uri, doc, doc.nodePrincipal,
systemPrincipal, 0,
Ci.nsIContentPolicy.TYPE_SCRIPT);
Ci.nsIContentPolicy.TYPE_INTERNAL_SCRIPT);
ioChannel.loadGroup = doc.documentLoadGroup.QueryInterface(Ci.nsILoadGroup);
ioChannel.notificationCallbacks = new RedirectHttpsOnly();

View File

@ -217,13 +217,7 @@ void MediaDecoder::UpdateDormantState(bool aDormantTimeout, bool aActivity)
if (mIsDormant) {
DECODER_LOG("UpdateDormantState() entering DORMANT state");
// enter dormant state
RefPtr<nsRunnable> event =
NS_NewRunnableMethodWithArg<bool>(
mDecoderStateMachine,
&MediaDecoderStateMachine::SetDormant,
true);
mDecoderStateMachine->OwnerThread()->Dispatch(event.forget());
mDecoderStateMachine->DispatchSetDormant(true);
if (IsEnded()) {
mWasEndedWhenEnteredDormant = true;
}
@ -232,13 +226,7 @@ void MediaDecoder::UpdateDormantState(bool aDormantTimeout, bool aActivity)
} else {
DECODER_LOG("UpdateDormantState() leaving DORMANT state");
// exit dormant state
// trigger to state machine.
RefPtr<nsRunnable> event =
NS_NewRunnableMethodWithArg<bool>(
mDecoderStateMachine,
&MediaDecoderStateMachine::SetDormant,
false);
mDecoderStateMachine->OwnerThread()->Dispatch(event.forget());
mDecoderStateMachine->DispatchSetDormant(false);
}
}
@ -351,7 +339,6 @@ MediaDecoder::MediaDecoder() :
mDormantSupported(false),
mLogicalPosition(0.0),
mDuration(std::numeric_limits<double>::quiet_NaN()),
mMediaSeekable(true),
mReentrantMonitor("media.decoder"),
mIgnoreProgressData(false),
mInfiniteStream(false),
@ -407,7 +394,9 @@ MediaDecoder::MediaDecoder() :
mPlaybackRateReliable(AbstractThread::MainThread(), true,
"MediaDecoder::mPlaybackRateReliable (Canonical)"),
mDecoderPosition(AbstractThread::MainThread(), 0,
"MediaDecoder::mDecoderPosition (Canonical)")
"MediaDecoder::mDecoderPosition (Canonical)"),
mMediaSeekable(AbstractThread::MainThread(), true,
"MediaDecoder::mMediaSeekable (Canonical)")
{
MOZ_COUNT_CTOR(MediaDecoder);
MOZ_ASSERT(NS_IsMainThread());
@ -617,9 +606,8 @@ void MediaDecoder::CallSeek(const SeekTarget& aTarget)
{
MOZ_ASSERT(NS_IsMainThread());
mSeekRequest.DisconnectIfExists();
mSeekRequest.Begin(InvokeAsync(mDecoderStateMachine->OwnerThread(),
mDecoderStateMachine.get(), __func__,
&MediaDecoderStateMachine::Seek, aTarget)
mSeekRequest.Begin(
mDecoderStateMachine->InvokeSeek(aTarget)
->Then(AbstractThread::MainThread(), __func__, this,
&MediaDecoder::OnSeekResolved, &MediaDecoder::OnSeekRejected));
}
@ -1110,6 +1098,7 @@ void MediaDecoder::UpdateEstimatedMediaDuration(int64_t aDuration)
}
void MediaDecoder::SetMediaSeekable(bool aMediaSeekable) {
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mMediaSeekable = aMediaSeekable;
}
@ -1123,8 +1112,8 @@ MediaDecoder::IsTransportSeekable()
bool MediaDecoder::IsMediaSeekable()
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE(GetStateMachine(), false);
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
return mMediaSeekable;
}
@ -1309,19 +1298,10 @@ void
MediaDecoder::NotifyWaitingForResourcesStatusChanged()
{
if (mDecoderStateMachine) {
RefPtr<nsRunnable> task =
NS_NewRunnableMethod(mDecoderStateMachine,
&MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged);
mDecoderStateMachine->OwnerThread()->Dispatch(task.forget());
mDecoderStateMachine->DispatchWaitingForResourcesStatusChanged();
}
}
bool MediaDecoder::IsShutdown() const {
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE(GetStateMachine(), true);
return mStateMachineIsShutdown;
}
// Drop reference to state machine. Only called during shutdown dance.
void MediaDecoder::BreakCycles() {
SetStateMachine(nullptr);

View File

@ -530,9 +530,6 @@ public:
// state.
ReentrantMonitor& GetReentrantMonitor() override;
// Returns true if the decoder is shut down
bool IsShutdown() const final override;
// Constructs the time ranges representing what segments of the media
// are buffered and playable.
virtual media::TimeIntervals GetBuffered();
@ -801,9 +798,6 @@ protected:
// Official duration of the media resource as observed by script.
double mDuration;
// True if the media is seekable (i.e. supports random access).
bool mMediaSeekable;
/******
* The following member variables can be accessed from any thread.
******/
@ -1001,6 +995,9 @@ protected:
// back again.
Canonical<int64_t> mDecoderPosition;
// True if the media is seekable (i.e. supports random access).
Canonical<bool> mMediaSeekable;
public:
AbstractCanonical<media::NullableTimeUnit>* CanonicalDurationOrNull() override;
AbstractCanonical<double>* CanonicalVolume() {
@ -1039,6 +1036,9 @@ public:
AbstractCanonical<int64_t>* CanonicalDecoderPosition() {
return &mDecoderPosition;
}
AbstractCanonical<bool>* CanonicalMediaSeekable() {
return &mMediaSeekable;
}
};
} // namespace mozilla

View File

@ -249,6 +249,8 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
"MediaDecoderStateMachine::mPlaybackRateReliable (Mirror)"),
mDecoderPosition(mTaskQueue, 0,
"MediaDecoderStateMachine::mDecoderPosition (Mirror)"),
mMediaSeekable(mTaskQueue, true,
"MediaDecoderStateMachine::mMediaSeekable (Mirror)"),
mDuration(mTaskQueue, NullableTimeUnit(),
"MediaDecoderStateMachine::mDuration (Canonical"),
mIsShutdown(mTaskQueue, false,
@ -334,6 +336,7 @@ MediaDecoderStateMachine::InitializationTask()
mPlaybackBytesPerSecond.Connect(mDecoder->CanonicalPlaybackBytesPerSecond());
mPlaybackRateReliable.Connect(mDecoder->CanonicalPlaybackRateReliable());
mDecoderPosition.Connect(mDecoder->CanonicalDecoderPosition());
mMediaSeekable.Connect(mDecoder->CanonicalMediaSeekable());
// Initialize watchers.
mWatchManager.Watch(mBuffered, &MediaDecoderStateMachine::BufferedRangeUpdated);
@ -1231,7 +1234,16 @@ void MediaDecoderStateMachine::RecomputeDuration()
mDuration = Some(duration);
}
void MediaDecoderStateMachine::SetDormant(bool aDormant)
void
MediaDecoderStateMachine::DispatchSetDormant(bool aDormant)
{
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<bool>(
this, &MediaDecoderStateMachine::SetDormant, aDormant);
OwnerThread()->Dispatch(r.forget());
}
void
MediaDecoderStateMachine::SetDormant(bool aDormant)
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
@ -1379,7 +1391,16 @@ void MediaDecoderStateMachine::StartDecoding()
ScheduleStateMachine();
}
void MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged()
void
MediaDecoderStateMachine::DispatchWaitingForResourcesStatusChanged()
{
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
this, &MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged);
OwnerThread()->Dispatch(r.forget());
}
void
MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged()
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
@ -1483,7 +1504,7 @@ MediaDecoderStateMachine::Seek(SeekTarget aTarget)
// We need to be able to seek both at a transport level and at a media level
// to seek.
if (!mDecoder->IsMediaSeekable()) {
if (!mMediaSeekable) {
DECODER_WARN("Seek() function should not be called on a non-seekable state machine");
return MediaDecoder::SeekPromise::CreateAndReject(/* aIgnored = */ true, __func__);
}
@ -1509,6 +1530,13 @@ MediaDecoderStateMachine::Seek(SeekTarget aTarget)
return mPendingSeek.mPromise.Ensure(__func__);
}
nsRefPtr<MediaDecoder::SeekPromise>
MediaDecoderStateMachine::InvokeSeek(SeekTarget aTarget)
{
return InvokeAsync(OwnerThread(), this, __func__,
&MediaDecoderStateMachine::Seek, aTarget);
}
void MediaDecoderStateMachine::StopMediaSink()
{
MOZ_ASSERT(OnTaskQueue());
@ -1932,7 +1960,7 @@ MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata)
// Set mode to PLAYBACK after reading metadata.
mResource->SetReadMode(MediaCacheStream::MODE_PLAYBACK);
mDecoder->SetMediaSeekable(mReader->IsMediaSeekable());
mDecoder->DispatchSetMediaSeekable(mReader->IsMediaSeekable());
mInfo = aMetadata->mInfo;
mMetadataTags = aMetadata->mTags.forget();
nsRefPtr<MediaDecoderStateMachine> self = this;
@ -2067,7 +2095,7 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
DECODER_LOG("Media duration %lld, "
"transportSeekable=%d, mediaSeekable=%d",
Duration().ToMicroseconds(), mResource->IsTransportSeekable(), mDecoder->IsMediaSeekable());
Duration().ToMicroseconds(), mResource->IsTransportSeekable(), mMediaSeekable.Ref());
if (HasAudio() && !HasVideo() && !mSentFirstFrameLoadedEvent) {
// We're playing audio only. We don't need to worry about slow video
@ -2236,6 +2264,7 @@ MediaDecoderStateMachine::FinishShutdown()
mPlaybackBytesPerSecond.DisconnectIfConnected();
mPlaybackRateReliable.DisconnectIfConnected();
mDecoderPosition.DisconnectIfConnected();
mMediaSeekable.DisconnectIfConnected();
mDuration.DisconnectAll();
mIsShutdown.DisconnectAll();

View File

@ -155,40 +155,116 @@ public:
// Remove an output stream added with AddOutputStream.
void RemoveOutputStream(MediaStream* aStream);
// Seeks to the decoder to aTarget asynchronously.
nsRefPtr<MediaDecoder::SeekPromise> InvokeSeek(SeekTarget aTarget);
// Set/Unset dormant state.
void SetDormant(bool aDormant);
void DispatchSetDormant(bool aDormant);
void DispatchShutdown();
void DispatchStartBuffering()
{
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::StartBuffering);
OwnerThread()->Dispatch(runnable.forget());
}
void DispatchNotifyDataArrived(uint32_t aLength, int64_t aOffset, bool aThrottleUpdates)
{
mReader->DispatchNotifyDataArrived(aLength, aOffset, aThrottleUpdates);
}
// Called when the reader may have acquired the hardware resources required
// to begin decoding.
void DispatchWaitingForResourcesStatusChanged();
// Notifies the state machine that should minimize the number of samples
// decoded we preroll, until playback starts. The first time playback starts
// the state machine is free to return to prerolling normally. Note
// "prerolling" in this context refers to when we decode and buffer decoded
// samples in advance of when they're needed for playback.
void DispatchMinimizePrerollUntilPlaybackStarts()
{
nsRefPtr<MediaDecoderStateMachine> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () -> void
{
MOZ_ASSERT(self->OnTaskQueue());
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
self->mMinimizePreroll = true;
// Make sure that this arrives before playback starts, otherwise this won't
// have the intended effect.
MOZ_DIAGNOSTIC_ASSERT(self->mPlayState == MediaDecoder::PLAY_STATE_LOADING);
});
OwnerThread()->Dispatch(r.forget());
}
// Set the media fragment end time. aEndTime is in microseconds.
void DispatchSetFragmentEndTime(int64_t aEndTime)
{
nsRefPtr<MediaDecoderStateMachine> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aEndTime] () {
self->mFragmentEndTime = aEndTime;
});
OwnerThread()->Dispatch(r.forget());
}
// Drop reference to decoder. Only called during shutdown dance.
void BreakCycles() {
MOZ_ASSERT(NS_IsMainThread());
if (mReader) {
mReader->BreakCycles();
}
mResource = nullptr;
mDecoder = nullptr;
}
TimedMetadataEventSource& TimedMetadataEvent() {
return mMetadataManager.TimedMetadataEvent();
}
// Immutable after construction - may be called on any thread.
bool IsRealTime() const { return mRealTime; }
// Functions used by assertions to ensure we're calling things
// on the appropriate threads.
bool OnDecodeTaskQueue() const;
bool OnTaskQueue() const;
size_t SizeOfVideoQueue() {
if (mReader) {
return mReader->SizeOfVideoQueueInBytes();
}
return 0;
}
size_t SizeOfAudioQueue() {
if (mReader) {
return mReader->SizeOfAudioQueueInBytes();
}
return 0;
}
private:
// Initialization that needs to happen on the task queue. This is the first
// task that gets run on the task queue, and is dispatched from the MDSM
// constructor immediately after the task queue is created.
void InitializationTask();
void SetDormant(bool aDormant);
void SetAudioCaptured(bool aCaptured);
void Shutdown();
public:
void NotifyWaitingForResourcesStatusChanged();
void DispatchShutdown();
nsRefPtr<MediaDecoder::SeekPromise> Seek(SeekTarget aTarget);
void Shutdown();
void FinishShutdown();
// Immutable after construction - may be called on any thread.
bool IsRealTime() const { return mRealTime; }
// Functions used by assertions to ensure we're calling things
// on the appropriate threads.
bool OnDecodeTaskQueue() const;
bool OnTaskQueue() const;
// Seeks to the decoder to aTarget asynchronously.
// Must be called on the state machine thread.
nsRefPtr<MediaDecoder::SeekPromise> Seek(SeekTarget aTarget);
// Clear the flag indicating that a playback position change event
// is currently queued. This is called from the main thread and must
// be called with the decode monitor held.
@ -201,7 +277,6 @@ public:
// the decode monitor held.
void UpdatePlaybackPosition(int64_t aTime);
private:
// Causes the state machine to switch to buffering state, and to
// immediately stop playback and buffer downloaded data. Called on
// the state machine thread.
@ -211,14 +286,6 @@ private:
MediaStatistics GetStatistics();
public:
void DispatchStartBuffering()
{
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::StartBuffering);
OwnerThread()->Dispatch(runnable.forget());
}
// This is called on the state machine thread and audio thread.
// The decoder monitor must be obtained before calling this.
bool HasAudio() const {
@ -252,25 +319,6 @@ public:
return mState == DECODER_STATE_SEEKING;
}
size_t SizeOfVideoQueue() {
if (mReader) {
return mReader->SizeOfVideoQueueInBytes();
}
return 0;
}
size_t SizeOfAudioQueue() {
if (mReader) {
return mReader->SizeOfAudioQueueInBytes();
}
return 0;
}
void DispatchNotifyDataArrived(uint32_t aLength, int64_t aOffset, bool aThrottleUpdates)
{
mReader->DispatchNotifyDataArrived(aLength, aOffset, aThrottleUpdates);
}
// Returns the state machine task queue.
TaskQueue* OwnerThread() const { return mTaskQueue; }
@ -306,26 +354,6 @@ public:
void NotReached() { MOZ_DIAGNOSTIC_ASSERT(false); }
// Set the media fragment end time. aEndTime is in microseconds.
void DispatchSetFragmentEndTime(int64_t aEndTime)
{
nsRefPtr<MediaDecoderStateMachine> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aEndTime] () {
self->mFragmentEndTime = aEndTime;
});
OwnerThread()->Dispatch(r.forget());
}
// Drop reference to decoder. Only called during shutdown dance.
void BreakCycles() {
MOZ_ASSERT(NS_IsMainThread());
if (mReader) {
mReader->BreakCycles();
}
mResource = nullptr;
mDecoder = nullptr;
}
// Discard audio/video data that are already played by MSG.
void DiscardStreamData();
bool HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs);
@ -339,31 +367,6 @@ public:
// be held.
bool IsPlaying() const;
// Called when the reader may have acquired the hardware resources required
// to begin decoding.
void NotifyWaitingForResourcesStatusChanged();
// Notifies the state machine that should minimize the number of samples
// decoded we preroll, until playback starts. The first time playback starts
// the state machine is free to return to prerolling normally. Note
// "prerolling" in this context refers to when we decode and buffer decoded
// samples in advance of when they're needed for playback.
void DispatchMinimizePrerollUntilPlaybackStarts()
{
nsRefPtr<MediaDecoderStateMachine> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () -> void
{
MOZ_ASSERT(self->OnTaskQueue());
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
self->mMinimizePreroll = true;
// Make sure that this arrives before playback starts, otherwise this won't
// have the intended effect.
MOZ_DIAGNOSTIC_ASSERT(self->mPlayState == MediaDecoder::PLAY_STATE_LOADING);
});
OwnerThread()->Dispatch(r.forget());
}
void OnAudioDecoded(MediaData* aAudioSample);
void OnVideoDecoded(MediaData* aVideoSample);
void OnNotDecoded(MediaData::Type aType, MediaDecoderReader::NotDecodedReason aReason);
@ -1299,6 +1302,9 @@ private:
// Current decoding position in the stream.
Mirror<int64_t> mDecoderPosition;
// True if the media is seekable (i.e. supports random access).
Mirror<bool> mMediaSeekable;
// Duration of the media. This is guaranteed to be non-null after we finish
// decoding the first frame.
Canonical<media::NullableTimeUnit> mDuration;

View File

@ -2365,8 +2365,8 @@ MediaInputPort::Disconnect()
return;
mSource->RemoveConsumer(this);
mSource = nullptr;
mDest->RemoveInput(this);
mSource = nullptr;
mDest = nullptr;
GraphImpl()->SetStreamOrderDirty();

View File

@ -51,9 +51,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
MediaKeySystemAccessManager::MediaKeySystemAccessManager(nsPIDOMWindow* aWindow)
: mWindow(aWindow)
, mAddedObservers(false)
#ifdef XP_WIN
, mTrialCreator(new GMPVideoDecoderTrialCreator())
#endif
{
}

View File

@ -27,7 +27,6 @@ using media::TimeIntervals;
MediaSourceDemuxer::MediaSourceDemuxer()
: mTaskQueue(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK),
/* aSupportsTailDispatch = */ true))
, mInitDone(false)
, mMonitor("MediaSourceDemuxer")
{
MOZ_ASSERT(NS_IsMainThread());
@ -46,7 +45,6 @@ MediaSourceDemuxer::AttemptInit()
MOZ_ASSERT(OnTaskQueue());
if (ScanSourceBuffersForContent()) {
mInitDone = true;
return InitPromise::CreateAndResolve(NS_OK, __func__);
}
@ -60,12 +58,10 @@ void MediaSourceDemuxer::NotifyDataArrived(uint32_t aLength, int64_t aOffset)
nsRefPtr<MediaSourceDemuxer> self = this;
nsCOMPtr<nsIRunnable> task =
NS_NewRunnableFunction([self] () {
if (self->mInitDone) {
if (self->mInitPromise.IsEmpty()) {
return;
}
MOZ_ASSERT(!self->mInitPromise.IsEmpty());
if (self->ScanSourceBuffersForContent()) {
self->mInitDone = true;
self->mInitPromise.ResolveIfExists(NS_OK, __func__);
}
});

View File

@ -74,7 +74,6 @@ private:
nsTArray<nsRefPtr<TrackBuffersManager>> mSourceBuffers;
MozPromiseHolder<InitPromise> mInitPromise;
bool mInitDone;
// Monitor to protect members below across multiple threads.
mutable Monitor mMonitor;

View File

@ -720,10 +720,7 @@ void OggReader::SetChained(bool aIsChained) {
ReentrantMonitorAutoEnter mon(mMonitor);
mIsChained = aIsChained;
}
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mDecoder->SetMediaSeekable(false);
}
mDecoder->DispatchSetMediaSeekable(false);
}
bool OggReader::ReadOggChain()

View File

@ -116,12 +116,7 @@ MediaOmxCommonDecoder::PauseStateMachine()
return;
}
// enter dormant state
RefPtr<nsRunnable> event =
NS_NewRunnableMethodWithArg<bool>(
GetStateMachine(),
&MediaDecoderStateMachine::SetDormant,
true);
GetStateMachine()->OwnerThread()->Dispatch(event.forget());
GetStateMachine()->DispatchSetDormant(true);
}
void
@ -145,22 +140,12 @@ MediaOmxCommonDecoder::ResumeStateMachine()
SeekTarget::Accurate,
MediaDecoderEventVisibility::Suppressed);
// Call Seek of MediaDecoderStateMachine to suppress seek events.
RefPtr<nsRunnable> event =
NS_NewRunnableMethodWithArg<SeekTarget>(
GetStateMachine(),
&MediaDecoderStateMachine::Seek,
target);
GetStateMachine()->OwnerThread()->Dispatch(event.forget());
GetStateMachine()->InvokeSeek(target);
mNextState = mPlayState;
ChangeState(PLAY_STATE_LOADING);
// exit dormant state
event =
NS_NewRunnableMethodWithArg<bool>(
GetStateMachine(),
&MediaDecoderStateMachine::SetDormant,
false);
GetStateMachine()->OwnerThread()->Dispatch(event.forget());
GetStateMachine()->DispatchSetDormant(false);
UpdateLogicalPosition();
}

View File

@ -65,15 +65,39 @@ public:
{
*aOutput = aInput;
if (aInput.IsNull()) {
// If AnalyserNode::mChunks has only null chunks, then there is no need
// to send further null chunks.
if (mChunksToProcess <= 0) {
if (mChunksToProcess != INT32_MIN) {
mChunksToProcess = INT32_MIN;
aStream->CheckForInactive();
}
return;
}
--mChunksToProcess;
} else {
// This many null chunks will be required to empty AnalyserNode::mChunks.
mChunksToProcess = CHUNK_COUNT;
}
nsRefPtr<TransferBuffer> transfer =
new TransferBuffer(aStream, aInput.AsAudioChunk());
NS_DispatchToMainThread(transfer);
}
virtual bool IsActive() const override
{
return mChunksToProcess != INT32_MIN;
}
virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override
{
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
int32_t mChunksToProcess = INT32_MIN;
};
AnalyserNode::AnalyserNode(AudioContext* aContext)

View File

@ -23,6 +23,7 @@ class AudioBlock : private AudioChunk
public:
AudioBlock() {
mDuration = WEBAUDIO_BLOCK_SIZE;
mBufferFormat = AUDIO_FORMAT_SILENCE;
}
// No effort is made in constructors to ensure that mBufferIsDownstreamRef
// is set because the block is expected to be a temporary and so the

View File

@ -111,7 +111,11 @@ public:
virtual void SetInt32Parameter(uint32_t aIndex, int32_t aParam) override
{
switch (aIndex) {
case AudioBufferSourceNode::SAMPLE_RATE: mBufferSampleRate = aParam; break;
case AudioBufferSourceNode::SAMPLE_RATE:
MOZ_ASSERT(aParam > 0);
mBufferSampleRate = aParam;
mSource->SetActive();
break;
case AudioBufferSourceNode::BUFFERSTART:
MOZ_ASSERT(aParam >= 0);
if (mBufferPosition == 0) {
@ -466,12 +470,21 @@ public:
return;
}
StreamTime streamPosition = aStream->GetCurrentPosition();
// We've finished if we've gone past mStop, or if we're past mDuration when
// looping is disabled.
if (streamPosition >= mStop ||
(!mLoop && mBufferPosition >= mBufferEnd && !mRemainingResamplerTail)) {
*aFinished = true;
aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
return;
}
uint32_t channels = mBuffer ? mBuffer->GetChannels() : 0;
UpdateSampleRateIfNeeded(channels);
uint32_t written = 0;
StreamTime streamPosition = aStream->GetCurrentPosition();
while (written < WEBAUDIO_BLOCK_SIZE) {
if (mStop != STREAM_TIME_MAX &&
streamPosition >= mStop) {
@ -499,13 +512,12 @@ public:
}
}
}
}
// We've finished if we've gone past mStop, or if we're past mDuration when
// looping is disabled.
if (streamPosition >= mStop ||
(!mLoop && mBufferPosition >= mBufferEnd && !mRemainingResamplerTail)) {
*aFinished = true;
}
virtual bool IsActive() const override
{
// Whether buffer has been set and start() has been called.
return mBufferSampleRate != 0;
}
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override

View File

@ -112,6 +112,14 @@ public:
}
}
virtual bool IsActive() const override
{
// Keep processing to track stream time, which is used for all timelines
// associated with the same AudioContext.
return true;
}
class OnCompleteTask final : public nsRunnable
{
public:
@ -255,6 +263,16 @@ public:
}
}
virtual bool IsActive() const override
{
// Keep processing to track stream time, which is used for all timelines
// associated with the same AudioContext. If there are no other engines
// for the AudioContext, then this could return false to suspend the
// stream, but the stream is blocked anyway through
// AudioDestinationNode::SetIsOnlyNodeForContext().
return true;
}
virtual void SetDoubleParameter(uint32_t aIndex, double aParam) override
{
if (aIndex == VOLUME) {

View File

@ -309,8 +309,10 @@ public:
* aInput is guaranteed to have float sample format (if it has samples at all)
* and to have been resampled to the sampling rate for the stream, and to have
* exactly WEBAUDIO_BLOCK_SIZE samples.
* *aFinished is set to false by the caller. If the callee sets it to true,
* we'll finish the stream and not call this again.
* *aFinished is set to false by the caller. The callee must not set this to
* true unless silent output is produced. If set to true, we'll finish the
* stream, consider this input inactive on any downstream nodes, and not
* call this again.
*/
virtual void ProcessBlock(AudioNodeStream* aStream,
const AudioBlock& aInput,
@ -346,6 +348,12 @@ public:
OutputChunks& aOutput,
bool* aFinished);
// IsActive() returns true if the engine needs to continue processing an
// unfinished stream even when it has silent or no input connections. This
// includes tail-times and when sources have been scheduled to start. If
// returning false, then the stream can be suspended.
virtual bool IsActive() const { return false; }
bool HasNode() const
{
MOZ_ASSERT(NS_IsMainThread());

View File

@ -109,8 +109,12 @@ static void ConvertSegmentToAudioBlock(AudioSegment* aSegment,
CopyChunkToBlock<float>(*ci, aBlock, duration);
break;
}
case AUDIO_FORMAT_SILENCE:
case AUDIO_FORMAT_SILENCE: {
// The actual type of the sample does not matter here, but we still need
// to send some audio to the graph.
CopyChunkToBlock<float>(*ci, aBlock, duration);
break;
}
}
duration += ci->GetDuration();
}

View File

@ -34,6 +34,7 @@ AudioNodeStream::AudioNodeStream(AudioNodeEngine* aEngine,
mSampleRate(aSampleRate),
mFlags(aFlags),
mNumberOfInputChannels(2),
mIsActive(aEngine->IsActive()),
mMarkAsFinishedAfterThisBlock(false),
mAudioParamStream(false),
mPassThrough(false)
@ -49,6 +50,7 @@ AudioNodeStream::AudioNodeStream(AudioNodeEngine* aEngine,
AudioNodeStream::~AudioNodeStream()
{
MOZ_ASSERT(mActiveInputCount == 0);
MOZ_COUNT_DTOR(AudioNodeStream);
}
@ -520,7 +522,14 @@ AudioNodeStream::ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags)
uint16_t outputCount = mLastChunks.Length();
MOZ_ASSERT(outputCount == std::max(uint16_t(1), mEngine->OutputCount()));
if (mFinished || InMutedCycle()) {
if (!mIsActive) {
// mLastChunks are already null.
#ifdef DEBUG
for (const auto& chunk : mLastChunks) {
MOZ_ASSERT(chunk.IsNull());
}
#endif
} else if (InMutedCycle()) {
mInputChunks.Clear();
for (uint16_t i = 0; i < outputCount; ++i) {
mLastChunks[i].SetNull(WEBAUDIO_BLOCK_SIZE);
@ -549,6 +558,7 @@ AudioNodeStream::ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags)
}
if (finished) {
mMarkAsFinishedAfterThisBlock = true;
CheckForInactive();
}
if (mDisabledTrackIDs.Contains(static_cast<TrackID>(AUDIO_TRACK))) {
@ -579,7 +589,7 @@ AudioNodeStream::ProduceOutputBeforeInput(GraphTime aFrom)
MOZ_ASSERT(!InMutedCycle(), "DelayNodes should break cycles");
MOZ_ASSERT(mLastChunks.Length() == 1);
if (mFinished) {
if (!mIsActive) {
mLastChunks[0].SetNull(WEBAUDIO_BLOCK_SIZE);
} else {
mEngine->ProduceBlockBeforeInput(&mLastChunks[0]);
@ -684,4 +694,88 @@ AudioNodeStream::DestinationTimeFromTicks(AudioNodeStream* aDestination,
return StreamTimeToSeconds(destinationTime);
}
void
AudioNodeStream::AddInput(MediaInputPort* aPort)
{
ProcessedMediaStream::AddInput(aPort);
AudioNodeStream* ns = aPort->GetSource()->AsAudioNodeStream();
// Streams that are not AudioNodeStreams are considered active.
if (!ns || (ns->mIsActive && !ns->IsAudioParamStream())) {
IncrementActiveInputCount();
}
}
void
AudioNodeStream::RemoveInput(MediaInputPort* aPort)
{
ProcessedMediaStream::RemoveInput(aPort);
AudioNodeStream* ns = aPort->GetSource()->AsAudioNodeStream();
// Streams that are not AudioNodeStreams are considered active.
if (!ns || (ns->mIsActive && !ns->IsAudioParamStream())) {
DecrementActiveInputCount();
}
}
void
AudioNodeStream::SetActive()
{
if (mIsActive || mMarkAsFinishedAfterThisBlock) {
return;
}
mIsActive = true;
if (IsAudioParamStream()) {
// Consumers merely influence stream order.
// They do not read from the stream.
return;
}
for (const auto& consumer : mConsumers) {
AudioNodeStream* ns = consumer->GetDestination()->AsAudioNodeStream();
if (ns) {
ns->IncrementActiveInputCount();
}
}
}
void
AudioNodeStream::CheckForInactive()
{
if (((mActiveInputCount > 0 || mEngine->IsActive()) &&
!mMarkAsFinishedAfterThisBlock) ||
!mIsActive) {
return;
}
mIsActive = false;
mInputChunks.Clear(); // not required for foreseeable future
for (auto& chunk : mLastChunks) {
chunk.SetNull(WEBAUDIO_BLOCK_SIZE);
}
if (IsAudioParamStream()) {
return;
}
for (const auto& consumer : mConsumers) {
AudioNodeStream* ns = consumer->GetDestination()->AsAudioNodeStream();
if (ns) {
ns->DecrementActiveInputCount();
}
}
}
void
AudioNodeStream::IncrementActiveInputCount()
{
++mActiveInputCount;
SetActive();
}
void
AudioNodeStream::DecrementActiveInputCount()
{
MOZ_ASSERT(mActiveInputCount > 0);
--mActiveInputCount;
CheckForInactive();
}
} // namespace mozilla

View File

@ -106,6 +106,8 @@ public:
}
virtual AudioNodeStream* AsAudioNodeStream() override { return this; }
virtual void AddInput(MediaInputPort* aPort) override;
virtual void RemoveInput(MediaInputPort* aPort) override;
// Graph thread only
void SetStreamTimeParameterImpl(uint32_t aIndex, MediaStream* aRelativeToStream,
@ -165,6 +167,22 @@ public:
void SizeOfAudioNodesIncludingThis(MallocSizeOf aMallocSizeOf,
AudioNodeSizes& aUsage) const;
/*
* SetActive() is called when either an active input is added or the engine
* for a source node transitions from inactive to active. This is not
* called from engines for processing nodes because they only become active
* when there are active input streams, in which case this stream is already
* active.
*/
void SetActive();
/*
* CheckForInactive() is called when the engine transitions from active to
* inactive, or an active input is removed, or the stream finishes. If the
* stream is now inactive, then mInputChunks will be cleared and mLastChunks
* will be set to null. ProcessBlock() will not be called on the engine
* again until SetActive() is called.
*/
void CheckForInactive();
protected:
virtual void DestroyImpl() override;
@ -180,6 +198,8 @@ protected:
uint32_t ComputedNumberOfChannels(uint32_t aInputChannelCount);
void ObtainInputBlock(AudioBlock& aTmpChunk, uint32_t aPortIndex);
void IncrementActiveInputCount();
void DecrementActiveInputCount();
// The engine that will generate output for this node.
nsAutoPtr<AudioNodeEngine> mEngine;
@ -192,11 +212,16 @@ protected:
const TrackRate mSampleRate;
// Whether this is an internal or external stream
const Flags mFlags;
// The number of input streams that may provide non-silent input.
uint32_t mActiveInputCount = 0;
// The number of input channels that this stream requires. 0 means don't care.
uint32_t mNumberOfInputChannels;
// The mixing modes
ChannelCountMode mChannelCountMode;
ChannelInterpretation mChannelInterpretation;
// Streams are considered active if the stream has not finished and either
// the engine is active or there are active input streams.
bool mIsActive;
// Whether the stream should be marked as finished as soon
// as the current time range has been computed block by block.
bool mMarkAsFinishedAfterThisBlock;

View File

@ -155,6 +155,7 @@ public:
if (!hasTail) {
if (!mBiquads.IsEmpty()) {
mBiquads.Clear();
aStream->CheckForInactive();
nsRefPtr<PlayingRefChangeHandler> refchanged =
new PlayingRefChangeHandler(aStream, PlayingRefChangeHandler::RELEASE);
@ -211,6 +212,11 @@ public:
}
}
virtual bool IsActive() const override
{
return !mBiquads.IsEmpty();
}
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
{
// Not owned:

View File

@ -45,13 +45,6 @@ BufferDecoder::GetReentrantMonitor()
return mReentrantMonitor;
}
bool
BufferDecoder::IsShutdown() const
{
// BufferDecoder cannot be shut down.
return false;
}
bool
BufferDecoder::OnStateMachineTaskQueue() const
{

View File

@ -33,8 +33,6 @@ public:
virtual ReentrantMonitor& GetReentrantMonitor() final override;
virtual bool IsShutdown() const final override;
virtual bool OnStateMachineTaskQueue() const final override;
virtual bool OnDecodeTaskQueue() const final override;

View File

@ -120,6 +120,7 @@ public:
} else {
if (mLeftOverData != INT32_MIN) {
mLeftOverData = INT32_MIN;
aStream->CheckForInactive();
nsRefPtr<PlayingRefChanged> refchanged =
new PlayingRefChanged(aStream, PlayingRefChanged::RELEASE);
aStream->Graph()->
@ -154,6 +155,11 @@ public:
mReverb->process(&input, aOutput, WEBAUDIO_BLOCK_SIZE);
}
virtual bool IsActive() const override
{
return mLeftOverData != INT32_MIN;
}
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
{
size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);

View File

@ -96,6 +96,8 @@ public:
} else {
if (mLeftOverData != INT32_MIN) {
mLeftOverData = INT32_MIN;
aStream->CheckForInactive();
// Delete our buffered data now we no longer need it
mBuffer.Reset();
@ -104,7 +106,7 @@ public:
aStream->Graph()->
DispatchToMainThreadAfterStreamStateUpdate(refchanged.forget());
}
*aOutput = aInput;
aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
return;
}
@ -161,6 +163,11 @@ public:
mHaveProducedBeforeInput = true;
}
virtual bool IsActive() const override
{
return mLeftOverData != INT32_MIN;
}
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
{
size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);

View File

@ -81,7 +81,10 @@ public:
virtual void SetStreamTimeParameter(uint32_t aIndex, StreamTime aParam) override
{
switch (aIndex) {
case START: mStart = aParam; break;
case START:
mStart = aParam;
mSource->SetActive();
break;
case STOP: mStop = aParam; break;
default:
NS_ERROR("Bad OscillatorNodeEngine StreamTimeParameter");
@ -330,6 +333,12 @@ public:
}
virtual bool IsActive() const override
{
// start() has been called.
return mStart != -1;
}
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
{
size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);

View File

@ -149,6 +149,7 @@ public:
} else {
if (mLeftOverData != INT_MIN) {
mLeftOverData = INT_MIN;
aStream->CheckForInactive();
mHRTFPanner->reset();
nsRefPtr<PlayingRefChangeHandler> refchanged =
@ -156,7 +157,7 @@ public:
aStream->Graph()->
DispatchToMainThreadAfterStreamStateUpdate(refchanged.forget());
}
*aOutput = aInput;
aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
return;
}
} else if (mPanningModelFunction == &PannerNodeEngine::HRTFPanningFunction) {
@ -172,6 +173,11 @@ public:
(this->*mPanningModelFunction)(aInput, aOutput);
}
virtual bool IsActive() const override
{
return mLeftOverData != INT_MIN;
}
void ComputeAzimuthAndElevation(float& aAzimuth, float& aElevation);
float ComputeConeGain();
// Compute how much the distance contributes to the gain reduction.

View File

@ -333,6 +333,14 @@ public:
}
}
virtual bool IsActive() const override
{
// Could return false when !mIsConnected after all output chunks produced
// by main thread events calling
// SharedBuffers::FinishProducingOutputBuffer() have been processed.
return true;
}
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
{
// Not owned:

View File

@ -121,6 +121,8 @@ skip-if = toolkit == 'android' # bug 1056706
[test_mediaDecoding.html]
[test_mediaElementAudioSourceNode.html]
tags=capturestream
[test_mediaElementAudioSourceNodeFidelity.html]
tags=capturestream
[test_mediaElementAudioSourceNodePassThrough.html]
tags=capturestream
skip-if = toolkit == 'android' # bug 1145816

View File

@ -0,0 +1,135 @@
<!DOCTYPE HTML>
<html>
<meta charset="utf-8">
<head>
<title>Test MediaStreamAudioSourceNode doesn't get data from cross-origin media resources</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
// Get an Opus file containing a sine wave at maximum amplitude, of duration
// `lengthSeconds`, and of frequency `frequency`.
function getSineWaveFile(frequency, lengthSeconds, callback) {
var chunks = [];
var off = new OfflineAudioContext(1, lengthSeconds * 48000, 48000);
var osc = off.createOscillator();
var rec = new MediaRecorder(osc);
rec.ondataavailable = function(e) {
chunks.push(e.data);
};
rec.onstop = function(e) {
var blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
callback(blob);
}
osc.frequency.value = 1.0;
osc.start();
rec.start();
off.startRendering().then(function(buffer) {
rec.stop();
});
}
function binIndexForFrequency(frequency, analyser) {
return 1 + Math.round(frequency *
analyser.fftSize /
analyser.context.sampleRate);
}
function debugCanvas(analyser) {
var cvs = document.createElement("canvas");
document.body.appendChild(cvs);
// Easy: 1px per bin
cvs.width = analyser.frequencyBinCount;
cvs.height = 256;
cvs.style.border = "1px solid red";
var c = cvs.getContext('2d');
var buf = new Uint8Array(analyser.frequencyBinCount);
function render() {
c.clearRect(0, 0, cvs.width, cvs.height);
analyser.getByteFrequencyData(buf);
for (var i = 0; i < buf.length; i++) {
c.fillRect(i, (256 - (buf[i])), 1, 256);
}
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
function checkFrequency(an) {
an.getFloatFrequencyData(frequencyArray);
// We should have no energy when checking the data largely outside the index
// for 440Hz (the frequency of the sine wave), start checking an octave above,
// the Opus compression can add some harmonics to the pure since wave.
var index = binIndexForFrequency(880, an);
var underTreshold = true;
for (var i = index; i < frequencyArray.length; i++) {
// Let some slack, there might be some noise here because of int -> float
// conversion or the Opus encoding.
if (frequencyArray[i] > an.minDecibels + 40) {
return false;
}
}
return true;
}
function test() {
getSineWaveFile(440, 1, (blob) => {
var audioElement = new Audio();
audioElement.src = URL.createObjectURL(blob);
audioElement.loop = true;
var ac = new AudioContext();
var mediaElementSource = ac.createMediaElementSource(audioElement);
var an = ac.createAnalyser();
frequencyArray = new Float32Array(an.frequencyBinCount);
// Uncomment this to check what the analyser is doing.
// debugCanvas(an);
mediaElementSource.connect(an);
audioElement.play();
// We want to check the we have the expected audio for at least one loop of
// the HTMLMediaElement. The file is one second, and we use the default FFT
// size.
var lastCurrentTime = 0;
var looped = false;
audioElement.onplaying = function() {
audioElement.ontimeupdate = function() {
if (checkFrequency(an)) {
ok(true, "Found correct audio signal during analysis");
dump(lastCurrentTime + " " + audioElement.currentTime + "\n");
if (lastCurrentTime > audioElement.currentTime) {
if (looped) {
audioElement.ontimeupdate = null;
audioElement.onplaying = null;
SimpleTest.finish()
}
lastCurrentTime = audioElement.currentTime;
looped = true;
} else {
lastCurrentTime = audioElement.currentTime;
}
} else {
ok(false, "Found unexpected noise during analysis.");
audioElement.ontimeupdate = null;
audioElement.onplaying = null;
ac.close();
audioElement.src = '';
SimpleTest.finish()
}
}
}
});
}
SpecialPowers.pushPrefEnv(
{'set': [['media.recorder.audio_node.enabled', true]]}, test);
</script>

View File

@ -133,7 +133,6 @@ SpecialPowers.pushPermissions([
{type: 'presentation', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0]]},
runTests);

View File

@ -171,7 +171,6 @@ SpecialPowers.pushPermissions([
{type: 'browser', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0],
["dom.mozBrowserFramesEnabled", true],

View File

@ -99,7 +99,6 @@ SpecialPowers.pushPermissions([
{type: 'presentation', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0]]},
runTests);

View File

@ -72,7 +72,6 @@ SpecialPowers.pushPermissions([
{type: 'presentation', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0],
["presentation.receiver.loading.timeout", 10]]},

View File

@ -193,7 +193,6 @@ SpecialPowers.pushPermissions([
{type: 'presentation', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0]]},
runTests);

View File

@ -139,7 +139,6 @@ SpecialPowers.pushPermissions([
{type: 'presentation', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0]]},
runTests);

View File

@ -160,7 +160,6 @@ SpecialPowers.pushPermissions([
{type: 'presentation', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0]]},
runTests);

View File

@ -252,7 +252,6 @@ SpecialPowers.pushPermissions([
{type: 'presentation', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0]]},
runTests);

View File

@ -115,6 +115,14 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
CSPCONTEXTLOG(("nsCSPContext::ShouldLoad, aContentLocation: %s", spec.get()));
}
bool isStyleOrScriptPreLoad =
(aContentType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
aContentType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD);
// Since we know whether we are dealing with a preload, we have to convert
// the internal policytype ot the external policy type before moving on.
aContentType = nsContentUtils::InternalContentPolicyTypeToExternal(aContentType);
nsresult rv = NS_OK;
// This ShouldLoad function is called from nsCSPService::ShouldLoad,
@ -145,29 +153,8 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
return NS_OK;
}
// This may be a load or a preload. If it is a preload, the document will
// not have been fully parsed yet, and aRequestContext will be an
// nsIDOMHTMLDocument rather than the nsIDOMHTMLElement associated with the
// resource. As a result, we cannot extract the element's corresponding
// nonce attribute, and so we cannot correctly check the nonce on a preload.
//
// Therefore, the decision returned here for a preload may be *incorrect* as
// it cannot take the nonce into account. We will still check the load, but
// we will not cache the result or report a violation. When the "real load"
// happens subsequently, we will re-check with the additional context to
// make a final decision.
//
// We don't just return false because that would block all preloads and
// degrade performance. However, we do want to block preloads that are
// clearly blocked (their urls are not whitelisted) by CSP.
nsCOMPtr<nsIDOMHTMLDocument> doc = do_QueryInterface(aRequestContext);
bool isPreload = doc &&
(aContentType == nsIContentPolicy::TYPE_SCRIPT ||
aContentType == nsIContentPolicy::TYPE_STYLESHEET);
nsAutoString nonce;
if (!isPreload) {
if (!isStyleOrScriptPreLoad) {
nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(aRequestContext);
if (htmlElement) {
rv = htmlElement->GetAttribute(NS_LITERAL_STRING("nonce"), nonce);
@ -184,7 +171,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
originalURI,
nonce,
wasRedirected,
isPreload,
isStyleOrScriptPreLoad,
false, // allow fallback to default-src
true, // send violation reports
true); // send blocked URI in violation reports
@ -193,7 +180,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
: nsIContentPolicy::REJECT_SERVER;
// Done looping, cache any relevant result
if (cacheKey.Length() > 0 && !isPreload) {
if (cacheKey.Length() > 0 && !isStyleOrScriptPreLoad) {
mShouldLoadCache.Put(cacheKey, *outDecision);
}

View File

@ -105,8 +105,9 @@ CSPService::ShouldLoad(uint32_t aContentType,
nsIPrincipal *aRequestPrincipal,
int16_t *aDecision)
{
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
"We should only see external content policy types here.");
MOZ_ASSERT(aContentType ==
nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(aContentType),
"We should only see external content policy types or preloads here.");
if (!aContentLocation) {
return NS_ERROR_FAILURE;
@ -251,8 +252,9 @@ CSPService::ShouldProcess(uint32_t aContentType,
nsIPrincipal *aRequestPrincipal,
int16_t *aDecision)
{
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
"We should only see external content policy types here.");
MOZ_ASSERT(aContentType ==
nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(aContentType),
"We should only see external content policy types or preloads here.");
if (!aContentLocation)
return NS_ERROR_FAILURE;

View File

@ -0,0 +1 @@
@import url("http://example.com/tests/dom/security/test/csp/file_report_for_import_server.sjs?stylesheet");

View File

@ -0,0 +1,10 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1048048 - Test sending csp-report when using import in css</title>
<link rel="stylesheet" type="text/css" href="file_report_for_import.css">
</head>
<body>
empty body, just testing @import in the included css for bug 1048048
</body>
</html>

View File

@ -0,0 +1,49 @@
// Custom *.sjs file specifically for the needs of Bug:
// Bug 1048048 - CSP violation report not sent for @import
const CC = Components.Constructor;
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream",
"setInputStream");
function handleRequest(request, response)
{
// avoid confusing cache behaviors
response.setHeader("Cache-Control", "no-cache", false);
response.setHeader("Content-Type", "text/html", false);
var queryString = request.queryString;
// (1) lets process the queryresult request async and
// wait till we have received the image request.
if (queryString === "queryresult") {
response.processAsync();
setObjectState("queryResult", response);
return;
}
// (2) handle the csp-report and return the JSON back to
// the testfile using the afore stored xml request in (1).
if (queryString === "report") {
getObjectState("queryResult", function(queryResponse) {
if (!queryResponse) {
return;
}
// send the report back to the XML request for verification
var report = new BinaryInputStream(request.bodyInputStream);
var avail;
var bytes = [];
while ((avail = report.available()) > 0) {
Array.prototype.push.apply(bytes, report.readByteArray(avail));
}
var data = String.fromCharCode.apply(null, bytes);
queryResponse.bodyOutputStream.write(data, data.length);
queryResponse.finish();
});
return;
}
// we should not get here ever, but just in case return
// something unexpected.
response.write("doh!");
}

View File

@ -127,6 +127,9 @@ support-files =
file_upgrade_insecure_referrer_server.sjs
file_upgrade_insecure_cors.html
file_upgrade_insecure_cors_server.sjs
file_report_for_import.css
file_report_for_import.html
file_report_for_import_server.sjs
[test_base-uri.html]
[test_blob_data_schemes.html]
@ -191,5 +194,6 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolk
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolkit == 'android'
[test_upgrade_insecure_cors.html]
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolkit == 'android'
[test_report_for_import.html]
[test_blocked_uri_in_reports.html]
skip-if = e10s || buildapp == 'b2g' # http-on-opening-request observer not supported in child process (bug 1009632)

View File

@ -0,0 +1,112 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=548193
-->
<head>
<title>Test for Bug 548193</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<iframe style="width:200px;height:200px;" id='cspframe'></iframe>
<script class="testbody" type="text/javascript">
/*
* Description of the test:
* We are loading a stylesheet using a csp policy that only allows styles from 'self'
* to be loaded. In other words, the *.css file itself should be allowed to load, but
* the @import file within the CSS should get blocked. We verify that the generated
* csp-report is sent and contains all the expected values.
* In detail, the test starts by sending an XHR request to the report-server
* which waits on the server side till the report was received and hands the
* report in JSON format back to the testfile which then verifies accuracy
* of all the different report fields in the CSP report.
*/
const TEST_FILE = "tests/dom/security/test/csp/file_report_for_import.html";
const REPORT_URI =
"http://mochi.test:8888/tests/dom/security/test/csp/file_report_for_import_server.sjs?report";
const POLICY = "style-src 'self'; report-uri " + REPORT_URI;
const DOC_URI =
"http://mochi.test:8888/tests/dom/security/test/csp/file_testserver.sjs?" +
"file=tests/dom/security/test/csp/file_report_for_import.html&" +
"csp=style-src%20%27self%27%3B%20" +
"report-uri%20http%3A//mochi.test%3A8888/tests/dom/security/test/csp/" +
"file_report_for_import_server.sjs%3Freport";
function checkResults(reportStr) {
try {
var reportObj = JSON.parse(reportStr);
var cspReport = reportObj["csp-report"];
is(cspReport["document-uri"], DOC_URI, "Incorrect document-uri");
is(cspReport["referrer"],
"http://mochi.test:8888/tests/dom/security/test/csp/test_report_for_import.html",
"Incorrect referrer");
is(cspReport["violated-directive"],
"style-src http://mochi.test:8888",
"Incorrect violated-directive");
is(cspReport["original-policy"],
"style-src http://mochi.test:8888; report-uri " +
"http://mochi.test:8888/tests/dom/security/test/csp/file_report_for_import_server.sjs?report",
"Incorrect original-policy");
is(cspReport["blocked-uri"],
"http://example.com/tests/dom/security/test/csp/file_report_for_import_server.sjs?stylesheet",
"Incorrect blocked-uri");
// we do not always set the following fields
is(cspReport["source-file"], undefined, "Incorrect source-file");
is(cspReport["script-sample"], undefined, "Incorrect script-sample");
is(cspReport["line-number"], undefined, "Incorrect line-number");
}
catch (e) {
ok(false, "Could not parse JSON (exception: " + e + ")");
}
}
function loadTestPageIntoFrame() {
// load the resource which will generate a CSP violation report
// save this for last so that our listeners are registered.
var src = "file_testserver.sjs";
// append the file that should be served
src += "?file=" + escape(TEST_FILE);
// append the CSP that should be used to serve the file
src += "&csp=" + escape(POLICY);
// appending a fragment so we can test that it's correctly stripped
// for document-uri and source-file.
src += "#foo";
document.getElementById("cspframe").src = src;
}
function runTest() {
// send an xhr request to the server which is processed async, which only
// returns after the server has received the csp report.
var myXHR = new XMLHttpRequest();
myXHR.open("GET", "file_report_for_import_server.sjs?queryresult");
myXHR.onload = function(e) {
checkResults(myXHR.responseText);
SimpleTest.finish();
}
myXHR.onerror = function(e) {
ok(false, "could not query results from server (" + e.message + ")");
SimpleTest.finish();
}
myXHR.send();
// give it some time and run the testpage
SimpleTest.executeSoon(loadTestPageIntoFrame);
}
SimpleTest.waitForExplicitFinish();
runTest();
</script>
</pre>
</body>
</html>

View File

@ -77,7 +77,9 @@ static const uint32_t sMaxStreamVolumeTbl[AUDIO_STREAM_CNT] = {
15, // enforced audible
15, // DTMF
15, // TTS
#if ANDROID_VERSION < 19
15, // FM
#endif
};
// Use a half value of each volume category as the default volume.
@ -794,12 +796,16 @@ AudioManager::SetFmRadioAudioEnabled(bool aFmRadioAudioEnabled)
aFmRadioAudioEnabled ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, "");
UpdateHeadsetConnectionState(GetCurrentSwitchState(SWITCH_HEADPHONES));
// AUDIO_STREAM_FM is not used on recent gonk.
// AUDIO_STREAM_MUSIC is used for FM radio volume control.
#if ANDROID_VERSION < 19
// sync volume with music after powering on fm radio
if (aFmRadioAudioEnabled) {
uint32_t volIndex = mCurrentStreamVolumeTbl[AUDIO_STREAM_MUSIC];
SetStreamVolumeIndex(AUDIO_STREAM_FM, volIndex);
mCurrentStreamVolumeTbl[AUDIO_STREAM_FM] = volIndex;
}
#endif
return NS_OK;
}
@ -819,6 +825,9 @@ AudioManager::SetVolumeByCategory(uint32_t aCategory, uint32_t aIndex)
nsresult status;
switch (static_cast<AudioVolumeCategories>(aCategory)) {
case VOLUME_MEDIA:
// AUDIO_STREAM_FM is not used on recent gonk.
// AUDIO_STREAM_MUSIC is used for FM radio volume control.
#if ANDROID_VERSION < 19
// sync FMRadio's volume with content channel.
if (IsDeviceOn(AUDIO_DEVICE_OUT_FM)) {
status = SetStreamVolumeIndex(AUDIO_STREAM_FM, aIndex);
@ -826,6 +835,7 @@ AudioManager::SetVolumeByCategory(uint32_t aCategory, uint32_t aIndex)
return status;
}
}
#endif
status = SetStreamVolumeIndex(AUDIO_STREAM_MUSIC, aIndex);
break;
case VOLUME_NOTIFICATION:
@ -1005,6 +1015,7 @@ AudioManager::SetStreamVolumeIndex(int32_t aStream, uint32_t aIndex) {
aIndex);
return status ? NS_ERROR_FAILURE : NS_OK;
#else
#if ANDROID_VERSION < 19
if (aStream == AUDIO_STREAM_FM) {
status = AudioSystem::setStreamVolumeIndex(
static_cast<audio_stream_type_t>(aStream),
@ -1012,7 +1023,7 @@ AudioManager::SetStreamVolumeIndex(int32_t aStream, uint32_t aIndex) {
AUDIO_DEVICE_OUT_FM);
return status ? NS_ERROR_FAILURE : NS_OK;
}
#endif
if (mPresentProfile == DEVICE_PRIMARY) {
status = AudioSystem::setStreamVolumeIndex(
static_cast<audio_stream_type_t>(aStream),

View File

@ -74,7 +74,9 @@ typedef enum {
AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user and must be routed to speaker */
AUDIO_STREAM_DTMF = 8,
AUDIO_STREAM_TTS = 9,
#if ANDROID_VERSION < 19
AUDIO_STREAM_FM = 10,
#endif
AUDIO_STREAM_CNT,
AUDIO_STREAM_MAX = AUDIO_STREAM_CNT - 1,

View File

@ -7,7 +7,8 @@
task(function* () {
// We just check if we can access storage as chrome using special powers!
yield chromePower();
var params = new URLSearchParams(location.search.substr(1));
yield chromePower(params.get('allowed') == 'yes', params.get('blockSessionStorage') == 'yes');
});
</script>

View File

@ -62,44 +62,49 @@ function runWorker(url) {
});
}
function chromePower() {
function chromePower(allowed, blockSessionStorage) {
// localStorage is affected by storage policy.
try {
SpecialPowers.wrap(window).localStorage.getItem("X");
ok(true, "getting localStorage didn't throw");
ok(allowed, "getting localStorage from chrome didn't throw");
} catch (e) {
ok(false, "getting localStorage should not throw");
ok(!allowed, "getting localStorage from chrome threw");
}
// sessionStorage is not. See bug 1183968.
try {
SpecialPowers.wrap(window).sessionStorage.getItem("X");
ok(true, "getting sessionStorage didn't throw");
ok(!blockSessionStorage, "getting sessionStorage from chrome didn't throw");
} catch (e) {
ok(false, "getting sessionStorage should not throw");
ok(blockSessionStorage, "getting sessionStorage from chrome threw");
}
// indexedDB is affected by storage policy.
try {
SpecialPowers.wrap(window).indexedDB;
ok(true, "getting indexedDB didn't throw");
ok(allowed, "getting indexedDB from chrome didn't throw");
} catch (e) {
ok(false, "getting indexedDB should not throw");
ok(!allowed, "getting indexedDB from chrome threw");
}
// Same with caches, along with the additional https-only requirement.
try {
var shouldResolve = allowed && location.protocol == "https:";
var promise = SpecialPowers.wrap(window).caches.keys();
ok(true, "getting caches didn't throw");
ok(true, "getting caches from chrome should never throw");
return new Promise((resolve, reject) => {
promise.then(function() {
ok(location.protocol == "https:", "The promise was not rejected");
ok(shouldResolve, "The promise was resolved for chrome");
resolve();
}, function(e) {
ok(location.protocol != "https:", "The promise should not have been rejected: " + e);
ok(!shouldResolve, "The promise was rejected for chrome: " + e);
resolve();
});
});
} catch (e) {
ok(false, "getting caches should not have thrown");
return Promise.resolve();
ok(false, "getting caches from chrome threw");
}
}

View File

@ -20,7 +20,7 @@ task(function* () {
// Same origin iframes should be allowed, unless they redirect to a URI with the null principal
yield runIFrame("frameStorageAllowed.html");
yield runIFrame("frameStorageNullprincipal.sjs");
yield runIFrame("frameStorageChrome.html");
yield runIFrame("frameStorageChrome.html?allowed=yes");
// Sandboxed iframes should have the null principal, and thus can't access storage
document.querySelector('iframe').setAttribute('sandbox', 'allow-scripts');
@ -31,7 +31,7 @@ task(function* () {
// Thirdparty iframes should be allowed, unless they redirect to a URI with the null principal
yield runIFrame(thirdparty + "frameStorageAllowed.html");
yield runIFrame(thirdparty + "frameStorageNullprincipal.sjs");
yield runIFrame(thirdparty + "frameStorageChrome.html");
yield runIFrame(thirdparty + "frameStorageChrome.html?allowed=yes");
// Workers should be able to access storage
yield runWorker("workerStorageAllowed.js");

View File

@ -17,10 +17,12 @@ task(function* () {
// We should be able to access storage
yield storageAllowed();
// Same origin iframes should be prevented, unless they have chrome privileges
// Same origin iframes should be allowed.
yield runIFrame("frameStorageAllowed.html");
yield runIFrame("frameStorageChrome.html?allowed=yes");
// Null principal iframes should not.
yield runIFrame("frameStorageNullprincipal.sjs");
yield runIFrame("frameStorageChrome.html");
// Sandboxed iframes should have the null principal, and thus can't access storage
document.querySelector('iframe').setAttribute('sandbox', 'allow-scripts');
@ -28,10 +30,10 @@ task(function* () {
yield runIFrame("frameStorageNullprincipal.sjs");
document.querySelector('iframe').removeAttribute('sandbox');
// Thirdparty iframes should be blocked, unless they have chrome privileges
// Thirdparty iframes should be blocked, even when accessed from chrome over Xrays.
yield runIFrame(thirdparty + "frameStoragePrevented.html#thirdparty");
yield runIFrame(thirdparty + "frameStorageNullprincipal.sjs");
yield runIFrame(thirdparty + "frameStorageChrome.html");
yield runIFrame(thirdparty + "frameStorageChrome.html?allowed=no");
// Workers should be unable to access storage
yield runWorker("workerStorageAllowed.js");

View File

@ -17,10 +17,10 @@ task(function* () {
// We should be unable to access storage
yield storagePrevented();
// Same origin iframes should be prevented, unless they have chrome privileges
// Same origin iframes should be blocked.
yield runIFrame("frameStoragePrevented.html");
yield runIFrame("frameStorageNullprincipal.sjs");
yield runIFrame("frameStorageChrome.html");
yield runIFrame("frameStorageChrome.html?allowed=no&blockSessionStorage=yes");
// Sandboxed iframes should have the null principal, and thus can't access storage
document.querySelector('iframe').setAttribute('sandbox', 'allow-scripts');
@ -28,9 +28,10 @@ task(function* () {
yield runIFrame("frameStorageNullprincipal.sjs");
document.querySelector('iframe').removeAttribute('sandbox');
// thirdparty iframes should be blocked, unless they have chrome privileges
// thirdparty iframes should be blocked.
yield runIFrame(thirdparty + "frameStoragePrevented.html");
yield runIFrame(thirdparty + "frameStorageNullprincipal.sjs");
yield runIFrame(thirdparty + "frameStorageChrome.html?allowed=no&blockSessionStorage=yes");
// Workers should be unable to access storage
yield runWorker("workerStoragePrevented.js");

View File

@ -20,7 +20,7 @@ task(function* () {
// Same origin iframes should be allowed, unless they redirect to a URI with the null principal
yield runIFrame("frameStorageAllowed.html");
yield runIFrame("frameStorageNullprincipal.sjs");
yield runIFrame("frameStorageChrome.html");
yield runIFrame("frameStorageChrome.html?allowed=yes");
// Sandboxed iframes should have the null principal, and thus can't access storage
document.querySelector('iframe').setAttribute('sandbox', 'allow-scripts');
@ -28,10 +28,10 @@ task(function* () {
yield runIFrame("frameStorageNullprincipal.sjs");
document.querySelector('iframe').removeAttribute('sandbox');
// thirdparty iframes should be blocked, unless they have chrome privileges
// thirdparty iframes should be blocked.
yield runIFrame(thirdparty + "frameStoragePrevented.html#thirdparty");
yield runIFrame(thirdparty + "frameStorageNullprincipal.sjs");
yield runIFrame(thirdparty + "frameStorageChrome.html");
yield runIFrame(thirdparty + "frameStorageChrome.html?allowed=no");
// Workers should be able to access storage
yield runWorker("workerStorageAllowed.js");

View File

@ -432,7 +432,7 @@ partial interface Navigator {
};
partial interface Navigator {
[Throws, Pref="dom.presentation.enabled", CheckAnyPermissions="presentation", AvailableIn="PrivilegedApps", SameObject]
[Throws, Pref="dom.presentation.enabled", CheckAnyPermissions="presentation", SameObject]
readonly attribute Presentation? presentation;
};

View File

@ -5,8 +5,7 @@
*/
[Pref="dom.presentation.enabled",
CheckAnyPermissions="presentation",
AvailableIn="PrivilegedApps"]
CheckAnyPermissions="presentation"]
interface Presentation : EventTarget {
/*
* This should be used by the UA as the default presentation request for the

View File

@ -5,8 +5,7 @@
*/
[Pref="dom.presentation.enabled",
CheckAnyPermissions="presentation",
AvailableIn="PrivilegedApps"]
CheckAnyPermissions="presentation"]
interface PresentationAvailability : EventTarget {
/*
* If there is at least one device discovered by UA, the value is |true|.

View File

@ -6,8 +6,7 @@
[Constructor(DOMString url),
Pref="dom.presentation.enabled",
CheckAnyPermissions="presentation",
AvailableIn="PrivilegedApps"]
CheckAnyPermissions="presentation"]
interface PresentationRequest : EventTarget {
/*
* A requesting page use start() to start a new session, and the session will

View File

@ -18,8 +18,7 @@ enum PresentationSessionState
};
[Pref="dom.presentation.enabled",
CheckAnyPermissions="presentation",
AvailableIn="PrivilegedApps"]
CheckAnyPermissions="presentation"]
interface PresentationSession : EventTarget {
/*
* Unique id for all existing sessions.

View File

@ -7,8 +7,7 @@
[Constructor(DOMString type,
optional PresentationSessionConnectEventInit eventInitDict),
Pref="dom.presentation.enabled",
CheckAnyPermissions="presentation",
AvailableIn="PrivilegedApps"]
CheckAnyPermissions="presentation"]
interface PresentationSessionConnectEvent : Event
{
[SameObject]

View File

@ -3982,20 +3982,22 @@ public:
NS_IMPL_ISUPPORTS_INHERITED(FetchEventRunnable, WorkerRunnable, nsIHttpHeaderVisitor)
void
ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttributes,
nsIDocument* aDoc,
nsIInterceptedChannel* aChannel,
bool aIsReload,
ErrorResult& aRv)
already_AddRefed<nsIRunnable>
ServiceWorkerManager::PrepareFetchEvent(const OriginAttributes& aOriginAttributes,
nsIDocument* aDoc,
nsIInterceptedChannel* aChannel,
bool aIsReload,
ErrorResult& aRv)
{
MOZ_ASSERT(aChannel);
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsISupports> serviceWorker;
bool isNavigation = false;
aRv = aChannel->GetIsNavigation(&isNavigation);
if (NS_WARN_IF(aRv.Failed())) {
return;
return nullptr;
}
// if the ServiceWorker script fails to load for some reason, just resume
@ -4014,13 +4016,13 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut
nsCOMPtr<nsIChannel> internalChannel;
aRv = aChannel->GetChannel(getter_AddRefs(internalChannel));
if (NS_WARN_IF(aRv.Failed())) {
return;
return nullptr;
}
nsCOMPtr<nsIURI> uri;
aRv = internalChannel->GetURI(getter_AddRefs(uri));
if (NS_WARN_IF(aRv.Failed())) {
return;
return nullptr;
}
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
@ -4028,7 +4030,7 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut
if (!registration) {
NS_WARNING("No registration found when dispatching the fetch event");
aRv.Throw(NS_ERROR_FAILURE);
return;
return nullptr;
}
// This should only happen if IsAvailable() returned true.
@ -4043,7 +4045,7 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut
}
if (NS_WARN_IF(aRv.Failed())) {
return;
return nullptr;
}
nsMainThreadPtrHandle<nsIInterceptedChannel> handle(
@ -4058,6 +4060,18 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut
serviceWorkerHandle, clientInfo,
aIsReload);
return continueRunnable.forget();
}
void
ServiceWorkerManager::DispatchPreparedFetchEvent(nsIInterceptedChannel* aChannel,
nsIRunnable* aPreparedRunnable,
ErrorResult& aRv)
{
MOZ_ASSERT(aChannel);
MOZ_ASSERT(aPreparedRunnable);
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIChannel> innerChannel;
aRv = aChannel->GetChannel(getter_AddRefs(innerChannel));
if (NS_WARN_IF(aRv.Failed())) {
@ -4068,13 +4082,13 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut
// If there is no upload stream, then continue immediately
if (!uploadChannel) {
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(continueRunnable->Run()));
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aPreparedRunnable->Run()));
return;
}
// Otherwise, ensure the upload stream can be cloned directly. This may
// require some async copying, so provide a callback.
aRv = uploadChannel->EnsureUploadStreamIsCloneable(continueRunnable);
aRv = uploadChannel->EnsureUploadStreamIsCloneable(aPreparedRunnable);
}
bool

View File

@ -315,12 +315,17 @@ public:
bool
IsControlled(nsIDocument* aDocument, ErrorResult& aRv);
already_AddRefed<nsIRunnable>
PrepareFetchEvent(const OriginAttributes& aOriginAttributes,
nsIDocument* aDoc,
nsIInterceptedChannel* aChannel,
bool aIsReload,
ErrorResult& aRv);
void
DispatchFetchEvent(const OriginAttributes& aOriginAttributes,
nsIDocument* aDoc,
nsIInterceptedChannel* aChannel,
bool aIsReload,
ErrorResult& aRv);
DispatchPreparedFetchEvent(nsIInterceptedChannel* aChannel,
nsIRunnable* aPreparedRunnable,
ErrorResult& aRv);
void
SoftUpdate(nsIPrincipal* aPrincipal,

View File

@ -111,12 +111,12 @@ public:
}
// Note that because there is no "serviceworker" RequestContext type, we can
// use the external TYPE_SCRIPT content policy types when loading a service
// use the TYPE_INTERNAL_SCRIPT content policy types when loading a service
// worker.
rv = NS_NewChannel(getter_AddRefs(mChannel),
uri, aPrincipal,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_SCRIPT,
nsIContentPolicy::TYPE_INTERNAL_SCRIPT,
loadGroup);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;

View File

@ -151,7 +151,7 @@ nsXBLResourceLoader::LoadResources(bool* aResult)
}
else
{
rv = cssLoader->LoadSheet(url, docPrincipal, EmptyCString(), this);
rv = cssLoader->LoadSheet(url, false, docPrincipal, EmptyCString(), this);
if (NS_SUCCEEDED(rv))
++mPendingSheets;
}

View File

@ -424,7 +424,7 @@ txCompileObserver::loadURI(const nsAString& aUri,
// Content Policy
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_STYLESHEET,
uri,
referrerPrincipal,
mLoaderDocument,
@ -524,7 +524,7 @@ TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor,
// Content Policy
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
nsresult rv =
NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_STYLESHEET,
aUri,
principal,
aLoaderDocument,
@ -666,7 +666,7 @@ txSyncCompileObserver::loadURI(const nsAString& aUri,
// Content Policy
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_STYLESHEET,
uri,
referrerPrincipal,
nullptr,

View File

@ -3250,7 +3250,8 @@ XULDocument::LoadScript(nsXULPrototypeScript* aScriptProto, bool* aBlock)
this,
static_cast<nsIDocument*>(this),
aScriptProto->mSrcURI,
NS_LITERAL_STRING("application/x-javascript"));
NS_LITERAL_STRING("application/x-javascript"),
false);
if (NS_FAILED(rv)) {
*aBlock = false;
return rv;

View File

@ -2791,7 +2791,7 @@ nsHTMLEditor::ReplaceStyleSheet(const nsAString& aURL)
NS_ENSURE_SUCCESS(rv, rv);
return ps->GetDocument()->CSSLoader()->
LoadSheet(uaURI, nullptr, EmptyCString(), this);
LoadSheet(uaURI, false, nullptr, EmptyCString(), this);
}
NS_IMETHODIMP

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