mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
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:
commit
651a168616
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()
|
||||
};
|
||||
|
@ -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}) => {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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>";
|
||||
}
|
||||
|
@ -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 =
|
||||
|
@ -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.
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
{
|
||||
/**
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
7
dom/cache/DBSchema.cpp
vendored
7
dom/cache/DBSchema.cpp
vendored
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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(),
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -2365,8 +2365,8 @@ MediaInputPort::Disconnect()
|
||||
return;
|
||||
|
||||
mSource->RemoveConsumer(this);
|
||||
mSource = nullptr;
|
||||
mDest->RemoveInput(this);
|
||||
mSource = nullptr;
|
||||
mDest = nullptr;
|
||||
|
||||
GraphImpl()->SetStreamOrderDirty();
|
||||
|
@ -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
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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__);
|
||||
}
|
||||
});
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -45,13 +45,6 @@ BufferDecoder::GetReentrantMonitor()
|
||||
return mReentrantMonitor;
|
||||
}
|
||||
|
||||
bool
|
||||
BufferDecoder::IsShutdown() const
|
||||
{
|
||||
// BufferDecoder cannot be shut down.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
BufferDecoder::OnStateMachineTaskQueue() const
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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>
|
@ -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);
|
||||
|
@ -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],
|
||||
|
@ -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);
|
||||
|
@ -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]]},
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
1
dom/security/test/csp/file_report_for_import.css
vendored
Normal file
1
dom/security/test/csp/file_report_for_import.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
@import url("http://example.com/tests/dom/security/test/csp/file_report_for_import_server.sjs?stylesheet");
|
10
dom/security/test/csp/file_report_for_import.html
Normal file
10
dom/security/test/csp/file_report_for_import.html
Normal 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>
|
49
dom/security/test/csp/file_report_for_import_server.sjs
Normal file
49
dom/security/test/csp/file_report_for_import_server.sjs
Normal 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!");
|
||||
}
|
@ -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)
|
||||
|
112
dom/security/test/csp/test_report_for_import.html
Normal file
112
dom/security/test/csp/test_report_for_import.html
Normal 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>
|
@ -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),
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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|.
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -7,8 +7,7 @@
|
||||
[Constructor(DOMString type,
|
||||
optional PresentationSessionConnectEventInit eventInitDict),
|
||||
Pref="dom.presentation.enabled",
|
||||
CheckAnyPermissions="presentation",
|
||||
AvailableIn="PrivilegedApps"]
|
||||
CheckAnyPermissions="presentation"]
|
||||
interface PresentationSessionConnectEvent : Event
|
||||
{
|
||||
[SameObject]
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user