зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound and m-c.
This commit is contained in:
Коммит
a4120936bf
2
CLOBBER
2
CLOBBER
|
@ -17,4 +17,4 @@
|
|||
#
|
||||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||
#
|
||||
Bug 880917 needs a clobber for the removal of testVersion.cpp
|
||||
Bug 848491 - Skia update.
|
||||
|
|
|
@ -9,11 +9,4 @@ VPATH = @srcdir@
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
Keyboard.jsm \
|
||||
TelURIParser.jsm \
|
||||
SignInToWebsite.jsm \
|
||||
ErrorPage.jsm \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -35,3 +35,10 @@ if CONFIG['MOZ_UPDATER']:
|
|||
EXTRA_PP_COMPONENTS += [
|
||||
'UpdatePrompt.js',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'ErrorPage.jsm',
|
||||
'Keyboard.jsm',
|
||||
'SignInToWebsite.jsm',
|
||||
'TelURIParser.jsm',
|
||||
]
|
||||
|
|
|
@ -135,17 +135,9 @@ pref("app.update.enabled", true);
|
|||
// the UI easier to construct.
|
||||
pref("app.update.auto", true);
|
||||
|
||||
// Defines how the Application Update Service notifies the user about updates:
|
||||
//
|
||||
// AUM Set to: Minor Releases: Major Releases:
|
||||
// 0 download no prompt download no prompt
|
||||
// 1 download no prompt download no prompt if no incompatibilities
|
||||
// 2 download no prompt prompt
|
||||
//
|
||||
// See chart in nsUpdateService.js source for more details
|
||||
// incompatibilities are ignored by updates in Metro
|
||||
//
|
||||
pref("app.update.mode", 0);
|
||||
pref("app.update.mode", 1);
|
||||
|
||||
#ifdef XP_WIN
|
||||
#ifdef MOZ_METRO
|
||||
|
|
|
@ -144,6 +144,11 @@ const DEFAULT_SNIPPETS_URLS = [
|
|||
|
||||
const SNIPPETS_UPDATE_INTERVAL_MS = 86400000; // 1 Day.
|
||||
|
||||
// IndexedDB storage constants.
|
||||
const DATABASE_NAME = "abouthome";
|
||||
const DATABASE_VERSION = 1;
|
||||
const SNIPPETS_OBJECTSTORE_NAME = "snippets";
|
||||
|
||||
// This global tracks if the page has been set up before, to prevent double inits
|
||||
let gInitialized = false;
|
||||
let gObserver = new MutationObserver(function (mutations) {
|
||||
|
@ -200,40 +205,87 @@ function ensureSnippetsMapThen(aCallback)
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO (bug 789348): use a real asynchronous storage here. This setTimeout
|
||||
// is done just to catch bugs with the asynchronous behavior.
|
||||
setTimeout(function() {
|
||||
// Populate the cache from the persistent storage.
|
||||
let cache = new Map();
|
||||
for (let key of [ "snippets-last-update",
|
||||
"snippets-cached-version",
|
||||
"snippets" ]) {
|
||||
cache.set(key, localStorage[key]);
|
||||
let invokeCallbacks = function () {
|
||||
if (!gSnippetsMap) {
|
||||
gSnippetsMap = Object.freeze(new Map());
|
||||
}
|
||||
|
||||
gSnippetsMap = Object.freeze({
|
||||
get: function (aKey) cache.get(aKey),
|
||||
set: function (aKey, aValue) {
|
||||
localStorage[aKey] = aValue;
|
||||
return cache.set(aKey, aValue);
|
||||
},
|
||||
has: function(aKey) cache.has(aKey),
|
||||
delete: function(aKey) {
|
||||
delete localStorage[aKey];
|
||||
return cache.delete(aKey);
|
||||
},
|
||||
clear: function() {
|
||||
localStorage.clear();
|
||||
return cache.clear();
|
||||
},
|
||||
get size() cache.size
|
||||
});
|
||||
|
||||
for (let callback of gSnippetsMapCallbacks) {
|
||||
callback(gSnippetsMap);
|
||||
}
|
||||
gSnippetsMapCallbacks.length = 0;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
let openRequest = indexedDB.open(DATABASE_NAME, DATABASE_VERSION);
|
||||
|
||||
openRequest.onerror = function (event) {
|
||||
// Try to delete the old database so that we can start this process over
|
||||
// next time.
|
||||
indexedDB.deleteDatabase(DATABASE_NAME);
|
||||
invokeCallbacks();
|
||||
};
|
||||
|
||||
openRequest.onupgradeneeded = function (event) {
|
||||
let db = event.target.result;
|
||||
if (!db.objectStoreNames.contains(SNIPPETS_OBJECTSTORE_NAME)) {
|
||||
db.createObjectStore(SNIPPETS_OBJECTSTORE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
openRequest.onsuccess = function (event) {
|
||||
let db = event.target.result;
|
||||
|
||||
db.onerror = function (event) {
|
||||
invokeCallbacks();
|
||||
}
|
||||
|
||||
db.onversionchange = function (event) {
|
||||
event.target.close();
|
||||
invokeCallbacks();
|
||||
}
|
||||
|
||||
let cache = new Map();
|
||||
let cursorRequest = db.transaction(SNIPPETS_OBJECTSTORE_NAME)
|
||||
.objectStore(SNIPPETS_OBJECTSTORE_NAME).openCursor();
|
||||
cursorRequest.onerror = function (event) {
|
||||
invokeCallbacks();
|
||||
}
|
||||
|
||||
cursorRequest.onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
|
||||
// Populate the cache from the persistent storage.
|
||||
if (cursor) {
|
||||
cache.set(cursor.key, cursor.value);
|
||||
cursor.continue();
|
||||
return;
|
||||
}
|
||||
|
||||
// The cache has been filled up, create the snippets map.
|
||||
gSnippetsMap = Object.freeze({
|
||||
get: function (aKey) cache.get(aKey),
|
||||
set: function (aKey, aValue) {
|
||||
db.transaction(SNIPPETS_OBJECTSTORE_NAME, "readwrite")
|
||||
.objectStore(SNIPPETS_OBJECTSTORE_NAME).put(aValue, aKey);
|
||||
return cache.set(aKey, aValue);
|
||||
},
|
||||
has: function (aKey) cache.has(aKey),
|
||||
delete: function (aKey) {
|
||||
db.transaction(SNIPPETS_OBJECTSTORE_NAME, "readwrite")
|
||||
.objectStore(SNIPPETS_OBJECTSTORE_NAME).delete(aKey);
|
||||
return cache.delete(aKey);
|
||||
},
|
||||
clear: function () {
|
||||
db.transaction(SNIPPETS_OBJECTSTORE_NAME, "readwrite")
|
||||
.objectStore(SNIPPETS_OBJECTSTORE_NAME).clear();
|
||||
return cache.clear();
|
||||
},
|
||||
get size() cache.size
|
||||
});
|
||||
|
||||
setTimeout(invokeCallbacks, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onSearchSubmit(aEvent)
|
||||
|
|
|
@ -13,6 +13,4 @@ DISABLED_EXTRA_COMPONENTS = \
|
|||
BrowserComponents.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = distribution.js
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -15,9 +15,4 @@ DISABLED_EXTRA_COMPONENTS = \
|
|||
DownloadsStartup.js \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
DownloadsCommon.jsm \
|
||||
DownloadsLogger.jsm \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -9,3 +9,9 @@ EXTRA_COMPONENTS += [
|
|||
'DownloadsStartup.js',
|
||||
'DownloadsUI.js',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'DownloadsCommon.jsm',
|
||||
'DownloadsLogger.jsm',
|
||||
]
|
||||
|
||||
|
|
|
@ -43,3 +43,8 @@ EXTRA_PP_COMPONENTS += [
|
|||
'nsBrowserContentHandler.js',
|
||||
'nsBrowserGlue.js',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'distribution.js',
|
||||
]
|
||||
|
||||
|
|
|
@ -937,7 +937,7 @@ PlacesController.prototype = {
|
|||
gen.next();
|
||||
} catch (ex if ex instanceof StopIteration) {}
|
||||
}, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
yield;
|
||||
yield undefined;
|
||||
}
|
||||
}
|
||||
let gen = pagesChunkGenerator(URIs);
|
||||
|
|
|
@ -15,9 +15,5 @@ DISABLED_EXTRA_COMPONENTS = \
|
|||
PlacesProtocolHandler.js \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
PlacesUIUtils.jsm \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
|
|
@ -12,3 +12,8 @@ EXTRA_COMPONENTS += [
|
|||
'BrowserPlaces.manifest',
|
||||
'PlacesProtocolHandler.js',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'PlacesUIUtils.jsm',
|
||||
]
|
||||
|
||||
|
|
|
@ -16,16 +16,6 @@ DISABLED_EXTRA_COMPONENTS = \
|
|||
nsSessionStartup.js \
|
||||
$(NULL)
|
||||
|
||||
JS_MODULES_PATH := modules/sessionstore
|
||||
|
||||
EXTRA_JS_MODULES := \
|
||||
DocumentUtils.jsm \
|
||||
SessionStorage.jsm \
|
||||
SessionMigration.jsm \
|
||||
XPathGenerator.jsm \
|
||||
_SessionFile.jsm \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_JS_MODULES := \
|
||||
SessionStore.jsm \
|
||||
$(NULL)
|
||||
|
|
|
@ -9,3 +9,13 @@ EXTRA_COMPONENTS += [
|
|||
'nsSessionStore.js',
|
||||
'nsSessionStore.manifest',
|
||||
]
|
||||
|
||||
JS_MODULES_PATH = 'modules/sessionstore'
|
||||
|
||||
EXTRA_JS_MODULES = [
|
||||
'DocumentUtils.jsm',
|
||||
'SessionMigration.jsm',
|
||||
'SessionStorage.jsm',
|
||||
'XPathGenerator.jsm',
|
||||
'_SessionFile.jsm',
|
||||
]
|
||||
|
|
|
@ -10,10 +10,4 @@ VPATH = @srcdir@
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
source-editor.jsm \
|
||||
source-editor-orion.jsm \
|
||||
source-editor-ui.jsm \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -5,3 +5,10 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'source-editor-orion.jsm',
|
||||
'source-editor-ui.jsm',
|
||||
'source-editor.jsm',
|
||||
]
|
||||
|
||||
|
|
|
@ -9,12 +9,6 @@ VPATH = @srcdir@
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
HUDService.jsm \
|
||||
NetworkPanel.jsm \
|
||||
WebConsolePanel.jsm \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
|
|
|
@ -6,3 +6,9 @@
|
|||
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'HUDService.jsm',
|
||||
'NetworkPanel.jsm',
|
||||
'WebConsolePanel.jsm',
|
||||
]
|
||||
|
||||
|
|
|
@ -102,6 +102,12 @@
|
|||
#ifdef MOZ_METRO
|
||||
@BINPATH@/vccorlib110.dll
|
||||
#endif
|
||||
#elif MOZ_MSVC_REDIST == 1800
|
||||
@BINPATH@/msvcp120.dll
|
||||
@BINPATH@/msvcr120.dll
|
||||
#ifdef MOZ_METRO
|
||||
@BINPATH@/vccorlib120.dll
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1443,6 +1443,13 @@ xpicleanup@BIN_SUFFIX@
|
|||
vccorlib110.dll
|
||||
#endif
|
||||
#endif
|
||||
#if MOZ_MSVC_REDIST != 1800
|
||||
msvcp120.dll
|
||||
msvcr120.dll
|
||||
#ifdef MOZ_METRO
|
||||
vccorlib120.dll
|
||||
#endif
|
||||
#endif
|
||||
plugins/npnul32.dll
|
||||
#endif
|
||||
@DLL_PREFIX@xpcom_core@DLL_SUFFIX@
|
||||
|
|
|
@ -18,6 +18,10 @@ const TOOLBARSTATE_LOADED = 2;
|
|||
// Page for which the start UI is shown
|
||||
const kStartOverlayURI = "about:start";
|
||||
|
||||
// Devtools Messages
|
||||
const debugServerStateChanged = "devtools.debugger.remote-enabled";
|
||||
const debugServerPortChanged = "devtools.debugger.remote-port";
|
||||
|
||||
/**
|
||||
* Cache of commonly used elements.
|
||||
*/
|
||||
|
@ -75,6 +79,14 @@ var BrowserUI = {
|
|||
|
||||
lastKnownGoodURL: "", //used when the user wants to escape unfinished url entry
|
||||
init: function() {
|
||||
|
||||
// start the debugger now so we can use it on the startup code as well
|
||||
if (Services.prefs.getBoolPref(debugServerStateChanged)) {
|
||||
this.runDebugServer();
|
||||
}
|
||||
Services.prefs.addObserver(debugServerStateChanged, this, false);
|
||||
Services.prefs.addObserver(debugServerPortChanged, this, false);
|
||||
|
||||
// listen content messages
|
||||
messageManager.addMessageListener("DOMTitleChanged", this);
|
||||
messageManager.addMessageListener("DOMWillOpenModalDialog", this);
|
||||
|
@ -181,8 +193,38 @@ var BrowserUI = {
|
|||
SettingsCharm.uninit();
|
||||
messageManager.removeMessageListener("Content:StateChange", this);
|
||||
PageThumbs.uninit();
|
||||
this.stopDebugServer();
|
||||
},
|
||||
|
||||
/************************************
|
||||
* Devtools Debugger
|
||||
*/
|
||||
runDebugServer: function runDebugServer(aPort) {
|
||||
let port = aPort || Services.prefs.getIntPref(debugServerPortChanged);
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
DebuggerServer.addActors('chrome://browser/content/dbg-metro-actors.js');
|
||||
}
|
||||
DebuggerServer.openListener(port);
|
||||
},
|
||||
|
||||
stopDebugServer: function stopDebugServer() {
|
||||
if (DebuggerServer.initialized) {
|
||||
DebuggerServer.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
// If the server is not on, port changes have nothing to effect. The new value
|
||||
// will be picked up if the server is started.
|
||||
// To be consistent with desktop fx, if the port is changed while the server
|
||||
// is running, restart server.
|
||||
changeDebugPort:function changeDebugPort(aPort) {
|
||||
if (DebuggerServer.initialized) {
|
||||
this.stopDebugServer();
|
||||
this.runDebugServer(aPort);
|
||||
}
|
||||
},
|
||||
|
||||
/*********************************
|
||||
* Content visibility
|
||||
|
@ -597,6 +639,16 @@ var BrowserUI = {
|
|||
case "browser.urlbar.trimURLs":
|
||||
this._mayTrimURLs = Services.prefs.getBoolPref(aData);
|
||||
break;
|
||||
case debugServerStateChanged:
|
||||
if (Services.prefs.getBoolPref(aData)) {
|
||||
this.runDebugServer();
|
||||
} else {
|
||||
this.stopDebugServer();
|
||||
}
|
||||
break;
|
||||
case debugServerPortChanged:
|
||||
this.changeDebugPort(Services.prefs.getIntPref(aData));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "metro_viewstate_changed":
|
||||
|
@ -1361,12 +1413,6 @@ var StartUI = {
|
|||
section.init();
|
||||
});
|
||||
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
DebuggerServer.addActors('chrome://browser/content/dbg-metro-actors.js');
|
||||
}
|
||||
DebuggerServer.openListener(6000);
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
|
|
|
@ -9,8 +9,4 @@ VPATH = @srcdir@
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/config.mk
|
||||
EXTRA_JS_MODULES = \
|
||||
colorUtils.jsm \
|
||||
CrossSlide.jsm \
|
||||
$(NULL)
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -4,3 +4,8 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'CrossSlide.jsm',
|
||||
'colorUtils.jsm',
|
||||
]
|
||||
|
||||
|
|
|
@ -413,13 +413,6 @@ pref("app.update.enabled", true);
|
|||
// the UI easier to construct.
|
||||
pref("app.update.auto", true);
|
||||
|
||||
// Defines how the Application Update Service notifies the user about updates:
|
||||
//
|
||||
// AUM Set to: Minor Releases: Major Releases:
|
||||
// 0 download no prompt download no prompt
|
||||
// 1 download no prompt download no prompt if no incompatibilities
|
||||
// 2 download no prompt prompt
|
||||
//
|
||||
// See chart in nsUpdateService.js source for more details
|
||||
pref("app.update.mode", 0);
|
||||
|
||||
|
|
|
@ -185,6 +185,7 @@ menulist {
|
|||
|
||||
.menu-popup > richlistbox > scrollbox {
|
||||
width: 100%;
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
.menu-popup richlistitem {
|
||||
|
|
|
@ -11,32 +11,11 @@ include $(DEPTH)/config/autoconf.mk
|
|||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
BrowserNewTabPreloader.jsm \
|
||||
openLocationLastURL.jsm \
|
||||
NetworkPrioritizer.jsm \
|
||||
offlineAppCache.jsm \
|
||||
SignInToWebsite.jsm \
|
||||
SitePermissions.jsm \
|
||||
webappsUI.jsm \
|
||||
webrtcUI.jsm \
|
||||
Social.jsm \
|
||||
SharedFrame.jsm \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_JS_MODULES = \
|
||||
AboutHomeUtils.jsm \
|
||||
RecentWindow.jsm \
|
||||
$(NULL)
|
||||
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
EXTRA_JS_MODULES += \
|
||||
WindowsJumpLists.jsm \
|
||||
WindowsPreviewPerTab.jsm \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifdef MOZILLA_OFFICIAL
|
||||
DEFINES += -DMOZILLA_OFFICIAL=1
|
||||
endif
|
||||
|
|
|
@ -6,3 +6,21 @@
|
|||
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'BrowserNewTabPreloader.jsm',
|
||||
'NetworkPrioritizer.jsm',
|
||||
'SharedFrame.jsm',
|
||||
'SignInToWebsite.jsm',
|
||||
'SitePermissions.jsm',
|
||||
'Social.jsm',
|
||||
'offlineAppCache.jsm',
|
||||
'openLocationLastURL.jsm',
|
||||
'webappsUI.jsm',
|
||||
'webrtcUI.jsm',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
EXTRA_JS_MODULES += [
|
||||
'WindowsJumpLists.jsm',
|
||||
'WindowsPreviewPerTab.jsm',
|
||||
]
|
||||
|
|
|
@ -55,6 +55,7 @@ SEARCH_PATHS = [
|
|||
MACH_MODULES = [
|
||||
'addon-sdk/mach_commands.py',
|
||||
'layout/tools/reftest/mach_commands.py',
|
||||
'python/mach_commands.py',
|
||||
'python/mach/mach/commands/commandinfo.py',
|
||||
'python/mozboot/mozboot/mach_commands.py',
|
||||
'python/mozbuild/mozbuild/config.py',
|
||||
|
|
|
@ -56,6 +56,13 @@ REDIST_FILES = \
|
|||
$(NULL)
|
||||
endif
|
||||
|
||||
ifeq (1800,$(_MSC_VER))
|
||||
REDIST_FILES = \
|
||||
msvcp120.dll \
|
||||
msvcr120.dll \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifdef REDIST_FILES
|
||||
libs-preqs = \
|
||||
$(call mkdir_deps,$(FINAL_TARGET)) \
|
||||
|
|
|
@ -46,7 +46,7 @@ static bool URIIsImmutable(nsIURI* aURI)
|
|||
return
|
||||
mutableObj &&
|
||||
NS_SUCCEEDED(mutableObj->GetMutable(&isMutable)) &&
|
||||
!isMutable;
|
||||
!isMutable;
|
||||
}
|
||||
|
||||
// Static member variables
|
||||
|
@ -344,18 +344,6 @@ nsPrincipal::GetURI(nsIURI** aURI)
|
|||
return NS_EnsureSafeToReturn(mCodebase, aURI);
|
||||
}
|
||||
|
||||
static bool
|
||||
URIIsLocalFile(nsIURI *aURI)
|
||||
{
|
||||
bool isFile;
|
||||
nsCOMPtr<nsINetUtil> util = do_GetNetUtil();
|
||||
|
||||
return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
|
||||
nsIProtocolHandler::URI_IS_LOCAL_FILE,
|
||||
&isFile)) &&
|
||||
isFile;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal)
|
||||
{
|
||||
|
@ -367,88 +355,23 @@ nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrinc
|
|||
}
|
||||
}
|
||||
|
||||
if (!nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) {
|
||||
if (nsScriptSecurityManager::GetStrictFileOriginPolicy() &&
|
||||
URIIsLocalFile(aURI)) {
|
||||
nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(aURI));
|
||||
|
||||
if (!URIIsLocalFile(mCodebase)) {
|
||||
// If the codebase is not also a file: uri then forget it
|
||||
// (don't want resource: principals in a file: doc)
|
||||
//
|
||||
// note: we're not de-nesting jar: uris here, we want to
|
||||
// keep archive content bottled up in its own little island
|
||||
|
||||
if (aReport) {
|
||||
nsScriptSecurityManager::ReportError(
|
||||
nullptr, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
|
||||
}
|
||||
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
//
|
||||
// pull out the internal files
|
||||
//
|
||||
nsCOMPtr<nsIFileURL> codebaseFileURL(do_QueryInterface(mCodebase));
|
||||
nsCOMPtr<nsIFile> targetFile;
|
||||
nsCOMPtr<nsIFile> codebaseFile;
|
||||
bool targetIsDir;
|
||||
|
||||
// Make sure targetFile is not a directory (bug 209234)
|
||||
// and that it exists w/out unescaping (bug 395343)
|
||||
|
||||
if (!codebaseFileURL || !fileURL ||
|
||||
NS_FAILED(fileURL->GetFile(getter_AddRefs(targetFile))) ||
|
||||
NS_FAILED(codebaseFileURL->GetFile(getter_AddRefs(codebaseFile))) ||
|
||||
!targetFile || !codebaseFile ||
|
||||
NS_FAILED(targetFile->Normalize()) ||
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
NS_FAILED(codebaseFile->Normalize()) ||
|
||||
#endif
|
||||
NS_FAILED(targetFile->IsDirectory(&targetIsDir)) ||
|
||||
targetIsDir) {
|
||||
if (aReport) {
|
||||
nsScriptSecurityManager::ReportError(
|
||||
nullptr, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
|
||||
}
|
||||
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
//
|
||||
// If the file to be loaded is in a subdirectory of the codebase
|
||||
// (or same-dir if codebase is not a directory) then it will
|
||||
// inherit its codebase principal and be scriptable by that codebase.
|
||||
//
|
||||
bool codebaseIsDir;
|
||||
bool contained = false;
|
||||
nsresult rv = codebaseFile->IsDirectory(&codebaseIsDir);
|
||||
if (NS_SUCCEEDED(rv) && codebaseIsDir) {
|
||||
rv = codebaseFile->Contains(targetFile, true, &contained);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIFile> codebaseParent;
|
||||
rv = codebaseFile->GetParent(getter_AddRefs(codebaseParent));
|
||||
if (NS_SUCCEEDED(rv) && codebaseParent) {
|
||||
rv = codebaseParent->Contains(targetFile, true, &contained);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && contained) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (aReport) {
|
||||
nsScriptSecurityManager::ReportError(
|
||||
nullptr, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
|
||||
}
|
||||
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
if (nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
// If strict file origin policy is in effect, local files will always fail
|
||||
// SecurityCompareURIs unless they are identical. Explicitly check file origin
|
||||
// policy, in that case.
|
||||
if (nsScriptSecurityManager::GetStrictFileOriginPolicy() &&
|
||||
NS_URIIsLocalFile(aURI) &&
|
||||
NS_RelaxStrictFileOriginPolicy(aURI, mCodebase)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aReport) {
|
||||
nsScriptSecurityManager::ReportError(nullptr, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
|
||||
}
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -562,7 +485,7 @@ NS_IMETHODIMP
|
|||
nsPrincipal::GetBaseDomain(nsACString& aBaseDomain)
|
||||
{
|
||||
// For a file URI, we return the file path.
|
||||
if (URIIsLocalFile(mCodebase)) {
|
||||
if (NS_URIIsLocalFile(mCodebase)) {
|
||||
nsCOMPtr<nsIURL> url = do_QueryInterface(mCodebase);
|
||||
|
||||
if (url) {
|
||||
|
|
|
@ -22,10 +22,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=758258
|
|||
|
||||
var Ci = Components.interfaces;
|
||||
|
||||
if (navigator.platform.startsWith("Linux")) {
|
||||
SimpleTest.expectAssertions(2, 4);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/*
|
||||
|
|
|
@ -58,7 +58,6 @@ endif
|
|||
|
||||
HEADERS_FILES = \
|
||||
$(DEPTH)/mozilla-config.h \
|
||||
$(srcdir)/nsStaticComponents.h \
|
||||
$(NULL)
|
||||
HEADERS_DEST := $(DIST)/include
|
||||
HEADERS_TARGET := export
|
||||
|
|
|
@ -239,9 +239,7 @@ _ENABLE_PIC=1
|
|||
|
||||
ifdef LIBXUL_LIBRARY
|
||||
ifdef IS_COMPONENT
|
||||
ifdef MODULE_NAME
|
||||
DEFINES += -DXPCOM_TRANSLATE_NSGM_ENTRY_POINT=1
|
||||
else
|
||||
ifndef MODULE_NAME
|
||||
$(error Component makefile does not specify MODULE_NAME.)
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
#line 2 "nsStaticComponents.cpp.in"
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#define XPCOM_TRANSLATE_NSGM_ENTRY_POINT 1
|
||||
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsStaticComponents.h"
|
||||
|
||||
/**
|
||||
* Declare an NSGetModule() routine for a generic module.
|
||||
*/
|
||||
#define MODULE(_name) \
|
||||
NSMODULE_DECL(_name);
|
||||
|
||||
%MODULE_LIST%
|
||||
#line 57 "nsStaticComponents.cpp.in"
|
||||
|
||||
#undef MODULE
|
||||
|
||||
|
||||
#define MODULE(_name) \
|
||||
&NSMODULE_NAME(_name),
|
||||
|
||||
/**
|
||||
* The nsStaticModuleInfo
|
||||
*/
|
||||
const mozilla::Module *const *const kPStaticModules[] = {
|
||||
%MODULE_LIST%
|
||||
#line 70 "nsStaticComponents.cpp.in"
|
||||
NULL
|
||||
};
|
|
@ -1,15 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsStaticComponents_h__
|
||||
#define nsStaticComponents_h__
|
||||
|
||||
#include "mozilla/Module.h"
|
||||
|
||||
// These symbols are provided by nsStaticComponents.cpp, and also by other
|
||||
// static component providers such as nsStaticXULComponents (libxul).
|
||||
|
||||
extern mozilla::Module const *const *const kPStaticModules[];
|
||||
|
||||
#endif
|
10
configure.in
10
configure.in
|
@ -487,16 +487,18 @@ case "$target" in
|
|||
AC_MSG_ERROR([The major versions of \$CC and \$CXX do not match.])
|
||||
fi
|
||||
|
||||
AC_DEFINE(_CRT_SECURE_NO_WARNINGS)
|
||||
AC_DEFINE(_CRT_NONSTDC_NO_WARNINGS)
|
||||
|
||||
if test "$_CC_MAJOR_VERSION" = "16"; then
|
||||
_CC_SUITE=10
|
||||
_MSVS_VERSION=2010
|
||||
AC_DEFINE(_CRT_SECURE_NO_WARNINGS)
|
||||
AC_DEFINE(_CRT_NONSTDC_NO_WARNINGS)
|
||||
elif test "$_CC_MAJOR_VERSION" = "17"; then
|
||||
_CC_SUITE=11
|
||||
_MSVS_VERSION=2012
|
||||
AC_DEFINE(_CRT_SECURE_NO_WARNINGS)
|
||||
AC_DEFINE(_CRT_NONSTDC_NO_WARNINGS)
|
||||
elif test "$_CC_MAJOR_VERSION" = "18"; then
|
||||
_CC_SUITE=12
|
||||
_MSVS_VERSION=2013
|
||||
else
|
||||
AC_MSG_ERROR([This version ($CC_VERSION) of the MSVC compiler is unsupported. See https://developer.mozilla.org/en/Windows_Build_Prerequisites.])
|
||||
fi
|
||||
|
|
|
@ -12,12 +12,19 @@
|
|||
|
||||
#define BLOBURI_SCHEME "blob"
|
||||
#define MEDIASTREAMURI_SCHEME "mediastream"
|
||||
#define MEDIASOURCEURI_SCHEME "mediasource"
|
||||
|
||||
class nsIDOMBlob;
|
||||
class nsIDOMMediaStream;
|
||||
class nsIPrincipal;
|
||||
class nsIInputStream;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class MediaSource;
|
||||
}
|
||||
}
|
||||
|
||||
class nsHostObjectProtocolHandler : public nsIProtocolHandler
|
||||
{
|
||||
public:
|
||||
|
@ -55,6 +62,12 @@ public:
|
|||
NS_IMETHOD GetScheme(nsACString &result) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
class nsMediaSourceProtocolHandler : public nsHostObjectProtocolHandler
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD GetScheme(nsACString &result) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
inline bool IsBlobURI(nsIURI* aUri)
|
||||
{
|
||||
bool isBlob;
|
||||
|
@ -67,12 +80,21 @@ inline bool IsMediaStreamURI(nsIURI* aUri)
|
|||
return NS_SUCCEEDED(aUri->SchemeIs(MEDIASTREAMURI_SCHEME, &isStream)) && isStream;
|
||||
}
|
||||
|
||||
inline bool IsMediaSourceURI(nsIURI* aUri)
|
||||
{
|
||||
bool isMediaSource;
|
||||
return NS_SUCCEEDED(aUri->SchemeIs(MEDIASOURCEURI_SCHEME, &isMediaSource)) && isMediaSource;
|
||||
}
|
||||
|
||||
extern nsresult
|
||||
NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream);
|
||||
|
||||
extern nsresult
|
||||
NS_GetStreamForMediaStreamURI(nsIURI* aURI, nsIDOMMediaStream** aStream);
|
||||
|
||||
extern nsresult
|
||||
NS_GetSourceForMediaSourceURI(nsIURI* aURI, mozilla::dom::MediaSource** aSource);
|
||||
|
||||
#define NS_BLOBPROTOCOLHANDLER_CID \
|
||||
{ 0xb43964aa, 0xa078, 0x44b2, \
|
||||
{ 0xb0, 0x6b, 0xfd, 0x4d, 0x1b, 0x17, 0x2e, 0x66 } }
|
||||
|
@ -81,4 +103,8 @@ NS_GetStreamForMediaStreamURI(nsIURI* aURI, nsIDOMMediaStream** aStream);
|
|||
{ 0x27d1fa24, 0x2b73, 0x4db3, \
|
||||
{ 0xab, 0x48, 0xb9, 0x83, 0x83, 0x40, 0xe0, 0x81 } }
|
||||
|
||||
#define NS_MEDIASOURCEPROTOCOLHANDLER_CID \
|
||||
{ 0x12ef31fc, 0xa8fb, 0x4661, \
|
||||
{ 0x9a, 0x63, 0xfb, 0x61, 0x04,0x5d, 0xb8, 0x61 } }
|
||||
|
||||
#endif /* nsHostObjectProtocolHandler_h */
|
||||
|
|
|
@ -34,10 +34,6 @@ EXTRA_COMPONENTS = \
|
|||
messageWakeupService.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
CSPUtils.jsm \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -157,3 +157,7 @@ CPP_SOURCES += [
|
|||
EXTRA_PP_COMPONENTS += [
|
||||
'contentSecurityPolicy.js',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'CSPUtils.jsm',
|
||||
]
|
||||
|
|
|
@ -1033,21 +1033,6 @@ nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope,
|
|||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsFrameScriptExecutor::Traverse(nsFrameScriptExecutor *tmp,
|
||||
nsCycleCollectionTraversalCallback &cb)
|
||||
{
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsFrameScriptExecutor::Unlink(nsFrameScriptExecutor* aTmp)
|
||||
{
|
||||
aTmp->mGlobal = nullptr;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsScriptCacheCleaner, nsIObserver)
|
||||
|
||||
nsFrameMessageManager* nsFrameMessageManager::sChildProcessManager = nullptr;
|
||||
|
|
|
@ -289,9 +289,6 @@ protected:
|
|||
void TryCacheLoadAndCompileScript(const nsAString& aURL,
|
||||
CacheFailedBehavior aBehavior = DONT_EXECUTE);
|
||||
bool InitTabChildGlobalInternal(nsISupports* aScope, const nsACString& aID);
|
||||
static void Traverse(nsFrameScriptExecutor *tmp,
|
||||
nsCycleCollectionTraversalCallback &cb);
|
||||
static void Unlink(nsFrameScriptExecutor* aTmp);
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
static nsDataHashtable<nsStringHashKey, nsFrameJSScriptExecutorHolder*>* sCachedScripts;
|
||||
|
|
|
@ -10,12 +10,13 @@
|
|||
#include "nsIPrincipal.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsIDOMMediaStream.h"
|
||||
#include "mozilla/dom/MediaSource.h"
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Hash table
|
||||
struct DataInfo
|
||||
{
|
||||
// mObject must be an nsIDOMBlob or an nsIDOMMediaStream
|
||||
// mObject is expected to be an nsIDOMBlob, nsIDOMMediaStream, or MediaSource
|
||||
nsCOMPtr<nsISupports> mObject;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
};
|
||||
|
@ -183,7 +184,8 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
|||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(info->mObject);
|
||||
if (!blob) {
|
||||
nsCOMPtr<mozilla::dom::MediaSource> mediasource = do_QueryInterface(info->mObject);
|
||||
if (!blob && !mediasource) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
|
@ -197,7 +199,12 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
|||
#endif
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
nsresult rv = blob->GetInternalStream(getter_AddRefs(stream));
|
||||
nsresult rv = NS_OK;
|
||||
if (blob) {
|
||||
rv = blob->GetInternalStream(getter_AddRefs(stream));
|
||||
} else {
|
||||
stream = mediasource->CreateInternalStream();
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
|
@ -209,25 +216,30 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
|||
nsCOMPtr<nsISupports> owner = do_QueryInterface(info->mPrincipal);
|
||||
|
||||
nsString type;
|
||||
rv = blob->GetType(type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(info->mObject);
|
||||
if (file) {
|
||||
nsString filename;
|
||||
rv = file->GetName(filename);
|
||||
if (blob) {
|
||||
rv = blob->GetType(type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
channel->SetContentDispositionFilename(filename);
|
||||
}
|
||||
|
||||
uint64_t size;
|
||||
rv = blob->GetSize(&size);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
uint64_t size;
|
||||
rv = blob->GetSize(&size);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(info->mObject);
|
||||
if (file) {
|
||||
nsString filename;
|
||||
rv = file->GetName(filename);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
channel->SetContentDispositionFilename(filename);
|
||||
}
|
||||
|
||||
channel->SetContentLength(size);
|
||||
} else {
|
||||
type = mediasource->GetType();
|
||||
}
|
||||
|
||||
channel->SetOwner(owner);
|
||||
channel->SetOriginalURI(uri);
|
||||
channel->SetContentType(NS_ConvertUTF16toUTF8(type));
|
||||
channel->SetContentLength(size);
|
||||
|
||||
channel.forget(result);
|
||||
|
||||
|
@ -257,6 +269,13 @@ nsMediaStreamProtocolHandler::GetScheme(nsACString &result)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMediaSourceProtocolHandler::GetScheme(nsACString &result)
|
||||
{
|
||||
result.AssignLiteral(MEDIASOURCEURI_SCHEME);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream)
|
||||
{
|
||||
|
@ -288,3 +307,19 @@ NS_GetStreamForMediaStreamURI(nsIURI* aURI, nsIDOMMediaStream** aStream)
|
|||
NS_ADDREF(*aStream);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_GetSourceForMediaSourceURI(nsIURI* aURI, mozilla::dom::MediaSource** aSource)
|
||||
{
|
||||
NS_ASSERTION(IsMediaSourceURI(aURI), "Only call this with mediasource URIs");
|
||||
|
||||
*aSource = nullptr;
|
||||
|
||||
nsCOMPtr<mozilla::dom::MediaSource> source = do_QueryInterface(GetDataObject(aURI));
|
||||
if (!source) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
source.forget(aSource);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -14,8 +14,9 @@
|
|||
#include "nsSimpleURI.h"
|
||||
|
||||
/**
|
||||
* These URIs refer to host objects: Blobs, with scheme "blob", and
|
||||
* MediaStreams, with scheme "mediastream".
|
||||
* These URIs refer to host objects: Blobs, with scheme "blob",
|
||||
* MediaStreams, with scheme "mediastream", and MediaSources, with scheme
|
||||
* "mediasource".
|
||||
*/
|
||||
class nsHostObjectURI : public nsSimpleURI,
|
||||
public nsIURIWithPrincipal
|
||||
|
|
|
@ -144,18 +144,10 @@ nsInProcessTabChildGlobal::Init()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsInProcessTabChildGlobal,
|
||||
nsDOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
|
||||
nsFrameScriptExecutor::Unlink(tmp);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsInProcessTabChildGlobal,
|
||||
nsDOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
|
||||
nsFrameScriptExecutor::Traverse(tmp, cb);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_2(nsInProcessTabChildGlobal,
|
||||
nsDOMEventTargetHelper,
|
||||
mMessageManager,
|
||||
mGlobal)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsInProcessTabChildGlobal)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
|
||||
|
|
|
@ -218,7 +218,8 @@ nsNodeUtils::LastRelease(nsINode* aNode)
|
|||
static_cast<nsGenericHTMLFormElement*>(aNode)->ClearForm(true);
|
||||
}
|
||||
|
||||
if (aNode->IsElement() && aNode->AsElement()->IsHTML(nsGkAtoms::img)) {
|
||||
if (aNode->IsElement() && aNode->AsElement()->IsHTML(nsGkAtoms::img) &&
|
||||
aNode->HasFlag(ADDED_TO_FORM)) {
|
||||
HTMLImageElement* imageElem = static_cast<HTMLImageElement*>(aNode);
|
||||
imageElem->ClearForm(true);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "nsJSNPRuntime.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsScriptSecurityManager.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIStreamConverterService.h"
|
||||
#include "nsIURILoader.h"
|
||||
|
@ -1190,6 +1191,46 @@ nsObjectLoadingContent::ObjectState() const
|
|||
return NS_EVENT_STATE_LOADING;
|
||||
}
|
||||
|
||||
// Returns false if mBaseURI is not acceptable for java applets.
|
||||
bool
|
||||
nsObjectLoadingContent::CheckJavaCodebase()
|
||||
{
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
nsCOMPtr<nsINetUtil> netutil = do_GetNetUtil();
|
||||
NS_ASSERTION(thisContent && secMan && netutil, "expected interfaces");
|
||||
|
||||
|
||||
// Note that mBaseURI is this tag's requested base URI, not the codebase of
|
||||
// the document for security purposes
|
||||
nsresult rv = secMan->CheckLoadURIWithPrincipal(thisContent->NodePrincipal(),
|
||||
mBaseURI, 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("OBJLC [%p]: Java codebase check failed", this));
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> principalBaseURI;
|
||||
rv = thisContent->NodePrincipal()->GetURI(getter_AddRefs(principalBaseURI));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_NOTREACHED("Failed to URI from node principal?");
|
||||
return false;
|
||||
}
|
||||
// We currently allow java's codebase to be non-same-origin, with
|
||||
// the exception of URIs that represent local files
|
||||
if (NS_URIIsLocalFile(mBaseURI) &&
|
||||
nsScriptSecurityManager::GetStrictFileOriginPolicy() &&
|
||||
!NS_RelaxStrictFileOriginPolicy(mBaseURI, principalBaseURI)) {
|
||||
LOG(("OBJLC [%p]: Java failed RelaxStrictFileOriginPolicy for file URI",
|
||||
this));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsObjectLoadingContent::CheckLoadPolicy(int16_t *aContentPolicy)
|
||||
{
|
||||
|
@ -1418,12 +1459,15 @@ nsObjectLoadingContent::UpdateObjectParameters(bool aJavaURI)
|
|||
}
|
||||
|
||||
if (isJava && hasCodebase && codebaseStr.IsEmpty()) {
|
||||
// Java treats an empty codebase as the document codebase, but codebase=""
|
||||
// as "/"
|
||||
// Java treats codebase="" as "/"
|
||||
codebaseStr.AssignLiteral("/");
|
||||
// XXX(johns): This doesn't cover the case of "https:" which java would
|
||||
// interpret as "https:///" but we interpret as this document's
|
||||
// URI but with a changed scheme.
|
||||
} else if (isJava && !hasCodebase) {
|
||||
// Java expects a directory as the codebase, or else it will construct
|
||||
// relative URIs incorrectly :(
|
||||
codebaseStr.AssignLiteral(".");
|
||||
}
|
||||
|
||||
if (!codebaseStr.IsEmpty()) {
|
||||
|
@ -1870,14 +1914,7 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
|||
if (mType != eType_Null) {
|
||||
bool allowLoad = true;
|
||||
if (nsPluginHost::IsJavaMIMEType(mContentType.get())) {
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
rv = secMan->CheckLoadURIWithPrincipal(thisContent->NodePrincipal(),
|
||||
mBaseURI, 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("OBJLC [%p]: Java codebase check failed", this));
|
||||
allowLoad = false;
|
||||
}
|
||||
allowLoad = CheckJavaCodebase();
|
||||
}
|
||||
int16_t contentPolicy = nsIContentPolicy::ACCEPT;
|
||||
// If mChannelLoaded is set we presumably already passed load policy
|
||||
|
|
|
@ -378,6 +378,11 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
*/
|
||||
bool ShouldPlay(FallbackType &aReason, bool aIgnoreCurrentType);
|
||||
|
||||
/*
|
||||
* Helper to check if mBaseURI can be used by java as a codebase
|
||||
*/
|
||||
bool CheckJavaCodebase();
|
||||
|
||||
/**
|
||||
* Helper to check if our current URI passes policy
|
||||
*
|
||||
|
|
|
@ -98,9 +98,14 @@
|
|||
#include "mozilla/dom/TextMetrics.h"
|
||||
|
||||
#ifdef USE_SKIA_GPU
|
||||
#undef free // apparently defined by some windows header, clashing with a free()
|
||||
// method in SkTypes.h
|
||||
#include "GLContext.h"
|
||||
#include "GLContextProvider.h"
|
||||
#include "GLContextSkia.h"
|
||||
#include "SurfaceTypes.h"
|
||||
using mozilla::gl::GLContext;
|
||||
using mozilla::gl::GLContextProvider;
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
@ -440,15 +445,20 @@ public:
|
|||
CanvasRenderingContext2DUserData* self =
|
||||
static_cast<CanvasRenderingContext2DUserData*>(aData);
|
||||
CanvasRenderingContext2D* context = self->mContext;
|
||||
if (self->mContext && context->mGLContext) {
|
||||
if (self->mContext->mTarget != nullptr) {
|
||||
// Since SkiaGL default to store drawing command until flush
|
||||
// We will have to flush it before present.
|
||||
self->mContext->mTarget->Flush();
|
||||
}
|
||||
context->mGLContext->MakeCurrent();
|
||||
context->mGLContext->PublishFrame();
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
GLContext* glContext = static_cast<GLContext*>(context->mTarget->GetGLContext());
|
||||
if (!glContext)
|
||||
return;
|
||||
|
||||
if (context->mTarget) {
|
||||
// Since SkiaGL default to store drawing command until flush
|
||||
// We will have to flush it before present.
|
||||
context->mTarget->Flush();
|
||||
}
|
||||
glContext->MakeCurrent();
|
||||
glContext->PublishFrame();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -547,6 +557,10 @@ CanvasRenderingContext2D::CanvasRenderingContext2D()
|
|||
{
|
||||
sNumLivingContexts++;
|
||||
SetIsDOMBinding();
|
||||
|
||||
#if USE_SKIA_GPU
|
||||
mForceSoftware = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
CanvasRenderingContext2D::~CanvasRenderingContext2D()
|
||||
|
@ -560,6 +574,12 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D()
|
|||
if (!sNumLivingContexts) {
|
||||
NS_IF_RELEASE(sErrorTarget);
|
||||
}
|
||||
|
||||
#if USE_SKIA_GPU
|
||||
std::vector<CanvasRenderingContext2D*>::iterator iter = std::find(DemotableContexts().begin(), DemotableContexts().end(), this);
|
||||
if (iter != DemotableContexts().end())
|
||||
DemotableContexts().erase(iter);
|
||||
#endif
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -757,6 +777,62 @@ CanvasRenderingContext2D::RedrawUser(const gfxRect& r)
|
|||
Redraw(newr);
|
||||
}
|
||||
|
||||
#if USE_SKIA_GPU
|
||||
|
||||
void CanvasRenderingContext2D::Demote()
|
||||
{
|
||||
if (!IsTargetValid() || mForceSoftware)
|
||||
return;
|
||||
|
||||
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
|
||||
RefPtr<DrawTarget> oldTarget = mTarget;
|
||||
mTarget = nullptr;
|
||||
mForceSoftware = true;
|
||||
|
||||
// Recreate target, now demoted to software only
|
||||
EnsureTarget();
|
||||
if (!IsTargetValid())
|
||||
return;
|
||||
|
||||
// Put back the content from the old DrawTarget
|
||||
mgfx::Rect r(0, 0, mWidth, mHeight);
|
||||
mTarget->DrawSurface(snapshot, r, r);
|
||||
}
|
||||
|
||||
std::vector<CanvasRenderingContext2D*>&
|
||||
CanvasRenderingContext2D::DemotableContexts()
|
||||
{
|
||||
static std::vector<CanvasRenderingContext2D*> contexts;
|
||||
return contexts;
|
||||
}
|
||||
|
||||
void
|
||||
CanvasRenderingContext2D::DemoteOldestContextIfNecessary()
|
||||
{
|
||||
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
|
||||
const size_t kMaxContexts = 2;
|
||||
#else
|
||||
const size_t kMaxContexts = 16;
|
||||
#endif
|
||||
|
||||
std::vector<CanvasRenderingContext2D*>& contexts = DemotableContexts();
|
||||
if (contexts.size() < kMaxContexts)
|
||||
return;
|
||||
|
||||
CanvasRenderingContext2D* oldest = contexts.front();
|
||||
contexts.erase(contexts.begin());
|
||||
|
||||
oldest->Demote();
|
||||
}
|
||||
|
||||
void
|
||||
CanvasRenderingContext2D::AddDemotableContext(CanvasRenderingContext2D* context)
|
||||
{
|
||||
DemotableContexts().push_back(context);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
CanvasRenderingContext2D::EnsureTarget()
|
||||
{
|
||||
|
@ -794,19 +870,25 @@ CanvasRenderingContext2D::EnsureTarget()
|
|||
}
|
||||
#endif
|
||||
|
||||
mGLContext = mozilla::gl::GLContextProvider::CreateOffscreen(gfxIntSize(size.width,
|
||||
size.height),
|
||||
caps,
|
||||
mozilla::gl::GLContext::ContextFlagsNone);
|
||||
DemoteOldestContextIfNecessary();
|
||||
|
||||
if (mGLContext) {
|
||||
mTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForFBO(0, mGLContext, size, format);
|
||||
nsRefPtr<GLContext> glContext;
|
||||
|
||||
if (!mForceSoftware) {
|
||||
glContext = GLContextProvider::CreateOffscreen(gfxIntSize(size.width, size.height),
|
||||
caps, GLContext::ContextFlagsNone);
|
||||
}
|
||||
|
||||
if (glContext) {
|
||||
SkAutoTUnref<GrGLInterface> i(CreateGrGLInterfaceFromGLContext(glContext));
|
||||
mTarget = Factory::CreateDrawTargetSkiaWithGLContextAndGrGLInterface(glContext, i, size, format);
|
||||
AddDemotableContext(this);
|
||||
} else {
|
||||
mTarget = layerManager->CreateDrawTarget(size, format);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
mTarget = layerManager->CreateDrawTarget(size, format);
|
||||
mTarget = layerManager->CreateDrawTarget(size, format);
|
||||
} else {
|
||||
mTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(size, format);
|
||||
}
|
||||
|
@ -891,6 +973,7 @@ CanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *shell,
|
|||
SetDimensions(width, height);
|
||||
mTarget = gfxPlatform::GetPlatform()->
|
||||
CreateDrawTargetForSurface(surface, IntSize(width, height));
|
||||
|
||||
if (!mTarget) {
|
||||
EnsureErrorTarget();
|
||||
mTarget = sErrorTarget;
|
||||
|
@ -3823,10 +3906,11 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
CanvasLayer::Data data;
|
||||
#ifdef USE_SKIA_GPU
|
||||
if (mGLContext) {
|
||||
GLContext* glContext = static_cast<GLContext*>(mTarget->GetGLContext());
|
||||
if (glContext) {
|
||||
canvasLayer->SetPreTransactionCallback(
|
||||
CanvasRenderingContext2DUserData::PreTransactionCallback, userData);
|
||||
data.mGLContext = mGLContext;
|
||||
data.mGLContext = glContext;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
|
|
@ -556,6 +556,19 @@ protected:
|
|||
return CurrentState().font;
|
||||
}
|
||||
|
||||
#if USE_SKIA_GPU
|
||||
|
||||
// Recreate the DrawTarget in software mode
|
||||
void Demote();
|
||||
|
||||
static std::vector<CanvasRenderingContext2D*>& DemotableContexts();
|
||||
static void DemoteOldestContextIfNecessary();
|
||||
static void AddDemotableContext(CanvasRenderingContext2D* context);
|
||||
|
||||
// Do not use GL
|
||||
bool mForceSoftware;
|
||||
#endif
|
||||
|
||||
// Member vars
|
||||
int32_t mWidth, mHeight;
|
||||
|
||||
|
@ -633,11 +646,6 @@ protected:
|
|||
uint32_t mInvalidateCount;
|
||||
static const uint32_t kCanvasMaxInvalidateCount = 100;
|
||||
|
||||
|
||||
#ifdef USE_SKIA_GPU
|
||||
nsRefPtr<gl::GLContext> mGLContext;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns true if a shadow should be drawn along with a
|
||||
* drawing operation.
|
||||
|
|
|
@ -1007,22 +1007,12 @@ WebGLContext::InitAndValidateGL()
|
|||
// specifically enabled on desktop GLSL.
|
||||
gl->fEnable(LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||
|
||||
// we don't do the following glEnable(GL_POINT_SPRITE) on ATI cards on Windows, because bug 602183 shows that it causes
|
||||
// crashes in the ATI/Windows driver; and point sprites on ATI seem like a lost cause anyway, see
|
||||
// http://www.gamedev.net/community/forums/topic.asp?topic_id=525643
|
||||
// Also, if the ATI/Windows driver implements a recent GL spec version, this shouldn't be needed anyway.
|
||||
#ifdef XP_WIN
|
||||
if (!(gl->WorkAroundDriverBugs() &&
|
||||
gl->Vendor() == gl::GLContext::VendorATI))
|
||||
#else
|
||||
if (true)
|
||||
#endif
|
||||
{
|
||||
// gl_PointCoord is always available in ES2 GLSL and in newer desktop GLSL versions, but apparently
|
||||
// not in OpenGL 2 and apparently not (due to a driver bug) on certain NVIDIA setups. See:
|
||||
// http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=261472
|
||||
gl->fEnable(LOCAL_GL_POINT_SPRITE);
|
||||
}
|
||||
// gl_PointCoord is always available in ES2 GLSL and in newer desktop GLSL versions, but apparently
|
||||
// not in OpenGL 2 and apparently not (due to a driver bug) on certain NVIDIA setups. See:
|
||||
// http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=261472
|
||||
// Note that this used to cause crashes on old ATI drivers... hopefully not a significant
|
||||
// problem anymore. See bug 602183.
|
||||
gl->fEnable(LOCAL_GL_POINT_SPRITE);
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
|
|
|
@ -40,40 +40,14 @@ MOCHITEST_FILES = \
|
|||
test_2d.composite.canvas.destination-in.html \
|
||||
test_2d.composite.canvas.source-in.html \
|
||||
test_2d.composite.canvas.source-out.html \
|
||||
test_2d.composite.canvas.multiply.html \
|
||||
test_2d.composite.canvas.screen.html \
|
||||
test_2d.composite.canvas.overlay.html \
|
||||
test_2d.composite.canvas.darken.html \
|
||||
test_2d.composite.canvas.lighten.html \
|
||||
test_2d.composite.canvas.color-dodge.html \
|
||||
test_2d.composite.canvas.color-burn.html \
|
||||
test_2d.composite.canvas.hard-light.html \
|
||||
test_2d.composite.canvas.soft-light.html \
|
||||
test_2d.composite.canvas.difference.html \
|
||||
test_2d.composite.canvas.exclusion.html \
|
||||
test_2d.composite.canvas.hue.html \
|
||||
test_2d.composite.canvas.saturation.html \
|
||||
test_2d.composite.canvas.color.html \
|
||||
test_2d.composite.canvas.luminosity.html \
|
||||
test_2d.composite.image.destination-atop.html \
|
||||
test_2d.composite.image.destination-in.html \
|
||||
test_2d.composite.image.source-in.html \
|
||||
test_2d.composite.image.source-out.html \
|
||||
test_2d.composite.solid.multiply.html \
|
||||
test_2d.composite.solid.screen.html \
|
||||
test_2d.composite.solid.overlay.html \
|
||||
test_2d.composite.solid.darken.html \
|
||||
test_2d.composite.solid.lighten.html \
|
||||
test_2d.composite.solid.color-dodge.html \
|
||||
test_2d.composite.solid.color-burn.html \
|
||||
test_2d.composite.solid.hard-light.html \
|
||||
test_2d.composite.solid.soft-light.html \
|
||||
test_2d.composite.solid.difference.html \
|
||||
test_2d.composite.solid.exclusion.html \
|
||||
test_2d.composite.solid.hue.html \
|
||||
test_2d.composite.solid.saturation.html \
|
||||
test_2d.composite.solid.color.html \
|
||||
test_2d.composite.solid.luminosity.html \
|
||||
test_2d.composite.uncovered.image.destination-in.html \
|
||||
test_2d.composite.uncovered.image.source-in.html \
|
||||
test_2d.composite.uncovered.image.source-out.html \
|
||||
|
@ -109,11 +83,48 @@ MOCHITEST_FILES = \
|
|||
test_bug866575.html \
|
||||
test_drawImage_edge_cases.html \
|
||||
test_drawImage_document_domain.html \
|
||||
test_mozDashOffset.html \
|
||||
test_mozDashOffset.html \
|
||||
file_drawImage_document_domain.html \
|
||||
test_windingRuleUndefined.html \
|
||||
$(NULL)
|
||||
|
||||
ifneq ($(MOZ_WIDGET_TOOLKIT), android)
|
||||
ifneq ($(MOZ_WIDGET_TOOLKIT), gonk)
|
||||
|
||||
# SkiaGL on Android/Gonk does not implement these composite ops yet
|
||||
|
||||
MOCHITEST_FILES += \
|
||||
test_2d.composite.canvas.color-burn.html \
|
||||
test_2d.composite.canvas.color-dodge.html \
|
||||
test_2d.composite.canvas.darken.html \
|
||||
test_2d.composite.canvas.difference.html \
|
||||
test_2d.composite.canvas.exclusion.html \
|
||||
test_2d.composite.canvas.hue.html \
|
||||
test_2d.composite.canvas.lighten.html \
|
||||
test_2d.composite.canvas.luminosity.html \
|
||||
test_2d.composite.canvas.multiply.html \
|
||||
test_2d.composite.canvas.overlay.html \
|
||||
test_2d.composite.canvas.saturation.html \
|
||||
test_2d.composite.canvas.screen.html \
|
||||
test_2d.composite.solid.color-burn.html \
|
||||
test_2d.composite.solid.color-dodge.html \
|
||||
test_2d.composite.solid.color.html \
|
||||
test_2d.composite.solid.darken.html \
|
||||
test_2d.composite.solid.difference.html \
|
||||
test_2d.composite.solid.exclusion.html \
|
||||
test_2d.composite.solid.hue.html \
|
||||
test_2d.composite.solid.lighten.html \
|
||||
test_2d.composite.solid.luminosity.html \
|
||||
test_2d.composite.solid.multiply.html \
|
||||
test_2d.composite.solid.overlay.html \
|
||||
test_2d.composite.solid.saturation.html \
|
||||
test_2d.composite.solid.screen.html \
|
||||
test_2d.composite.solid.soft-light.html \
|
||||
$(NULL)
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (1_Linux,$(MOZ_SUITE)_$(OS_ARCH))
|
||||
# This test fails in Suite on Linux for some reason, disable it there
|
||||
MOCHITEST_FILES += test_2d.composite.uncovered.image.destination-atop.html
|
||||
|
@ -140,8 +151,11 @@ MOCHITEST_FILES += \
|
|||
test_2d.line.join.parallel.html \
|
||||
$(NULL)
|
||||
|
||||
ifneq ($(MOZ_WIDGET_TOOLKIT), android)
|
||||
ifneq ($(MOZ_WIDGET_TOOLKIT), gonk)
|
||||
# This is an issue with Quartz's handling of radial gradients and some numeric
|
||||
# imprecision that results in errors here.
|
||||
# imprecision that results in errors here. SkiaGL (on Android/Gonk) also has
|
||||
# a similar problem.
|
||||
MOCHITEST_FILES += \
|
||||
test_2d.gradient.radial.inside2.html \
|
||||
test_2d.gradient.radial.inside3.html \
|
||||
|
@ -149,6 +163,8 @@ MOCHITEST_FILES += \
|
|||
test_2d.gradient.radial.cone.front.html \
|
||||
test_2d.gradient.radial.cone.top.html \
|
||||
$(NULL)
|
||||
endif
|
||||
endif
|
||||
|
||||
# This is another Quartz bug -- closed paths that don't lie fully within the
|
||||
# destination bounds seem to have problems with the BEVEL/SQUARE join/cap combo.
|
||||
|
|
|
@ -51,6 +51,17 @@ function IsAzureSkia() {
|
|||
return enabled;
|
||||
}
|
||||
|
||||
function IsAcceleratedSkia() {
|
||||
var enabled = false;
|
||||
|
||||
try {
|
||||
var props = Cc["@mozilla.org/gfx/info;1"].getService(SpecialPowers.Ci.nsIGfxInfo).getInfo();
|
||||
enabled = props.AzureCanvasBackend == "skia" && props.AzureSkiaAccelerated;
|
||||
} catch(e) { }
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
function IsAzureCairo() {
|
||||
var enabled = false;
|
||||
|
||||
|
@ -6641,6 +6652,9 @@ isPixel(ctx, 98,48, 0,255,0,255, 0);
|
|||
|
||||
function test_2d_gradient_radial_inside1() {
|
||||
|
||||
if (IsAcceleratedSkia())
|
||||
return;
|
||||
|
||||
var canvas = document.getElementById('c240');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace mozilla {
|
|||
namespace dom {
|
||||
|
||||
class MediaError;
|
||||
class MediaSource;
|
||||
|
||||
class HTMLMediaElement : public nsGenericHTMLElement,
|
||||
public nsIObserver,
|
||||
|
@ -867,6 +868,9 @@ protected:
|
|||
// Holds a reference to the MediaStreamListener attached to mSrcStream.
|
||||
nsRefPtr<StreamListener> mSrcStreamListener;
|
||||
|
||||
// Holds a reference to the MediaSource supplying data for playback.
|
||||
nsRefPtr<MediaSource> mMediaSource;
|
||||
|
||||
// Holds a reference to the first channel we open to the media resource.
|
||||
// Once the decoder is created, control over the channel passes to the
|
||||
// decoder, and we null out this reference. We must store this in case
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "nsIDOMHTMLVideoElement.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/dom/VideoPlaybackQuality.h"
|
||||
#include "nsPerformance.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -114,6 +116,8 @@ public:
|
|||
|
||||
void NotifyOwnerDocumentActivityChanged() MOZ_OVERRIDE;
|
||||
|
||||
already_AddRefed<dom::VideoPlaybackQuality> VideoPlaybackQuality();
|
||||
|
||||
protected:
|
||||
virtual JSObject* WrapNode(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#include "MediaStreamGraph.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsHostObjectProtocolHandler.h"
|
||||
#include "mozilla/dom/MediaSource.h"
|
||||
#include "MediaMetadataManager.h"
|
||||
|
||||
#include "AudioChannelService.h"
|
||||
|
@ -402,6 +403,7 @@ NS_IMPL_ADDREF_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
|
|||
NS_IMPL_RELEASE_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaSource)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSrcStream)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSrcAttrStream)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourcePointer)
|
||||
|
@ -423,6 +425,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLE
|
|||
tmp->EndSrcMediaStreamPlayback();
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSrcAttrStream)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaSource)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourcePointer)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoadBlockedDoc)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourceLoadCandidate)
|
||||
|
@ -590,6 +593,10 @@ void HTMLMediaElement::AbortExistingLoads()
|
|||
if (mSrcStream) {
|
||||
EndSrcMediaStreamPlayback();
|
||||
}
|
||||
if (mMediaSource) {
|
||||
mMediaSource->DetachElement();
|
||||
mMediaSource = nullptr;
|
||||
}
|
||||
if (mAudioStream) {
|
||||
mAudioStream->Shutdown();
|
||||
mAudioStream = nullptr;
|
||||
|
@ -1111,6 +1118,30 @@ nsresult HTMLMediaElement::LoadResource()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (IsMediaSourceURI(mLoadingSrc)) {
|
||||
nsRefPtr<MediaSource> source;
|
||||
rv = NS_GetSourceForMediaSourceURI(mLoadingSrc, getter_AddRefs(source));
|
||||
if (NS_FAILED(rv)) {
|
||||
nsCString specUTF8;
|
||||
mLoadingSrc->GetSpec(specUTF8);
|
||||
NS_ConvertUTF8toUTF16 spec(specUTF8);
|
||||
const PRUnichar* params[] = { spec.get() };
|
||||
ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params));
|
||||
return rv;
|
||||
}
|
||||
mMediaSource = source.forget();
|
||||
if (!mMediaSource->AttachElement(this)) {
|
||||
// XXX(kinetik): Handle failure: run "If the media data cannot be
|
||||
// fetched at all, due to network errors, causing the user agent to
|
||||
// give up trying to fetch the resource" section of resource fetch
|
||||
// algorithm.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// XXX(kinetik): Bug 881512. Wire this up properly; return from here (as
|
||||
// MediaStreams setup does) rather than relying on mediasource->channel
|
||||
// conversion.
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
|
||||
|
||||
// check for a Content Security Policy to pass down to the channel
|
||||
|
@ -1357,7 +1388,17 @@ already_AddRefed<TimeRanges>
|
|||
HTMLMediaElement::Seekable() const
|
||||
{
|
||||
nsRefPtr<TimeRanges> ranges = new TimeRanges();
|
||||
if (mDecoder && mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING) {
|
||||
if (mMediaSource) {
|
||||
double duration = mMediaSource->Duration();
|
||||
if (IsNaN(duration)) {
|
||||
// Return empty range.
|
||||
} else if (duration > 0 && IsInfinite(duration)) {
|
||||
nsRefPtr<TimeRanges> bufferedRanges = Buffered();
|
||||
ranges->Add(0, bufferedRanges->GetFinalEndTime());
|
||||
} else {
|
||||
ranges->Add(0, duration);
|
||||
}
|
||||
} else if (mDecoder && mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING) {
|
||||
mDecoder->GetSeekable(ranges);
|
||||
}
|
||||
return ranges.forget();
|
||||
|
@ -1942,6 +1983,10 @@ HTMLMediaElement::~HTMLMediaElement()
|
|||
if (mSrcStream) {
|
||||
EndSrcMediaStreamPlayback();
|
||||
}
|
||||
if (mMediaSource) {
|
||||
mMediaSource->DetachElement();
|
||||
mMediaSource = nullptr;
|
||||
}
|
||||
|
||||
NS_ASSERTION(MediaElementTableCount(this, mLoadingSrc) == 0,
|
||||
"Destroyed media element should no longer be in element table");
|
||||
|
@ -3494,7 +3539,9 @@ already_AddRefed<TimeRanges>
|
|||
HTMLMediaElement::Buffered() const
|
||||
{
|
||||
nsRefPtr<TimeRanges> ranges = new TimeRanges();
|
||||
if (mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING && mDecoder) {
|
||||
if (mMediaSource) {
|
||||
mMediaSource->GetBuffered(ranges);
|
||||
} else if (mDecoder && mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING) {
|
||||
// If GetBuffered fails we ignore the error result and just return the
|
||||
// time ranges we found up till the error.
|
||||
mDecoder->GetBuffered(ranges);
|
||||
|
|
|
@ -258,6 +258,33 @@ HTMLVideoElement::NotifyOwnerDocumentActivityChanged()
|
|||
WakeLockUpdate();
|
||||
}
|
||||
|
||||
already_AddRefed<dom::VideoPlaybackQuality>
|
||||
HTMLVideoElement::VideoPlaybackQuality()
|
||||
{
|
||||
nsPIDOMWindow* window = OwnerDoc()->GetInnerWindow();
|
||||
NS_ENSURE_TRUE(window, nullptr);
|
||||
nsPerformance* perf = window->GetPerformance();
|
||||
NS_ENSURE_TRUE(perf, nullptr);
|
||||
DOMHighResTimeStamp creationTime = perf->GetDOMTiming()->TimeStampToDOMHighRes(TimeStamp::Now());
|
||||
|
||||
uint64_t totalFrames = 0;
|
||||
uint64_t droppedFrames = 0;
|
||||
uint64_t corruptedFrames = 0;
|
||||
double playbackJitter = 0.0;
|
||||
if (mDecoder && sVideoStatsEnabled) {
|
||||
MediaDecoder::FrameStatistics& stats = mDecoder->GetFrameStatistics();
|
||||
totalFrames = stats.GetParsedFrames();
|
||||
droppedFrames = totalFrames - stats.GetPresentedFrames();
|
||||
corruptedFrames = totalFrames - stats.GetDecodedFrames();
|
||||
playbackJitter = stats.GetPlaybackJitter();
|
||||
}
|
||||
|
||||
nsRefPtr<dom::VideoPlaybackQuality> playbackQuality =
|
||||
new dom::VideoPlaybackQuality(this, creationTime, totalFrames, droppedFrames,
|
||||
corruptedFrames, playbackJitter);
|
||||
return playbackQuality.forget();
|
||||
}
|
||||
|
||||
void
|
||||
HTMLVideoElement::WakeLockCreate()
|
||||
{
|
||||
|
|
|
@ -818,6 +818,7 @@ public:
|
|||
|
||||
FrameStatistics() :
|
||||
mReentrantMonitor("MediaDecoder::FrameStats"),
|
||||
mPlaybackJitter(0.0),
|
||||
mParsedFrames(0),
|
||||
mDecodedFrames(0),
|
||||
mPresentedFrames(0) {}
|
||||
|
@ -844,6 +845,11 @@ public:
|
|||
return mPresentedFrames;
|
||||
}
|
||||
|
||||
double GetPlaybackJitter() {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
return mPlaybackJitter;
|
||||
}
|
||||
|
||||
// Increments the parsed and decoded frame counters by the passed in counts.
|
||||
// Can be called on any thread.
|
||||
void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) {
|
||||
|
@ -861,11 +867,22 @@ public:
|
|||
++mPresentedFrames;
|
||||
}
|
||||
|
||||
// Tracks the sum of display errors.
|
||||
// Can be called on any thread.
|
||||
void NotifyPlaybackJitter(double aDisplayError) {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
mPlaybackJitter += aDisplayError;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// ReentrantMonitor to protect access of playback statistics.
|
||||
ReentrantMonitor mReentrantMonitor;
|
||||
|
||||
// Sum of display duration error.
|
||||
// Access protected by mStatsReentrantMonitor.
|
||||
double mPlaybackJitter;
|
||||
|
||||
// Number of frames parsed and demuxed from media.
|
||||
// Access protected by mStatsReentrantMonitor.
|
||||
uint32_t mParsedFrames;
|
||||
|
|
|
@ -2535,8 +2535,12 @@ void MediaDecoderStateMachine::AdvanceFrame()
|
|||
ScheduleStateMachine();
|
||||
return;
|
||||
}
|
||||
mDecoder->GetFrameStatistics().NotifyPresentedFrame();
|
||||
MediaDecoder::FrameStatistics& frameStats = mDecoder->GetFrameStatistics();
|
||||
frameStats.NotifyPresentedFrame();
|
||||
remainingTime = currentFrame->mEndTime - clock_time;
|
||||
int64_t frameDuration = currentFrame->mEndTime - currentFrame->mTime;
|
||||
double displayError = fabs(double(frameDuration - remainingTime) / USECS_PER_S);
|
||||
frameStats.NotifyPlaybackJitter(displayError);
|
||||
currentFrame = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "VideoPlaybackQuality.h"
|
||||
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/dom/VideoPlaybackQualityBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "MediaDecoder.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
VideoPlaybackQuality::VideoPlaybackQuality(HTMLMediaElement* aElement,
|
||||
DOMHighResTimeStamp aCreationTime,
|
||||
uint64_t aTotalFrames,
|
||||
uint64_t aDroppedFrames,
|
||||
uint64_t aCorruptedFrames,
|
||||
double aPlaybackJitter)
|
||||
: mElement(aElement)
|
||||
, mCreationTime(aCreationTime)
|
||||
, mTotalFrames(aTotalFrames)
|
||||
, mDroppedFrames(aDroppedFrames)
|
||||
, mCorruptedFrames(aCorruptedFrames)
|
||||
, mPlaybackJitter(aPlaybackJitter)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
HTMLMediaElement*
|
||||
VideoPlaybackQuality::GetParentObject() const
|
||||
{
|
||||
return mElement;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
VideoPlaybackQuality::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aScope)
|
||||
{
|
||||
return VideoPlaybackQualityBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VideoPlaybackQuality, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VideoPlaybackQuality, Release)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(VideoPlaybackQuality, mElement)
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_VideoPlaybackQuality_h_
|
||||
#define mozilla_dom_VideoPlaybackQuality_h_
|
||||
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class VideoPlaybackQuality MOZ_FINAL : public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VideoPlaybackQuality)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VideoPlaybackQuality)
|
||||
|
||||
VideoPlaybackQuality(HTMLMediaElement* aElement, DOMHighResTimeStamp aCreationTime,
|
||||
uint64_t aTotalFrames, uint64_t aDroppedFrames,
|
||||
uint64_t aCorruptedFrames, double aPlaybackJitter);
|
||||
|
||||
HTMLMediaElement* GetParentObject() const;
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
DOMHighResTimeStamp CreationTime() const
|
||||
{
|
||||
return mCreationTime;
|
||||
}
|
||||
|
||||
uint64_t TotalVideoFrames()
|
||||
{
|
||||
return mTotalFrames;
|
||||
}
|
||||
|
||||
uint64_t DroppedVideoFrames()
|
||||
{
|
||||
return mDroppedFrames;
|
||||
}
|
||||
|
||||
uint64_t CorruptedVideoFrames()
|
||||
{
|
||||
return mCorruptedFrames;
|
||||
}
|
||||
|
||||
double PlaybackJitter()
|
||||
{
|
||||
return mPlaybackJitter;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<HTMLMediaElement> mElement;
|
||||
DOMHighResTimeStamp mCreationTime;
|
||||
uint64_t mTotalFrames;
|
||||
uint64_t mDroppedFrames;
|
||||
uint64_t mCorruptedFrames;
|
||||
double mPlaybackJitter;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
#endif /* mozilla_dom_VideoPlaybackQuality_h_ */
|
|
@ -0,0 +1,35 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_ASYNCEVENTRUNNER_H_
|
||||
#define MOZILLA_ASYNCEVENTRUNNER_H_
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template <typename T>
|
||||
class AsyncEventRunnner : public nsRunnable
|
||||
{
|
||||
public:
|
||||
AsyncEventRunnner(T* aTarget, const char* aName)
|
||||
: mTarget(aTarget)
|
||||
, mName(aName)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
mTarget->DispatchSimpleEvent(mName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<T> mTarget;
|
||||
const char* mName;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
#endif /* MOZILLA_ASYNCEVENTRUNNER_H_ */
|
|
@ -0,0 +1,18 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
FAIL_ON_WARNINGS := 1
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
LIBRARY_NAME = gkconmediasource_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,396 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MediaSource.h"
|
||||
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "MediaSourceInputAdapter.h"
|
||||
#include "SourceBuffer.h"
|
||||
#include "SourceBufferList.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo* gMediaSourceLog;
|
||||
#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
|
||||
#else
|
||||
#define LOG(type, msg)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
already_AddRefed<nsIInputStream>
|
||||
MediaSource::CreateInternalStream()
|
||||
{
|
||||
nsRefPtr<MediaSourceInputAdapter> adapter = new MediaSourceInputAdapter(this);
|
||||
mAdapters.AppendElement(adapter);
|
||||
return adapter.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<MediaSource>
|
||||
MediaSource::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.Get());
|
||||
if (!window) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<MediaSource> mediaSource = new MediaSource(window);
|
||||
return mediaSource.forget();
|
||||
}
|
||||
|
||||
SourceBufferList*
|
||||
MediaSource::SourceBuffers()
|
||||
{
|
||||
MOZ_ASSERT_IF(mReadyState == MediaSourceReadyState::Closed, mSourceBuffers->IsEmpty());
|
||||
return mSourceBuffers;
|
||||
}
|
||||
|
||||
SourceBufferList*
|
||||
MediaSource::ActiveSourceBuffers()
|
||||
{
|
||||
MOZ_ASSERT_IF(mReadyState == MediaSourceReadyState::Closed, mActiveSourceBuffers->IsEmpty());
|
||||
return mActiveSourceBuffers;
|
||||
}
|
||||
|
||||
MediaSourceReadyState
|
||||
MediaSource::ReadyState()
|
||||
{
|
||||
return mReadyState;
|
||||
}
|
||||
|
||||
double
|
||||
MediaSource::Duration()
|
||||
{
|
||||
if (mReadyState == MediaSourceReadyState::Closed) {
|
||||
return UnspecifiedNaN();
|
||||
}
|
||||
return mDuration;
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::SetDuration(double aDuration, ErrorResult& aRv)
|
||||
{
|
||||
if (aDuration < 0 || IsNaN(aDuration)) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return;
|
||||
}
|
||||
if (mReadyState != MediaSourceReadyState::Open ||
|
||||
mSourceBuffers->AnyUpdating()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
DurationChange(aDuration, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<SourceBuffer>
|
||||
MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv)
|
||||
{
|
||||
if (!IsTypeSupportedInternal(aType, aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
// TODO: Temporary limit until multiple decoders are supported. Bug 881512.
|
||||
if (mSourceBuffers->Length() >= 1) {
|
||||
aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
if (mReadyState != MediaSourceReadyState::Open) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
mContentType = aType;
|
||||
nsRefPtr<SourceBuffer> sourceBuffer = new SourceBuffer(this);
|
||||
mSourceBuffers->Append(sourceBuffer);
|
||||
sourceBuffer->Attach();
|
||||
return sourceBuffer.forget();
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::RemoveSourceBuffer(SourceBuffer& aSourceBuffer, ErrorResult& aRv)
|
||||
{
|
||||
SourceBuffer* sourceBuffer = &aSourceBuffer;
|
||||
if (!mSourceBuffers->Contains(sourceBuffer)) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
return;
|
||||
}
|
||||
if (sourceBuffer->Updating()) {
|
||||
// TODO:
|
||||
// abort stream append loop (if running)
|
||||
// set updating to false
|
||||
// fire "abort" at sourceBuffer
|
||||
// fire "updateend" at sourceBuffer
|
||||
}
|
||||
// TODO:
|
||||
// For all sourceBuffer audioTracks, videoTracks, textTracks:
|
||||
// set sourceBuffer to null
|
||||
// remove sourceBuffer video, audio, text Tracks from MediaElement tracks
|
||||
// remove sourceBuffer video, audio, text Tracks and fire "removetrack" at affected lists
|
||||
// fire "removetrack" at modified MediaElement track lists
|
||||
// If removed enabled/selected, fire "change" at affected MediaElement list.
|
||||
if (mActiveSourceBuffers->Contains(sourceBuffer)) {
|
||||
mActiveSourceBuffers->Remove(sourceBuffer);
|
||||
}
|
||||
mSourceBuffers->Remove(sourceBuffer);
|
||||
sourceBuffer->Detach();
|
||||
// TODO: Free all resources associated with sourceBuffer
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::EndOfStream(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv)
|
||||
{
|
||||
if (mReadyState != MediaSourceReadyState::Open ||
|
||||
mSourceBuffers->AnyUpdating()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
EndOfStreamInternal(aError, aRv);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
MediaSource::IsTypeSupported(const GlobalObject& aGlobal, const nsAString& aType)
|
||||
{
|
||||
ErrorResult unused;
|
||||
return IsTypeSupportedInternal(aType, unused);
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
|
||||
{
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
LOG(PR_LOG_DEBUG, ("%p Append(ArrayBuffer=%u) mData=%u", this, aLength, mData.Length()));
|
||||
mData.AppendElements(aData, aLength);
|
||||
NotifyListeners();
|
||||
}
|
||||
|
||||
bool
|
||||
MediaSource::AttachElement(HTMLMediaElement* aElement)
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("%p Attaching element %p", this, aElement));
|
||||
MOZ_ASSERT(aElement);
|
||||
mElement = aElement;
|
||||
if (mReadyState != MediaSourceReadyState::Closed) {
|
||||
return false;
|
||||
}
|
||||
SetReadyState(MediaSourceReadyState::Open);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::DetachElement()
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("%p Detaching element %p", this, mElement.get()));
|
||||
MOZ_ASSERT(mElement);
|
||||
mElement = nullptr;
|
||||
mDuration = UnspecifiedNaN();
|
||||
mActiveSourceBuffers->Clear();
|
||||
mSourceBuffers->DetachAndClear();
|
||||
SetReadyState(MediaSourceReadyState::Closed);
|
||||
|
||||
for (uint32_t i = 0; i < mAdapters.Length(); ++i) {
|
||||
mAdapters[i]->Close();
|
||||
}
|
||||
mAdapters.Clear();
|
||||
}
|
||||
|
||||
MediaSource::MediaSource(nsPIDOMWindow* aWindow)
|
||||
: nsDOMEventTargetHelper(aWindow)
|
||||
, mDuration(UnspecifiedNaN())
|
||||
, mMonitor("mozilla::dom::MediaSource::mMonitor")
|
||||
, mReadyState(MediaSourceReadyState::Closed)
|
||||
{
|
||||
mSourceBuffers = new SourceBufferList(this);
|
||||
mActiveSourceBuffers = new SourceBufferList(this);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (!gMediaSourceLog) {
|
||||
gMediaSourceLog = PR_NewLogModule("MediaSource");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::SetReadyState(MediaSourceReadyState aState)
|
||||
{
|
||||
MOZ_ASSERT(aState != mReadyState);
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
|
||||
NotifyListeners();
|
||||
|
||||
if ((mReadyState == MediaSourceReadyState::Closed ||
|
||||
mReadyState == MediaSourceReadyState::Ended) &&
|
||||
aState == MediaSourceReadyState::Open) {
|
||||
mReadyState = aState;
|
||||
QueueAsyncSimpleEvent("sourceopen");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mReadyState == MediaSourceReadyState::Open &&
|
||||
aState == MediaSourceReadyState::Ended) {
|
||||
mReadyState = aState;
|
||||
QueueAsyncSimpleEvent("sourceended");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((mReadyState == MediaSourceReadyState::Open ||
|
||||
mReadyState == MediaSourceReadyState::Ended) &&
|
||||
aState == MediaSourceReadyState::Closed) {
|
||||
mReadyState = aState;
|
||||
QueueAsyncSimpleEvent("sourceclose");
|
||||
return;
|
||||
}
|
||||
|
||||
NS_WARNING("Invalid MediaSource readyState transition");
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::GetBuffered(TimeRanges* aRanges)
|
||||
{
|
||||
if (mActiveSourceBuffers->Length() == 0) {
|
||||
return;
|
||||
}
|
||||
// TODO: Implement intersection computation.
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::DispatchSimpleEvent(const char* aName)
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("%p Dispatching event %s to MediaSource", this, aName));
|
||||
DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName));
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::QueueAsyncSimpleEvent(const char* aName)
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("%p Queuing event %s to MediaSource", this, aName));
|
||||
nsCOMPtr<nsIRunnable> event = new AsyncEventRunnner<MediaSource>(this, aName);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::NotifyListeners()
|
||||
{
|
||||
for (uint32_t i = 0; i < mAdapters.Length(); ++i) {
|
||||
mAdapters[i]->NotifyListener();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::DurationChange(double aNewDuration, ErrorResult& aRv)
|
||||
{
|
||||
if (mDuration == aNewDuration) {
|
||||
return;
|
||||
}
|
||||
double oldDuration = mDuration;
|
||||
mDuration = aNewDuration;
|
||||
if (aNewDuration < oldDuration) {
|
||||
mSourceBuffers->Remove(aNewDuration, oldDuration, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// TODO: If partial audio frames/text cues exist, clamp duration based on mSourceBuffers.
|
||||
// TODO: Update media element's duration and run element's duration change algorithm.
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::EndOfStreamInternal(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv)
|
||||
{
|
||||
SetReadyState(MediaSourceReadyState::Ended);
|
||||
if (!aError.WasPassed()) {
|
||||
// TODO:
|
||||
// Run duration change algorithm.
|
||||
// DurationChange(highestDurationOfSourceBuffers, aRv);
|
||||
// if (aRv.Failed()) {
|
||||
// return;
|
||||
// }
|
||||
// Notify media element that all data is now available.
|
||||
return;
|
||||
}
|
||||
switch (aError.Value()) {
|
||||
case MediaSourceEndOfStreamError::Network:
|
||||
// TODO: If media element has a readyState of:
|
||||
// HAVE_NOTHING -> run resource fetch algorithm
|
||||
// > HAVE_NOTHING -> run "interrupted" steps of resource fetch
|
||||
break;
|
||||
case MediaSourceEndOfStreamError::Decode:
|
||||
// TODO: If media element has a readyState of:
|
||||
// HAVE_NOTHING -> run "unsupported" steps of resource fetch
|
||||
// > HAVE_NOTHING -> run "corrupted" steps of resource fetch
|
||||
break;
|
||||
default:
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* const gMediaSourceTypes[5] = {
|
||||
"video/webm",
|
||||
"audio/webm",
|
||||
"video/mp4",
|
||||
"audio/mp4",
|
||||
nullptr
|
||||
};
|
||||
|
||||
/* static */ bool
|
||||
MediaSource::IsTypeSupportedInternal(const nsAString& aType, ErrorResult& aRv)
|
||||
{
|
||||
if (aType.IsEmpty()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return false;
|
||||
}
|
||||
// TODO: Further restrict this to formats in the spec.
|
||||
nsContentTypeParser parser(aType);
|
||||
nsAutoString mimeType;
|
||||
nsresult rv = parser.GetType(mimeType);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return false;
|
||||
}
|
||||
bool found = false;
|
||||
for (uint32_t i = 0; gMediaSourceTypes[i]; ++i) {
|
||||
if (mimeType.EqualsASCII(gMediaSourceTypes[i])) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return false;
|
||||
}
|
||||
// Check aType against HTMLMediaElement list of MIME types. Since we've
|
||||
// already restricted the container format, this acts as a specific check
|
||||
// of any specified "codecs" parameter of aType.
|
||||
if (HTMLMediaElement::GetCanPlay(aType) == CANPLAY_NO) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
nsPIDOMWindow*
|
||||
MediaSource::GetParentObject() const
|
||||
{
|
||||
return GetOwner();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
MediaSource::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
{
|
||||
return MediaSourceBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_4(MediaSource, nsDOMEventTargetHelper,
|
||||
mSourceBuffers, mActiveSourceBuffers, mAdapters, mElement)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(MediaSource, nsDOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(MediaSource, nsDOMEventTargetHelper)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaSource)
|
||||
NS_INTERFACE_MAP_ENTRY(mozilla::dom::MediaSource)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,134 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_MediaSource_h_
|
||||
#define mozilla_dom_MediaSource_h_
|
||||
|
||||
#include "AsyncEventRunner.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/dom/MediaSourceBinding.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nscore.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class HTMLMediaElement;
|
||||
class MediaSourceInputAdapter;
|
||||
class SourceBufferList;
|
||||
class SourceBuffer;
|
||||
class TimeRanges;
|
||||
|
||||
#define MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID \
|
||||
{ 0x3839d699, 0x22c5, 0x439f, \
|
||||
{ 0x94, 0xca, 0x0e, 0x0b, 0x26, 0xf9, 0xca, 0xbf } }
|
||||
|
||||
class MediaSource MOZ_FINAL : public nsDOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
/** WebIDL Methods. */
|
||||
static already_AddRefed<MediaSource> Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
|
||||
|
||||
SourceBufferList* SourceBuffers();
|
||||
SourceBufferList* ActiveSourceBuffers();
|
||||
MediaSourceReadyState ReadyState();
|
||||
|
||||
double Duration();
|
||||
void SetDuration(double aDuration, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<SourceBuffer> AddSourceBuffer(const nsAString& aType, ErrorResult& aRv);
|
||||
void RemoveSourceBuffer(SourceBuffer& aSourceBuffer, ErrorResult& aRv);
|
||||
|
||||
void EndOfStream(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv);
|
||||
static bool IsTypeSupported(const GlobalObject& aGlobal, const nsAString& aType);
|
||||
/** End WebIDL Methods. */
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaSource, nsDOMEventTargetHelper)
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID)
|
||||
|
||||
nsPIDOMWindow* GetParentObject() const;
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
const nsString& GetType()
|
||||
{
|
||||
return mContentType;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIInputStream> CreateInternalStream();
|
||||
|
||||
|
||||
void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
|
||||
|
||||
// Semi-private, for MediaSourceInputAdapter only.
|
||||
nsTArray<uint8_t> const& GetData()
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
|
||||
Monitor& GetMonitor()
|
||||
{
|
||||
return mMonitor;
|
||||
}
|
||||
|
||||
bool AppendDone() const
|
||||
{
|
||||
return mReadyState == MediaSourceReadyState::Closed;
|
||||
}
|
||||
|
||||
// Attach this MediaSource to MediaElement aElement. Returns false if already attached.
|
||||
bool AttachElement(HTMLMediaElement* aElement);
|
||||
void DetachElement();
|
||||
|
||||
// Set mReadyState to aState and fire the required events at the MediaSource.
|
||||
void SetReadyState(MediaSourceReadyState aState);
|
||||
|
||||
void GetBuffered(TimeRanges* aRanges);
|
||||
|
||||
private:
|
||||
explicit MediaSource(nsPIDOMWindow* aWindow);
|
||||
|
||||
friend class AsyncEventRunnner<MediaSource>;
|
||||
void DispatchSimpleEvent(const char* aName);
|
||||
void QueueAsyncSimpleEvent(const char* aName);
|
||||
|
||||
void NotifyListeners();
|
||||
|
||||
void DurationChange(double aNewDuration, ErrorResult& aRv);
|
||||
void EndOfStreamInternal(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv);
|
||||
|
||||
static bool IsTypeSupportedInternal(const nsAString& aType, ErrorResult& aRv);
|
||||
|
||||
double mDuration;
|
||||
|
||||
nsTArray<nsRefPtr<MediaSourceInputAdapter> > mAdapters;
|
||||
|
||||
// Protected by monitor.
|
||||
nsTArray<uint8_t> mData;
|
||||
|
||||
// Protects access to mData.
|
||||
Monitor mMonitor;
|
||||
|
||||
nsRefPtr<SourceBufferList> mSourceBuffers;
|
||||
nsRefPtr<SourceBufferList> mActiveSourceBuffers;
|
||||
|
||||
nsRefPtr<HTMLMediaElement> mElement;
|
||||
|
||||
nsString mContentType;
|
||||
MediaSourceReadyState mReadyState;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(MediaSource, MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID)
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
#endif /* mozilla_dom_MediaSource_h_ */
|
|
@ -0,0 +1,176 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MediaSourceInputAdapter.h"
|
||||
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* gMediaSourceLog;
|
||||
#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
|
||||
#else
|
||||
#define LOG(type, msg)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaSourceInputAdapter::Close()
|
||||
{
|
||||
MonitorAutoLock mon(mMediaSource->GetMonitor());
|
||||
LOG(PR_LOG_DEBUG, ("%p IA::Close", this));
|
||||
//MOZ_ASSERT(!mClosed);
|
||||
mClosed = true;
|
||||
NotifyListener();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaSourceInputAdapter::Available(uint64_t* aAvailable)
|
||||
{
|
||||
MonitorAutoLock mon(mMediaSource->GetMonitor());
|
||||
if (mClosed) {
|
||||
LOG(PR_LOG_DEBUG, ("%p IA::Available (closed)", this));
|
||||
return NS_BASE_STREAM_CLOSED;
|
||||
}
|
||||
*aAvailable = Available();
|
||||
LOG(PR_LOG_DEBUG, ("%p IA::Available available=%llu", this, *aAvailable));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaSourceInputAdapter::Read(char* aBuf, uint32_t aCount, uint32_t* aWriteCount)
|
||||
{
|
||||
return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, aWriteCount);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaSourceInputAdapter::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
|
||||
uint32_t aCount, uint32_t* aWriteCount)
|
||||
{
|
||||
MonitorAutoLock mon(mMediaSource->GetMonitor());
|
||||
|
||||
uint32_t available = Available();
|
||||
LOG(PR_LOG_DEBUG, ("%p IA::ReadSegments aCount=%u available=%u appendDone=%d rv=%x",
|
||||
this, aCount, available, mMediaSource->AppendDone(),
|
||||
mMediaSource->AppendDone() ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK));
|
||||
if (available == 0) {
|
||||
*aWriteCount = 0;
|
||||
return mMediaSource->AppendDone() ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK;
|
||||
}
|
||||
|
||||
uint32_t count = std::min(aCount, available);
|
||||
nsresult rv = aWriter(this, aClosure,
|
||||
reinterpret_cast<const char*>(&mMediaSource->GetData()[mOffset]),
|
||||
0, count, aWriteCount);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
MOZ_ASSERT(*aWriteCount <= count);
|
||||
mOffset += *aWriteCount;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaSourceInputAdapter::IsNonBlocking(bool* aNonBlocking)
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("%p IA::IsNonBlocking", this));
|
||||
*aNonBlocking = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaSourceInputAdapter::CloseWithStatus(nsresult aStatus)
|
||||
{
|
||||
return Close();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaSourceInputAdapter::AsyncWait(nsIInputStreamCallback* aCallback, uint32_t aFlags,
|
||||
uint32_t aRequestedCount, nsIEventTarget* aTarget)
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("%p IA::AsyncWait aCallback=%p aFlags=%u aRequestedCount=%u aTarget=%p",
|
||||
this, aCallback, aFlags, aRequestedCount, aTarget));
|
||||
|
||||
if (aFlags != 0) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (mCallback || mCallbackTarget) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
mCallback = aCallback;
|
||||
mCallbackTarget = aTarget;
|
||||
mNotifyThreshold = aRequestedCount;
|
||||
if (!aRequestedCount) {
|
||||
mNotifyThreshold = 1024;
|
||||
}
|
||||
|
||||
NotifyListener();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
MediaSourceInputAdapter::NotifyListener()
|
||||
{
|
||||
if (!mCallback) {
|
||||
return;
|
||||
}
|
||||
// Don't notify unless more data is available than the threshold, except
|
||||
// in the case that there's no more data coming.
|
||||
if (Available() < mNotifyThreshold && !mClosed && !mMediaSource->AppendDone()) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIInputStreamCallback> callback;
|
||||
if (mCallbackTarget) {
|
||||
callback = NS_NewInputStreamReadyEvent(mCallback, mCallbackTarget);
|
||||
} else {
|
||||
callback = mCallback;
|
||||
}
|
||||
MOZ_ASSERT(callback);
|
||||
mCallback = nullptr;
|
||||
mCallbackTarget = nullptr;
|
||||
mNotifyThreshold = 0;
|
||||
LOG(PR_LOG_DEBUG, ("%p IA::NotifyListener", this));
|
||||
callback->OnInputStreamReady(this);
|
||||
|
||||
}
|
||||
|
||||
uint64_t
|
||||
MediaSourceInputAdapter::Available()
|
||||
{
|
||||
return mMediaSource->GetData().Length() - mOffset;
|
||||
}
|
||||
|
||||
MediaSourceInputAdapter::~MediaSourceInputAdapter()
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("%p Destroy input adapter", this));
|
||||
}
|
||||
|
||||
MediaSourceInputAdapter::MediaSourceInputAdapter(MediaSource* aMediaSource)
|
||||
: mMediaSource(aMediaSource)
|
||||
, mOffset(0)
|
||||
, mClosed(false)
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("%p Create input adapter for %p", this, aMediaSource));
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_1(MediaSourceInputAdapter, mMediaSource)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaSourceInputAdapter)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaSourceInputAdapter)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaSourceInputAdapter)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIAsyncInputStream)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,43 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_MEDIASOURCEINPUTADAPTER_H_
|
||||
#define MOZILLA_MEDIASOURCEINPUTADAPTER_H_
|
||||
|
||||
#include "nsIAsyncInputStream.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "MediaSource.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class MediaSourceInputAdapter MOZ_FINAL : public nsIAsyncInputStream
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(MediaSourceInputAdapter)
|
||||
NS_DECL_NSIINPUTSTREAM
|
||||
NS_DECL_NSIASYNCINPUTSTREAM
|
||||
|
||||
MediaSourceInputAdapter(MediaSource* aMediaSource);
|
||||
~MediaSourceInputAdapter();
|
||||
|
||||
void NotifyListener();
|
||||
|
||||
private:
|
||||
uint64_t Available();
|
||||
|
||||
nsRefPtr<MediaSource> mMediaSource;
|
||||
nsCOMPtr<nsIInputStreamCallback> mCallback;
|
||||
nsCOMPtr<nsIEventTarget> mCallbackTarget;
|
||||
int64_t mOffset;
|
||||
uint32_t mNotifyThreshold;
|
||||
bool mClosed;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
#endif /* MOZILLA_MEDIASOURCEINPUTADAPTER_H_ */
|
|
@ -0,0 +1,249 @@
|
|||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "SourceBuffer.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* gMediaSourceLog;
|
||||
#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
|
||||
#else
|
||||
#define LOG(type, msg)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
void
|
||||
SourceBuffer::SetMode(SourceBufferAppendMode aMode, ErrorResult& aRv)
|
||||
{
|
||||
if (!mAttached || mUpdating) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
|
||||
mMediaSource->SetReadyState(MediaSourceReadyState::Open);
|
||||
}
|
||||
// TODO:: Test append state.
|
||||
// TODO:: If aMode is "sequence", set sequence start time.
|
||||
mAppendMode = aMode;
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::SetTimestampOffset(double aTimestampOffset, ErrorResult& aRv)
|
||||
{
|
||||
if (!mAttached || mUpdating) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
|
||||
mMediaSource->SetReadyState(MediaSourceReadyState::Open);
|
||||
}
|
||||
// TODO: Test append state.
|
||||
// TODO: If aMode is "sequence", set sequence start time.
|
||||
mTimestampOffset = aTimestampOffset;
|
||||
}
|
||||
|
||||
already_AddRefed<TimeRanges>
|
||||
SourceBuffer::GetBuffered(ErrorResult& aRv)
|
||||
{
|
||||
if (!mAttached) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
nsRefPtr<TimeRanges> ranges = new TimeRanges();
|
||||
// TODO: Populate ranges.
|
||||
return ranges.forget();
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::SetAppendWindowStart(double aAppendWindowStart, ErrorResult& aRv)
|
||||
{
|
||||
if (!mAttached || mUpdating) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
if (aAppendWindowStart < 0 || aAppendWindowStart >= mAppendWindowEnd) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return;
|
||||
}
|
||||
mAppendWindowStart = aAppendWindowStart;
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv)
|
||||
{
|
||||
if (!mAttached || mUpdating) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
if (IsNaN(aAppendWindowEnd) ||
|
||||
aAppendWindowEnd <= mAppendWindowStart) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return;
|
||||
}
|
||||
mAppendWindowEnd = aAppendWindowEnd;
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::AppendBuffer(ArrayBuffer& aData, ErrorResult& aRv)
|
||||
{
|
||||
AppendData(aData.Data(), aData.Length(), aRv);
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::AppendBuffer(ArrayBufferView& aData, ErrorResult& aRv)
|
||||
{
|
||||
AppendData(aData.Data(), aData.Length(), aRv);
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::Abort(ErrorResult& aRv)
|
||||
{
|
||||
if (!mAttached) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
if (mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
if (mUpdating) {
|
||||
// TODO: Abort segment parser loop, buffer append, and stream append loop algorithms.
|
||||
AbortUpdating();
|
||||
}
|
||||
// TODO: Run reset parser algorithm.
|
||||
// XXX: Need to run these two resets through setters?
|
||||
mAppendWindowStart = 0;
|
||||
mAppendWindowEnd = PositiveInfinity();
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
|
||||
{
|
||||
if (aStart < 0 || aStart > mMediaSource->Duration() ||
|
||||
aEnd <= aStart) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return;
|
||||
}
|
||||
if (!mAttached || mUpdating ||
|
||||
mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
StartUpdating();
|
||||
/// TODO: Run coded frame removal algorithm asynchronously (would call StopUpdating()).
|
||||
StopUpdating();
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::Attach()
|
||||
{
|
||||
MOZ_ASSERT(!mAttached);
|
||||
mAttached = true;
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::Detach()
|
||||
{
|
||||
MOZ_ASSERT(mAttached);
|
||||
mAttached = false;
|
||||
}
|
||||
|
||||
SourceBuffer::SourceBuffer(MediaSource* aMediaSource)
|
||||
: nsDOMEventTargetHelper(aMediaSource->GetParentObject())
|
||||
, mMediaSource(aMediaSource)
|
||||
, mAppendWindowStart(0)
|
||||
, mAppendWindowEnd(PositiveInfinity())
|
||||
, mTimestampOffset(0)
|
||||
, mAppendMode(SourceBufferAppendMode::Segments)
|
||||
, mUpdating(false)
|
||||
, mAttached(false)
|
||||
{
|
||||
MOZ_ASSERT(aMediaSource);
|
||||
}
|
||||
|
||||
MediaSource*
|
||||
SourceBuffer::GetParentObject() const
|
||||
{
|
||||
return mMediaSource;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
SourceBuffer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
{
|
||||
return SourceBufferBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::DispatchSimpleEvent(const char* aName)
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("%p Dispatching event %s to SourceBuffer", this, aName));
|
||||
DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName));
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::QueueAsyncSimpleEvent(const char* aName)
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("%p Queuing event %s to SourceBuffer", this, aName));
|
||||
nsCOMPtr<nsIRunnable> event = new AsyncEventRunnner<SourceBuffer>(this, aName);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::StartUpdating()
|
||||
{
|
||||
MOZ_ASSERT(!mUpdating);
|
||||
mUpdating = true;
|
||||
QueueAsyncSimpleEvent("updatestart");
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::StopUpdating()
|
||||
{
|
||||
MOZ_ASSERT(mUpdating);
|
||||
mUpdating = false;
|
||||
QueueAsyncSimpleEvent("update");
|
||||
QueueAsyncSimpleEvent("updateend");
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::AbortUpdating()
|
||||
{
|
||||
MOZ_ASSERT(mUpdating);
|
||||
mUpdating = false;
|
||||
QueueAsyncSimpleEvent("abort");
|
||||
QueueAsyncSimpleEvent("updateend");
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
|
||||
{
|
||||
if (!mAttached || mUpdating) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
|
||||
mMediaSource->SetReadyState(MediaSourceReadyState::Open);
|
||||
}
|
||||
// TODO: Run coded frame eviction algorithm.
|
||||
// TODO: Test buffer full flag.
|
||||
mMediaSource->AppendData(aData, aLength, aRv); // XXX: Appending to input buffer.
|
||||
StartUpdating();
|
||||
// TODO: Run buffer append algorithm asynchronously (would call StopUpdating()).
|
||||
StopUpdating();
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_1(SourceBuffer, nsDOMEventTargetHelper, mMediaSource)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(SourceBuffer, nsDOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(SourceBuffer, nsDOMEventTargetHelper)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SourceBuffer)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,115 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_SourceBuffer_h_
|
||||
#define mozilla_dom_SourceBuffer_h_
|
||||
|
||||
#include "AsyncEventRunner.h"
|
||||
#include "MediaSource.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/SourceBufferBinding.h"
|
||||
#include "mozilla/dom/TimeRanges.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nscore.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class SourceBuffer MOZ_FINAL : public nsDOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
/** WebIDL Methods. */
|
||||
SourceBufferAppendMode Mode() const
|
||||
{
|
||||
return mAppendMode;
|
||||
}
|
||||
|
||||
void SetMode(SourceBufferAppendMode aMode, ErrorResult& aRv);
|
||||
|
||||
bool Updating() const
|
||||
{
|
||||
return mUpdating;
|
||||
}
|
||||
|
||||
already_AddRefed<TimeRanges> GetBuffered(ErrorResult& aRv);
|
||||
|
||||
double TimestampOffset() const
|
||||
{
|
||||
return mTimestampOffset;
|
||||
}
|
||||
|
||||
void SetTimestampOffset(double aTimestampOffset, ErrorResult& aRv);
|
||||
|
||||
double AppendWindowStart() const
|
||||
{
|
||||
return mAppendWindowStart;
|
||||
}
|
||||
|
||||
void SetAppendWindowStart(double aAppendWindowStart, ErrorResult& aRv);
|
||||
|
||||
double AppendWindowEnd() const
|
||||
{
|
||||
return mAppendWindowEnd;
|
||||
}
|
||||
|
||||
void SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv);
|
||||
|
||||
void AppendBuffer(ArrayBuffer& aData, ErrorResult& aRv);
|
||||
void AppendBuffer(ArrayBufferView& aData, ErrorResult& aRv);
|
||||
|
||||
void Abort(ErrorResult& aRv);
|
||||
|
||||
void Remove(double aStart, double aEnd, ErrorResult& aRv);
|
||||
/** End WebIDL Methods. */
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SourceBuffer, nsDOMEventTargetHelper)
|
||||
|
||||
explicit SourceBuffer(MediaSource* aMediaSource);
|
||||
|
||||
MediaSource* GetParentObject() const;
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
// Notify the SourceBuffer that it has been attached to or detached from
|
||||
// the MediaSource's sourceBuffer list.
|
||||
void Attach();
|
||||
void Detach();
|
||||
|
||||
private:
|
||||
friend class AsyncEventRunnner<SourceBuffer>;
|
||||
void DispatchSimpleEvent(const char* aName);
|
||||
void QueueAsyncSimpleEvent(const char* aName);
|
||||
|
||||
// Update mUpdating and fire the appropriate events.
|
||||
void StartUpdating();
|
||||
void StopUpdating();
|
||||
void AbortUpdating();
|
||||
|
||||
// Shared implementation of AppendBuffer overloads.
|
||||
void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
|
||||
|
||||
nsRefPtr<MediaSource> mMediaSource;
|
||||
|
||||
double mAppendWindowStart;
|
||||
double mAppendWindowEnd;
|
||||
|
||||
double mTimestampOffset;
|
||||
|
||||
SourceBufferAppendMode mAppendMode;
|
||||
bool mUpdating;
|
||||
|
||||
bool mAttached;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
#endif /* mozilla_dom_SourceBuffer_h_ */
|
|
@ -0,0 +1,143 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "SourceBufferList.h"
|
||||
|
||||
#include "mozilla/dom/SourceBufferListBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* gMediaSourceLog;
|
||||
#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
|
||||
#else
|
||||
#define LOG(type, msg)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
SourceBuffer*
|
||||
SourceBufferList::IndexedGetter(uint32_t aIndex, bool& aFound)
|
||||
{
|
||||
aFound = aIndex < mSourceBuffers.Length();
|
||||
return aFound ? mSourceBuffers[aIndex] : nullptr;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SourceBufferList::Length()
|
||||
{
|
||||
return mSourceBuffers.Length();
|
||||
}
|
||||
|
||||
void
|
||||
SourceBufferList::Append(SourceBuffer* aSourceBuffer)
|
||||
{
|
||||
mSourceBuffers.AppendElement(aSourceBuffer);
|
||||
QueueAsyncSimpleEvent("addsourcebuffer");
|
||||
}
|
||||
|
||||
void
|
||||
SourceBufferList::Remove(SourceBuffer* aSourceBuffer)
|
||||
{
|
||||
MOZ_ALWAYS_TRUE(mSourceBuffers.RemoveElement(aSourceBuffer));
|
||||
QueueAsyncSimpleEvent("removesourcebuffer");
|
||||
}
|
||||
|
||||
bool
|
||||
SourceBufferList::Contains(SourceBuffer* aSourceBuffer)
|
||||
{
|
||||
return mSourceBuffers.Contains(aSourceBuffer);
|
||||
}
|
||||
|
||||
void
|
||||
SourceBufferList::Clear()
|
||||
{
|
||||
mSourceBuffers.Clear();
|
||||
QueueAsyncSimpleEvent("removesourcebuffer");
|
||||
}
|
||||
|
||||
bool
|
||||
SourceBufferList::IsEmpty()
|
||||
{
|
||||
return mSourceBuffers.IsEmpty();
|
||||
}
|
||||
|
||||
void
|
||||
SourceBufferList::DetachAndClear()
|
||||
{
|
||||
for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
|
||||
mSourceBuffers[i]->Detach();
|
||||
}
|
||||
Clear();
|
||||
}
|
||||
|
||||
bool
|
||||
SourceBufferList::AnyUpdating()
|
||||
{
|
||||
for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
|
||||
if (mSourceBuffers[i]->Updating()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
SourceBufferList::Remove(double aStart, double aEnd, ErrorResult& aRv)
|
||||
{
|
||||
for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
|
||||
mSourceBuffers[i]->Remove(aStart, aEnd, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SourceBufferList::DispatchSimpleEvent(const char* aName)
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("%p Dispatching event %s to SourceBufferList", this, aName));
|
||||
DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName));
|
||||
}
|
||||
|
||||
void
|
||||
SourceBufferList::QueueAsyncSimpleEvent(const char* aName)
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("%p Queuing event %s to SourceBufferList", this, aName));
|
||||
nsCOMPtr<nsIRunnable> event = new AsyncEventRunnner<SourceBufferList>(this, aName);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
SourceBufferList::SourceBufferList(MediaSource* aMediaSource)
|
||||
: nsDOMEventTargetHelper(aMediaSource->GetParentObject())
|
||||
, mMediaSource(aMediaSource)
|
||||
{
|
||||
MOZ_ASSERT(aMediaSource);
|
||||
}
|
||||
|
||||
MediaSource*
|
||||
SourceBufferList::GetParentObject() const
|
||||
{
|
||||
return mMediaSource;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
SourceBufferList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
{
|
||||
return SourceBufferListBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_2(SourceBufferList, nsDOMEventTargetHelper,
|
||||
mMediaSource, mSourceBuffers)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(SourceBufferList, nsDOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(SourceBufferList, nsDOMEventTargetHelper)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SourceBufferList)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,79 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_SourceBufferList_h_
|
||||
#define mozilla_dom_SourceBufferList_h_
|
||||
|
||||
#include "AsyncEventRunner.h"
|
||||
#include "MediaSource.h"
|
||||
#include "SourceBuffer.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nscore.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class MediaSource;
|
||||
|
||||
class SourceBufferList MOZ_FINAL : public nsDOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
/** WebIDL Methods. */
|
||||
SourceBuffer* IndexedGetter(uint32_t aIndex, bool& aFound);
|
||||
|
||||
uint32_t Length();
|
||||
/** End WebIDL methods. */
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SourceBufferList, nsDOMEventTargetHelper)
|
||||
|
||||
explicit SourceBufferList(MediaSource* aMediaSource);
|
||||
|
||||
MediaSource* GetParentObject() const;
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
// Append a SourceBuffer and fire "addsourcebuffer" at the list.
|
||||
void Append(SourceBuffer* aSourceBuffer);
|
||||
|
||||
// Remove a SourceBuffer and fire "removesourcebuffer" at the list.
|
||||
void Remove(SourceBuffer* aSourceBuffer);
|
||||
|
||||
// Returns true if aSourceBuffer is present in the list.
|
||||
bool Contains(SourceBuffer* aSourceBuffer);
|
||||
|
||||
// Remove all SourceBuffers and fire a single "removesourcebuffer" at the list.
|
||||
void Clear();
|
||||
|
||||
// True if list has zero entries.
|
||||
bool IsEmpty();
|
||||
|
||||
// Detach and remove all SourceBuffers and fire a single "removesourcebuffer" at the list.
|
||||
void DetachAndClear();
|
||||
|
||||
// Returns true if updating is true on any SourceBuffers in the list.
|
||||
bool AnyUpdating();
|
||||
|
||||
// Calls Remove(aStart, aEnd) on each SourceBuffer in the list. Aborts on
|
||||
// first error, with result returned in aRv.
|
||||
void Remove(double aStart, double aEnd, ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
friend class AsyncEventRunnner<SourceBufferList>;
|
||||
void DispatchSimpleEvent(const char* aName);
|
||||
void QueueAsyncSimpleEvent(const char* aName);
|
||||
|
||||
nsRefPtr<MediaSource> mMediaSource;
|
||||
nsTArray<nsRefPtr<SourceBuffer> > mSourceBuffers;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
#endif /* mozilla_dom_SourceBufferList_h_ */
|
|
@ -0,0 +1,28 @@
|
|||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
PARALLEL_DIRS += [
|
||||
'test'
|
||||
]
|
||||
|
||||
MODULE = 'content'
|
||||
|
||||
EXPORTS += [
|
||||
'AsyncEventRunner.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'MediaSource.h',
|
||||
'SourceBuffer.h',
|
||||
'SourceBufferList.h',
|
||||
]
|
||||
|
||||
CPP_SOURCES += [
|
||||
'MediaSource.cpp',
|
||||
'MediaSourceInputAdapter.cpp',
|
||||
'SourceBuffer.cpp',
|
||||
'SourceBufferList.cpp',
|
||||
]
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH := @DEPTH@
|
||||
topsrcdir := @top_srcdir@
|
||||
srcdir := @srcdir@
|
||||
VPATH := @srcdir@
|
||||
relativesrcdir := @relativesrcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MOCHITEST_FILES = \
|
||||
test_MediaSource.html \
|
||||
seek.webm \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -1,7 +1,4 @@
|
|||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
toolkit.jar:
|
||||
content/global/cpow/test.xul (tests/adhoc/test.xul)
|
||||
content/global/cpow/child.html (tests/adhoc/child.html)
|
Двоичный файл не отображается.
|
@ -0,0 +1,84 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test whether we can create an MediaSource interface</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();
|
||||
|
||||
addLoadEvent(function() {
|
||||
ok(!window.MediaSource, "MediaSource should be hidden behind a pref");
|
||||
if (navigator.appVersion.indexOf("Android") != -1) {
|
||||
todo(false, "Fix this test on Android: bug 889712.");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
var accessThrows = false;
|
||||
try {
|
||||
new MediaSource();
|
||||
} catch (e) {
|
||||
accessThrows = true;
|
||||
}
|
||||
ok(accessThrows, "MediaSource should be hidden behind a pref");
|
||||
SpecialPowers.setBoolPref("media.mediasource.enabled", true);
|
||||
var ms = new MediaSource();
|
||||
ok(ms, "Create a MediaSource object");
|
||||
ok(ms instanceof EventTarget, "MediaSource must be an EventTarget");
|
||||
is(ms.readyState, "closed", "New MediaSource must be in closed state");
|
||||
// Force wrapper creation, tests for leaks.
|
||||
ms.foo = null;
|
||||
var o = URL.createObjectURL(ms);
|
||||
ok(o, "Create an objectURL from the MediaSource");
|
||||
var v = document.createElement("video");
|
||||
document.body.appendChild(v);
|
||||
v.src = o;
|
||||
ms.addEventListener("sourceopen", function () {
|
||||
ok(true, "Receive a sourceopen event");
|
||||
is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
|
||||
var sb = ms.addSourceBuffer("video/webm");
|
||||
ok(sb, "Create a SourceBuffer");
|
||||
is(ms.sourceBuffers.length, 1, "MediaSource.sourceBuffers is expected length");
|
||||
is(ms.sourceBuffers[0], sb, "SourceBuffer in list matches our SourceBuffer");
|
||||
fetch("seek.webm", function (blob) {
|
||||
var r = new FileReader();
|
||||
r.addEventListener("load", function (e) {
|
||||
sb.appendBuffer(new Uint8Array(e.target.result));
|
||||
ms.endOfStream();
|
||||
v.play();
|
||||
});
|
||||
r.readAsArrayBuffer(blob);
|
||||
});
|
||||
});
|
||||
ms.addEventListener("sourceended", function () {
|
||||
ok(true, "Receive a sourceended event");
|
||||
is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
|
||||
});
|
||||
v.addEventListener("playing", function () {
|
||||
is(v.duration, 4, "Video has correct duration");
|
||||
v.parentNode.removeChild(v);
|
||||
SpecialPowers.clearUserPref("media.mediasource.enabled");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
||||
function fetch(src, cb) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", src, true);
|
||||
xhr.responseType = "blob";
|
||||
xhr.addEventListener("load", function (e) {
|
||||
if (xhr.status != 200) {
|
||||
return false;
|
||||
}
|
||||
cb(xhr.response);
|
||||
});
|
||||
xhr.send();
|
||||
};
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
PARALLEL_DIRS += ['encoder']
|
||||
|
||||
PARALLEL_DIRS += ['mediasource']
|
||||
|
||||
PARALLEL_DIRS += ['webaudio']
|
||||
|
||||
if CONFIG['MOZ_RAW']:
|
||||
|
@ -85,6 +87,7 @@ EXPORTS.mozilla.dom += [
|
|||
'TextTrackCue.h',
|
||||
'TextTrackCueList.h',
|
||||
'TextTrackList.h',
|
||||
'VideoPlaybackQuality.h',
|
||||
'VideoStreamTrack.h',
|
||||
]
|
||||
|
||||
|
@ -112,6 +115,7 @@ CPP_SOURCES += [
|
|||
'TextTrackCueList.cpp',
|
||||
'TextTrackList.cpp',
|
||||
'VideoFrameContainer.cpp',
|
||||
'VideoPlaybackQuality.cpp',
|
||||
'VideoSegment.cpp',
|
||||
'VideoStreamTrack.cpp',
|
||||
'VideoUtils.cpp',
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "MediaPluginHost.h"
|
||||
#include "nsXPCOMStrings.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "pratom.h"
|
||||
#include "MediaPluginReader.h"
|
||||
#include "nsIGfxInfo.h"
|
||||
#include "gfxCrashReporterUtils.h"
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<script>
|
||||
(new AudioContext()).createConvolver().buffer = null;
|
||||
</script>
|
|
@ -49,3 +49,4 @@ load 881775.html
|
|||
load 882956.html
|
||||
test-pref(media.webvtt.enabled,true) load 882549.html
|
||||
load 884459.html
|
||||
load 889042.html
|
||||
|
|
|
@ -168,15 +168,17 @@ ConvolverNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
|||
void
|
||||
ConvolverNode::SetBuffer(JSContext* aCx, AudioBuffer* aBuffer, ErrorResult& aRv)
|
||||
{
|
||||
switch (aBuffer->NumberOfChannels()) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
// Supported number of channels
|
||||
break;
|
||||
default:
|
||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
return;
|
||||
if (aBuffer) {
|
||||
switch (aBuffer->NumberOfChannels()) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
// Supported number of channels
|
||||
break;
|
||||
default:
|
||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mBuffer = aBuffer;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "mozilla/dom/SVGMatrix.h"
|
||||
#include "DOMSVGPoint.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsFrameSelection.h"
|
||||
#include "nsISVGSVGFrame.h" //XXX
|
||||
#include "mozilla/dom/SVGRect.h"
|
||||
#include "nsError.h"
|
||||
|
@ -364,6 +365,16 @@ SVGSVGElement::SetCurrentTime(float seconds)
|
|||
// else we're not the outermost <svg> or not bound to a tree, so silently fail
|
||||
}
|
||||
|
||||
void
|
||||
SVGSVGElement::DeselectAll()
|
||||
{
|
||||
nsIFrame* frame = GetPrimaryFrame();
|
||||
if (frame) {
|
||||
nsRefPtr<nsFrameSelection> frameSelection = frame->GetFrameSelection();
|
||||
frameSelection->ClearNormalSelection();
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMSVGNumber>
|
||||
SVGSVGElement::CreateSVGNumber()
|
||||
{
|
||||
|
|
|
@ -237,6 +237,7 @@ public:
|
|||
bool AnimationsPaused();
|
||||
float GetCurrentTime();
|
||||
void SetCurrentTime(float seconds);
|
||||
void DeselectAll();
|
||||
already_AddRefed<nsIDOMSVGNumber> CreateSVGNumber();
|
||||
already_AddRefed<nsIDOMSVGLength> CreateSVGLength();
|
||||
already_AddRefed<SVGAngle> CreateSVGAngle();
|
||||
|
|
|
@ -331,16 +331,23 @@ this.AlarmService = {
|
|||
},
|
||||
|
||||
_getAlarmTime: function _getAlarmTime(aAlarm) {
|
||||
let alarmTime = (new Date(aAlarm.date)).getTime();
|
||||
// Avoid casting a Date object to a Date again to
|
||||
// preserve milliseconds. See bug 810973.
|
||||
let alarmTime;
|
||||
if (aAlarm.date instanceof Date) {
|
||||
alarmTime = aAlarm.date.getTime();
|
||||
} else {
|
||||
alarmTime = (new Date(aAlarm.date)).getTime();
|
||||
}
|
||||
|
||||
// For an alarm specified with "ignoreTimezone", it must be fired respect
|
||||
// to the user's timezone. Supposing an alarm was set at 7:00pm at Tokyo,
|
||||
// it must be gone off at 7:00pm respect to Paris' local time when the user
|
||||
// is located at Paris. We can adjust the alarm UTC time by calculating
|
||||
// the difference of the orginal timezone and the current timezone.
|
||||
if (aAlarm.ignoreTimezone)
|
||||
if (aAlarm.ignoreTimezone) {
|
||||
alarmTime += (this._currentTimezoneOffset - aAlarm.timezoneOffset) * 60000;
|
||||
|
||||
}
|
||||
return alarmTime;
|
||||
},
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "nsGlobalWindow.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "DOMMediaStream.h"
|
||||
#include "mozilla/dom/MediaSource.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
@ -38,6 +39,17 @@ URL::CreateObjectURL(const GlobalObject& aGlobal, DOMMediaStream& aStream,
|
|||
aResult, aError);
|
||||
}
|
||||
|
||||
void
|
||||
URL::CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource,
|
||||
const objectURLOptions& aOptions,
|
||||
nsString& aResult,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
CreateObjectURLInternal(aGlobal.Get(), &aSource,
|
||||
NS_LITERAL_CSTRING(MEDIASOURCEURI_SCHEME), aOptions,
|
||||
aResult, aError);
|
||||
}
|
||||
|
||||
void
|
||||
URL::CreateObjectURLInternal(nsISupports* aGlobal, nsISupports* aObject,
|
||||
const nsACString& aScheme,
|
||||
|
|
|
@ -16,6 +16,8 @@ class DOMMediaStream;
|
|||
|
||||
namespace dom {
|
||||
|
||||
class MediaSource;
|
||||
|
||||
class URL MOZ_FINAL
|
||||
{
|
||||
public:
|
||||
|
@ -29,6 +31,11 @@ public:
|
|||
const mozilla::dom::objectURLOptions& aOptions,
|
||||
nsString& aResult,
|
||||
mozilla::ErrorResult& aError);
|
||||
static void CreateObjectURL(const GlobalObject& aGlobal,
|
||||
MediaSource& aSource,
|
||||
const objectURLOptions& aOptions,
|
||||
nsString& aResult,
|
||||
mozilla::ErrorResult& aError);
|
||||
static void RevokeObjectURL(const GlobalObject& aGlobal,
|
||||
const nsAString& aURL);
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ EXPORTS += [
|
|||
'nsDOMClassInfoClasses.h',
|
||||
'nsDOMClassInfoID.h',
|
||||
'nsDOMJSUtils.h',
|
||||
'nsDOMNavigationTiming.h',
|
||||
'nsDOMString.h',
|
||||
'nsFocusManager.h',
|
||||
'nsIDOMClassInfo.h',
|
||||
|
@ -47,6 +48,7 @@ EXPORTS += [
|
|||
'nsJSUtils.h',
|
||||
'nsPIDOMWindow.h',
|
||||
'nsPIWindowRoot.h',
|
||||
'nsPerformance.h',
|
||||
'nsStructuredCloneContainer.h',
|
||||
'nsWindowMemoryReporter.h',
|
||||
'nsWrapperCache.h',
|
||||
|
|
|
@ -4026,6 +4026,12 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
|||
if (name_struct->mChromeOnly && !nsContentUtils::IsCallerChrome())
|
||||
return NS_OK;
|
||||
|
||||
// Before defining a global property, check for a named subframe of the
|
||||
// same name. If it exists, we don't want to shadow it.
|
||||
nsCOMPtr<nsIDOMWindow> childWin = aWin->GetChildWindow(name);
|
||||
if (childWin)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsISupports> native(do_CreateInstance(name_struct->mCID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
|
|
@ -609,6 +609,15 @@ DOMInterfaces = {
|
|||
'register': False
|
||||
},
|
||||
|
||||
'MediaSource': [{
|
||||
'resultNotAddRefed': [ 'sourceBuffers', 'activeSourceBuffers' ],
|
||||
},
|
||||
{
|
||||
'nativeType': 'JSObject',
|
||||
'workers': True,
|
||||
'skipGen': True
|
||||
}],
|
||||
|
||||
'MediaStream': [{
|
||||
'headerFile': 'DOMMediaStream.h',
|
||||
'nativeType': 'mozilla::DOMMediaStream'
|
||||
|
@ -807,6 +816,10 @@ DOMInterfaces = {
|
|||
'nativeType': 'nsDOMSimpleGestureEvent',
|
||||
},
|
||||
|
||||
'SourceBufferList': {
|
||||
'resultNotAddRefed': [ '__indexedGetter' ],
|
||||
},
|
||||
|
||||
'StyleSheet': {
|
||||
'nativeType': 'nsCSSStyleSheet',
|
||||
},
|
||||
|
@ -1126,6 +1139,10 @@ DOMInterfaces = {
|
|||
'workers': True,
|
||||
}],
|
||||
|
||||
'VideoPlaybackQuality': {
|
||||
'nativeOwnership': 'refcounted',
|
||||
},
|
||||
|
||||
'VideoStreamTrack': {
|
||||
},
|
||||
|
||||
|
|
|
@ -29,11 +29,11 @@
|
|||
#include <cstdio>
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#include "pratom.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/ipc/UnixSocket.h"
|
||||
#include "mozilla/ipc/DBusThread.h"
|
||||
|
@ -151,7 +151,7 @@ static const char* sBluetoothDBusSignals[] =
|
|||
static nsAutoPtr<RawDBusConnection> gThreadConnection;
|
||||
static nsDataHashtable<nsStringHashKey, DBusMessage* > sPairingReqTable;
|
||||
static nsDataHashtable<nsStringHashKey, DBusMessage* > sAuthorizeReqTable;
|
||||
static int32_t sIsPairing = 0;
|
||||
static Atomic<int32_t> sIsPairing;
|
||||
static nsString sAdapterPath;
|
||||
|
||||
typedef void (*UnpackFunc)(DBusMessage*, DBusError*, BluetoothValue&, nsAString&);
|
||||
|
@ -456,7 +456,7 @@ GetObjectPathCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
|
|||
if (sIsPairing) {
|
||||
RunDBusCallback(aMsg, aBluetoothReplyRunnable,
|
||||
UnpackObjectPathMessage);
|
||||
PR_AtomicDecrement(&sIsPairing);
|
||||
sIsPairing--;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1678,7 +1678,7 @@ BluetoothDBusService::StopInternal()
|
|||
sAuthorizeReqTable.EnumerateRead(UnrefDBusMessages, nullptr);
|
||||
sAuthorizeReqTable.Clear();
|
||||
|
||||
PR_AtomicSet(&sIsPairing, 0);
|
||||
sIsPairing = 0;
|
||||
|
||||
StopDBus();
|
||||
return NS_OK;
|
||||
|
@ -2173,7 +2173,7 @@ BluetoothDBusService::CreatePairedDeviceInternal(
|
|||
*
|
||||
* Please see Bug 818696 for more information.
|
||||
*/
|
||||
PR_AtomicIncrement(&sIsPairing);
|
||||
sIsPairing++;
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
|
||||
// Then send CreatePairedDevice, it will register a temp device agent then
|
||||
|
|
|
@ -27,6 +27,7 @@ DOM_SRCDIRS = \
|
|||
content/base/src \
|
||||
content/html/content/src \
|
||||
content/html/document/src \
|
||||
content/media/mediasource \
|
||||
content/media/webaudio \
|
||||
content/svg/content/src \
|
||||
layout/generic \
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
#include "mozilla/ipc/TestShellChild.h"
|
||||
#include "mozilla/ipc/XPCShellEnvironment.h"
|
||||
#include "mozilla/jsipc/PContextWrapperChild.h"
|
||||
#include "mozilla/layers/CompositorChild.h"
|
||||
#include "mozilla/layers/ImageBridgeChild.h"
|
||||
#include "mozilla/layers/PCompositorChild.h"
|
||||
|
@ -50,6 +49,7 @@
|
|||
#include "nsDebugImpl.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsLayoutStylesheetCache.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
|
||||
#include "IHistory.h"
|
||||
#include "nsDocShellCID.h"
|
||||
|
@ -64,6 +64,7 @@
|
|||
#include "nsFrameMessageManager.h"
|
||||
|
||||
#include "nsIGeolocationProvider.h"
|
||||
#include "JavaScriptParent.h"
|
||||
#include "mozilla/dom/PMemoryReportRequestChild.h"
|
||||
|
||||
#ifdef MOZ_PERMISSIONS
|
||||
|
@ -109,6 +110,7 @@
|
|||
#include "nsIPrincipal.h"
|
||||
#include "nsDeviceStorage.h"
|
||||
#include "AudioChannelService.h"
|
||||
#include "JavaScriptChild.h"
|
||||
#include "ProcessPriorityManager.h"
|
||||
|
||||
using namespace base;
|
||||
|
@ -123,6 +125,7 @@ using namespace mozilla::hal_sandbox;
|
|||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::net;
|
||||
using namespace mozilla::jsipc;
|
||||
#if defined(MOZ_WIDGET_GONK)
|
||||
using namespace mozilla::system;
|
||||
#endif
|
||||
|
@ -552,6 +555,31 @@ static void FirstIdle(void)
|
|||
ContentChild::GetSingleton()->SendFirstIdle();
|
||||
}
|
||||
|
||||
mozilla::jsipc::PJavaScriptChild *
|
||||
ContentChild::AllocPJavaScript()
|
||||
{
|
||||
nsCOMPtr<nsIJSRuntimeService> svc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
|
||||
NS_ENSURE_TRUE(svc, NULL);
|
||||
|
||||
JSRuntime *rt;
|
||||
svc->GetRuntime(&rt);
|
||||
NS_ENSURE_TRUE(svc, NULL);
|
||||
|
||||
mozilla::jsipc::JavaScriptChild *child = new mozilla::jsipc::JavaScriptChild(rt);
|
||||
if (!child->init()) {
|
||||
delete child;
|
||||
return NULL;
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::DeallocPJavaScript(PJavaScriptChild *child)
|
||||
{
|
||||
delete child;
|
||||
return true;
|
||||
}
|
||||
|
||||
PBrowserChild*
|
||||
ContentChild::AllocPBrowser(const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags)
|
||||
|
@ -760,10 +788,19 @@ ContentChild::DeallocPTestShell(PTestShellChild* shell)
|
|||
return true;
|
||||
}
|
||||
|
||||
jsipc::JavaScriptChild *
|
||||
ContentChild::GetCPOWManager()
|
||||
{
|
||||
if (ManagedPJavaScriptChild().Length()) {
|
||||
return static_cast<JavaScriptChild*>(ManagedPJavaScriptChild()[0]);
|
||||
}
|
||||
JavaScriptChild* actor = static_cast<JavaScriptChild*>(SendPJavaScriptConstructor());
|
||||
return actor;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvPTestShellConstructor(PTestShellChild* actor)
|
||||
{
|
||||
actor->SendPContextWrapperConstructor()->SendPObjectWrapperConstructor(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,10 @@ class OptionalURIParams;
|
|||
class URIParams;
|
||||
}// namespace ipc
|
||||
|
||||
namespace jsipc {
|
||||
class JavaScriptChild;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
class PCompositorChild;
|
||||
} // namespace layers
|
||||
|
@ -126,6 +130,7 @@ public:
|
|||
virtual PTestShellChild* AllocPTestShell();
|
||||
virtual bool DeallocPTestShell(PTestShellChild*);
|
||||
virtual bool RecvPTestShellConstructor(PTestShellChild*);
|
||||
jsipc::JavaScriptChild *GetCPOWManager();
|
||||
|
||||
virtual PNeckoChild* AllocPNecko();
|
||||
virtual bool DeallocPNecko(PNeckoChild*);
|
||||
|
@ -156,6 +161,9 @@ public:
|
|||
const InfallibleTArray<OverrideMapping>& overrides,
|
||||
const nsCString& locale);
|
||||
|
||||
virtual mozilla::jsipc::PJavaScriptChild* AllocPJavaScript();
|
||||
virtual bool DeallocPJavaScript(mozilla::jsipc::PJavaScriptChild*);
|
||||
|
||||
virtual bool RecvSetOffline(const bool& offline);
|
||||
|
||||
virtual bool RecvNotifyVisited(const URIParams& aURI);
|
||||
|
|
|
@ -119,6 +119,7 @@ using namespace mozilla::system;
|
|||
#include "BluetoothService.h"
|
||||
#endif
|
||||
|
||||
#include "JavaScriptParent.h"
|
||||
#include "Crypto.h"
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
|
@ -140,6 +141,7 @@ using namespace mozilla::idl;
|
|||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::net;
|
||||
using namespace mozilla::jsipc;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -905,8 +907,6 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
|||
threadInt(do_QueryInterface(NS_GetCurrentThread()));
|
||||
if (threadInt)
|
||||
threadInt->RemoveObserver(this);
|
||||
if (mRunToCompletionDepth)
|
||||
mRunToCompletionDepth = 0;
|
||||
|
||||
MarkAsDead();
|
||||
|
||||
|
@ -1010,6 +1010,16 @@ ContentParent::NotifyTabDestroyed(PBrowserParent* aTab,
|
|||
}
|
||||
}
|
||||
|
||||
jsipc::JavaScriptParent*
|
||||
ContentParent::GetCPOWManager()
|
||||
{
|
||||
if (ManagedPJavaScriptParent().Length()) {
|
||||
return static_cast<JavaScriptParent*>(ManagedPJavaScriptParent()[0]);
|
||||
}
|
||||
JavaScriptParent* actor = static_cast<JavaScriptParent*>(SendPJavaScriptConstructor());
|
||||
return actor;
|
||||
}
|
||||
|
||||
TestShellParent*
|
||||
ContentParent::CreateTestShell()
|
||||
{
|
||||
|
@ -1039,8 +1049,6 @@ ContentParent::ContentParent(mozIApplication* aApp,
|
|||
, mOSPrivileges(aOSPrivileges)
|
||||
, mChildID(gContentChildID++)
|
||||
, mGeolocationWatchID(-1)
|
||||
, mRunToCompletionDepth(0)
|
||||
, mShouldCallUnblockChild(false)
|
||||
, mForceKillTask(nullptr)
|
||||
, mNumDestroyingTabs(0)
|
||||
, mIsAlive(true)
|
||||
|
@ -1582,6 +1590,24 @@ ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline)
|
|||
return true;
|
||||
}
|
||||
|
||||
mozilla::jsipc::PJavaScriptParent *
|
||||
ContentParent::AllocPJavaScript()
|
||||
{
|
||||
mozilla::jsipc::JavaScriptParent *parent = new mozilla::jsipc::JavaScriptParent();
|
||||
if (!parent->init()) {
|
||||
delete parent;
|
||||
return NULL;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::DeallocPJavaScript(PJavaScriptParent *parent)
|
||||
{
|
||||
static_cast<mozilla::jsipc::JavaScriptParent *>(parent)->destroyFromContent();
|
||||
return true;
|
||||
}
|
||||
|
||||
PBrowserParent*
|
||||
ContentParent::AllocPBrowser(const IPCTabContext& aContext,
|
||||
const uint32_t &aChromeFlags)
|
||||
|
@ -2051,32 +2077,6 @@ ContentParent::RecvPSpeechSynthesisConstructor(PSpeechSynthesisParent* aActor)
|
|||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::ReportChildAlreadyBlocked()
|
||||
{
|
||||
if (!mRunToCompletionDepth) {
|
||||
#ifdef DEBUG
|
||||
printf("Running to completion...\n");
|
||||
#endif
|
||||
mRunToCompletionDepth = 1;
|
||||
mShouldCallUnblockChild = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RequestRunToCompletion()
|
||||
{
|
||||
if (!mRunToCompletionDepth &&
|
||||
BlockChild()) {
|
||||
#ifdef DEBUG
|
||||
printf("Running to completion...\n");
|
||||
#endif
|
||||
mRunToCompletionDepth = 1;
|
||||
mShouldCallUnblockChild = true;
|
||||
}
|
||||
return !!mRunToCompletionDepth;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvStartVisitedQuery(const URIParams& aURI)
|
||||
{
|
||||
|
@ -2245,9 +2245,6 @@ ContentParent::OnProcessNextEvent(nsIThreadInternal *thread,
|
|||
bool mayWait,
|
||||
uint32_t recursionDepth)
|
||||
{
|
||||
if (mRunToCompletionDepth)
|
||||
++mRunToCompletionDepth;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2256,17 +2253,6 @@ NS_IMETHODIMP
|
|||
ContentParent::AfterProcessNextEvent(nsIThreadInternal *thread,
|
||||
uint32_t recursionDepth)
|
||||
{
|
||||
if (mRunToCompletionDepth &&
|
||||
!--mRunToCompletionDepth) {
|
||||
#ifdef DEBUG
|
||||
printf("... ran to completion.\n");
|
||||
#endif
|
||||
if (mShouldCallUnblockChild) {
|
||||
mShouldCallUnblockChild = false;
|
||||
UnblockChild();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,10 @@ class URIParams;
|
|||
class TestShellParent;
|
||||
} // namespace ipc
|
||||
|
||||
namespace jsipc {
|
||||
class JavaScriptParent;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
class PCompositorParent;
|
||||
} // namespace layers
|
||||
|
@ -126,6 +130,7 @@ public:
|
|||
TestShellParent* CreateTestShell();
|
||||
bool DestroyTestShell(TestShellParent* aTestShell);
|
||||
TestShellParent* GetTestShellSingleton();
|
||||
jsipc::JavaScriptParent *GetCPOWManager();
|
||||
|
||||
void ReportChildAlreadyBlocked();
|
||||
bool RequestRunToCompletion();
|
||||
|
@ -194,6 +199,7 @@ private:
|
|||
// using them.
|
||||
using PContentParent::SendPBrowserConstructor;
|
||||
using PContentParent::SendPTestShellConstructor;
|
||||
using PContentParent::SendPJavaScriptConstructor;
|
||||
|
||||
// No more than one of !!aApp, aIsForBrowser, and aIsForPreallocated may be
|
||||
// true.
|
||||
|
@ -251,6 +257,9 @@ private:
|
|||
bool* aIsForBrowser) MOZ_OVERRIDE;
|
||||
virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline) MOZ_OVERRIDE;
|
||||
|
||||
virtual mozilla::jsipc::PJavaScriptParent* AllocPJavaScript();
|
||||
virtual bool DeallocPJavaScript(mozilla::jsipc::PJavaScriptParent*);
|
||||
|
||||
virtual PBrowserParent* AllocPBrowser(const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags);
|
||||
virtual bool DeallocPBrowser(PBrowserParent* frame);
|
||||
|
@ -414,8 +423,6 @@ private:
|
|||
|
||||
uint64_t mChildID;
|
||||
int32_t mGeolocationWatchID;
|
||||
int mRunToCompletionDepth;
|
||||
bool mShouldCallUnblockChild;
|
||||
|
||||
// This is a cache of all of the memory reporters
|
||||
// registered in the child process. To update this, one
|
||||
|
|
|
@ -42,6 +42,7 @@ LOCAL_INCLUDES += \
|
|||
-I$(topsrcdir)/dom/bluetooth \
|
||||
-I$(topsrcdir)/dom/bluetooth/ipc \
|
||||
-I$(topsrcdir)/content/media/webspeech/synth/ipc \
|
||||
-I$(topsrcdir)/js/ipc \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -DBIN_SUFFIX='"$(BIN_SUFFIX)"'
|
||||
|
|
|
@ -20,6 +20,7 @@ include protocol PSms;
|
|||
include protocol PSpeechSynthesis;
|
||||
include protocol PStorage;
|
||||
include protocol PTestShell;
|
||||
include protocol PJavaScript;
|
||||
include DOMTypes;
|
||||
include InputStreamParams;
|
||||
include URIParams;
|
||||
|
@ -252,6 +253,7 @@ rpc protocol PContent
|
|||
manages PSpeechSynthesis;
|
||||
manages PStorage;
|
||||
manages PTestShell;
|
||||
manages PJavaScript;
|
||||
|
||||
both:
|
||||
// Depending on exactly how the new browser is being created, it might be
|
||||
|
@ -281,6 +283,8 @@ both:
|
|||
|
||||
async PBlob(BlobConstructorParams params);
|
||||
|
||||
PJavaScript();
|
||||
|
||||
child:
|
||||
/**
|
||||
* Update OS process privileges to |privs|. Can usually only be
|
||||
|
|
|
@ -1529,7 +1529,10 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
|
|||
utils->SetScrollPositionClampingScrollPortSize(
|
||||
cssCompositedRect.width, cssCompositedRect.height);
|
||||
ScrollWindowTo(window, aFrameMetrics.mScrollOffset);
|
||||
CSSToScreenScale resolution = aFrameMetrics.CalculateResolution();
|
||||
LayoutDeviceToLayerScale resolution =
|
||||
aFrameMetrics.CalculateResolution()
|
||||
/ aFrameMetrics.mDevPixelsPerCSSPixel
|
||||
* ScreenToLayerScale(1);
|
||||
utils->SetResolution(resolution.scale, resolution.scale);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
|
|
|
@ -15,6 +15,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=857555
|
|||
|
||||
addLoadEvent(function() {
|
||||
is(content, $("t").contentWindow, "'content' as iframe name should work");
|
||||
is(sidebar, $("u").contentWindow, "'sidebar' as iframe name should work");
|
||||
is(external, $("v").contentWindow, "'external' as iframe name should work");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
|
@ -24,6 +26,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=857555
|
|||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<iframe name="content" id="t"></iframe>
|
||||
<iframe name="sidebar" id="u"></iframe>
|
||||
<iframe name="external" id="v"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
|
|
@ -45,3 +45,9 @@ partial interface HTMLVideoElement {
|
|||
// True if the video has an audio track available.
|
||||
readonly attribute boolean mozHasAudio;
|
||||
};
|
||||
|
||||
// https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#idl-def-HTMLVideoElement
|
||||
partial interface HTMLVideoElement {
|
||||
[Pref="media.mediasource.enabled"]
|
||||
readonly attribute VideoPlaybackQuality videoPlaybackQuality;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
enum MediaSourceReadyState {
|
||||
"closed",
|
||||
"open",
|
||||
"ended"
|
||||
};
|
||||
|
||||
enum MediaSourceEndOfStreamError {
|
||||
"network",
|
||||
"decode"
|
||||
};
|
||||
|
||||
[Constructor, Pref="media.mediasource.enabled"]
|
||||
interface MediaSource : EventTarget {
|
||||
readonly attribute SourceBufferList sourceBuffers;
|
||||
readonly attribute SourceBufferList activeSourceBuffers;
|
||||
readonly attribute MediaSourceReadyState readyState;
|
||||
[SetterThrows]
|
||||
attribute unrestricted double duration;
|
||||
[Creator, Throws]
|
||||
SourceBuffer addSourceBuffer(DOMString type);
|
||||
[Throws]
|
||||
void removeSourceBuffer(SourceBuffer sourceBuffer);
|
||||
[Throws]
|
||||
void endOfStream(optional MediaSourceEndOfStreamError error);
|
||||
static boolean isTypeSupported(DOMString type);
|
||||
};
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче