Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2014-12-09 13:20:50 +01:00
commit 45230b6414
703 changed files with 22831 additions and 176045 deletions

View File

@ -97,3 +97,5 @@ if CONFIG['MOZ_ENABLE_GTK']:
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
include('/ipc/chromium/chromium-config.mozbuild')
FAIL_ON_WARNINGS = True

View File

@ -57,3 +57,5 @@ else:
FINAL_LIBRARY = 'xul'
include('/ipc/chromium/chromium-config.mozbuild')
FAIL_ON_WARNINGS = True

View File

@ -43,3 +43,5 @@ else:
]
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -38,3 +38,5 @@ LOCAL_INCLUDES += [
]
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -48,3 +48,5 @@ else:
]
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -725,6 +725,8 @@ var CustomEventManager = {
CaptivePortalLoginHelper.handleEvent(detail);
break;
case 'inputmethod-update-layouts':
case 'inputregistry-add':
case 'inputregistry-remove':
KeyboardHelper.handleEvent(detail);
break;
case 'do-command':
@ -868,7 +870,17 @@ let IndexedDBPromptHelper = {
let KeyboardHelper = {
handleEvent: function keyboard_handleEvent(detail) {
Keyboard.setLayouts(detail.layouts);
switch (detail.type) {
case 'inputmethod-update-layouts':
Keyboard.setLayouts(detail.layouts);
break;
case 'inputregistry-add':
case 'inputregistry-remove':
Keyboard.inputRegistryGlue.returnMessage(detail);
break;
}
}
};

View File

@ -979,7 +979,7 @@ chatbox:-moz-full-screen-ancestor > .chat-titlebar {
/* Combobox dropdown renderer */
#ContentSelectDropdown {
max-height: 400px;
-moz-binding: url("chrome://global/content/bindings/popup.xml#popup-scrollbars");
}
.contentSelectDropdown-optgroup {

View File

@ -490,5 +490,4 @@ skip-if = e10s # Bug 1100687 - test directly manipulates content (content.docume
skip-if = e10s # bug 1100687 - test directly manipulates content (content.document.getElementById)
[browser_mcb_redirect.js]
skip-if = e10s # bug 1084504 - [e10s] Mixed content detection does not take redirection into account
[browser_updatecommands.js]
[browser_windowactivation.js]

View File

@ -1,93 +0,0 @@
let testPage = "data:text/html,<body><input id='input1' value='value'><select size=2><option val=1>One</select></body>";
let browser;
function test() {
waitForExplicitFinish();
gURLBar.focus();
var tab = gBrowser.addTab();
browser = gBrowser.getBrowserForTab(tab);
gBrowser.selectedTab = tab;
addEventListener("commandupdate", checkTest, false);
function runFirstTest(event) {
browser.removeEventListener("load", runFirstTest, true);
doTest();
}
browser.addEventListener("load", runFirstTest, true);
browser.contentWindow.location = testPage;
}
let currentTest;
let tests = [
// Switch focus to 'input1'. Paste and select all should be enabled.
{ name: "focus input", test: function() { EventUtils.synthesizeKey("VK_TAB", {}) },
commands: { "cmd_copy" : true, "cmd_paste": true, "cmd_selectAll" : true, "cmd_undo" : false, "cmd_redo": false } },
// Move cursor to end which will deselect the text. Copy should be disabled but paste and select all should still be enabled.
{ name: "cursor right", test: function() { EventUtils.synthesizeKey("VK_RIGHT", {}) },
commands: { "cmd_copy" : false, "cmd_paste": true, "cmd_selectAll" : true, "cmd_undo" : false, "cmd_redo": false } },
// Select all of the text. Copy should become enabled.
{ name: "select all", test: function() { EventUtils.synthesizeKey("a", { accelKey: true }) },
commands: { "cmd_copy" : true, "cmd_paste": true, "cmd_selectAll" : true, "cmd_undo" : false, "cmd_redo": false } },
// Replace the text with 'c'. Copy should now be disabled and undo enabled.
{ name: "change value", test: function() { EventUtils.synthesizeKey("c", {}) },
commands: { "cmd_copy" : false, "cmd_paste": true, "cmd_selectAll" : true, "cmd_undo" : true, "cmd_redo": false } },
// Undo. Undo should be disabled and redo enabled. The text is reselected so copy is enabled.
{ name: "undo", test: function() { EventUtils.synthesizeKey("z", {accelKey: true }) },
commands: { "cmd_copy" : true, "cmd_paste": true, "cmd_selectAll" : true, "cmd_undo" : false, "cmd_redo": true } },
// Switch focus to the select. Only select all should now be enabled.
{ name: "focus select", test: function() { EventUtils.synthesizeKey("VK_TAB", {}) },
commands: { "cmd_copy" : false, "cmd_paste": false, "cmd_selectAll" : true, "cmd_undo" : false, "cmd_redo": false } },
];
function doTest()
{
if (!tests.length) {
removeEventListener("commandupdate", checkTest, false);
gBrowser.removeCurrentTab();
finish();
return;
}
currentTest = tests.shift();
currentTest.test();
}
function checkTest(event)
{
// Ignore commandupdates before the test starts
if (document.activeElement != browser || !currentTest) {
return;
}
// Skip events fired on command updaters other than the main edit menu one.
if (event.target != document.getElementById("editMenuCommandSetAll")) {
return;
}
for (let command in currentTest.commands) {
// Command updates can come several at a time, and, especially with multiple
// processes, the updates can come asynchronously. Handle this by just waiting
// until the command have the correct state. The test will timeout if the
// correct command update never occurs.
if ((document.getElementById(command).getAttribute("disabled") != "true") != currentTest.commands[command]) {
return;
}
is(document.getElementById(command).getAttribute("disabled") != "true", currentTest.commands[command],
currentTest["name"] + " " + command);
}
currentTest = null; // prevent the check from running again
SimpleTest.executeSoon(doTest);
}

View File

@ -203,6 +203,17 @@ BrowserToolboxProcess.prototype = {
dumpn("Running chrome debugging process.");
let args = ["-no-remote", "-foreground", "-profile", this._dbgProfilePath, "-chrome", xulURI];
// During local development, incremental builds can trigger the main process
// to clear its startup cache with the "flag file" .purgecaches, but this
// file is removed during app startup time, so we aren't able to know if it
// was present in order to also clear the child profile's startup cache as
// well.
//
// As an approximation of "isLocalBuild", check for an unofficial build.
if (!Services.appinfo.isOfficial) {
args.push("-purgecaches");
}
process.runwAsync(args, args.length, { observe: () => this.close() });
this._telemetry.toolOpened("jsbrowserdebugger");

View File

@ -205,11 +205,23 @@ this.ContentSearch = {
"searchString",
"whence",
]);
let browserWin = msg.target.ownerDocument.defaultView;
let engine = Services.search.getEngineByName(data.engineName);
browserWin.BrowserSearch.recordSearchInHealthReport(engine, data.whence, data.selection);
let submission = engine.getSubmission(data.searchString, "", data.whence);
browserWin.loadURI(submission.uri.spec, null, submission.postData);
let browser = msg.target;
try {
browser.loadURIWithFlags(submission.uri.spec,
Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null,
submission.postData);
}
catch (err) {
// The browser may have been closed between the time its content sent the
// message and the time we handle it. In that case, trying to call any
// method on it will throw.
return Promise.resolve();
}
let win = browser.ownerDocument.defaultView;
win.BrowserSearch.recordSearchInHealthReport(engine, data.whence,
data.selection || null);
return Promise.resolve();
},

View File

@ -102,24 +102,34 @@ add_task(function* search() {
});
let submissionURL =
engine.getSubmission(data.searchString, "", data.whence).uri.spec;
let deferred = Promise.defer();
let listener = {
onStateChange: function (webProg, req, flags, status) {
let url = req.originalURI.spec;
info("onStateChange " + url);
let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
Ci.nsIWebProgressListener.STATE_START;
if ((flags & docStart) && webProg.isTopLevel && url == submissionURL) {
gBrowser.removeProgressListener(listener);
ok(true, "Search URL loaded");
req.cancel(Components.results.NS_ERROR_FAILURE);
deferred.resolve();
}
}
yield waitForLoadAndStopIt(gBrowser.selectedBrowser, submissionURL);
});
add_task(function* searchInBackgroundTab() {
// This test is like search(), but it opens a new tab after starting a search
// in another. In other words, it performs a search in a background tab. The
// search page should be loaded in the same tab that performed the search, in
// the background tab.
yield addTab();
let searchBrowser = gBrowser.selectedBrowser;
let engine = Services.search.currentEngine;
let data = {
engineName: engine.name,
searchString: "ContentSearchTest",
whence: "ContentSearchTest",
};
gBrowser.addProgressListener(listener);
info("Waiting for search URL to load: " + submissionURL);
yield deferred.promise;
gMsgMan.sendAsyncMessage(TEST_MSG, {
type: "Search",
data: data,
});
let newTab = gBrowser.addTab();
gBrowser.selectedTab = newTab;
registerCleanupFunction(() => gBrowser.removeTab(newTab));
let submissionURL =
engine.getSubmission(data.searchString, "", data.whence).uri.spec;
yield waitForLoadAndStopIt(searchBrowser, submissionURL);
});
add_task(function* badImage() {
@ -319,6 +329,33 @@ function waitForNewEngine(basename, numImages) {
return Promise.all([addDeferred.promise].concat(eventPromises));
}
function waitForLoadAndStopIt(browser, expectedURL) {
let deferred = Promise.defer();
let listener = {
onStateChange: function (webProg, req, flags, status) {
if (req instanceof Ci.nsIChannel) {
let url = req.originalURI.spec;
info("onStateChange " + url);
let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
Ci.nsIWebProgressListener.STATE_START;
if ((flags & docStart) && webProg.isTopLevel && url == expectedURL) {
browser.removeProgressListener(listener);
ok(true, "Expected URL loaded");
req.cancel(Components.results.NS_ERROR_FAILURE);
deferred.resolve();
}
}
},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
]),
};
browser.addProgressListener(listener);
info("Waiting for URL to load: " + expectedURL);
return deferred.promise;
}
function addTab() {
let deferred = Promise.defer();
let tab = gBrowser.addTab();

View File

@ -507,7 +507,7 @@ class Automation(object):
env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1'
# Set WebRTC logging in case it is not set yet
env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5')
env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5,jsep:5,MediaPipelineFactory:5')
env.setdefault('R_LOG_LEVEL', '6')
env.setdefault('R_LOG_DESTINATION', 'stderr')
env.setdefault('R_LOG_VERBOSE', '1')

View File

@ -410,7 +410,7 @@ def environment(xrePath, env=None, crashreporter=True, debugger=False, dmdPath=N
env.setdefault('MOZ_DISABLE_NONLOCAL_CONNECTIONS', '1')
# Set WebRTC logging in case it is not set yet
env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5')
env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5,jsep:5,MediaPipelineFactory:5')
env.setdefault('R_LOG_LEVEL', '6')
env.setdefault('R_LOG_DESTINATION', 'stderr')
env.setdefault('R_LOG_VERBOSE', '1')

View File

@ -38,3 +38,4 @@ LOCAL_INCLUDES += [
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -42,3 +42,5 @@ LOCAL_INCLUDES += [
if CONFIG['MOZ_ENABLE_GTK']:
CXXFLAGS += CONFIG['TK_CFLAGS']
FAIL_ON_WARNINGS = True

View File

@ -26,7 +26,6 @@
#include "nsIWebNavigation.h"
#include "nsCaret.h"
#include "nsIBaseWindow.h"
#include "nsIXULWindow.h"
#include "nsViewManager.h"
#include "nsFrameSelection.h"
#include "mozilla/dom/Selection.h"
@ -735,10 +734,7 @@ nsFocusManager::WindowRaised(nsIDOMWindow* aWindow)
frameSelection->SetDragState(false);
}
// If there is no nsIXULWindow, then this is an embedded or child process window.
// Pass false for aWindowRaised so that commands get updated.
nsCOMPtr<nsIXULWindow> xulWin(do_GetInterface(baseWindow));
Focus(currentWindow, currentFocus, 0, true, false, xulWin != nullptr, true);
Focus(currentWindow, currentFocus, 0, true, false, true, true);
return NS_OK;
}

View File

@ -9270,36 +9270,6 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs_,
return rv.ErrorCode();
}
class ChildCommandDispatcher : public nsRunnable
{
public:
ChildCommandDispatcher(nsGlobalWindow* aWindow,
nsITabChild* aTabChild,
const nsAString& aAction)
: mWindow(aWindow), mTabChild(aTabChild), mAction(aAction) {}
NS_IMETHOD Run()
{
nsCOMPtr<nsPIWindowRoot> root = mWindow->GetTopWindowRoot();
if (!root) {
return NS_OK;
}
nsTArray<nsCString> enabledCommands, disabledCommands;
root->GetEnabledDisabledCommands(enabledCommands, disabledCommands);
if (enabledCommands.Length() || disabledCommands.Length()) {
mTabChild->EnableDisableCommands(mAction, enabledCommands, disabledCommands);
}
return NS_OK;
}
private:
nsRefPtr<nsGlobalWindow> mWindow;
nsCOMPtr<nsITabChild> mTabChild;
nsString mAction;
};
class CommandDispatcher : public nsRunnable
{
public:
@ -9319,12 +9289,6 @@ public:
NS_IMETHODIMP
nsGlobalWindow::UpdateCommands(const nsAString& anAction, nsISelection* aSel, int16_t aReason)
{
// If this is a child process, redirect to the parent process.
if (nsCOMPtr<nsITabChild> child = do_GetInterface(GetDocShell())) {
nsContentUtils::AddScriptRunner(new ChildCommandDispatcher(this, child, anAction));
return NS_OK;
}
nsPIDOMWindow *rootWindow = nsGlobalWindow::GetPrivateRoot();
if (!rootWindow)
return NS_OK;

View File

@ -15,8 +15,8 @@ class nsIControllers;
class nsIController;
#define NS_IWINDOWROOT_IID \
{ 0x728a2682, 0x55c0, 0x4860, \
{ 0x82, 0x6b, 0x0c, 0x30, 0x0a, 0xac, 0xaa, 0x60 } }
{ 0x3f71f50c, 0xa7e0, 0x43bc, \
{ 0xac, 0x25, 0x4d, 0xbb, 0x88, 0x7b, 0x21, 0x09 } }
class nsPIWindowRoot : public mozilla::dom::EventTarget
{
@ -33,9 +33,6 @@ public:
nsIController** aResult) = 0;
virtual nsresult GetControllers(nsIControllers** aResult) = 0;
virtual void GetEnabledDisabledCommands(nsTArray<nsCString>& aEnabledCommands,
nsTArray<nsCString>& aDisabledCommands) = 0;
virtual void SetParentTarget(mozilla::dom::EventTarget* aTarget) = 0;
virtual mozilla::dom::EventTarget* GetParentTarget() = 0;
virtual nsIDOMWindow* GetOwnerGlobal() MOZ_OVERRIDE = 0;

View File

@ -281,75 +281,6 @@ nsWindowRoot::GetControllerForCommand(const char * aCommand,
return NS_OK;
}
void
nsWindowRoot::GetEnabledDisabledCommandsForControllers(nsIControllers* aControllers,
nsTHashtable<nsCharPtrHashKey>& aCommandsHandled,
nsTArray<nsCString>& aEnabledCommands,
nsTArray<nsCString>& aDisabledCommands)
{
uint32_t controllerCount;
aControllers->GetControllerCount(&controllerCount);
for (uint32_t c = 0; c < controllerCount; c++) {
nsCOMPtr<nsIController> controller;
aControllers->GetControllerAt(c, getter_AddRefs(controller));
nsCOMPtr<nsICommandController> commandController(do_QueryInterface(controller));
if (commandController) {
uint32_t commandsCount;
char** commands;
if (NS_SUCCEEDED(commandController->GetSupportedCommands(&commandsCount, &commands))) {
for (uint32_t e = 0; e < commandsCount; e++) {
// Use a hash to determine which commands have already been handled by
// earlier controllers, as the earlier controller's result should get
// priority.
if (!aCommandsHandled.Contains(commands[e])) {
aCommandsHandled.PutEntry(commands[e]);
bool enabled = false;
controller->IsCommandEnabled(commands[e], &enabled);
const nsDependentCSubstring commandStr(commands[e], strlen(commands[e]));
if (enabled) {
aEnabledCommands.AppendElement(commandStr);
} else {
aDisabledCommands.AppendElement(commandStr);
}
}
}
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(commandsCount, commands);
}
}
}
}
void
nsWindowRoot::GetEnabledDisabledCommands(nsTArray<nsCString>& aEnabledCommands,
nsTArray<nsCString>& aDisabledCommands)
{
nsTHashtable<nsCharPtrHashKey> commandsHandled;
nsCOMPtr<nsIControllers> controllers;
GetControllers(getter_AddRefs(controllers));
if (controllers) {
GetEnabledDisabledCommandsForControllers(controllers, commandsHandled,
aEnabledCommands, aDisabledCommands);
}
nsCOMPtr<nsPIDOMWindow> focusedWindow;
nsFocusManager::GetFocusedDescendant(mWindow, true, getter_AddRefs(focusedWindow));
while (focusedWindow) {
focusedWindow->GetControllers(getter_AddRefs(controllers));
if (controllers) {
GetEnabledDisabledCommandsForControllers(controllers, commandsHandled,
aEnabledCommands, aDisabledCommands);
}
nsGlobalWindow* win = static_cast<nsGlobalWindow*>(focusedWindow.get());
focusedWindow = win->GetPrivateParent();
}
}
nsIDOMNode*
nsWindowRoot::GetPopupNode()
{

View File

@ -23,8 +23,6 @@ class EventChainPreVisitor;
#include "nsPIWindowRoot.h"
#include "nsCycleCollectionParticipant.h"
#include "nsAutoPtr.h"
#include "nsTHashtable.h"
#include "nsHashKeys.h"
class nsWindowRoot : public nsPIWindowRoot
{
@ -54,9 +52,6 @@ public:
virtual nsresult GetControllerForCommand(const char * aCommand,
nsIController** _retval) MOZ_OVERRIDE;
virtual void GetEnabledDisabledCommands(nsTArray<nsCString>& aEnabledCommands,
nsTArray<nsCString>& aDisabledCommands) MOZ_OVERRIDE;
virtual nsIDOMNode* GetPopupNode() MOZ_OVERRIDE;
virtual void SetPopupNode(nsIDOMNode* aNode) MOZ_OVERRIDE;
@ -77,11 +72,6 @@ public:
protected:
virtual ~nsWindowRoot();
void GetEnabledDisabledCommandsForControllers(nsIControllers* aControllers,
nsTHashtable<nsCharPtrHashKey>& aCommandsHandled,
nsTArray<nsCString>& aEnabledCommands,
nsTArray<nsCString>& aDisabledCommands);
// Members
nsCOMPtr<nsPIDOMWindow> mWindow;
// We own the manager, which owns event listeners attached to us.

View File

@ -278,9 +278,9 @@ nsresult TestIgnoreUpperLowerCasePolicies() {
return runTestSuite(policies, policyCount, 1);
}
// ============================= TestIgnorePaths ========================
// ============================= TestPaths ========================
nsresult TestIgnorePaths() {
nsresult TestPaths() {
static const PolicyTest policies[] =
{
@ -360,6 +360,12 @@ nsresult TestIgnorePaths() {
"report-uri http://www.example.com:8888/path_1/path_2/report.sjs&301" },
{ "report-uri /examplepath",
"report-uri http://www.selfuri.com/examplepath" },
{ "connect-src http://www.example.com/foo%3Bsessionid=12%2C34",
"connect-src http://www.example.com/foo;sessionid=12,34" },
{ "connect-src http://www.example.com/foo%3bsessionid=12%2c34",
"connect-src http://www.example.com/foo;sessionid=12,34" },
{ "connect-src http://test.com/pathIncludingAz19-._~!$&'()*+=:@",
"connect-src http://test.com/pathincludingaz19-._~!$&'()*+=:@" },
};
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
@ -492,6 +498,10 @@ nsresult TestPoliciesWithInvalidSrc() {
"script-src 'none'" },
{ "script-src http://www.example.com:*.",
"script-src 'none'" },
{ "connect-src http://www.example.com/foo%zz;",
"connect-src 'none'" },
{ "script-src https://foo.com/%$",
"script-src 'none'" },
};
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
@ -1083,7 +1093,7 @@ int main(int argc, char** argv) {
if (NS_FAILED(TestDirectives())) { return 1; }
if (NS_FAILED(TestKeywords())) { return 1; }
if (NS_FAILED(TestIgnoreUpperLowerCasePolicies())) { return 1; }
if (NS_FAILED(TestIgnorePaths())) { return 1; }
if (NS_FAILED(TestPaths())) { return 1; }
if (NS_FAILED(TestSimplePolicies())) { return 1; }
if (NS_FAILED(TestPoliciesWithInvalidSrc())) { return 1; }
if (NS_FAILED(TestBadPolicies())) { return 1; }

View File

@ -20,6 +20,8 @@ var tests = { "font-src": thisSite+page+"?testid=font-src&csp=1",
"style-src": thisSite+page+"?testid=style-src&csp=1",
"worker": thisSite+page+"?testid=worker&csp=1",
"xhr-src": thisSite+page+"?testid=xhr-src&csp=1",
"script-src-from-worker": thisSite+page+"?testid=script-src-from-worker&csp=1",
"img-src-from-css": thisSite+page+"?testid=img-src-from-css&csp=1",
};
var container = document.getElementById("container");

View File

@ -76,4 +76,21 @@ function handleRequest(request, response)
response.write('<script src="'+resource+'?res=xhr"></script>');
return;
}
// for bug949706
if (query["testid"] == "img-src-from-css") {
// loads a stylesheet, which in turn loads an image that redirects.
response.write('<link rel="stylesheet" type="text/css" href="'+resource+'?res=cssLoader&id=img-src-redir-from-css">');
return;
}
if (query["testid"] == "script-src-from-worker") {
// loads a script; launches a worker; that worker uses importscript; which then gets redirected
// So it's:
// <script "res=loadWorkerThatImports">
// .. loads Worker("res=importScriptWorker")
// .. calls importScript("res=script")
response.write('<script src="'+resource+'?res=loadWorkerThatImports&id=script-src-redir-from-worker"></script>');
return;
}
}

View File

@ -92,6 +92,34 @@ function handleRequest(request, response)
return;
}
// internal stylesheet that loads an image from an external site
if (query["res"] == "cssLoader") {
let bgURL = thisSite + resource + '?redir=other&res=image&id=' + query["id"];
response.setHeader("Content-Type", "text/css", false);
response.write("body { background:url('" + bgURL + "'); }");
return;
}
// script that loads an internal worker that uses importScripts on a redirect
// to an external script.
if (query["res"] == "loadWorkerThatImports") {
// this creates a worker (same origin) that imports a redirecting script.
let workerURL = thisSite + resource + '?res=importScriptWorker&id=' + query["id"];
response.setHeader("Content-Type", "application/javascript", false);
response.write("var w=new Worker('" + workerURL + "'); w.onmessage=function(event){ alert(event.data); }");
return;
}
// source for a worker that simply calls importScripts on a script that
// redirects.
if (query["res"] == "importScriptWorker") {
// this is code for a worker that imports a redirected script.
let scriptURL = thisSite + resource + "?redir=other&res=script&id=" + query["id"];
response.setHeader("Content-Type", "application/javascript", false);
response.write("importScripts('" + scriptURL + "');");
return;
}
// script that invokes XHR
if (query["res"] == "xhr") {
response.setHeader("Content-Type", "text/html", false);

View File

@ -0,0 +1,9 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 949706 - CSP: Correct handling of web workers importing scripts that get redirected</title>
</head>
<body>
<script src="file_worker_redirect.sjs?stage_0_script_loads_worker"></script>
</body>
</html>

View File

@ -0,0 +1,37 @@
// testserver customized for the needs of:
// Bug 949706 - CSP: Correct handling of web workers importing scripts that get redirected
function handleRequest(request, response)
{
response.setHeader("Cache-Control", "no-cache", false);
response.setHeader("Content-Type", "text/html", false);
var query = request.queryString;
if (query === "stage_0_script_loads_worker") {
var newWorker =
"var myWorker = new Worker(\"file_worker_redirect.sjs?stage_1_worker_import_scripts\");" +
"myWorker.onmessage = function (event) { parent.checkResult(\"allowed\"); };" +
"myWorker.onerror = function (event) { parent.checkResult(\"blocked\"); };";
response.write(newWorker);
return;
}
if (query === "stage_1_worker_import_scripts") {
response.write("importScripts(\"file_worker_redirect.sjs?stage_2_redirect_imported_script\");");
return;
}
if (query === "stage_2_redirect_imported_script") {
var newLocation =
"http://test1.example.com/tests/dom/base/test/csp/file_worker_redirect.sjs?stage_3_target_script";
response.setStatusLine("1.1", 302, "Found");
response.setHeader("Location", newLocation, false);
return;
}
if (query === "stage_3_target_script") {
response.write("postMessage(\"imported script loaded\");");
return;
}
}

View File

@ -101,6 +101,8 @@ support-files =
file_multi_policy_injection_bypass_2.html
file_multi_policy_injection_bypass_2.html^headers^
file_form-action.html
file_worker_redirect.html
file_worker_redirect.sjs
[test_base-uri.html]
[test_connect-src.html]
@ -147,3 +149,4 @@ skip-if = buildapp == 'b2g' # intermittent orange (bug 1028490)
[test_subframe_run_js_if_allowed.html]
[test_leading_wildcard.html]
[test_multi_policy_injection_bypass.html]
[test_worker_redirect.html]

View File

@ -86,6 +86,10 @@ var testExpectedResults = { "font-src": true,
"worker-redir": false,
"xhr-src": true,
"xhr-src-redir": false,
"script-src-from-worker": true, /* test runs */
"script-src-redir-from-worker": false, /* redir is blocked */
"img-src-from-css": true, /* test runs */
"img-src-redir-from-css": false, /* redir is blocked */
};
// takes the name of the test, the URL that was tested, and whether the

View File

@ -0,0 +1,76 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 949706 - CSP: Correct handling of web workers importing scripts that get redirected</title>
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<div id="content" style="visibility: hidden">
<iframe style="width:100%;" id="testframe"></iframe>
</div>
<script class="testbody" type="text/javascript">
/* Description of the test:
* We load a page that loads a script which then instantiates a web worker,
* where that web worker then imports a script which gets redirected.
* We verify that the CSP applies correctly after the imported script of
* the worker gets redirected. More specifically, the test works as follows:
*
* test_worker_redirect.html
* -> loads file_worker_redirect.html file into iframe
* -> loads worker file_worker_redirect.sjs?stage_0_script_loads_worker
* -> creates script file_worker_redirect.sjs?stage_1_worker_import_scripts
* -> redirects script file_worker_redirect.sjs?stage_2_redirect_imported_script
* -> loads target script file_worker_redirect.sjs?stage_3_target_script
*
* Please note that we have to use 'unsafe-eval' in the policy
* so that workers are actually permitted by the CSP.
*
* The main test is loaded using:
* http://mochi.test:8888
* where the imported script gets redirected to:
* http://test1.example.com
*/
var tests = [
{
policy: "default-src 'self'; script-src 'self' 'unsafe-eval' http://test1.example.com;",
expected: "allowed"
},
{
policy: "default-src 'self'; script-src 'self' 'unsafe-eval';",
expected: "blocked",
},
];
var counter = 0;
var curTest;
function checkResult(aResult) {
is(aResult, curTest.expected, "Should be (" + curTest.expected + ") in Test " + counter + "!");
loadNextTest();
}
function loadNextTest() {
if (counter == tests.length) {
SimpleTest.finish();
return;
}
curTest = tests[counter++];
var src = "file_csp_testserver.sjs";
// append the file that should be served
src += "?file=" + escape("tests/dom/base/test/csp/file_worker_redirect.html");
// append the CSP that should be used to serve the file
src += "&csp=" + escape(curTest.policy);
document.getElementById("testframe").src = src;
}
SimpleTest.waitForExplicitFinish();
loadNextTest();
</script>
</body>
</html>

View File

@ -862,7 +862,7 @@ DOMInterfaces = {
},
'PeerConnectionImpl': {
'nativeType': 'sipcc::PeerConnectionImpl',
'nativeType': 'mozilla::PeerConnectionImpl',
'headerFile': 'PeerConnectionImpl.h',
'wrapperCache': False
},

View File

@ -64,6 +64,7 @@ LOCAL_INCLUDES += [
'/layout/style',
'/layout/xul/tree',
'/media/mtransport',
'/media/webrtc/',
'/media/webrtc/signaling/src/common/time_profiling',
'/media/webrtc/signaling/src/peerconnection',
]

View File

@ -19,6 +19,36 @@ XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
"resource://gre/modules/SystemAppProxy.jsm");
XPCOMUtils.defineLazyGetter(this, "appsService", function() {
return Cc["@mozilla.org/AppsService;1"].getService(Ci.nsIAppsService);
});
let Utils = {
getMMFromMessage: function u_getMMFromMessage(msg) {
let mm;
try {
mm = msg.target.QueryInterface(Ci.nsIFrameLoaderOwner)
.frameLoader.messageManager;
} catch(e) {
mm = msg.target;
}
return mm;
},
checkPermissionForMM: function u_checkPermissionForMM(mm, permName) {
let testing = false;
try {
testing = Services.prefs.getBoolPref("dom.mozInputMethod.testing");
} catch (e) { }
if (testing) {
return true;
}
return mm.assertPermission(permName);
}
};
this.Keyboard = {
_formMM: null, // The current web page message manager.
_keyboardMM: null, // The keyboard app message manager.
@ -72,6 +102,8 @@ this.Keyboard = {
for (let name of this._systemMessageName) {
ppmm.addMessageListener('System:' + name, this);
}
this.inputRegistryGlue = new InputRegistryGlue();
},
observe: function keyboardObserve(subject, topic, data) {
@ -122,12 +154,7 @@ this.Keyboard = {
return;
}
try {
mm = msg.target.QueryInterface(Ci.nsIFrameLoaderOwner)
.frameLoader.messageManager;
} catch(e) {
mm = msg.target;
}
mm = Utils.getMMFromMessage(msg);
// That should never happen.
if (!mm) {
@ -135,16 +162,10 @@ this.Keyboard = {
return;
}
let testing = false;
try {
testing = Services.prefs.getBoolPref("dom.mozInputMethod.testing");
} catch (e) {
}
let perm = (msg.name.indexOf("Keyboard:") === 0) ? "input"
: "input-manage";
if (!isKeyboardRegistration && !testing &&
!mm.assertPermission(perm)) {
if (!isKeyboardRegistration && !Utils.checkPermissionForMM(mm, perm)) {
dump("Keyboard message " + msg.name +
" from a content process with no '" + perm + "' privileges.");
return;
@ -364,4 +385,93 @@ this.Keyboard = {
}
};
function InputRegistryGlue() {
this._messageId = 0;
this._msgMap = new Map();
ppmm.addMessageListener('InputRegistry:Add', this);
ppmm.addMessageListener('InputRegistry:Remove', this);
};
InputRegistryGlue.prototype.receiveMessage = function(msg) {
let mm = Utils.getMMFromMessage(msg);
if (!Utils.checkPermissionForMM(mm, 'input')) {
dump("InputRegistryGlue message " + msg.name +
" from a content process with no 'input' privileges.");
return;
}
switch (msg.name) {
case 'InputRegistry:Add':
this.addInput(msg, mm);
break;
case 'InputRegistry:Remove':
this.removeInput(msg, mm);
break;
}
};
InputRegistryGlue.prototype.addInput = function(msg, mm) {
let msgId = this._messageId++;
this._msgMap.set(msgId, {
mm: mm,
requestId: msg.data.requestId
});
let manifestURL = appsService.getManifestURLByLocalId(msg.data.appId);
SystemAppProxy.dispatchEvent({
type: 'inputregistry-add',
id: msgId,
manifestURL: manifestURL,
inputId: msg.data.inputId,
inputManifest: msg.data.inputManifest
});
};
InputRegistryGlue.prototype.removeInput = function(msg, mm) {
let msgId = this._messageId++;
this._msgMap.set(msgId, {
mm: mm,
requestId: msg.data.requestId
});
let manifestURL = appsService.getManifestURLByLocalId(msg.data.appId);
SystemAppProxy.dispatchEvent({
type: 'inputregistry-remove',
id: msgId,
manifestURL: manifestURL,
inputId: msg.data.inputId
});
};
InputRegistryGlue.prototype.returnMessage = function(detail) {
if (!this._msgMap.has(detail.id)) {
return;
}
let { mm, requestId } = this._msgMap.get(detail.id);
this._msgMap.delete(detail.id);
if (Cu.isDeadWrapper(mm)) {
return;
}
if (!('error' in detail)) {
mm.sendAsyncMessage('InputRegistry:Result:OK', {
requestId: requestId
});
} else {
mm.sendAsyncMessage('InputRegistry:Result:Error', {
error: detail.error,
requestId: requestId
});
}
};
this.Keyboard.init();

View File

@ -149,6 +149,8 @@ MozInputMethodManager.prototype = {
function MozInputMethod() { }
MozInputMethod.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
_inputcontext: null,
_wrappedInputContext: null,
_layouts: {},
@ -196,6 +198,8 @@ MozInputMethod.prototype = {
cpmm.addWeakMessageListener('Keyboard:SelectionChange', this);
cpmm.addWeakMessageListener('Keyboard:GetContext:Result:OK', this);
cpmm.addWeakMessageListener('Keyboard:LayoutsChange', this);
cpmm.addWeakMessageListener('InputRegistry:Result:OK', this);
cpmm.addWeakMessageListener('InputRegistry:Result:Error', this);
},
uninit: function mozInputMethodUninit() {
@ -210,21 +214,26 @@ MozInputMethod.prototype = {
cpmm.removeWeakMessageListener('Keyboard:SelectionChange', this);
cpmm.removeWeakMessageListener('Keyboard:GetContext:Result:OK', this);
cpmm.removeWeakMessageListener('Keyboard:LayoutsChange', this);
cpmm.removeWeakMessageListener('InputRegistry:Result:OK', this);
cpmm.removeWeakMessageListener('InputRegistry:Result:Error', this);
this.setActive(false);
},
receiveMessage: function mozInputMethodReceiveMsg(msg) {
if (!WindowMap.isActive(this._window)) {
if (!msg.name.startsWith('InputRegistry') &&
!WindowMap.isActive(this._window)) {
return;
}
let json = msg.json;
let data = msg.data;
let resolver = ('requestId' in data) ?
this.takePromiseResolver(data.requestId) : null;
switch(msg.name) {
case 'Keyboard:FocusChange':
if (json.type !== 'blur') {
if (data.type !== 'blur') {
// XXX Bug 904339 could receive 'text' event twice
this.setInputContext(json);
this.setInputContext(data);
}
else {
this.setInputContext(null);
@ -232,14 +241,24 @@ MozInputMethod.prototype = {
break;
case 'Keyboard:SelectionChange':
if (this.inputcontext) {
this._inputcontext.updateSelectionContext(json, false);
this._inputcontext.updateSelectionContext(data, false);
}
break;
case 'Keyboard:GetContext:Result:OK':
this.setInputContext(json);
this.setInputContext(data);
break;
case 'Keyboard:LayoutsChange':
this._layouts = json;
this._layouts = data;
break;
case 'InputRegistry:Result:OK':
resolver.resolve();
break;
case 'InputRegistry:Result:Error':
resolver.reject(data.error);
break;
}
},
@ -330,6 +349,31 @@ MozInputMethod.prototype = {
}
},
addInput: function(inputId, inputManifest) {
return this._sendPromise(function(resolverId) {
let appId = this._window.document.nodePrincipal.appId;
cpmm.sendAsyncMessage('InputRegistry:Add', {
requestId: resolverId,
inputId: inputId,
inputManifest: inputManifest,
appId: appId
});
}.bind(this));
},
removeInput: function(inputId) {
return this._sendPromise(function(resolverId) {
let appId = this._window.document.nodePrincipal.appId;
cpmm.sendAsyncMessage('InputRegistry:Remove', {
requestId: resolverId,
inputId: inputId,
appId: appId
});
}.bind(this));
},
setValue: function(value) {
this._ensureIsSystem();
cpmm.sendAsyncMessage('System:SetValue', {
@ -361,6 +405,14 @@ MozInputMethod.prototype = {
throw new this._window.DOMError("Security",
"Should have 'input-manage' permssion.");
}
},
_sendPromise: function(callback) {
let self = this;
return this.createPromise(function(resolve, reject) {
let resolverId = self.getPromiseResolverId({ resolve: resolve, reject: reject });
callback(resolverId);
});
}
};

View File

@ -31,7 +31,6 @@ XPIDL_SOURCES += [
'nsIFrameRequestCallback.idl',
'nsIIdleObserver.idl',
'nsIQueryContentEventResult.idl',
'nsIRemoteBrowser.idl',
'nsIServiceWorkerManager.idl',
'nsIStructuredCloneContainer.idl',
'nsITabChild.idl',

View File

@ -1,26 +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/. */
#include "nsISupports.idl"
[scriptable, uuid(C8379366-F79F-4D25-89A6-22BEC0A93D16)]
interface nsIRemoteBrowser : nsISupports
{
/*
* Called by the child to inform the parent that a command update has occurred
* and the supplied set of commands are now enabled and disabled.
*
* @param action command updater action
* @param enabledLength length of enabledCommands array
* @param enabledCommands commands to enable
* @param disabledLength length of disabledCommands array
* @param disabledCommand commands to disable
*/
void enableDisableCommands(in AString action,
in unsigned long enabledLength,
[array, size_is(enabledLength)] in string enabledCommands,
in unsigned long disabledLength,
[array, size_is(disabledLength)] in string disabledCommands);
};

View File

@ -7,10 +7,7 @@
interface nsIContentFrameMessageManager;
interface nsIWebBrowserChrome3;
native CommandsArray(nsTArray<nsCString>);
[ref] native CommandsArrayRef(nsTArray<nsCString>);
[scriptable, uuid(7227bac4-b6fe-4090-aeb4-bc288b790925)]
[scriptable, uuid(2eb3bc54-78bf-40f2-b301-a5b5b70f7da0)]
interface nsITabChild : nsISupports
{
readonly attribute nsIContentFrameMessageManager messageManager;
@ -18,9 +15,5 @@ interface nsITabChild : nsISupports
attribute nsIWebBrowserChrome3 webBrowserChrome;
[notxpcom] void sendRequestFocus(in boolean canFocus);
[noscript, notxpcom] void enableDisableCommands(in AString action,
in CommandsArrayRef enabledCommands,
in CommandsArrayRef disabledCommands);
};

View File

@ -244,14 +244,6 @@ parent:
*/
RequestFocus(bool canRaise);
/**
* Indicate, based on the current state, that some commands are enabled and
* some are disabled.
*/
EnableDisableCommands(nsString action,
nsCString[] enabledCommands,
nsCString[] disabledCommands);
prio(urgent) sync GetInputContext() returns (int32_t IMEEnabled,
int32_t IMEOpen,
intptr_t NativeIMEContext);

View File

@ -3226,15 +3226,6 @@ TabChild::SendRequestFocus(bool aCanFocus)
PBrowserChild::SendRequestFocus(aCanFocus);
}
void
TabChild::EnableDisableCommands(const nsAString& aAction,
nsTArray<nsCString>& aEnabledCommands,
nsTArray<nsCString>& aDisabledCommands)
{
PBrowserChild::SendEnableDisableCommands(PromiseFlatString(aAction),
aEnabledCommands, aDisabledCommands);
}
bool
TabChild::DoSendBlockingMessage(JSContext* aCx,
const nsAString& aMessage,

View File

@ -47,7 +47,6 @@
#include "nsIWindowCreator2.h"
#include "nsIXULBrowserWindow.h"
#include "nsIXULWindow.h"
#include "nsIRemoteBrowser.h"
#include "nsViewManager.h"
#include "nsIWidget.h"
#include "nsIWindowWatcher.h"
@ -1468,37 +1467,6 @@ TabParent::RecvRequestFocus(const bool& aCanRaise)
return true;
}
bool
TabParent::RecvEnableDisableCommands(const nsString& aAction,
const nsTArray<nsCString>& aEnabledCommands,
const nsTArray<nsCString>& aDisabledCommands)
{
nsCOMPtr<nsIRemoteBrowser> remoteBrowser = do_QueryInterface(mFrameElement);
if (remoteBrowser) {
nsAutoArrayPtr<const char*> enabledCommands, disabledCommands;
if (aEnabledCommands.Length()) {
enabledCommands = new const char* [aEnabledCommands.Length()];
for (uint32_t c = 0; c < aEnabledCommands.Length(); c++) {
enabledCommands[c] = aEnabledCommands[c].get();
}
}
if (aDisabledCommands.Length()) {
disabledCommands = new const char* [aDisabledCommands.Length()];
for (uint32_t c = 0; c < aDisabledCommands.Length(); c++) {
disabledCommands[c] = aDisabledCommands[c].get();
}
}
remoteBrowser->EnableDisableCommands(aAction,
aEnabledCommands.Length(), enabledCommands,
aDisabledCommands.Length(), disabledCommands);
}
return true;
}
nsIntPoint
TabParent::GetChildProcessOffset()
{

View File

@ -191,9 +191,6 @@ public:
const int32_t& aCause,
const int32_t& aFocusChange) MOZ_OVERRIDE;
virtual bool RecvRequestFocus(const bool& aCanRaise) MOZ_OVERRIDE;
virtual bool RecvEnableDisableCommands(const nsString& aAction,
const nsTArray<nsCString>& aEnabledCommands,
const nsTArray<nsCString>& aDisabledCommands) MOZ_OVERRIDE;
virtual bool RecvSetCursor(const uint32_t& aValue, const bool& aForce) MOZ_OVERRIDE;
virtual bool RecvSetBackgroundColor(const nscolor& aValue) MOZ_OVERRIDE;
virtual bool RecvSetStatus(const uint32_t& aType, const nsString& aStatus) MOZ_OVERRIDE;

View File

@ -20,8 +20,6 @@ class MediaData;
template<class Target>
class MediaDataDecodedListener : public RequestSampleCallback {
public:
using RequestSampleCallback::NotDecodedReason;
MediaDataDecodedListener(Target* aTarget,
MediaTaskQueue* aTaskQueue)
: mMonitor("MediaDataDecodedListener")
@ -52,7 +50,8 @@ public:
mTaskQueue->Dispatch(task);
}
virtual void OnNotDecoded(MediaData::Type aType, NotDecodedReason aReason) MOZ_OVERRIDE {
virtual void OnNotDecoded(MediaData::Type aType,
MediaDecoderReader::NotDecodedReason aReason) MOZ_OVERRIDE {
MonitorAutoLock lock(mMonitor);
if (!mTarget || !mTaskQueue) {
// We've been shutdown, abort.
@ -133,7 +132,7 @@ private:
class DeliverNotDecodedTask : public nsRunnable {
public:
DeliverNotDecodedTask(MediaData::Type aType,
RequestSampleCallback::NotDecodedReason aReason,
MediaDecoderReader::NotDecodedReason aReason,
Target* aTarget)
: mType(aType)
, mReason(aReason)
@ -153,7 +152,7 @@ private:
}
private:
MediaData::Type mType;
RequestSampleCallback::NotDecodedReason mReason;
MediaDecoderReader::NotDecodedReason mReason;
RefPtr<Target> mTarget;
};

View File

@ -461,7 +461,6 @@ MediaDecoder::MediaDecoder() :
gMediaDecoderLog = PR_NewLogModule("MediaDecoder");
}
#endif
mAudioChannel = AudioChannelService::GetDefaultAudioChannel();
}

View File

@ -27,6 +27,16 @@ extern PRLogModuleInfo* gMediaDecoderLog;
#define DECODER_LOG(x, ...)
#endif
PRLogModuleInfo* gMediaPromiseLog;
void
EnsureMediaPromiseLog()
{
if (!gMediaPromiseLog) {
gMediaPromiseLog = PR_NewLogModule("MediaPromise");
}
}
class VideoQueueMemoryFunctor : public nsDequeFunctor {
public:
VideoQueueMemoryFunctor() : mSize(0) {}
@ -69,6 +79,7 @@ MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder)
, mShutdown(false)
{
MOZ_COUNT_CTOR(MediaDecoderReader);
EnsureMediaPromiseLog();
}
MediaDecoderReader::~MediaDecoderReader()
@ -204,7 +215,7 @@ MediaDecoderReader::RequestVideoData(bool aSkipToNextKeyframe,
}
GetCallback()->OnVideoDecoded(v);
} else if (VideoQueue().IsFinished()) {
GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA, RequestSampleCallback::END_OF_STREAM);
GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA, END_OF_STREAM);
}
}
@ -237,7 +248,7 @@ MediaDecoderReader::RequestAudioData()
GetCallback()->OnAudioDecoded(a);
return;
} else if (AudioQueue().IsFinished()) {
GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, RequestSampleCallback::END_OF_STREAM);
GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, END_OF_STREAM);
return;
}
}
@ -307,12 +318,13 @@ AudioDecodeRendezvous::OnAudioDecoded(AudioData* aSample)
}
void
AudioDecodeRendezvous::OnNotDecoded(MediaData::Type aType, NotDecodedReason aReason)
AudioDecodeRendezvous::OnNotDecoded(MediaData::Type aType,
MediaDecoderReader::NotDecodedReason aReason)
{
MOZ_ASSERT(aType == MediaData::AUDIO_DATA);
MonitorAutoLock mon(mMonitor);
mSample = nullptr;
mStatus = aReason == DECODE_ERROR ? NS_ERROR_FAILURE : NS_OK;
mStatus = aReason == MediaDecoderReader::DECODE_ERROR ? NS_ERROR_FAILURE : NS_OK;
mHaveResult = true;
mon.NotifyAll();
}

View File

@ -30,6 +30,13 @@ class SharedDecoderManager;
// be accessed on the decode task queue.
class MediaDecoderReader {
public:
enum NotDecodedReason {
END_OF_STREAM,
DECODE_ERROR,
WAITING_FOR_DATA,
CANCELED
};
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReader)
explicit MediaDecoderReader(AbstractMediaDecoder* aDecoder);
@ -290,13 +297,6 @@ class RequestSampleCallback {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RequestSampleCallback)
enum NotDecodedReason {
END_OF_STREAM,
DECODE_ERROR,
WAITING_FOR_DATA,
CANCELED
};
// Receives the result of a RequestAudioData() call.
virtual void OnAudioDecoded(AudioData* aSample) = 0;
@ -305,7 +305,8 @@ public:
// Called when a RequestAudioData() or RequestVideoData() call can't be
// fulfiled. The reason is passed as aReason.
virtual void OnNotDecoded(MediaData::Type aType, NotDecodedReason aReason) = 0;
virtual void OnNotDecoded(MediaData::Type aType,
MediaDecoderReader::NotDecodedReason aReason) = 0;
virtual void OnSeekCompleted(nsresult aResult) = 0;
@ -322,8 +323,6 @@ protected:
// model of the MediaDecoderReader to a synchronous model.
class AudioDecodeRendezvous : public RequestSampleCallback {
public:
using RequestSampleCallback::NotDecodedReason;
AudioDecodeRendezvous();
~AudioDecodeRendezvous();
@ -331,7 +330,8 @@ public:
// Note: aSample is null at end of stream.
virtual void OnAudioDecoded(AudioData* aSample) MOZ_OVERRIDE;
virtual void OnVideoDecoded(VideoData* aSample) MOZ_OVERRIDE {}
virtual void OnNotDecoded(MediaData::Type aType, NotDecodedReason aReason) MOZ_OVERRIDE;
virtual void OnNotDecoded(MediaData::Type aType,
MediaDecoderReader::NotDecodedReason aReason) MOZ_OVERRIDE;
virtual void OnSeekCompleted(nsresult aResult) MOZ_OVERRIDE {};
virtual void BreakCycles() MOZ_OVERRIDE {};
void Reset();

View File

@ -805,7 +805,7 @@ MediaDecoderStateMachine::Push(VideoData* aSample)
void
MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
RequestSampleCallback::NotDecodedReason aReason)
MediaDecoderReader::NotDecodedReason aReason)
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
SAMPLE_LOG("OnNotDecoded (aType=%u, aReason=%u)", aType, aReason);
@ -820,7 +820,7 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
}
// If this is a decode error, delegate to the generic error path.
if (aReason == RequestSampleCallback::DECODE_ERROR) {
if (aReason == MediaDecoderReader::DECODE_ERROR) {
DecodeError();
return;
}
@ -828,7 +828,7 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
// If the decoder is waiting for data, we need to make sure that the requests
// are cleared, which happened above. Additionally, if we're out of decoded
// samples, we need to switch to buffering mode.
if (aReason == RequestSampleCallback::WAITING_FOR_DATA) {
if (aReason == MediaDecoderReader::WAITING_FOR_DATA) {
bool outOfSamples = isAudio ? !AudioQueue().GetSize() : !VideoQueue().GetSize();
if (outOfSamples) {
StartBuffering();
@ -837,14 +837,14 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
return;
}
if (aReason == RequestSampleCallback::CANCELED) {
if (aReason == MediaDecoderReader::CANCELED) {
DispatchDecodeTasksIfNeeded();
return;
}
// This is an EOS. Finish off the queue, and then handle things based on our
// state.
MOZ_ASSERT(aReason == RequestSampleCallback::END_OF_STREAM);
MOZ_ASSERT(aReason == MediaDecoderReader::END_OF_STREAM);
if (!isAudio && mState == DECODER_STATE_SEEKING &&
mCurrentSeekTarget.IsValid() && mFirstVideoFrameAfterSeek) {
// Null sample. Hit end of stream. If we have decoded a frame,

View File

@ -373,7 +373,7 @@ public:
void OnAudioDecoded(AudioData* aSample);
void OnVideoDecoded(VideoData* aSample);
void OnNotDecoded(MediaData::Type aType, RequestSampleCallback::NotDecodedReason aReason);
void OnNotDecoded(MediaData::Type aType, MediaDecoderReader::NotDecodedReason aReason);
void OnSeekCompleted(nsresult aResult);
private:

View File

@ -0,0 +1,27 @@
/* -*- 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 "MediaPromise.h"
#include "MediaTaskQueue.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace detail {
nsresult
DispatchMediaPromiseRunnable(MediaTaskQueue* aTaskQueue, nsIRunnable* aRunnable)
{
return aTaskQueue->ForceDispatch(aRunnable);
}
nsresult
DispatchMediaPromiseRunnable(nsIEventTarget* aEventTarget, nsIRunnable* aRunnable)
{
return aEventTarget->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
}
}
} // namespace mozilla

394
dom/media/MediaPromise.h Normal file
View File

@ -0,0 +1,394 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#if !defined(MediaPromise_h_)
#define MediaPromise_h_
#include "prlog.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Maybe.h"
#include "mozilla/Mutex.h"
#include "mozilla/Monitor.h"
/* Polyfill __func__ on MSVC for consumers to pass to the MediaPromise API. */
#ifdef _MSC_VER
#define __func__ __FUNCTION__
#endif
class nsIEventTarget;
namespace mozilla {
extern PRLogModuleInfo* gMediaPromiseLog;
void EnsureMediaPromiseLog();
#define PROMISE_LOG(x, ...) \
MOZ_ASSERT(gMediaPromiseLog); \
PR_LOG(gMediaPromiseLog, PR_LOG_DEBUG, (x, ##__VA_ARGS__))
class MediaTaskQueue;
namespace detail {
nsresult DispatchMediaPromiseRunnable(MediaTaskQueue* aQueue, nsIRunnable* aRunnable);
nsresult DispatchMediaPromiseRunnable(nsIEventTarget* aTarget, nsIRunnable* aRunnable);
} // namespace detail
/*
* A promise manages an asynchronous request that may or may not be able to be
* fulfilled immediately. When an API returns a promise, the consumer may attach
* callbacks to be invoked (asynchronously, on a specified thread) when the
* request is either completed (resolved) or cannot be completed (rejected).
*
* By default, resolve and reject callbacks are always invoked on the same thread
* where Then() was invoked.
*/
template<typename T> class MediaPromiseHolder;
template<typename ResolveValueT, typename RejectValueT>
class MediaPromise
{
public:
typedef ResolveValueT ResolveValueType;
typedef RejectValueT RejectValueType;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaPromise)
MediaPromise(const char* aCreationSite)
: mCreationSite(aCreationSite)
, mMutex("MediaPromise Mutex")
{
MOZ_COUNT_CTOR(MediaPromise);
PROMISE_LOG("%s creating MediaPromise (%p)", mCreationSite, this);
}
protected:
/*
* A ThenValue tracks a single consumer waiting on the promise. When a consumer
* invokes promise->Then(...), a ThenValue is created. Once the Promise is
* resolved or rejected, a {Resolve,Reject}Runnable is dispatched, which
* invokes the resolve/reject method and then deletes the ThenValue.
*/
class ThenValueBase
{
public:
class ResolveRunnable : public nsRunnable
{
public:
ResolveRunnable(ThenValueBase* aThenValue, ResolveValueType aResolveValue)
: mThenValue(aThenValue)
, mResolveValue(aResolveValue)
{
MOZ_COUNT_CTOR(ResolveRunnable);
}
~ResolveRunnable()
{
MOZ_COUNT_DTOR(ResolveRunnable);
MOZ_ASSERT(!mThenValue);
}
NS_IMETHODIMP Run()
{
PROMISE_LOG("ResolveRunnable::Run() [this=%p]", this);
mThenValue->DoResolve(mResolveValue);
delete mThenValue;
mThenValue = nullptr;
return NS_OK;
}
private:
ThenValueBase* mThenValue;
ResolveValueType mResolveValue;
};
class RejectRunnable : public nsRunnable
{
public:
RejectRunnable(ThenValueBase* aThenValue, RejectValueType aRejectValue)
: mThenValue(aThenValue)
, mRejectValue(aRejectValue)
{
MOZ_COUNT_CTOR(RejectRunnable);
}
~RejectRunnable()
{
MOZ_COUNT_DTOR(RejectRunnable);
MOZ_ASSERT(!mThenValue);
}
NS_IMETHODIMP Run()
{
PROMISE_LOG("RejectRunnable::Run() [this=%p]", this);
mThenValue->DoReject(mRejectValue);
delete mThenValue;
mThenValue = nullptr;
return NS_OK;
}
private:
ThenValueBase* mThenValue;
RejectValueType mRejectValue;
};
ThenValueBase(const char* aCallSite) : mCallSite(aCallSite)
{
MOZ_COUNT_CTOR(ThenValueBase);
}
virtual void Dispatch(MediaPromise *aPromise) = 0;
protected:
// This may only be deleted by {Resolve,Reject}Runnable::Run.
virtual ~ThenValueBase() { MOZ_COUNT_DTOR(ThenValueBase); }
virtual void DoResolve(ResolveValueType aResolveValue) = 0;
virtual void DoReject(RejectValueType aRejectValue) = 0;
const char* mCallSite;
};
template<typename TargetType, typename ThisType,
typename ResolveMethodType, typename RejectMethodType>
class ThenValue : public ThenValueBase
{
public:
ThenValue(TargetType* aResponseTarget, ThisType* aThisVal,
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod,
const char* aCallSite)
: ThenValueBase(aCallSite)
, mResponseTarget(aResponseTarget)
, mThisVal(aThisVal)
, mResolveMethod(aResolveMethod)
, mRejectMethod(aRejectMethod) {}
void Dispatch(MediaPromise *aPromise) MOZ_OVERRIDE
{
aPromise->mMutex.AssertCurrentThreadOwns();
MOZ_ASSERT(!aPromise->IsPending());
bool resolved = aPromise->mResolveValue.isSome();
nsRefPtr<nsRunnable> runnable =
resolved ? static_cast<nsRunnable*>(new (typename ThenValueBase::ResolveRunnable)(this, aPromise->mResolveValue.ref()))
: static_cast<nsRunnable*>(new (typename ThenValueBase::RejectRunnable)(this, aPromise->mRejectValue.ref()));
PROMISE_LOG("%s Then() call made from %s [Runnable=%p, Promise=%p, ThenValue=%p]",
resolved ? "Resolving" : "Rejecting", ThenValueBase::mCallSite,
runnable.get(), aPromise, this);
DebugOnly<nsresult> rv = detail::DispatchMediaPromiseRunnable(mResponseTarget, runnable);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
protected:
virtual void DoResolve(ResolveValueType aResolveValue)
{
((*mThisVal).*mResolveMethod)(aResolveValue);
}
virtual void DoReject(RejectValueType aRejectValue)
{
((*mThisVal).*mRejectMethod)(aRejectValue);
}
virtual ~ThenValue() {}
private:
nsRefPtr<TargetType> mResponseTarget;
nsRefPtr<ThisType> mThisVal;
ResolveMethodType mResolveMethod;
RejectMethodType mRejectMethod;
};
public:
template<typename TargetType, typename ThisType,
typename ResolveMethodType, typename RejectMethodType>
void Then(TargetType* aResponseTarget, const char* aCallSite, ThisType* aThisVal,
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
{
MutexAutoLock lock(mMutex);
ThenValueBase* thenValue = new ThenValue<TargetType, ThisType, ResolveMethodType,
RejectMethodType>(aResponseTarget, aThisVal,
aResolveMethod, aRejectMethod,
aCallSite);
PROMISE_LOG("%s invoking Then() [this=%p, thenValue=%p, aThisVal=%p, isPending=%d]",
aCallSite, this, thenValue, aThisVal, (int) IsPending());
if (!IsPending()) {
thenValue->Dispatch(this);
} else {
mThenValues.AppendElement(thenValue);
}
}
void ChainTo(already_AddRefed<MediaPromise> aChainedPromise, const char* aCallSite)
{
MutexAutoLock lock(mMutex);
nsRefPtr<MediaPromise> chainedPromise = aChainedPromise;
PROMISE_LOG("%s invoking Chain() [this=%p, chainedPromise=%p, isPending=%d]",
aCallSite, this, chainedPromise.get(), (int) IsPending());
if (!IsPending()) {
ForwardTo(chainedPromise);
} else {
mChainedPromises.AppendElement(chainedPromise);
}
}
void Resolve(ResolveValueType aResolveValue, const char* aResolveSite)
{
MutexAutoLock lock(mMutex);
MOZ_ASSERT(IsPending());
PROMISE_LOG("%s resolving MediaPromise (%p created at %s)", aResolveSite, this, mCreationSite);
mResolveValue.emplace(aResolveValue);
DispatchAll();
}
void Reject(RejectValueType aRejectValue, const char* aRejectSite)
{
MutexAutoLock lock(mMutex);
MOZ_ASSERT(IsPending());
PROMISE_LOG("%s rejecting MediaPromise (%p created at %s)", aRejectSite, this, mCreationSite);
mRejectValue.emplace(aRejectValue);
DispatchAll();
}
protected:
bool IsPending() { return mResolveValue.isNothing() && mRejectValue.isNothing(); }
void DispatchAll()
{
mMutex.AssertCurrentThreadOwns();
for (size_t i = 0; i < mThenValues.Length(); ++i)
mThenValues[i]->Dispatch(this);
mThenValues.Clear();
for (size_t i = 0; i < mChainedPromises.Length(); ++i) {
ForwardTo(mChainedPromises[i]);
}
mChainedPromises.Clear();
}
void ForwardTo(MediaPromise* aOther)
{
MOZ_ASSERT(!IsPending());
if (mResolveValue.isSome()) {
aOther->Resolve(mResolveValue.ref(), "<chained promise>");
} else {
aOther->Reject(mRejectValue.ref(), "<chained promise>");
}
}
~MediaPromise()
{
MOZ_COUNT_DTOR(MediaPromise);
PROMISE_LOG("MediaPromise::~MediaPromise [this=%p]", this);
MOZ_ASSERT(!IsPending());
MOZ_ASSERT(mThenValues.IsEmpty());
MOZ_ASSERT(mChainedPromises.IsEmpty());
};
const char* mCreationSite; // For logging
Mutex mMutex;
Maybe<ResolveValueType> mResolveValue;
Maybe<RejectValueType> mRejectValue;
nsTArray<ThenValueBase*> mThenValues;
nsTArray<nsRefPtr<MediaPromise>> mChainedPromises;
};
/*
* Class to encapsulate a promise for a particular role. Use this as the member
* variable for a class whose method returns a promise.
*/
template<typename PromiseType>
class MediaPromiseHolder
{
public:
MediaPromiseHolder()
: mMonitor(nullptr) {}
~MediaPromiseHolder() { MOZ_ASSERT(!mPromise); }
already_AddRefed<PromiseType> Ensure(const char* aMethodName) {
if (mMonitor) {
mMonitor->AssertCurrentThreadOwns();
}
if (!mPromise) {
mPromise = new PromiseType(aMethodName);
}
nsRefPtr<PromiseType> p = mPromise;
return p.forget();
}
// Provide a Monitor that should always be held when accessing this instance.
void SetMonitor(Monitor* aMonitor) { mMonitor = aMonitor; }
bool IsEmpty()
{
if (mMonitor) {
mMonitor->AssertCurrentThreadOwns();
}
return !mPromise;
}
already_AddRefed<PromiseType> Steal()
{
if (mMonitor) {
mMonitor->AssertCurrentThreadOwns();
}
nsRefPtr<PromiseType> p = mPromise;
mPromise = nullptr;
return p.forget();
}
void Resolve(typename PromiseType::ResolveValueType aResolveValue,
const char* aMethodName)
{
if (mMonitor) {
mMonitor->AssertCurrentThreadOwns();
}
MOZ_ASSERT(mPromise);
mPromise->Resolve(aResolveValue, aMethodName);
mPromise = nullptr;
}
void ResolveIfExists(typename PromiseType::ResolveValueType aResolveValue,
const char* aMethodName)
{
if (!IsEmpty()) {
Resolve(aResolveValue, aMethodName);
}
}
void Reject(typename PromiseType::RejectValueType aRejectValue,
const char* aMethodName)
{
if (mMonitor) {
mMonitor->AssertCurrentThreadOwns();
}
MOZ_ASSERT(mPromise);
mPromise->Reject(aRejectValue, aMethodName);
mPromise = nullptr;
}
void RejectIfExists(typename PromiseType::RejectValueType aRejectValue,
const char* aMethodName)
{
if (!IsEmpty()) {
Reject(aRejectValue, aMethodName);
}
}
private:
Monitor* mMonitor;
nsRefPtr<PromiseType> mPromise;
};
#undef PROMISE_LOG
} // namespace mozilla
#endif

View File

@ -34,6 +34,13 @@ MediaTaskQueue::Dispatch(TemporaryRef<nsIRunnable> aRunnable)
return DispatchLocked(aRunnable, AbortIfFlushing);
}
nsresult
MediaTaskQueue::ForceDispatch(TemporaryRef<nsIRunnable> aRunnable)
{
MonitorAutoLock mon(mQueueMonitor);
return DispatchLocked(aRunnable, Forced);
}
nsresult
MediaTaskQueue::DispatchLocked(TemporaryRef<nsIRunnable> aRunnable,
DispatchMode aMode)
@ -45,7 +52,7 @@ MediaTaskQueue::DispatchLocked(TemporaryRef<nsIRunnable> aRunnable,
if (mIsShutdown) {
return NS_ERROR_FAILURE;
}
mTasks.push(aRunnable);
mTasks.push(TaskQueueEntry(aRunnable, aMode == Forced));
if (mIsRunning) {
return NS_OK;
}
@ -140,9 +147,7 @@ MediaTaskQueue::FlushAndDispatch(TemporaryRef<nsIRunnable> aRunnable)
{
MonitorAutoLock mon(mQueueMonitor);
AutoSetFlushing autoFlush(this);
while (!mTasks.empty()) {
mTasks.pop();
}
FlushLocked();
nsresult rv = DispatchLocked(aRunnable, IgnoreFlushing);
NS_ENSURE_SUCCESS(rv, rv);
AwaitIdleLocked();
@ -154,10 +159,25 @@ MediaTaskQueue::Flush()
{
MonitorAutoLock mon(mQueueMonitor);
AutoSetFlushing autoFlush(this);
while (!mTasks.empty()) {
FlushLocked();
AwaitIdleLocked();
}
void
MediaTaskQueue::FlushLocked()
{
mQueueMonitor.AssertCurrentThreadOwns();
MOZ_ASSERT(mIsFlushing);
// Clear the tasks, but preserve those with mForceDispatch by re-appending
// them to the queue.
size_t numTasks = mTasks.size();
for (size_t i = 0; i < numTasks; ++i) {
if (mTasks.front().mForceDispatch) {
mTasks.push(mTasks.front());
}
mTasks.pop();
}
AwaitIdleLocked();
}
bool
@ -191,7 +211,7 @@ MediaTaskQueue::Runner::Run()
mon.NotifyAll();
return NS_OK;
}
event = mQueue->mTasks.front();
event = mQueue->mTasks.front().mRunnable;
mQueue->mTasks.pop();
}
MOZ_ASSERT(event);

View File

@ -34,6 +34,10 @@ public:
nsresult Dispatch(TemporaryRef<nsIRunnable> aRunnable);
// This should only be used for things that absolutely can't afford to be
// flushed. Normal operations should use Dispatch.
nsresult ForceDispatch(TemporaryRef<nsIRunnable> aRunnable);
nsresult SyncDispatch(TemporaryRef<nsIRunnable> aRunnable);
nsresult FlushAndDispatch(TemporaryRef<nsIRunnable> aRunnable);
@ -68,18 +72,27 @@ private:
// mQueueMonitor must be held.
void AwaitIdleLocked();
enum DispatchMode { AbortIfFlushing, IgnoreFlushing };
enum DispatchMode { AbortIfFlushing, IgnoreFlushing, Forced };
nsresult DispatchLocked(TemporaryRef<nsIRunnable> aRunnable,
DispatchMode aMode);
void FlushLocked();
RefPtr<SharedThreadPool> mPool;
// Monitor that protects the queue and mIsRunning;
Monitor mQueueMonitor;
struct TaskQueueEntry {
RefPtr<nsIRunnable> mRunnable;
bool mForceDispatch;
TaskQueueEntry(TemporaryRef<nsIRunnable> aRunnable, bool aForceDispatch = false)
: mRunnable(aRunnable), mForceDispatch(aForceDispatch) {}
};
// Queue of tasks to run.
std::queue<RefPtr<nsIRunnable>> mTasks;
std::queue<TaskQueueEntry> mTasks;
// The thread currently running the task queue. We store a reference
// to this so that IsCurrentThreadIn() can tell if the current thread

View File

@ -25,7 +25,7 @@ const PC_STATIC_CONTRACT = "@mozilla.org/dom/peerconnectionstatic;1";
const PC_SENDER_CONTRACT = "@mozilla.org/dom/rtpsender;1";
const PC_RECEIVER_CONTRACT = "@mozilla.org/dom/rtpreceiver;1";
const PC_CID = Components.ID("{00e0e20d-1494-4776-8e0e-0f0acbea3c79}");
const PC_CID = Components.ID("{bdc2e533-b308-4708-ac8e-a8bfade6d851}");
const PC_OBS_CID = Components.ID("{d1748d4c-7f6a-4dc5-add6-d55b7678537e}");
const PC_ICE_CID = Components.ID("{02b9970c-433d-4cc2-923d-f7028ac66073}");
const PC_SESSION_CID = Components.ID("{1775081b-b62d-4954-8ffe-a067bbf508a7}");
@ -849,7 +849,7 @@ RTCPeerConnection.prototype = {
this._impl.addIceCandidate(cand.candidate, cand.sdpMid || "",
(cand.sdpMLineIndex === null) ? 0 :
cand.sdpMLineIndex + 1);
cand.sdpMLineIndex);
},
addStream: function(stream) {
@ -1122,7 +1122,7 @@ PeerConnectionObserver.prototype = {
const reasonName = [
"",
"InternalError",
"InternalError",
"InvalidCandidateError",
"InvalidParameter",
"InvalidStateError",
"InvalidSessionDescriptionError",
@ -1221,7 +1221,7 @@ PeerConnectionObserver.prototype = {
{
candidate: candidate,
sdpMid: mid,
sdpMLineIndex: level - 1
sdpMLineIndex: level
}
));
}

View File

@ -1,4 +1,4 @@
component {00e0e20d-1494-4776-8e0e-0f0acbea3c79} PeerConnection.js
component {bdc2e533-b308-4708-ac8e-a8bfade6d851} PeerConnection.js
component {d1748d4c-7f6a-4dc5-add6-d55b7678537e} PeerConnection.js
component {02b9970c-433d-4cc2-923d-f7028ac66073} PeerConnection.js
component {1775081b-b62d-4954-8ffe-a067bbf508a7} PeerConnection.js
@ -9,7 +9,7 @@ component {0fb47c47-a205-4583-a9fc-cbadf8c95880} PeerConnection.js
component {4fff5d46-d827-4cd4-a970-8fd53977440e} PeerConnection.js
component {d974b814-8fde-411c-8c45-b86791b81030} PeerConnection.js
contract @mozilla.org/dom/peerconnection;1 {00e0e20d-1494-4776-8e0e-0f0acbea3c79}
contract @mozilla.org/dom/peerconnection;1 {bdc2e533-b308-4708-ac8e-a8bfade6d851}
contract @mozilla.org/dom/peerconnectionobserver;1 {d1748d4c-7f6a-4dc5-add6-d55b7678537e}
contract @mozilla.org/dom/rtcicecandidate;1 {02b9970c-433d-4cc2-923d-f7028ac66073}
contract @mozilla.org/dom/rtcsessiondescription;1 {1775081b-b62d-4954-8ffe-a067bbf508a7}

View File

@ -25,3 +25,5 @@ LOCAL_INCLUDES += [
]
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -59,6 +59,7 @@ interface IPeerConnection : nsISupports
/* Constants for 'name' in error callbacks */
const unsigned long kNoError = 0; // Test driver only
const unsigned long kInvalidCandidate = 2;
const unsigned long kInvalidMediastreamTrack = 3;
const unsigned long kInvalidState = 4;
const unsigned long kInvalidSessionDescription = 5;

View File

@ -21,9 +21,9 @@ NS_DEFINE_NAMED_CID(NS_STUN_UDP_SOCKET_FILTER_HANDLER_CID)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsStunUDPSocketFilterHandler)
namespace sipcc
namespace mozilla
{
// Factory defined in sipcc::, defines sipcc::PeerConnectionImplConstructor
// Factory defined in mozilla::, defines mozilla::PeerConnectionImplConstructor
NS_GENERIC_FACTORY_CONSTRUCTOR(PeerConnectionImpl)
}
@ -31,7 +31,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(PeerConnectionImpl)
NS_DEFINE_NAMED_CID(PEERCONNECTION_CID);
static const mozilla::Module::CIDEntry kCIDs[] = {
{ &kPEERCONNECTION_CID, false, nullptr, sipcc::PeerConnectionImplConstructor },
{ &kPEERCONNECTION_CID, false, nullptr, mozilla::PeerConnectionImplConstructor },
{ &kNS_STUN_UDP_SOCKET_FILTER_HANDLER_CID, false, nullptr, nsStunUDPSocketFilterHandlerConstructor },
{ nullptr }
};

View File

@ -17,12 +17,12 @@ SOURCES += [
LOCAL_INCLUDES += [
'/ipc/chromium/src',
'/media/mtransport',
'/media/webrtc/signaling/include',
'/media/mtransport',
'/media/webrtc/',
'/media/webrtc/signaling/src/common/time_profiling',
'/media/webrtc/signaling/src/media-conduit',
'/media/webrtc/signaling/src/mediapipeline',
'/media/webrtc/signaling/src/peerconnection',
'/media/webrtc/signaling/src/sipcc/include',
]
FINAL_LIBRARY = 'xul'

View File

@ -666,8 +666,7 @@ MP4Reader::ReturnOutput(MediaData* aData, TrackType aTrack)
void
MP4Reader::ReturnEOS(TrackType aTrack)
{
GetCallback()->OnNotDecoded(aTrack == kAudio ? MediaData::AUDIO_DATA : MediaData::VIDEO_DATA,
RequestSampleCallback::END_OF_STREAM);
GetCallback()->OnNotDecoded(aTrack == kAudio ? MediaData::AUDIO_DATA : MediaData::VIDEO_DATA, END_OF_STREAM);
}
MP4Sample*
@ -753,8 +752,7 @@ MP4Reader::Error(TrackType aTrack)
MonitorAutoLock mon(data.mMonitor);
data.mError = true;
}
GetCallback()->OnNotDecoded(aTrack == kVideo ? MediaData::VIDEO_DATA : MediaData::AUDIO_DATA,
RequestSampleCallback::DECODE_ERROR);
GetCallback()->OnNotDecoded(aTrack == kVideo ? MediaData::VIDEO_DATA : MediaData::AUDIO_DATA, DECODE_ERROR);
}
void
@ -784,8 +782,7 @@ MP4Reader::Flush(TrackType aTrack)
data.mNumSamplesOutput = 0;
data.mInputExhausted = false;
if (data.mOutputRequested) {
GetCallback()->OnNotDecoded(aTrack == kVideo ? MediaData::VIDEO_DATA : MediaData::AUDIO_DATA,
RequestSampleCallback::CANCELED);
GetCallback()->OnNotDecoded(aTrack == kVideo ? MediaData::VIDEO_DATA : MediaData::AUDIO_DATA, CANCELED);
}
data.mOutputRequested = false;
data.mDiscontinuity = true;
@ -810,8 +807,7 @@ MP4Reader::SkipVideoDemuxToNextKeyFrame(int64_t aTimeThreshold, uint32_t& parsed
nsAutoPtr<MP4Sample> compressed(PopSample(kVideo));
if (!compressed) {
// EOS, or error. Let the state machine know.
GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA,
RequestSampleCallback::END_OF_STREAM);
GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA, END_OF_STREAM);
{
MonitorAutoLock mon(mVideo.mMonitor);
mVideo.mDemuxEOS = true;

View File

@ -18,4 +18,7 @@ UNIFIED_SOURCES += [
LOCAL_INCLUDES += [
'..',
]
]
if CONFIG['GNU_CXX']:
FAIL_ON_WARNINGS = True

View File

@ -100,7 +100,7 @@ MediaSourceReader::RequestAudioData()
MSE_DEBUGV("MediaSourceReader(%p)::RequestAudioData", this);
if (!mAudioReader) {
MSE_DEBUG("MediaSourceReader(%p)::RequestAudioData called with no audio reader", this);
GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, RequestSampleCallback::DECODE_ERROR);
GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, DECODE_ERROR);
return;
}
mAudioIsSeeking = false;
@ -139,7 +139,7 @@ MediaSourceReader::RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThres
this, aSkipToNextKeyframe, aTimeThreshold);
if (!mVideoReader) {
MSE_DEBUG("MediaSourceReader(%p)::RequestVideoData called with no video reader", this);
GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA, RequestSampleCallback::DECODE_ERROR);
GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA, DECODE_ERROR);
return;
}
if (aSkipToNextKeyframe) {
@ -177,17 +177,16 @@ MediaSourceReader::OnVideoDecoded(VideoData* aSample)
}
void
MediaSourceReader::OnNotDecoded(MediaData::Type aType, RequestSampleCallback::NotDecodedReason aReason)
MediaSourceReader::OnNotDecoded(MediaData::Type aType, NotDecodedReason aReason)
{
MSE_DEBUG("MediaSourceReader(%p)::OnNotDecoded aType=%u aReason=%u IsEnded: %d", this, aType, aReason, IsEnded());
if (aReason == RequestSampleCallback::DECODE_ERROR ||
aReason == RequestSampleCallback::CANCELED) {
if (aReason == DECODE_ERROR || aReason == CANCELED) {
GetCallback()->OnNotDecoded(aType, aReason);
return;
}
// End of stream. Force switching past this stream to another reader by
// switching to the end of the buffered range.
MOZ_ASSERT(aReason == RequestSampleCallback::END_OF_STREAM);
MOZ_ASSERT(aReason == END_OF_STREAM);
nsRefPtr<MediaDecoderReader> reader = aType == MediaData::AUDIO_DATA ?
mAudioReader : mVideoReader;
@ -228,13 +227,13 @@ MediaSourceReader::OnNotDecoded(MediaData::Type aType, RequestSampleCallback::No
// If the entire MediaSource is done, generate an EndOfStream.
if (IsEnded()) {
GetCallback()->OnNotDecoded(aType, RequestSampleCallback::END_OF_STREAM);
GetCallback()->OnNotDecoded(aType, END_OF_STREAM);
return;
}
// We don't have the data the caller wants. Tell that we're waiting for JS to
// give us more data.
GetCallback()->OnNotDecoded(aType, RequestSampleCallback::WAITING_FOR_DATA);
GetCallback()->OnNotDecoded(aType, WAITING_FOR_DATA);
}
void

View File

@ -54,7 +54,7 @@ public:
void OnVideoDecoded(VideoData* aSample);
void OnNotDecoded(MediaData::Type aType, RequestSampleCallback::NotDecodedReason aReason);
void OnNotDecoded(MediaData::Type aType, NotDecodedReason aReason);
void OnSeekCompleted(nsresult aResult);

View File

@ -67,7 +67,7 @@ private:
nsRefPtr<SourceBufferDecoder> mDecoder;
};
MOZ_STACK_CLASS class DecodersToInitialize MOZ_FINAL {
class MOZ_STACK_CLASS DecodersToInitialize MOZ_FINAL {
public:
explicit DecodersToInitialize(TrackBuffer* aOwner)
: mOwner(aOwner)

View File

@ -105,6 +105,7 @@ EXPORTS += [
'MediaDecoderStateMachine.h',
'MediaInfo.h',
'MediaMetadataManager.h',
'MediaPromise.h',
'MediaQueue.h',
'MediaRecorder.h',
'MediaResource.h',
@ -181,6 +182,7 @@ UNIFIED_SOURCES += [
'MediaDecoderStateMachineScheduler.cpp',
'MediaDevices.cpp',
'MediaManager.cpp',
'MediaPromise.cpp',
'MediaRecorder.cpp',
'MediaResource.cpp',
'MediaShutdownManager.cpp',

View File

@ -488,7 +488,7 @@ MediaCodecReader::DecodeAudioDataTask()
}
}
if (AudioQueue().AtEndOfStream()) {
GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, RequestSampleCallback::END_OF_STREAM);
GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, END_OF_STREAM);
}
return result;
}
@ -508,7 +508,7 @@ MediaCodecReader::DecodeVideoFrameTask(int64_t aTimeThreshold)
}
}
if (VideoQueue().AtEndOfStream()) {
GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA, RequestSampleCallback::END_OF_STREAM);
GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA, END_OF_STREAM);
}
return result;
}

View File

@ -40,3 +40,5 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -53,7 +53,7 @@ var fingerprintRegex = /^a=fingerprint:(\S+) (\S+)/m;
var identityRegex = /^a=identity:(\S+)/m;
function fingerprintSdp(fingerprints) {
return fingerprints.map(fp => "a=fInGeRpRiNt=" + fp.algorithm +
return fingerprints.map(fp => "a=fInGeRpRiNt:" + fp.algorithm +
" " + fp.digest + "\n").join("");
}
@ -78,20 +78,20 @@ function testMultipleFingerprints() {
pcDouble.createOffer(function(offer) {
ok(offer, "Got offer");
var m = offer.sdp.match(fingerprintRegex);
if (!m) {
var fp = offer.sdp.match(fingerprintRegex);
if (!fp) {
finished(false, "No fingerprint in offer SDP");
return;
}
var fingerprints = makeFingerprints(m[1], m[2]);
var fingerprints = makeFingerprints(fp[1], fp[2]);
getIdentityAssertion(fingerprints, function(assertion) {
ok(assertion, "Should have assertion");
var sdp = offer.sdp.slice(0, m.index) +
var sdp = offer.sdp.slice(0, fp.index) +
"a=identity:" + assertion + "\n" +
fingerprintSdp(fingerprints.slice(1)) +
offer.sdp.slice(m.index);
offer.sdp.slice(fp.index);
var desc = new mozRTCSessionDescription({ type: "offer", sdp: sdp });
pcStrict.setRemoteDescription(desc, function() {

View File

@ -128,5 +128,12 @@ skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabl
[test_peerConnection_toJSON.html]
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
# multistream is not ready quite yet (bug 1056650)
# [test_peerConnection_twoAudioStreams.html]
# [test_peerConnection_twoAudioVideoStreams.html]
# [test_peerConnection_twoAudioVideoStreamsCombined.html]
# [test_peerConnection_twoVideoStreams.html]
# [test_peerConnection_addSecondAudioStream.html]
# Bug 950317: Hack for making a cleanup hook after finishing all WebRTC cases
[test_zmedia_cleanup.html]

View File

@ -1755,11 +1755,13 @@ PeerConnectionWrapper.prototype = {
*
* @param {function} onSuccess
* Callback to execute if all media has been requested successfully
* @param {array} constraintsList
* Array of constraints for GUM calls
*/
getAllUserMedia : function PCW_GetAllUserMedia(onSuccess) {
getAllUserMedia : function PCW_GetAllUserMedia(constraintsList, onSuccess) {
var self = this;
function _getAllUserMedia(constraintsList, index) {
function _getAllUserMedia(index) {
if (index < constraintsList.length) {
var constraints = constraintsList[index];
@ -1776,20 +1778,20 @@ PeerConnectionWrapper.prototype = {
self.attachMedia(stream, type, 'local');
_getAllUserMedia(constraintsList, index + 1);
_getAllUserMedia(index + 1);
}, generateErrorCallback());
} else {
onSuccess();
}
}
if (this.constraints.length === 0) {
if (constraintsList.length === 0) {
info("Skipping GUM: no UserMedia requested");
onSuccess();
}
else {
info("Get " + this.constraints.length + " local streams");
_getAllUserMedia(this.constraints, 0);
info("Get " + constraintsList.length + " local streams");
_getAllUserMedia(0);
}
},
@ -2174,13 +2176,13 @@ PeerConnectionWrapper.prototype = {
if ((!constraints) || (constraints.length === 0)) {
return 0;
}
var audioTracks = 0;
var numAudioTracks = 0;
for (var i = 0; i < constraints.length; i++) {
if (constraints[i].audio) {
audioTracks++;
numAudioTracks++;
}
}
return audioTracks;
return numAudioTracks;
},
/**
@ -2223,13 +2225,13 @@ PeerConnectionWrapper.prototype = {
if ((!constraints) || (constraints.length === 0)) {
return 0;
}
var videoTracks = 0;
var numVideoTracks = 0;
for (var i = 0; i < constraints.length; i++) {
if (constraints[i].video) {
videoTracks++;
numVideoTracks++;
}
}
return videoTracks;
return numVideoTracks;
},
/**
@ -2272,11 +2274,11 @@ PeerConnectionWrapper.prototype = {
if (!streams || (streams.length === 0)) {
return 0;
}
var audioTracks = 0;
var numAudioTracks = 0;
streams.forEach(function(st) {
audioTracks += st.getAudioTracks().length;
numAudioTracks += st.getAudioTracks().length;
});
return audioTracks;
return numAudioTracks;
},
/*
@ -2290,11 +2292,11 @@ PeerConnectionWrapper.prototype = {
if (!streams || (streams.length === 0)) {
return 0;
}
var videoTracks = 0;
var numVideoTracks = 0;
streams.forEach(function(st) {
videoTracks += st.getVideoTracks().length;
numVideoTracks += st.getVideoTracks().length;
});
return videoTracks;
return numVideoTracks;
},
/**
@ -2367,10 +2369,9 @@ PeerConnectionWrapper.prototype = {
},
verifySdp : function PCW_verifySdp(desc, expectedType, offerConstraintsList,
answerConstraintsList, offerOptions, trickleIceCallback) {
offerOptions, trickleIceCallback) {
info("Examining this SessionDescription: " + JSON.stringify(desc));
info("offerConstraintsList: " + JSON.stringify(offerConstraintsList));
info("answerConstraintsList: " + JSON.stringify(answerConstraintsList));
info("offerOptions: " + JSON.stringify(offerOptions));
ok(desc, "SessionDescription is not null");
is(desc.type, expectedType, "SessionDescription type is " + expectedType);
@ -2390,8 +2391,7 @@ PeerConnectionWrapper.prototype = {
//TODO: how can we check for absence/presence of m=application?
var audioTracks =
Math.max(this.countAudioTracksInMediaConstraint(offerConstraintsList),
this.countAudioTracksInMediaConstraint(answerConstraintsList)) ||
this.countAudioTracksInMediaConstraint(offerConstraintsList) ||
this.audioInOfferOptions(offerOptions);
info("expected audio tracks: " + audioTracks);
@ -2407,8 +2407,7 @@ PeerConnectionWrapper.prototype = {
}
var videoTracks =
Math.max(this.countVideoTracksInMediaConstraint(offerConstraintsList),
this.countVideoTracksInMediaConstraint(answerConstraintsList)) ||
this.countVideoTracksInMediaConstraint(offerConstraintsList) ||
this.videoInOfferOptions(offerOptions);
info("expected video tracks: " + videoTracks);
@ -2636,6 +2635,46 @@ PeerConnectionWrapper.prototype = {
}
},
/**
* Compares amount of established ICE connection according to ICE candidate
* pairs in the stats reporting with the expected amount of connection based
* on the constraints.
*
* @param {object} stats
* The stats to check for ICE candidate pairs
* @param {object} counters
* The counters for media and data tracks based on constraints
* @param {object} answer
* The SDP answer to check for SDP bundle support
*/
checkStatsIceConnections : function PCW_checkStatsIceConnections(stats,
offerConstraintsList, offerOptions, numDataTracks, answer) {
var numIceConnections = 0;
Object.keys(stats).forEach(function(key) {
if ((stats[key].type === "candidatepair") && stats[key].selected) {
numIceConnections += 1;
}
});
info("ICE connections according to stats: " + numIceConnections);
if (answer.sdp.contains('a=group:BUNDLE')) {
is(numIceConnections, 1, "stats reports exactly 1 ICE connection");
} else {
// This code assumes that no media sections have been rejected due to
// codec mismatch or other unrecoverable negotiation failures.
var numAudioTracks =
this.countAudioTracksInMediaConstraint(offerConstraintsList) ||
this.audioInOfferOptions(offerOptions);
var numVideoTracks =
this.countVideoTracksInMediaConstraint(offerConstraintsList) ||
this.videoInOfferOptions(offerOptions);
var numAudioVideoDataTracks = numAudioTracks + numVideoTracks + numDataTracks;
info("expected audio + video + data tracks: " + numAudioVideoDataTracks);
is(numAudioVideoDataTracks, numIceConnections, "stats ICE connections matches expected A/V tracks");
}
},
/**
* Property-matching function for finding a certain stat in passed-in stats
*

View File

@ -111,7 +111,7 @@ var commandsPeerConnection = [
[
'PC_LOCAL_GUM',
function (test) {
test.pcLocal.getAllUserMedia(function () {
test.pcLocal.getAllUserMedia(test.pcLocal.constraints, function () {
test.next();
});
}
@ -119,7 +119,7 @@ var commandsPeerConnection = [
[
'PC_REMOTE_GUM',
function (test) {
test.pcRemote.getAllUserMedia(function () {
test.pcRemote.getAllUserMedia(test.pcRemote.constraints, function () {
test.next();
});
}
@ -232,7 +232,7 @@ var commandsPeerConnection = [
'PC_LOCAL_SANE_LOCAL_SDP',
function (test) {
test.pcLocal.verifySdp(test._local_offer, "offer",
test._offer_constraints, test._answer_constraints, test._offer_options,
test._offer_constraints, test._offer_options,
function(trickle) {
test.pcLocal.localRequiresTrickleIce = trickle;
});
@ -243,7 +243,7 @@ var commandsPeerConnection = [
'PC_REMOTE_SANE_REMOTE_SDP',
function (test) {
test.pcRemote.verifySdp(test._local_offer, "offer",
test._offer_constraints, test._answer_constraints, test._offer_options,
test._offer_constraints, test._offer_options,
function (trickle) {
test.pcRemote.remoteRequiresTrickleIce = trickle;
});
@ -356,7 +356,7 @@ var commandsPeerConnection = [
'PC_REMOTE_SANE_LOCAL_SDP',
function (test) {
test.pcRemote.verifySdp(test._remote_answer, "answer",
test._offer_constraints, test._answer_constraints, test._offer_options,
test._offer_constraints, test._offer_options,
function (trickle) {
test.pcRemote.localRequiresTrickleIce = trickle;
});
@ -367,7 +367,7 @@ var commandsPeerConnection = [
'PC_LOCAL_SANE_REMOTE_SDP',
function (test) {
test.pcLocal.verifySdp(test._remote_answer, "answer",
test._offer_constraints, test._answer_constraints, test._offer_options,
test._offer_constraints, test._offer_options,
function (trickle) {
test.pcLocal.remoteRequiresTrickleIce = trickle;
});
@ -522,6 +522,32 @@ var commandsPeerConnection = [
});
}
],
[
'PC_LOCAL_CHECK_ICE_CONNECTIONS',
function (test) {
test.pcLocal.getStats(null, function(stats) {
test.pcLocal.checkStatsIceConnections(stats,
test._offer_constraints,
test._offer_options,
0,
test.originalAnswer);
test.next();
});
}
],
[
'PC_REMOTE_CHECK_ICE_CONNECTIONS',
function (test) {
test.pcRemote.getStats(null, function(stats) {
test.pcRemote.checkStatsIceConnections(stats,
test._offer_constraints,
test._offer_options,
0,
test.originalAnswer);
test.next();
});
}
],
[
'PC_LOCAL_CHECK_GETSTATS_AUDIOTRACK_OUTBOUND',
function (test) {
@ -728,7 +754,7 @@ var commandsDataChannel = [
[
'PC_LOCAL_GUM',
function (test) {
test.pcLocal.getAllUserMedia(function () {
test.pcLocal.getAllUserMedia(test.pcLocal.constraints, function () {
test.next();
});
}
@ -752,7 +778,7 @@ var commandsDataChannel = [
[
'PC_REMOTE_GUM',
function (test) {
test.pcRemote.getAllUserMedia(function () {
test.pcRemote.getAllUserMedia(test.pcRemote.constraints, function () {
test.next();
});
}
@ -867,7 +893,7 @@ var commandsDataChannel = [
'PC_LOCAL_SANE_LOCAL_SDP',
function (test) {
test.pcLocal.verifySdp(test._local_offer, "offer",
test._offer_constraints, test._answer_constraints, test._offer_options,
test._offer_constraints, test._offer_options,
function(trickle) {
test.pcLocal.localRequiresTrickleIce = trickle;
});
@ -878,7 +904,7 @@ var commandsDataChannel = [
'PC_REMOTE_SANE_REMOTE_SDP',
function (test) {
test.pcRemote.verifySdp(test._local_offer, "offer",
test._offer_constraints, test._answer_constraints, test._offer_options,
test._offer_constraints, test._offer_options,
function (trickle) {
test.pcRemote.remoteRequiresTrickleIce = trickle;
});
@ -971,7 +997,7 @@ var commandsDataChannel = [
'PC_REMOTE_SANE_LOCAL_SDP',
function (test) {
test.pcRemote.verifySdp(test._remote_answer, "answer",
test._offer_constraints, test._answer_constraints, test._offer_options,
test._offer_constraints, test._offer_options,
function (trickle) {
test.pcRemote.localRequiresTrickleIce = trickle;
});
@ -982,7 +1008,7 @@ var commandsDataChannel = [
'PC_LOCAL_SANE_REMOTE_SDP',
function (test) {
test.pcLocal.verifySdp(test._remote_answer, "answer",
test._offer_constraints, test._answer_constraints, test._offer_options,
test._offer_constraints, test._offer_options,
function (trickle) {
test.pcLocal.remoteRequiresTrickleIce = trickle;
});
@ -1129,6 +1155,32 @@ var commandsDataChannel = [
});
}
],
[
'PC_LOCAL_CHECK_ICE_CONNECTIONS',
function (test) {
test.pcLocal.getStats(null, function(stats) {
test.pcLocal.checkStatsIceConnections(stats,
test._offer_constraints,
test._offer_options,
1,
test.originalAnswer);
test.next();
});
}
],
[
'PC_REMOTE_CHECK_ICE_CONNECTIONS',
function (test) {
test.pcRemote.getStats(null, function(stats) {
test.pcRemote.checkStatsIceConnections(stats,
test._offer_constraints,
test._offer_options,
1,
test.originalAnswer);
test.next();
});
}
],
[
'SEND_MESSAGE',
function (test) {

View File

@ -0,0 +1,102 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
<script type="application/javascript" src="pc.js"></script>
<script type="application/javascript" src="templates.js"></script>
<script type="application/javascript" src="turnConfig.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "1091242",
title: "Renegotiation: add second audio stream"
});
var test;
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
test.chain.append([
[
'PC_LOCAL_SETUP_NEGOTIATION_CALLBACK',
function (test) {
test.pcLocal.onNegotiationneededFired = false;
test.pcLocal._pc.onnegotiationneeded = function (anEvent) {
info("pcLocal.onnegotiationneeded fired");
test.pcLocal.onNegotiationneededFired = true;
};
test.next();
}
],
[
'PC_LOCAL_ADD_SECOND_STREAM',
function (test) {
test.pcLocal.getAllUserMedia([{audio: true}], function () {
test.next();
});
}
],
[
'PC_LOCAL_CREATE_NEW_OFFER',
function (test) {
ok(test.pcLocal.onNegotiationneededFired, "onnegotiationneeded");
test.createOffer(test.pcLocal, function (offer) {
test._new_offer = offer;
test.next();
});
}
],
[
'PC_LOCAL_SET_NEW_LOCAL_DESCRIPTION',
function (test) {
test.setLocalDescription(test.pcLocal, test._new_offer, HAVE_LOCAL_OFFER, function () {
test.next();
});
}
],
[
'PC_REMOTE_SET_NEW_REMOTE_DESCRIPTION',
function (test) {
test.setRemoteDescription(test.pcRemote, test._new_offer, HAVE_REMOTE_OFFER, function () {
test.next();
});
}
],
[
'PC_REMOTE_CREATE_NEW_ANSWER',
function (test) {
test.createAnswer(test.pcRemote, function (answer) {
test._new_answer = answer;
test.next();
});
}
],
[
'PC_REMOTE_SET_NEW_LOCAL_DESCRIPTION',
function (test) {
test.setLocalDescription(test.pcRemote, test._new_answer, STABLE, function () {
test.next();
});
}
],
[
'PC_LOCAL_SET_NEW_REMOTE_DESCRIPTION',
function (test) {
test.setRemoteDescription(test.pcLocal, test._new_answer, STABLE, function () {
test.next();
});
}
]
// TODO(bug 1093835): figure out how to verify if media flows through the new stream
]);
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.run();
});
</script>
</pre>
</body>
</html>

View File

@ -18,7 +18,7 @@
runNetworkTest(function() {
var test = new PeerConnectionTest();
test.setMediaConstraints([], [{audio: true}]);
// TODO: Stop using old constraint-like RTCOptions soon (Bug 1064223).
// Watch out for case-difference when fixing: { offerToReceiveAudio: true }
test.setOfferOptions({ mandatory: { OfferToReceiveAudio: true } });

View File

@ -18,6 +18,7 @@
runNetworkTest(function() {
var test = new PeerConnectionTest();
test.setMediaConstraints([], [{video: true}]);
// TODO: Stop using old constraint-like RTCOptions soon (Bug 1064223).
// Watch out for case-difference when fixing: { offerToReceiveVideo: true }
test.setOfferOptions({ optional: [{ OfferToReceiveVideo: true }] });

View File

@ -18,10 +18,8 @@
runNetworkTest(function() {
var test = new PeerConnectionTest();
test.setOfferOptions({
offerToReceiveVideo: true,
offerToReceiveAudio: true
});
test.setMediaConstraints([], [{audio: true, video: true}]);
test.setOfferOptions({ offerToReceiveVideo: true, offerToReceiveAudio: true });
test.run();
});
</script>

View File

@ -0,0 +1,30 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
<script type="application/javascript" src="pc.js"></script>
<script type="application/javascript" src="templates.js"></script>
<script type="application/javascript" src="turnConfig.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "1091242",
title: "Multistream: Two audio streams"
});
var test;
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
test.setMediaConstraints([{audio: true}, {audio: true}],
[{audio: true}, {audio: true}]);
test.run();
});
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,33 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
<script type="application/javascript" src="pc.js"></script>
<script type="application/javascript" src="templates.js"></script>
<script type="application/javascript" src="turnConfig.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "1091242",
title: "Multistream: Two audio streams, two video streams"
});
var test;
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
test.setMediaConstraints([{audio: true}, {video: true}, {audio: true},
{video: true}],
[{audio: true}, {video: true}, {audio: true},
{video: true}]);
test.run();
});
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,33 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
<script type="application/javascript" src="pc.js"></script>
<script type="application/javascript" src="templates.js"></script>
<script type="application/javascript" src="turnConfig.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "1091242",
title: "Multistream: Two audio/video streams"
});
var test;
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
test.setMediaConstraints([{audio: true, video: true},
{audio: true, video: true}],
[{audio: true, video: true},
{audio: true, video: true}]);
test.run();
});
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,30 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
<script type="application/javascript" src="pc.js"></script>
<script type="application/javascript" src="templates.js"></script>
<script type="application/javascript" src="turnConfig.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "1091242",
title: "Multistream: Two video streams"
});
var test;
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
test.setMediaConstraints([{video: true}, {video: true}],
[{video: true}, {video: true}]);
test.run();
});
</script>
</pre>
</body>
</html>

View File

@ -31,3 +31,5 @@ LOCAL_INCLUDES += [
'/dom/media/webaudio',
]
if CONFIG['GNU_CXX']:
FAIL_ON_WARNINGS = True

View File

@ -743,7 +743,7 @@ bool WebMReader::DecodeOpus(const unsigned char* aData, size_t aLength,
// Discard padding should be used only on the final packet, so
// decoding after a padding discard is invalid.
LOG(PR_LOG_DEBUG, ("Opus error, discard padding on interstitial packet"));
GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, RequestSampleCallback::DECODE_ERROR);
GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, DECODE_ERROR);
return false;
}
@ -797,7 +797,7 @@ bool WebMReader::DecodeOpus(const unsigned char* aData, size_t aLength,
if (discardPadding < 0) {
// Negative discard padding is invalid.
LOG(PR_LOG_DEBUG, ("Opus error, negative discard padding"));
GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, RequestSampleCallback::DECODE_ERROR);
GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, DECODE_ERROR);
return false;
}
if (discardPadding > 0) {
@ -810,7 +810,7 @@ bool WebMReader::DecodeOpus(const unsigned char* aData, size_t aLength,
if (discardFrames.value() > frames) {
// Discarding more than the entire packet is invalid.
LOG(PR_LOG_DEBUG, ("Opus error, discard padding larger than packet"));
GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, RequestSampleCallback::DECODE_ERROR);
GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, DECODE_ERROR);
return false;
}
LOG(PR_LOG_DEBUG, ("Opus decoder discarding %d of %d frames",

View File

@ -43,3 +43,5 @@ LOCAL_INCLUDES += [
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -13,3 +13,5 @@ UNIFIED_SOURCES += [
]
OS_LIBS += ['-framework Carbon']
FAIL_ON_WARNINGS = True

View File

@ -45,6 +45,15 @@ static const char16_t OPEN_CURL = '{';
static const char16_t CLOSE_CURL = '}';
static const char16_t NUMBER_SIGN = '#';
static const char16_t QUESTIONMARK = '?';
static const char16_t PERCENT_SIGN = '%';
static const char16_t EXCLAMATION = '!';
static const char16_t DOLLAR = '$';
static const char16_t AMPERSAND = '&';
static const char16_t OPENBRACE = '(';
static const char16_t CLOSINGBRACE = ')';
static const char16_t COMMA = ',';
static const char16_t EQUALS = '=';
static const char16_t ATSYMBOL = '@';
static uint32_t kSubHostPathCharacterCutoff = 512;
@ -140,6 +149,14 @@ isNumberToken(char16_t aSymbol)
return (aSymbol >= '0' && aSymbol <= '9');
}
bool
isValidHexDig(char16_t aHexDig)
{
return (isNumberToken(aHexDig) ||
(aHexDig >= 'A' && aHexDig <= 'F') ||
(aHexDig >= 'a' && aHexDig <= 'f'));
}
void
nsCSPParser::resetCurChar(const nsAString& aToken)
{
@ -157,14 +174,118 @@ nsCSPParser::atEndOfPath()
return (atEnd() || peek(QUESTIONMARK) || peek(NUMBER_SIGN));
}
void
nsCSPParser::percentDecodeStr(const nsAString& aEncStr, nsAString& outDecStr)
{
outDecStr.Truncate();
// helper function that should not be visible outside this methods scope
struct local {
static inline char16_t convertHexDig(char16_t aHexDig) {
if (isNumberToken(aHexDig)) {
return aHexDig - '0';
}
if (aHexDig >= 'A' && aHexDig <= 'F') {
return aHexDig - 'A' + 10;
}
// must be a lower case character
// (aHexDig >= 'a' && aHexDig <= 'f')
return aHexDig - 'a' + 10;
}
};
const char16_t *cur, *end, *hexDig1, *hexDig2;
cur = aEncStr.BeginReading();
end = aEncStr.EndReading();
while (cur != end) {
// if it's not a percent sign then there is
// nothing to do for that character
if (*cur != PERCENT_SIGN) {
outDecStr.Append(*cur);
cur++;
continue;
}
// get the two hexDigs following the '%'-sign
hexDig1 = cur + 1;
hexDig2 = cur + 2;
// if there are no hexdigs after the '%' then
// there is nothing to do for us.
if (hexDig1 == end || hexDig2 == end ||
!isValidHexDig(*hexDig1) ||
!isValidHexDig(*hexDig2)) {
outDecStr.Append(PERCENT_SIGN);
cur++;
continue;
}
// decode "% hexDig1 hexDig2" into a character.
char16_t decChar = (local::convertHexDig(*hexDig1) << 4) +
local::convertHexDig(*hexDig2);
outDecStr.Append(decChar);
// increment 'cur' to after the second hexDig
cur = ++hexDig2;
}
}
// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
bool
nsCSPParser::atValidPathChar()
nsCSPParser::atValidUnreservedChar()
{
return (peek(isCharacterToken) || peek(isNumberToken) ||
peek(DASH) || peek(DOT) ||
peek(UNDERLINE) || peek(TILDE));
}
// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
// / "*" / "+" / "," / ";" / "="
// Please note that even though ',' and ';' appear to be
// valid sub-delims according to the RFC production of paths,
// both can not appear here by itself, they would need to be
// pct-encoded in order to be part of the path.
bool
nsCSPParser::atValidSubDelimChar()
{
return (peek(EXCLAMATION) || peek(DOLLAR) || peek(AMPERSAND) ||
peek(SINGLEQUOTE) || peek(OPENBRACE) || peek(CLOSINGBRACE) ||
peek(WILDCARD) || peek(PLUS) || peek(EQUALS));
}
// pct-encoded = "%" HEXDIG HEXDIG
bool
nsCSPParser::atValidPctEncodedChar()
{
const char16_t* pctCurChar = mCurChar;
if ((pctCurChar + 2) >= mEndChar) {
// string too short, can't be a valid pct-encoded char.
return false;
}
// Any valid pct-encoding must follow the following format:
// "% HEXDIG HEXDIG"
if (PERCENT_SIGN != *pctCurChar ||
!isValidHexDig(*(pctCurChar+1)) ||
!isValidHexDig(*(pctCurChar+2))) {
return false;
}
return true;
}
// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
// http://tools.ietf.org/html/rfc3986#section-3.3
bool
nsCSPParser::atValidPathChar()
{
return (atValidUnreservedChar() ||
atValidSubDelimChar() ||
atValidPctEncodedChar() ||
peek(COLON) || peek(ATSYMBOL));
}
void
nsCSPParser::logWarningErrorToConsole(uint32_t aSeverityFlag,
const char* aProperty,
@ -253,10 +374,15 @@ nsCSPParser::subPath(nsCSPHostSrc* aCspHost)
// is longer than 512 characters, or also to avoid endless loops
// in case we are parsing unrecognized characters in the following loop.
uint32_t charCounter = 0;
nsString pctDecodedSubPath;
while (!atEndOfPath()) {
if (peek(SLASH)) {
aCspHost->appendPath(mCurValue);
// before appendig any additional portion of a subpath we have to pct-decode
// that portion of the subpath. atValidPathChar() already verified a correct
// pct-encoding, now we can safely decode and append the decoded-sub path.
percentDecodeStr(mCurValue, pctDecodedSubPath);
aCspHost->appendPath(pctDecodedSubPath);
// Resetting current value since we are appending parts of the path
// to aCspHost, e.g; "http://www.example.com/path1/path2" then the
// first part is "/path1", second part "/path2"
@ -269,12 +395,23 @@ nsCSPParser::subPath(nsCSPHostSrc* aCspHost)
params, ArrayLength(params));
return false;
}
// potentially we have encountred a valid pct-encoded character in atValidPathChar();
// if so, we have to account for "% HEXDIG HEXDIG" and advance the pointer past
// the pct-encoded char.
if (peek(PERCENT_SIGN)) {
advance();
advance();
}
advance();
if (++charCounter > kSubHostPathCharacterCutoff) {
return false;
}
}
aCspHost->appendPath(mCurValue);
// before appendig any additional portion of a subpath we have to pct-decode
// that portion of the subpath. atValidPathChar() already verified a correct
// pct-encoding, now we can safely decode and append the decoded-sub path.
percentDecodeStr(mCurValue, pctDecodedSubPath);
aCspHost->appendPath(pctDecodedSubPath);
resetCurValue();
return true;
}
@ -301,7 +438,9 @@ nsCSPParser::path(nsCSPHostSrc* aCspHost)
if (atEndOfPath()) {
// one slash right after host [port] is also considered a path, e.g.
// www.example.com/ should result in www.example.com/
aCspHost->appendPath(mCurValue);
// please note that we do not have to perform any pct-decoding here
// because we are just appending a '/' and not any actual chars.
aCspHost->appendPath(NS_LITERAL_STRING("/"));
return true;
}
// path can begin with "/" but not "//"

View File

@ -128,8 +128,13 @@ class nsCSPParser {
bool path(nsCSPHostSrc* aCspHost);
bool subHost(); // helper function to parse subDomains
bool atValidUnreservedChar(); // helper function to parse unreserved
bool atValidSubDelimChar(); // helper function to parse sub-delims
bool atValidPctEncodedChar(); // helper function to parse pct-encoded
bool subPath(nsCSPHostSrc* aCspHost); // helper function to parse paths
void reportURIList(nsTArray<nsCSPBaseSrc*>& outSrcs); // helper function to parse report-uris
void percentDecodeStr(const nsAString& aEncStr, // helper function to percent-decode
nsAString& outDecStr);
inline bool atEnd()
{

View File

@ -29,6 +29,20 @@ interface MozInputMethod : EventTarget {
// Activate or decactive current input method window.
void setActive(boolean isActive);
// Add a dynamically declared input.
//
// The id must not be the same with any statically declared input in the app
// manifest. If an input of the same id is already declared, the info of that
// input will be updated.
Promise<void> addInput(DOMString inputId, object inputManifest);
// Remove a dynamically declared input.
//
// The id must not be the same with any statically declared input in the app
// manifest. Silently resolves if the input is not previously declared;
// rejects if attempt to remove a statically declared input.
Promise<void> removeInput(DOMString id);
// The following are internal methods for Firefox OS system app only.
// Set the value on the currently focused element. This has to be used

View File

@ -67,6 +67,7 @@ interface PeerConnectionImpl {
boolean pluginCrash(unsigned long long pluginId, DOMString name, DOMString pluginDumpID);
/* Attributes */
[Constant]
readonly attribute DOMString fingerprint;
readonly attribute DOMString localDescription;
readonly attribute DOMString remoteDescription;
@ -74,7 +75,6 @@ interface PeerConnectionImpl {
readonly attribute PCImplIceConnectionState iceConnectionState;
readonly attribute PCImplIceGatheringState iceGatheringState;
readonly attribute PCImplSignalingState signalingState;
readonly attribute PCImplSipccState sipccState;
attribute DOMString id;
attribute DOMString peerIdentity;

View File

@ -38,3 +38,5 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
]
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -7,12 +7,12 @@
[scriptable, uuid(D5B61B82-1DA4-11d3-BF87-00105A1B0627)]
interface nsIController : nsISupports {
boolean isCommandEnabled(in string command);
boolean supportsCommand(in string command);
boolean isCommandEnabled(in string command);
boolean supportsCommand(in string command);
void doCommand(in string command);
void doCommand(in string command);
void onEvent(in string eventName);
void onEvent(in string eventName);
};
@ -25,7 +25,7 @@ interface nsIController : nsISupports {
interface nsICommandParams;
[scriptable, uuid(EEC0B435-7F53-44FE-B00A-CF3EED65C01A)]
[scriptable, uuid(EBE55080-C8A9-11D5-A73C-DD620D6E04BC)]
interface nsICommandController : nsISupports
{
@ -33,8 +33,6 @@ interface nsICommandController : nsISupports
void doCommandWithParams(in string command, in nsICommandParams aCommandParams);
void getSupportedCommands(out unsigned long count,
[array, size_is(count), retval] out string commands);
};

View File

@ -55,3 +55,5 @@ LOCAL_INCLUDES += [
]
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -98,12 +98,12 @@ skip-if(Android||B2G) needs-focus == 462758-grabbers-resizers.html 462758-grabbe
== 388980-1.html 388980-1-ref.html
needs-focus == spellcheck-superscript-1.html spellcheck-superscript-1-ref.html
skip-if(B2G) fails-if(Android) needs-focus != spellcheck-superscript-2.html spellcheck-superscript-2-ref.html # bug 783658
needs-focus == 824080-1.html 824080-1-ref.html
needs-focus pref(selectioncaret.enabled,false) == 824080-1.html 824080-1-ref.html
needs-focus == 824080-2.html 824080-2-ref.html
needs-focus test-pref(selectioncaret.enabled,false) == 824080-3.html 824080-3-ref.html
needs-focus pref(selectioncaret.enabled,false) == 824080-3.html 824080-3-ref.html
needs-focus != 824080-2.html 824080-3.html
needs-focus == 824080-4.html 824080-4-ref.html
needs-focus test-pref(selectioncaret.enabled,false) == 824080-5.html 824080-5-ref.html
needs-focus pref(selectioncaret.enabled,false) == 824080-4.html 824080-4-ref.html
needs-focus pref(selectioncaret.enabled,false) == 824080-5.html 824080-5-ref.html
needs-focus != 824080-4.html 824080-5.html
needs-focus == 824080-6.html 824080-6-ref.html
needs-focus pref(selectioncaret.enabled,false) == 824080-7.html 824080-7-ref.html

View File

@ -174,10 +174,3 @@ nsBaseCommandController::OnEvent(const char * aEventName)
NS_ENSURE_ARG_POINTER(aEventName);
return NS_OK;
}
NS_IMETHODIMP
nsBaseCommandController::GetSupportedCommands(uint32_t* aCount, char*** aCommands)
{
NS_ENSURE_STATE(mCommandTable);
return mCommandTable->GetSupportedCommands(aCount, aCommands);
}

View File

@ -188,30 +188,6 @@ nsControllerCommandTable::GetCommandState(const char *aCommandName, nsICommandPa
return commandHandler->GetCommandStateParams(aCommandName, aParams, aCommandRefCon);
}
static PLDHashOperator
AddCommand(const nsACString& aKey, nsIControllerCommand* aData, void* aArg)
{
// aArg is a pointer to a array of strings. It gets incremented after
// allocating each one so that it points to the next location for AddCommand
// to assign a string to.
char*** commands = static_cast<char***>(aArg);
(**commands) = ToNewCString(aKey);
(*commands)++;
return PL_DHASH_NEXT;
}
NS_IMETHODIMP
nsControllerCommandTable::GetSupportedCommands(uint32_t* aCount,
char*** aCommands)
{
char** commands =
static_cast<char **>(NS_Alloc(sizeof(char *) * mCommandsTable.Count()));
*aCount = mCommandsTable.Count();
*aCommands = commands;
mCommandsTable.EnumerateRead(AddCommand, &commands);
return NS_OK;
}
nsresult
NS_NewControllerCommandTable(nsIControllerCommandTable** aResult)

View File

@ -18,7 +18,7 @@
*
*/
[scriptable, uuid(c847f90e-b8f3-49db-a4df-8867831f2800)]
[scriptable, uuid(d1a47834-6ad4-11d7-bfad-000393636592)]
interface nsIControllerCommandTable : nsISupports
{
/**
@ -82,9 +82,6 @@ interface nsIControllerCommandTable : nsISupports
void doCommandParams(in string aCommandName, in nsICommandParams aParam, in nsISupports aCommandRefCon);
void getCommandState(in string aCommandName, in nsICommandParams aParam, in nsISupports aCommandRefCon);
void getSupportedCommands(out unsigned long count,
[array, size_is(count), retval] out string commands);
};

View File

@ -25,3 +25,5 @@ else:
]
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -27,3 +27,5 @@ MSVC_ENABLE_PGO = True
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -10,3 +10,5 @@ UNIFIED_SOURCES += [
]
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -12,3 +12,5 @@ UNIFIED_SOURCES += [
]
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -23,7 +23,7 @@ UNIFIED_SOURCES += [
'TestTiledLayerBuffer.cpp',
]
# Because of gkmedia on windows we wont find these
# Because of gkmedia on windows we won't find these
# symbols in xul.dll.
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'windows':
UNIFIED_SOURCES += [ '%s/gfx/2d/unittest/%s' % (TOPSRCDIR, p) for p in [
@ -48,3 +48,5 @@ LOCAL_INCLUDES += [
FINAL_LIBRARY = 'xul-gtest'
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
FAIL_ON_WARNINGS = True

View File

@ -70,3 +70,5 @@ if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['HAVE_ARM_NEON']:
]
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -216,7 +216,8 @@ DynamicImage::IsOpaque()
}
NS_IMETHODIMP
DynamicImage::GetImageContainer(LayerManager* aManager, ImageContainer** _retval)
DynamicImage::GetImageContainer(LayerManager* aManager,
ImageContainer** _retval)
{
*_retval = nullptr;
return NS_OK;
@ -331,7 +332,9 @@ DynamicImage::SetAnimationStartTime(const mozilla::TimeStamp& aTime)
{ }
nsIntSize
DynamicImage::OptimalImageSizeForDest(const gfxSize& aDest, uint32_t aWhichFrame, GraphicsFilter aFilter, uint32_t aFlags)
DynamicImage::OptimalImageSizeForDest(const gfxSize& aDest,
uint32_t aWhichFrame,
GraphicsFilter aFilter, uint32_t aFlags)
{
gfxIntSize size(mDrawable->Size());
return nsIntSize(size.width, size.height);

View File

@ -14,7 +14,6 @@ namespace mozilla {
namespace image {
/**
* An Image that is dynamically created. The content of the image is provided by
* a gfxDrawable. It's anticipated that most uses of DynamicImage will be
* ephemeral.
@ -36,8 +35,8 @@ public:
virtual already_AddRefed<ProgressTracker> GetProgressTracker() MOZ_OVERRIDE;
virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE;
virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE;
virtual size_t SizeOfSourceWithComputedFallback(
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE;
virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE;

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