Merge inbound to m-c a=merge

This commit is contained in:
Wes Kocher 2015-10-21 16:28:43 -07:00
commit 49d831b1c1
261 changed files with 29081 additions and 4651 deletions

View File

@ -1662,7 +1662,10 @@ nsAccessibilityService::CreateAccessibleByFrameType(nsIFrame* aFrame,
newAcc = new HTMLSpinnerAccessible(aContent, document);
break;
case eHTMLTableType:
newAcc = new HTMLTableAccessibleWrap(aContent, document);
if (aContent->IsHTMLElement(nsGkAtoms::table))
newAcc = new HTMLTableAccessibleWrap(aContent, document);
else
newAcc = new HyperTextAccessibleWrap(aContent, document);
break;
case eHTMLTableCellType:
// Accessible HTML table cell should be a child of accessible HTML table

View File

@ -969,8 +969,8 @@ HTMLTableAccessible::IsProbablyLayoutTable()
RETURN_LAYOUT_ANSWER(false, "Has role attribute, weak role, and role is table");
}
if (!mContent->IsHTMLElement(nsGkAtoms::table))
RETURN_LAYOUT_ANSWER(true, "table built by CSS display:table style");
NS_ASSERTION(mContent->IsHTMLElement(nsGkAtoms::table),
"table should not be built by CSS display:table style");
// Check if datatable attribute has "0" value.
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::datatable,

View File

@ -1,5 +1,6 @@
[DEFAULT]
[test_css_tables.html]
[test_headers_ariagrid.html]
[test_headers_ariatable.html]
[test_headers_listbox.xul]

View File

@ -0,0 +1,116 @@
<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<title>CSS display:table is not a table</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript">
function doTest()
{
//////////////////////////////////////////////////////////////////////////
// elements with display:table
// only display:table
var accTree =
{ SECTION: [
{ TEXT_LEAF: [ ] }
] };
testAccessibleTree("table1", accTree);
// only display:table and display:table-cell
accTree =
{ SECTION: [
{ SECTION: [
{ TEXT_LEAF: [ ] }
] }
] };
testAccessibleTree("table2", accTree);
// display:table, display:table-row, and display:table-cell
accTree =
{ SECTION: [
{ SECTION: [
{ TEXT_LEAF: [ ] }
] }
] };
testAccessibleTree("table3", accTree);
// display:table, display:table-row-group, display:table-row, and display:table-cell
accTree =
{ SECTION: [
{ SECTION: [
{ TEXT_LEAF: [ ] }
] }
] };
testAccessibleTree("table4", accTree);
// display:inline-table
accTree =
{ TEXT_CONTAINER: [
{ TEXT_CONTAINER: [
{ TEXT_LEAF: [ ] }
] }
] };
testAccessibleTree("table5", accTree);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
title=" div with display:table exposes table semantics"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1007975">Mozilla Bug 1007975</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="table1" style="display:table">
table1
</div>
<div id="table2" style="display:table">
<div style="display:table-cell">table2</div>
</div>
<div id="table3" style="display:table">
<div style="display:table-row">
<div style="display:table-cell">table3</div>
</div>
</div>
<div id="table4" style="display:table">
<div style="display:table-row-group">
<div style="display:table-row">
<div style="display:table-cell">table4</div>
</div>
</div>
</div>
<div>
<span id="table5" style="display:inline-table">
<span style="display:table-row">
<span style="display:table-cell">table5</div>
</span>
</span>
</div>
</body>
</html>

View File

@ -128,14 +128,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=410052
];
testTableIndexes("tableinsane6", idxes);
//////////////////////////////////////////////////////////////////////////
// csstablecrazy1 (no rows)
idxes = [
[0, 1]
];
testTableIndexes("csstablecrazy1", idxes);
SimpleTest.finish();
}
@ -150,11 +142,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=410052
href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">
Bug 410052
</a>
<a target="_blank"
title="Table cell accessibles not exposed for CSS table without table-row "
href="https://bugzilla.mozilla.org/show_bug.cgi?id=834120">
Bug 834120
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
@ -419,11 +406,5 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=410052
</tbody>
</table>
<div id="csstablecrazy1"
style="width: 100%; border: 1px solid red; display:table;">
<div style="display:table-cell;">cell1</div>
<div style="display:table-cell;">cell2</div>
</div>
</body>
</html>

View File

@ -116,9 +116,6 @@
// layout table having datatable="0" attribute and containing data table structure (tfoot element)
testAttrs("table22", attr, true);
// css table with non-table tag
testAttrs("table23", attr, true);
SimpleTest.finish();
}
@ -138,11 +135,6 @@
title="Data table elements used to determine layout-guess attribute shouldn't be picked from nested tables">
Mozilla Bug 690222
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=693948"
title="Expose layout-guess: true object attribute on CSS table accessible">
Mozilla Bug 693948
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=696975"
title="Extend the list of legitimate data table structures">
@ -344,28 +336,28 @@
<!-- table with a bordered cell -->
<table id="table13" border="1" width="100%" bordercolor="#0000FF">
<tr>
<td bordercolor="#000000"> </td>
<td bordercolor="#000000"> </td>
<td bordercolor="#000000"> </td>
<td bordercolor="#000000"> </td>
<td bordercolor="#000000"> </td>
<td bordercolor="#000000"> </td>
</tr>
<tr>
<td bordercolor="#000000"> </td>
<td bordercolor="#000000"> </td>
<td bordercolor="#000000"> </td>
<td bordercolor="#000000"> </td>
<td bordercolor="#000000"> </td>
<td bordercolor="#000000"> </td>
</tr>
</table>
<!-- table with alternating row background colors -->
<table id="table14" width="100%">
<tr style="background-color: #0000FF;">
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr style="background-color: #00FF00;">
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
</table>
@ -510,13 +502,5 @@
</tfoot>
</table>
<!-- css table with noon-table tag -->
<div id="table23" style="display:table;">
<div style="display:table-row;">
<div style="display:table-cell;">Row 1, column 1</div>
<div style="display:table-cell;">Row 1, column 2</div>
<div style="display:table-cell;">Row 1, column 3</div>
</div>
</div>
</body>
</html>

View File

@ -49,11 +49,6 @@ function doTest()
is(accTable4.getCellAt(1,1).firstChild.name, "cell3", "wrong cell");
}
// test crazy table
var table6 = getAccessible("table6", [nsIAccessibleTable]);
ok(!table6.getCellAt(0, 0),
"We don't expect cell accessible for crazy table 6!");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
@ -89,11 +84,6 @@ addA11yLoadEvent(doTest);
</tr>
</table>
<div style="display:table;" id="table6">
<input type="checkbox">
<a href="bar">Bad checkbox</a>
</div>
</center>
</body>
</html>

View File

@ -101,10 +101,6 @@ ifneq (,$(filter rtsp,$(NECKO_PROTOCOLS)))
DEFINES += -DMOZ_RTSP
endif
ifdef GKMEDIAS_SHARED_LIBRARY
DEFINES += -DGKMEDIAS_SHARED_LIBRARY
endif
DEFINES += -DMOZ_ICU_VERSION=$(MOZ_ICU_VERSION)
ifdef MOZ_NATIVE_ICU
DEFINES += -DMOZ_NATIVE_ICU

View File

@ -44,9 +44,6 @@
[xpcom]
@RESPATH@/dependentlibs.list
#ifdef GKMEDIAS_SHARED_LIBRARY
@BINPATH@/@DLL_PREFIX@gkmedias@DLL_SUFFIX@
#endif
#ifndef MOZ_STATIC_JS
@BINPATH@/@DLL_PREFIX@mozjs@DLL_SUFFIX@
#endif

View File

@ -1653,7 +1653,7 @@
// and the URL is "about:newtab". We do not support preloading for
// custom newtab URLs.
return Services.prefs.getBoolPref("browser.newtab.preload") &&
!NewTabURL.overridden;
!aboutNewTabService.overridden;
]]>
</body>
</method>
@ -6011,8 +6011,8 @@
let overlayIcon =
document.getAnonymousElementByAttribute(this, "anonid", "overlay-icon");
return soundPlayingIcon && soundPlayingIcon.mozMatchesSelector(":hover") ||
(overlayIcon && overlayIcon.mozMatchesSelector(":hover") && iconVisible);
return soundPlayingIcon && soundPlayingIcon.matches(":hover") ||
(overlayIcon && overlayIcon.matches(":hover") && iconVisible);
]]></getter>
</property>
<field name="mCorrespondingMenuitem">null</field>

View File

@ -6,6 +6,9 @@
function test() {
// initialization
waitForExplicitFinish();
let aboutNewTabService = Components.classes["@mozilla.org/browser/aboutnewtab-service;1"]
.getService(Components.interfaces.nsIAboutNewTabService);
let windowsToClose = [];
let newTab;
let newTabURL;
@ -18,7 +21,7 @@ function test() {
newTabURL = "about:privatebrowsing";
} else {
mode = "normal";
newTabURL = NewTabURL.get();
newTabURL = aboutNewTabService.newTabURL;
}
is(aWindow.gBrowser.currentURI.spec, newTabURL,

View File

@ -5,6 +5,8 @@
function test() {
//initialization
waitForExplicitFinish();
let aboutNewTabService = Components.classes["@mozilla.org/browser/aboutnewtab-service;1"]
.getService(Components.interfaces.nsIAboutNewTabService);
let newTabURL;
let testURL = "http://example.com/";
let mode;
@ -16,15 +18,15 @@ function test() {
newTabURL = "about:privatebrowsing";
} else {
mode = "normal";
newTabURL = NewTabURL.get();
newTabURL = aboutNewTabService.newTabURL;
}
// Check the new tab opened while in normal/private mode
is(aWindow.gBrowser.selectedBrowser.currentURI.spec, newTabURL,
"URL of NewTab should be " + newTabURL + " in " + mode + " mode");
// Set the custom newtab url
NewTabURL.override(testURL);
is(NewTabURL.get(), testURL, "Custom newtab url is set");
aboutNewTabService.newTabURL = testURL;
is(aboutNewTabService.newTabURL, testURL, "Custom newtab url is set");
// Open a newtab after setting the custom newtab url
openNewTab(aWindow, function () {
@ -32,8 +34,8 @@ function test() {
"URL of NewTab should be the custom url");
// Clear the custom url.
NewTabURL.reset();
is(NewTabURL.get(), "about:newtab", "No custom newtab url is set");
aboutNewTabService.resetNewTabURL();
is(aboutNewTabService.newTabURL, "about:newtab", "No custom newtab url is set");
aWindow.gBrowser.removeTab(aWindow.gBrowser.selectedTab);
aWindow.gBrowser.removeTab(aWindow.gBrowser.selectedTab);
@ -50,7 +52,7 @@ function test() {
}
// check whether any custom new tab url has been configured
ok(!NewTabURL.overridden, "No custom newtab url is set");
ok(!aboutNewTabService.overridden, "No custom newtab url is set");
// test normal mode
testOnWindow(false, function(aWindow) {

View File

@ -51,3 +51,6 @@ support-files =
[browser_newtab_bug1178586.js]
[browser_newtab_bug1194895.js]
[browser_newtab_1188015.js]
[browser_newtab_external_resource.js]
support-files =
external_newtab.html

View File

@ -0,0 +1,69 @@
/*
* Description of the Tests for
* - Bug 1204983 - Allow about: pages to load remote content
*
* We perform two tests:
* (1) We load a new tab (about:newtab) using the default url and make sure that URL
* of the doucment matches about:newtab and the principal is the systemPrincipal.
* (2) We load a new tab (about:newtab) and make sure that document.location as well
* as the nodePrincipal match the URL in the URL bar.
*/
const ABOUT_NEWTAB_URI = "about:newtab";
const PREF_URI = "http://example.com/browser/browser/base/content/test/newtab/external_newtab.html";
var browser = null;
var aboutNewTabService = Cc["@mozilla.org/browser/aboutnewtab-service;1"]
.getService(Ci.nsIAboutNewTabService);
function testPref() {
// set the pref for about:newtab to point to an exteranl resource
aboutNewTabService.newTabURL = PREF_URI;
ok(aboutNewTabService.overridden,
"sanity check: default URL for about:newtab should be overriden");
is(aboutNewTabService.newTabURL, PREF_URI,
"sanity check: default URL for about:newtab should return the new URL");
browser.contentWindow.location = ABOUT_NEWTAB_URI;
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
is(content.document.location, PREF_URI, "document.location should match the external resource");
is(content.document.documentURI, PREF_URI, "document.documentURI should match the external resource");
is(content.document.nodePrincipal.URI.spec, PREF_URI, "nodePrincipal should match the external resource");
// reset to about:newtab and perform sanity check
aboutNewTabService.resetNewTabURL();
is(aboutNewTabService.newTabURL, ABOUT_NEWTAB_URI,
"sanity check: resetting the URL to about:newtab should return about:newtab");
// remove the tab and move on
gBrowser.removeCurrentTab();
TestRunner.next();
}, true);
}
function runTests() {
// test the default behavior
yield addNewTabPageTab();
browser = gWindow.gBrowser.selectedBrowser;
ok(!aboutNewTabService.overridden,
"sanity check: default URL for about:newtab should not be overriden");
browser.contentWindow.location = ABOUT_NEWTAB_URI;
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
is(content.document.location, ABOUT_NEWTAB_URI, "document.location should match about:newtab");
is(content.document.documentURI, ABOUT_NEWTAB_URI, "document.documentURI should match about:newtab");
is(content.document.nodePrincipal,
Services.scriptSecurityManager.getSystemPrincipal(),
"nodePrincipal should match systemPrincipal");
// also test the pref
testPref();
}, true);
info("Waiting for about:newtab to load ...");
yield true;
}

View File

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=1204983 -->
<head>
<meta charset="utf-8">
<title>Testpage for bug 1204983</title>
</head>
<body>
Just a testpage for Bug 1204983<br/>
</body>
</html>

View File

@ -9,16 +9,17 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
Components.utils.import("resource:///modules/RecentWindow.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NewTabURL",
"resource:///modules/NewTabURL.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
"@mozilla.org/browser/aboutnewtab-service;1",
"nsIAboutNewTabService");
this.__defineGetter__("BROWSER_NEW_TAB_URL", () => {
if (PrivateBrowsingUtils.isWindowPrivate(window) &&
!PrivateBrowsingUtils.permanentPrivateBrowsing &&
!NewTabURL.overridden) {
!aboutNewTabService.overridden) {
return "about:privatebrowsing";
}
return NewTabURL.get();
return aboutNewTabService.newTabURL;
});
var TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab";

View File

@ -46,3 +46,5 @@ component {d8903bf6-68d5-4e97-bcd1-e4d3012f721a} nsBrowserGlue.js
#ifndef MOZ_MULET
contract @mozilla.org/content-permission/prompt;1 {d8903bf6-68d5-4e97-bcd1-e4d3012f721a}
#endif
component {97eea4bb-db50-4ae0-9147-1e5ed55b4ed5} nsBrowserGlue.js
contract @mozilla.org/browser/aboutnewtab-service;1 {97eea4bb-db50-4ae0-9147-1e5ed55b4ed5}

View File

@ -7,11 +7,14 @@
#include "AboutRedirector.h"
#include "nsNetUtil.h"
#include "nsIAboutNewTabService.h"
#include "nsIChannel.h"
#include "nsIURI.h"
#include "nsIScriptSecurityManager.h"
#include "nsIProtocolHandler.h"
#include "mozilla/ArrayUtils.h"
#include "nsDOMString.h"
#include "nsServiceManagerUtils.h"
namespace mozilla {
namespace browser {
@ -176,14 +179,50 @@ AboutRedirector::NewChannel(nsIURI* aURI,
for (int i = 0; i < kRedirTotal; i++) {
if (!strcmp(path.get(), kRedirMap[i].id)) {
nsAutoCString url;
// check if about:newtab got overridden
if (path.EqualsLiteral("newtab")) {
nsCOMPtr<nsIAboutNewTabService> aboutNewTabService =
do_GetService("@mozilla.org/browser/aboutnewtab-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
bool overridden = false;
rv = aboutNewTabService->GetOverridden(&overridden);
NS_ENSURE_SUCCESS(rv, rv);
if (overridden) {
rv = aboutNewTabService->GetNewTabURL(url);
NS_ENSURE_SUCCESS(rv, rv);
}
}
// fall back to the specified url in the map
if (url.IsEmpty()) {
url.AssignASCII(kRedirMap[i].url);
}
nsCOMPtr<nsIChannel> tempChannel;
nsCOMPtr<nsIURI> tempURI;
rv = NS_NewURI(getter_AddRefs(tempURI),
nsDependentCString(kRedirMap[i].url));
rv = NS_NewURI(getter_AddRefs(tempURI), url);
NS_ENSURE_SUCCESS(rv, rv);
// If tempURI links to an external URI (i.e. something other than
// chrome:// or resource://) then set the LOAD_REPLACE flag on the
// channel which forces the channel owner to reflect the displayed
// URL rather then being the systemPrincipal.
bool isUIResource = false;
rv = NS_URIChainHasFlags(tempURI, nsIProtocolHandler::URI_IS_UI_RESOURCE,
&isUIResource);
NS_ENSURE_SUCCESS(rv, rv);
nsLoadFlags loadFlags =
isUIResource ? static_cast<nsLoadFlags>(nsIChannel::LOAD_NORMAL)
: static_cast<nsLoadFlags>(nsIChannel::LOAD_REPLACE);
rv = NS_NewChannelInternal(getter_AddRefs(tempChannel),
tempURI,
aLoadInfo);
aLoadInfo,
nullptr, // aLoadGroup
nullptr, // aCallbacks
loadFlags);
NS_ENSURE_SUCCESS(rv, rv);
tempChannel->SetOriginalURI(aURI);

View File

@ -1,5 +1,6 @@
XPCOMUtils.defineLazyModuleGetter(this, "NewTabURL",
"resource:///modules/NewTabURL.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
"@mozilla.org/browser/aboutnewtab-service;1",
"nsIAboutNewTabService");
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
var {
@ -246,7 +247,7 @@ extensions.registerAPI((extension, context) => {
createProperties = {};
}
let url = createProperties.url || NewTabURL.get();
let url = createProperties.url || aboutNewTabService.newTabURL;
url = extension.baseURI.resolve(url);
function createInWindow(window) {

View File

@ -1,5 +1,6 @@
XPCOMUtils.defineLazyModuleGetter(this, "NewTabURL",
"resource:///modules/NewTabURL.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
"@mozilla.org/browser/aboutnewtab-service;1",
"nsIAboutNewTabService");
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
var {
@ -95,7 +96,7 @@ extensions.registerAPI((extension, context) => {
args.AppendElement(mkstr(createData.url));
}
} else {
args.AppendElement(mkstr(NewTabURL.get()));
args.AppendElement(mkstr(aboutNewTabService.newTabURL));
}
let extraFeatures = "";

View File

@ -30,6 +30,7 @@ DIRS += [
DIRS += ['build']
XPIDL_SOURCES += [
'nsIAboutNewTabService.idl',
'nsIBrowserGlue.idl',
'nsIBrowserHandler.idl',
]

View File

@ -10,34 +10,34 @@ var Cu = Components.utils;
this.EXPORTED_SYMBOLS = [ "NewTabURL" ];
Components.utils.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
"@mozilla.org/browser/aboutnewtab-service;1",
"nsIAboutNewTabService");
XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
"resource://gre/modules/Deprecated.jsm");
const DepecationURL = "https://bugzilla.mozilla.org/show_bug.cgi?id=1204983#c89";
this.NewTabURL = {
_url: "about:newtab",
_remoteUrl: "about:remote-newtab",
_overridden: false,
get: function() {
let output = this._url;
if (Services.prefs.getBoolPref("browser.newtabpage.remote")) {
output = this._remoteUrl;
}
return output;
Deprecated.warning("NewTabURL.get is deprecated, please query aboutNewTabService.newTabURL", DepecationURL);
return aboutNewTabService.newTabURL;
},
get overridden() {
return this._overridden;
Deprecated.warning("NewTabURL.overridden is deprecated, please query aboutNewTabService.overridden", DepecationURL);
return aboutNewTabService.overridden;
},
override: function(newURL) {
this._url = newURL;
this._overridden = true;
Services.obs.notifyObservers(null, "newtab-url-changed", this._url);
Deprecated.warning("NewTabURL.override is deprecated, please set aboutNewTabService.newTabURL", DepecationURL);
aboutNewTabService.newTabURL = newURL;
},
reset: function() {
this._url = "about:newtab";
this._overridden = false;
Services.obs.notifyObservers(null, "newtab-url-changed", this._url);
Deprecated.warning("NewTabURL.reset is deprecated, please use aboutNewTabService.resetNewTabURL()", DepecationURL);
aboutNewTabService.resetNewTabURL();
}
};

View File

@ -0,0 +1,39 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
"use strict";
Components.utils.import("resource://gre/modules/Services.jsm");
let aboutNewTabService = Components.classes["@mozilla.org/browser/aboutnewtab-service;1"]
.getService(Components.interfaces.nsIAboutNewTabService);
add_task(function* () {
Assert.equal(aboutNewTabService.newTabURL, "about:newtab", "Default newtab URL should be about:newtab");
let url = "http://example.com/";
let notificationPromise = promiseNewtabURLNotification(url);
aboutNewTabService.newTabURL = url;
yield notificationPromise;
Assert.ok(aboutNewTabService.overridden, "Newtab URL should be overridden");
Assert.equal(aboutNewTabService.newTabURL, url, "Newtab URL should be the custom URL");
notificationPromise = promiseNewtabURLNotification("about:newtab");
aboutNewTabService.resetNewTabURL();
yield notificationPromise;
Assert.ok(!aboutNewTabService.overridden, "Newtab URL should not be overridden");
Assert.equal(aboutNewTabService.newTabURL, "about:newtab", "Newtab URL should be the about:newtab");
// change newtab page to remote
Services.prefs.setBoolPref("browser.newtabpage.remote", true);
Assert.equal(aboutNewTabService.newTabURL, "about:remote-newtab", "Newtab URL should be the about:remote-newtab");
Assert.ok(!aboutNewTabService.overridden, "Newtab URL should not be overridden");
});
function promiseNewtabURLNotification(aNewURL) {
return new Promise(resolve => {
Services.obs.addObserver(function observer(aSubject, aTopic, aData) {
Services.obs.removeObserver(observer, aTopic);
Assert.equal(aData, aNewURL, "Data for newtab-url-changed notification should be new URL.");
resolve();
}, "newtab-url-changed", false);
});
}

View File

@ -4,6 +4,7 @@ tail =
firefox-appdir = browser
skip-if = toolkit == 'android' || toolkit == 'gonk'
[test_AboutNewTabService.js]
[test_NewTabURL.js]
[test_PlacesProvider.js]
[test_RemoteDirectoryLinksProvider.js]

View File

@ -187,6 +187,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
XPCOMUtils.defineLazyServiceGetter(this, "WindowsUIUtils",
"@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils");
const ABOUT_NEWTAB = "about:newtab";
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
@ -2475,6 +2477,48 @@ BrowserGlue.prototype = {
_xpcom_factory: BrowserGlueServiceFactory,
}
// ------------------------------------
// nsIAboutNewTabService implementation
//-------------------------------------
function AboutNewTabService()
{
this._newTabURL = ABOUT_NEWTAB;
this._overridden = false;
}
AboutNewTabService.prototype = {
classID: Components.ID("{97eea4bb-db50-4ae0-9147-1e5ed55b4ed5}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutNewTabService]),
get newTabURL() {
if (Services.prefs.getBoolPref("browser.newtabpage.remote")) {
return "about:remote-newtab";
}
return this._newTabURL;
},
set newTabURL(aNewTabURL) {
if (aNewTabURL === ABOUT_NEWTAB) {
this.resetNewTabURL();
return;
}
this._newTabURL = aNewTabURL;
this._overridden = true;
Services.obs.notifyObservers(null, "newtab-url-changed", this._newTabURL);
},
get overridden() {
return this._overridden;
},
resetNewTabURL: function() {
this._newTabURL = ABOUT_NEWTAB;
this._overridden = false;
Services.obs.notifyObservers(null, "newtab-url-changed", this._newTabURL);
}
};
function ContentPermissionPrompt() {}
ContentPermissionPrompt.prototype = {
@ -3219,7 +3263,7 @@ var E10SUINotification = {
};
#endif
var components = [BrowserGlue, ContentPermissionPrompt];
var components = [BrowserGlue, ContentPermissionPrompt, AboutNewTabService];
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);

View File

@ -0,0 +1,32 @@
/* 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"
/**
* Allows to override about:newtab to point to a different location
* than the one specified within AboutRedirector.cpp
*/
[scriptable, uuid(6c66f022-beb1-46ea-8af6-c6c6dd937ea9)]
interface nsIAboutNewTabService : nsISupports
{
/**
* Returns "about:newtab" if not overridden, otherwise
* a string represenation of the new URL.
*/
attribute ACString newTabURL;
/**
* Returns true if the default of "about:newtab" got
* overridden.
*/
readonly attribute bool overridden;
/**
* Resets "about:newtab" to the default and also resets the
* overridden attribute to false.
*/
void resetNewTabURL();
};

View File

@ -6,6 +6,8 @@
"use strict";
Components.utils.import("resource://gre/modules/Promise.jsm", this);
let aboutNewTabService = Components.classes["@mozilla.org/browser/aboutnewtab-service;1"]
.getService(Components.interfaces.nsIAboutNewTabService);
function checkUrlbarFocus(win) {
let urlbar = win.gURLBar;
@ -28,14 +30,14 @@ add_task(function* () {
});
add_task(function* () {
NewTabURL.override("about:blank");
aboutNewTabService.newTabURL = "about:blank";
registerCleanupFunction(() => {
NewTabURL.reset();
aboutNewTabService.resetNewTabURL();
});
let win = yield openNewPrivateWindow();
checkUrlbarFocus(win);
win.close();
NewTabURL.reset();
aboutNewTabService.resetNewTabURL();
});

View File

@ -84,10 +84,6 @@ ifdef NECKO_WIFI
DEFINES += -DNECKO_WIFI
endif
ifdef GKMEDIAS_SHARED_LIBRARY
DEFINES += -DGKMEDIAS_SHARED_LIBRARY
endif
ifdef MAKENSISU
DEFINES += -DHAVE_MAKENSISU=1
endif

View File

@ -63,9 +63,6 @@
[xpcom]
@RESPATH@/dependentlibs.list
#ifdef GKMEDIAS_SHARED_LIBRARY
@BINPATH@/@DLL_PREFIX@gkmedias@DLL_SUFFIX@
#endif
#ifdef MOZ_SHARED_MOZGLUE
@BINPATH@/@DLL_PREFIX@mozglue@DLL_SUFFIX@
#endif

View File

@ -1,17 +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/. -->
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
<ShortName>Answers.com</ShortName>
<Description>Dictionary Search on Answers.com</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAABMLAAATCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////K////4f////E////5f///+n////P////mv///0EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8E////fv///+//////////////////////7NnP/+LFtv/////+////of///xYAAAAAAAAAAAAAAAD///8D////lf////////////j0//bi1v/OlXf/tGU9/6FCEv/OmH3////////////////D////FgAAAAAAAAAA////avPm4P/evaz/8NbI//7r3//23M3/xYRi/5kzAP/Df1z//u/l//749P/v4dn/+PPw/////6j///8B////GP///+W/f1//smM7//bczf/+69///uvf/9ytlP+ZMwD/5se3/+/f1//AgmP/nj0N/927qv/////+////QP///2z/////8NvQ/8WCYP/+69///uvf//7r3/+7ckz/pUkb/9m1ov+ePQ3/okUW/8+fh//38O3//////////5r///+t//////7y6v/Cflv/58Cr//DRwP/mwKv/okQU/8ODYv/cuqj/yZN4//Tq5f/+9e///vDn///////////Q////yf/////+7+b/05yA/65ZLv+9dVD/sF40/5kzAP/kvKb//vTu//Tr5v/7+Pb//vfz//707f//////////6f///8X//////vDm/+K4ov/KjGz//ure/8uNbf+jRBX/+OTX/+3b0v+jSBr/pk0h/717Wv/Wrpr//Pn4/////+b///+i//////7z7f/02Mj/wn5b//vl2P+uWS7/vXhU//v49//48u//1q6a/717Wv+oUSb/tWxH//jz8P/////K////V///////+/j//ure/8aFZP/fs5v/oEAQ/9q1o/+zaEL/1ayX//718P/+9/P/+PHu//jz8P//////////h////wr////O///////38v/YpYr/tGQ7/6ZLHf/06eX/s2dB/549Df/x49z//vDn//7x6f//////////8////yoAAAAA////R/////v/////7dXI/5kzAP+7cUv//vHp/+vYzv+bNwX/vHlY//38/P///////////////30AAAAAAAAAAAAAAAD///9n////+/z5+P++e1n/3LGc//7w5//++PT/0KKL/8OIa//9/Pv//////////5X///8GAAAAAAAAAAAAAAAAAAAAAP///0n////K///////////////////////////+/v7/////5v///2z///8CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////Cv///1f///+g////xP///8n///+r////bP///xoAAAAAAAAAAAAAAAAAAAAA+B////AH///AA///wAH//4AB//+AAP//AAD//wAA//8AAP//AAD//4AA//+AAf//wAP//+AD///wD////D///w==</Image>
<Url type="text/html" method="GET" template="http://www.answers.com/main/ntquery">
<Param name="s" value="{searchTerms}"/>
<Param name="gwp" value="13"/>
</Url>
<Url type="application/x-suggestions+json" method="GET"
template="http://www.answers.com/main/startswith?output=json&amp;client=firefox&amp;s={searchTerms}"/>
<SearchForm>http://www.answers.com/</SearchForm>
</SearchPlugin>

View File

@ -1,15 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
<ShortName>Creative Commons</ShortName>
<Description>Find photos, movies, music, and text to rip, sample, mash, and share.</Description>
<InputEncoding>utf-8</InputEncoding>
<Image width="16" height="16">data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAJUSURBVDiNjZO9S1thGMXPvTfJFbnkipNkLLS0ksFg0M0lf4CboNCEgIIg/RiKtEOn0qGWTtbVoBYcIji10I9J0ApWCjp0kRaXdhHjTW4+uGnur4NJ8GOwZ3nf4TnnfZ5z3scAdBGGYdyVdN+yrGHTNNOtVqsVhuG+pO+S3gE/LtV3BIxzPDJNc8FxHGN0dNRKpVIGoJ2dndr+/r5Vr9cl6bmkN0AoSQIEyHXdj5KYnZ3F932uolKpkM/nK5KQ9FmSCZwLOI7zQBLr6+vXiFdRLBaDtsiTTve3YrFYkM/nbyR3MDU1dSKpLumO+vr6Xruui+d5AFSrVVZWVtjY2KDRaABwdHTE4uIie3t7AJTLZaLRaFXSCyUSid1MJgOA53n09/eTTqdJJpPMzc2xurqKbduMj48Tj8fZ3d0FYHBw8FjSezmOU56fnwdgeXkZ27ap1WpUKhWazSZjY2Nks1kASqVSd4zp6eljSX/MtiHdRDpnEATyfb+bkiSVSqXu3TCM8xgHBga+dkY4OzvDdV2GhoZIJBLMzMxQKBSIRqNkMhlisRhbW1sAJJPJn5I+KB6Pv7poou/7rK2tsbm5SRAEXROXlpY4ODgAoFarYdu2J+llN8ZcLvffMeZyud+SGpLuCVBPT89jSRQKhRvJxWKxISmU9JTOT5Rk9Pb2fpHE5OQkJycn14inp6dMTEx4bdM/SbKAy8sk6WEkElmwLCuSSqUYGRmxgHB7e7t+eHgYazabgaRnkt7SeZnr63xbUtYwjGHTNNNhGP4F9iR9a6/zr4v1/wDE1D9XlC4rrAAAAABJRU5ErkJggg==</Image>
<Url type="text/html" method="GET" template="http://search.creativecommons.org/" resultdomain="creativecommons.org">
<Param name="q" value="{searchTerms}"/>
<Param name="sourceid" value="Mozilla-search"/>
</Url>
<SearchForm>http://search.creativecommons.org/</SearchForm>
</SearchPlugin>

View File

@ -26,9 +26,6 @@ if CONFIG['HOST_OS_ARCH'] != 'WINNT':
]
HostProgram('nsinstall_real')
if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
DEFINES['GKMEDIAS_SHARED_LIBRARY'] = True
if CONFIG['MOZ_SHARED_ICU']:
DEFINES['MOZ_SHARED_ICU'] = True

View File

@ -1313,22 +1313,6 @@ vpx/vp8cx.h
vpx/vp8dx.h
vpx_mem/vpx_mem.h
#endif
#ifdef GKMEDIAS_SHARED_LIBRARY
vpx/vpx_codec.h
vpx/vpx_decoder.h
vpx/vpx_encoder.h
vpx/vp8cx.h
vpx/vp8dx.h
vpx_mem/vpx_mem.h
vorbis/codec.h
theora/theoradec.h
tremor/ivorbiscodec.h
speex/speex_resampler.h
ogg/ogg.h
ogg/os_types.h
nestegg/nestegg.h
cubeb/cubeb.h
#endif
gst/gst.h
gst/app/gstappsink.h
gst/app/gstappsrc.h

View File

@ -74,7 +74,7 @@ GNOMEUI_VERSION=2.2.0
GCONF_VERSION=1.2.1
STARTUP_NOTIFICATION_VERSION=0.8
DBUS_VERSION=0.60
SQLITE_VERSION=3.8.11.1
SQLITE_VERSION=3.9.1
MSMANIFEST_TOOL=
@ -7993,13 +7993,8 @@ dnl =
dnl ========================================================
MOZ_ARG_HEADER(Static build options)
if test -n "$GKMEDIAS_SHARED_LIBRARY"; then
AC_DEFINE(GKMEDIAS_SHARED_LIBRARY)
fi
AC_SUBST(GKMEDIAS_SHARED_LIBRARY)
if test -z "$MOZ_NATIVE_ZLIB"; then
if test -n "$JS_SHARED_LIBRARY" -o "$GKMEDIAS_SHARED_LIBRARY"; then
if test -n "$JS_SHARED_LIBRARY"; then
ZLIB_IN_MOZGLUE=1
AC_DEFINE(ZLIB_IN_MOZGLUE)
fi

File diff suppressed because it is too large Load Diff

View File

@ -111,9 +111,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.8.11.1"
#define SQLITE_VERSION_NUMBER 3008011
#define SQLITE_SOURCE_ID "2015-07-29 20:00:57 cf538e2783e468bbc25e7cb2a9ee64d3e0e80b2f"
#define SQLITE_VERSION "3.9.1"
#define SQLITE_VERSION_NUMBER 3009001
#define SQLITE_SOURCE_ID "2015-10-16 17:31:12 767c1727fec4ce11b83f25b3f1bfcfe68a2c8b02"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -124,7 +124,7 @@ extern "C" {
** but are associated with the library instead of the header file. ^(Cautious
** programmers might include assert() statements in their application to
** verify that values returned by these interfaces match the macros in
** the header, and thus insure that the application is
** the header, and thus ensure that the application is
** compiled with matching library and header files.
**
** <blockquote><pre>
@ -374,7 +374,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** Restrictions:
**
** <ul>
** <li> The application must insure that the 1st parameter to sqlite3_exec()
** <li> The application must ensure that the 1st parameter to sqlite3_exec()
** is a valid and open [database connection].
** <li> The application must not close the [database connection] specified by
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
@ -477,6 +477,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec(
#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8))
#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8))
#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8))
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
@ -1366,9 +1367,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void);
** applications and so this routine is usually not necessary. It is
** provided to support rare applications with unusual needs.
**
** The sqlite3_config() interface is not threadsafe. The application
** must insure that no other SQLite interfaces are invoked by other
** threads while sqlite3_config() is running. Furthermore, sqlite3_config()
** <b>The sqlite3_config() interface is not threadsafe. The application
** must ensure that no other SQLite interfaces are invoked by other
** threads while sqlite3_config() is running.</b>
**
** The sqlite3_config() interface
** may only be invoked prior to library initialization using
** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()].
** ^If sqlite3_config() is called after [sqlite3_initialize()] and before
@ -3373,7 +3376,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
**
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
** [prepared statement] S has been stepped at least once using
** [sqlite3_step(S)] but has not run to completion and/or has not
** [sqlite3_step(S)] but has neither run to completion (returned
** [SQLITE_DONE] from [sqlite3_step(S)]) nor
** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S)
** interface returns false if S is a NULL pointer. If S is not a
** NULL pointer and is not a pointer to a valid [prepared statement]
@ -3626,7 +3630,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*,
**
** See also: [sqlite3_bind_blob|sqlite3_bind()],
** [sqlite3_bind_parameter_count()], and
** [sqlite3_bind_parameter_index()].
** [sqlite3_bind_parameter_name()].
*/
SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
@ -4355,6 +4359,22 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value*);
SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*);
SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*);
/*
** CAPI3REF: Finding The Subtype Of SQL Values
** METHOD: sqlite3_value
**
** The sqlite3_value_subtype(V) function returns the subtype for
** an [application-defined SQL function] argument V. The subtype
** information can be used to pass a limited amount of context from
** one SQL function to another. Use the [sqlite3_result_subtype()]
** routine to set the subtype for the return value of an SQL function.
**
** SQLite makes no use of subtype itself. It merely passes the subtype
** from the result of one [application-defined SQL function] into the
** input of another.
*/
SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value*);
/*
** CAPI3REF: Copy And Free SQL Values
** METHOD: sqlite3_value
@ -4654,6 +4674,21 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_va
SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n);
SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
/*
** CAPI3REF: Setting The Subtype Of An SQL Function
** METHOD: sqlite3_context
**
** The sqlite3_result_subtype(C,T) function causes the subtype of
** the result from the [application-defined SQL function] with
** [sqlite3_context] C to be the value T. Only the lower 8 bits
** of the subtype T are preserved in current versions of SQLite;
** higher order bits are discarded.
** The number of subtype bytes preserved by SQLite might increase
** in future releases of SQLite.
*/
SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context*,unsigned int);
/*
** CAPI3REF: Define New Collating Sequences
** METHOD: sqlite3
@ -5599,13 +5634,31 @@ struct sqlite3_module {
** ^The estimatedRows value is an estimate of the number of rows that
** will be returned by the strategy.
**
** The xBestIndex method may optionally populate the idxFlags field with a
** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
** assumes that the strategy may visit at most one row.
**
** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
** SQLite also assumes that if a call to the xUpdate() method is made as
** part of the same statement to delete or update a virtual table row and the
** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback
** any database changes. In other words, if the xUpdate() returns
** SQLITE_CONSTRAINT, the database contents must be exactly as they were
** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not
** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by
** the xUpdate method are automatically rolled back by SQLite.
**
** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
** structure for SQLite version 3.8.2. If a virtual table extension is
** used with an SQLite version earlier than 3.8.2, the results of attempting
** to read or write the estimatedRows field are undefined (but are likely
** to included crashing the application). The estimatedRows field should
** therefore only be used if [sqlite3_libversion_number()] returns a
** value greater than or equal to 3008002.
** value greater than or equal to 3008002. Similarly, the idxFlags field
** was added for version 3.9.0. It may therefore only be used if
** sqlite3_libversion_number() returns a value greater than or equal to
** 3009000.
*/
struct sqlite3_index_info {
/* Inputs */
@ -5633,8 +5686,15 @@ struct sqlite3_index_info {
double estimatedCost; /* Estimated cost of using this index */
/* Fields below are only available in SQLite 3.8.2 and later */
sqlite3_int64 estimatedRows; /* Estimated number of rows returned */
/* Fields below are only available in SQLite 3.9.0 and later */
int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */
};
/*
** CAPI3REF: Virtual Table Scan Flags
*/
#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
/*
** CAPI3REF: Virtual Table Constraint Operator Codes
**
@ -6092,6 +6152,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*);
** <li> SQLITE_MUTEX_STATIC_APP1
** <li> SQLITE_MUTEX_STATIC_APP2
** <li> SQLITE_MUTEX_STATIC_APP3
** <li> SQLITE_MUTEX_STATIC_VFS1
** <li> SQLITE_MUTEX_STATIC_VFS2
** <li> SQLITE_MUTEX_STATIC_VFS3
** </ul>
**
** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
@ -7858,3 +7921,523 @@ struct sqlite3_rtree_query_info {
#endif /* ifndef _SQLITE3RTREE_H_ */
/*
** 2014 May 31
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** Interfaces to extend FTS5. Using the interfaces defined in this file,
** FTS5 may be extended with:
**
** * custom tokenizers, and
** * custom auxiliary functions.
*/
#ifndef _FTS5_H
#define _FTS5_H
#ifdef __cplusplus
extern "C" {
#endif
/*************************************************************************
** CUSTOM AUXILIARY FUNCTIONS
**
** Virtual table implementations may overload SQL functions by implementing
** the sqlite3_module.xFindFunction() method.
*/
typedef struct Fts5ExtensionApi Fts5ExtensionApi;
typedef struct Fts5Context Fts5Context;
typedef struct Fts5PhraseIter Fts5PhraseIter;
typedef void (*fts5_extension_function)(
const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
Fts5Context *pFts, /* First arg to pass to pApi functions */
sqlite3_context *pCtx, /* Context for returning result/error */
int nVal, /* Number of values in apVal[] array */
sqlite3_value **apVal /* Array of trailing arguments */
);
struct Fts5PhraseIter {
const unsigned char *a;
const unsigned char *b;
};
/*
** EXTENSION API FUNCTIONS
**
** xUserData(pFts):
** Return a copy of the context pointer the extension function was
** registered with.
**
** xColumnTotalSize(pFts, iCol, pnToken):
** If parameter iCol is less than zero, set output variable *pnToken
** to the total number of tokens in the FTS5 table. Or, if iCol is
** non-negative but less than the number of columns in the table, return
** the total number of tokens in column iCol, considering all rows in
** the FTS5 table.
**
** If parameter iCol is greater than or equal to the number of columns
** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
** an OOM condition or IO error), an appropriate SQLite error code is
** returned.
**
** xColumnCount(pFts):
** Return the number of columns in the table.
**
** xColumnSize(pFts, iCol, pnToken):
** If parameter iCol is less than zero, set output variable *pnToken
** to the total number of tokens in the current row. Or, if iCol is
** non-negative but less than the number of columns in the table, set
** *pnToken to the number of tokens in column iCol of the current row.
**
** If parameter iCol is greater than or equal to the number of columns
** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
** an OOM condition or IO error), an appropriate SQLite error code is
** returned.
**
** xColumnText:
** This function attempts to retrieve the text of column iCol of the
** current document. If successful, (*pz) is set to point to a buffer
** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
** if an error occurs, an SQLite error code is returned and the final values
** of (*pz) and (*pn) are undefined.
**
** xPhraseCount:
** Returns the number of phrases in the current query expression.
**
** xPhraseSize:
** Returns the number of tokens in phrase iPhrase of the query. Phrases
** are numbered starting from zero.
**
** xInstCount:
** Set *pnInst to the total number of occurrences of all phrases within
** the query within the current row. Return SQLITE_OK if successful, or
** an error code (i.e. SQLITE_NOMEM) if an error occurs.
**
** xInst:
** Query for the details of phrase match iIdx within the current row.
** Phrase matches are numbered starting from zero, so the iIdx argument
** should be greater than or equal to zero and smaller than the value
** output by xInstCount().
**
** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
** if an error occurs.
**
** xRowid:
** Returns the rowid of the current row.
**
** xTokenize:
** Tokenize text using the tokenizer belonging to the FTS5 table.
**
** xQueryPhrase(pFts5, iPhrase, pUserData, xCallback):
** This API function is used to query the FTS table for phrase iPhrase
** of the current query. Specifically, a query equivalent to:
**
** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid
**
** with $p set to a phrase equivalent to the phrase iPhrase of the
** current query is executed. For each row visited, the callback function
** passed as the fourth argument is invoked. The context and API objects
** passed to the callback function may be used to access the properties of
** each matched row. Invoking Api.xUserData() returns a copy of the pointer
** passed as the third argument to pUserData.
**
** If the callback function returns any value other than SQLITE_OK, the
** query is abandoned and the xQueryPhrase function returns immediately.
** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK.
** Otherwise, the error code is propagated upwards.
**
** If the query runs to completion without incident, SQLITE_OK is returned.
** Or, if some error occurs before the query completes or is aborted by
** the callback, an SQLite error code is returned.
**
**
** xSetAuxdata(pFts5, pAux, xDelete)
**
** Save the pointer passed as the second argument as the extension functions
** "auxiliary data". The pointer may then be retrieved by the current or any
** future invocation of the same fts5 extension function made as part of
** of the same MATCH query using the xGetAuxdata() API.
**
** Each extension function is allocated a single auxiliary data slot for
** each FTS query (MATCH expression). If the extension function is invoked
** more than once for a single FTS query, then all invocations share a
** single auxiliary data context.
**
** If there is already an auxiliary data pointer when this function is
** invoked, then it is replaced by the new pointer. If an xDelete callback
** was specified along with the original pointer, it is invoked at this
** point.
**
** The xDelete callback, if one is specified, is also invoked on the
** auxiliary data pointer after the FTS5 query has finished.
**
** If an error (e.g. an OOM condition) occurs within this function, an
** the auxiliary data is set to NULL and an error code returned. If the
** xDelete parameter was not NULL, it is invoked on the auxiliary data
** pointer before returning.
**
**
** xGetAuxdata(pFts5, bClear)
**
** Returns the current auxiliary data pointer for the fts5 extension
** function. See the xSetAuxdata() method for details.
**
** If the bClear argument is non-zero, then the auxiliary data is cleared
** (set to NULL) before this function returns. In this case the xDelete,
** if any, is not invoked.
**
**
** xRowCount(pFts5, pnRow)
**
** This function is used to retrieve the total number of rows in the table.
** In other words, the same value that would be returned by:
**
** SELECT count(*) FROM ftstable;
**
** xPhraseFirst()
** This function is used, along with type Fts5PhraseIter and the xPhraseNext
** method, to iterate through all instances of a single query phrase within
** the current row. This is the same information as is accessible via the
** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient
** to use, this API may be faster under some circumstances. To iterate
** through instances of phrase iPhrase, use the following code:
**
** Fts5PhraseIter iter;
** int iCol, iOff;
** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
** iOff>=0;
** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
** ){
** // An instance of phrase iPhrase at offset iOff of column iCol
** }
**
** The Fts5PhraseIter structure is defined above. Applications should not
** modify this structure directly - it should only be used as shown above
** with the xPhraseFirst() and xPhraseNext() API methods.
**
** xPhraseNext()
** See xPhraseFirst above.
*/
struct Fts5ExtensionApi {
int iVersion; /* Currently always set to 1 */
void *(*xUserData)(Fts5Context*);
int (*xColumnCount)(Fts5Context*);
int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);
int (*xTokenize)(Fts5Context*,
const char *pText, int nText, /* Text to tokenize */
void *pCtx, /* Context passed to xToken() */
int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
);
int (*xPhraseCount)(Fts5Context*);
int (*xPhraseSize)(Fts5Context*, int iPhrase);
int (*xInstCount)(Fts5Context*, int *pnInst);
int (*xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff);
sqlite3_int64 (*xRowid)(Fts5Context*);
int (*xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn);
int (*xColumnSize)(Fts5Context*, int iCol, int *pnToken);
int (*xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData,
int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
);
int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
void *(*xGetAuxdata)(Fts5Context*, int bClear);
void (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
};
/*
** CUSTOM AUXILIARY FUNCTIONS
*************************************************************************/
/*************************************************************************
** CUSTOM TOKENIZERS
**
** Applications may also register custom tokenizer types. A tokenizer
** is registered by providing fts5 with a populated instance of the
** following structure. All structure methods must be defined, setting
** any member of the fts5_tokenizer struct to NULL leads to undefined
** behaviour. The structure methods are expected to function as follows:
**
** xCreate:
** This function is used to allocate and inititalize a tokenizer instance.
** A tokenizer instance is required to actually tokenize text.
**
** The first argument passed to this function is a copy of the (void*)
** pointer provided by the application when the fts5_tokenizer object
** was registered with FTS5 (the third argument to xCreateTokenizer()).
** The second and third arguments are an array of nul-terminated strings
** containing the tokenizer arguments, if any, specified following the
** tokenizer name as part of the CREATE VIRTUAL TABLE statement used
** to create the FTS5 table.
**
** The final argument is an output variable. If successful, (*ppOut)
** should be set to point to the new tokenizer handle and SQLITE_OK
** returned. If an error occurs, some value other than SQLITE_OK should
** be returned. In this case, fts5 assumes that the final value of *ppOut
** is undefined.
**
** xDelete:
** This function is invoked to delete a tokenizer handle previously
** allocated using xCreate(). Fts5 guarantees that this function will
** be invoked exactly once for each successful call to xCreate().
**
** xTokenize:
** This function is expected to tokenize the nText byte string indicated
** by argument pText. pText may or may not be nul-terminated. The first
** argument passed to this function is a pointer to an Fts5Tokenizer object
** returned by an earlier call to xCreate().
**
** The second argument indicates the reason that FTS5 is requesting
** tokenization of the supplied text. This is always one of the following
** four values:
**
** <ul><li> <b>FTS5_TOKENIZE_DOCUMENT</b> - A document is being inserted into
** or removed from the FTS table. The tokenizer is being invoked to
** determine the set of tokens to add to (or delete from) the
** FTS index.
**
** <li> <b>FTS5_TOKENIZE_QUERY</b> - A MATCH query is being executed
** against the FTS index. The tokenizer is being called to tokenize
** a bareword or quoted string specified as part of the query.
**
** <li> <b>(FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX)</b> - Same as
** FTS5_TOKENIZE_QUERY, except that the bareword or quoted string is
** followed by a "*" character, indicating that the last token
** returned by the tokenizer will be treated as a token prefix.
**
** <li> <b>FTS5_TOKENIZE_AUX</b> - The tokenizer is being invoked to
** satisfy an fts5_api.xTokenize() request made by an auxiliary
** function. Or an fts5_api.xColumnSize() request made by the same
** on a columnsize=0 database.
** </ul>
**
** For each token in the input string, the supplied callback xToken() must
** be invoked. The first argument to it should be a copy of the pointer
** passed as the second argument to xTokenize(). The third and fourth
** arguments are a pointer to a buffer containing the token text, and the
** size of the token in bytes. The 4th and 5th arguments are the byte offsets
** of the first byte of and first byte immediately following the text from
** which the token is derived within the input.
**
** The second argument passed to the xToken() callback ("tflags") should
** normally be set to 0. The exception is if the tokenizer supports
** synonyms. In this case see the discussion below for details.
**
** FTS5 assumes the xToken() callback is invoked for each token in the
** order that they occur within the input text.
**
** If an xToken() callback returns any value other than SQLITE_OK, then
** the tokenization should be abandoned and the xTokenize() method should
** immediately return a copy of the xToken() return value. Or, if the
** input buffer is exhausted, xTokenize() should return SQLITE_OK. Finally,
** if an error occurs with the xTokenize() implementation itself, it
** may abandon the tokenization and return any error code other than
** SQLITE_OK or SQLITE_DONE.
**
** SYNONYM SUPPORT
**
** Custom tokenizers may also support synonyms. Consider a case in which a
** user wishes to query for a phrase such as "first place". Using the
** built-in tokenizers, the FTS5 query 'first + place' will match instances
** of "first place" within the document set, but not alternative forms
** such as "1st place". In some applications, it would be better to match
** all instances of "first place" or "1st place" regardless of which form
** the user specified in the MATCH query text.
**
** There are several ways to approach this in FTS5:
**
** <ol><li> By mapping all synonyms to a single token. In this case, the
** In the above example, this means that the tokenizer returns the
** same token for inputs "first" and "1st". Say that token is in
** fact "first", so that when the user inserts the document "I won
** 1st place" entries are added to the index for tokens "i", "won",
** "first" and "place". If the user then queries for '1st + place',
** the tokenizer substitutes "first" for "1st" and the query works
** as expected.
**
** <li> By adding multiple synonyms for a single term to the FTS index.
** In this case, when tokenizing query text, the tokenizer may
** provide multiple synonyms for a single term within the document.
** FTS5 then queries the index for each synonym individually. For
** example, faced with the query:
**
** <codeblock>
** ... MATCH 'first place'</codeblock>
**
** the tokenizer offers both "1st" and "first" as synonyms for the
** first token in the MATCH query and FTS5 effectively runs a query
** similar to:
**
** <codeblock>
** ... MATCH '(first OR 1st) place'</codeblock>
**
** except that, for the purposes of auxiliary functions, the query
** still appears to contain just two phrases - "(first OR 1st)"
** being treated as a single phrase.
**
** <li> By adding multiple synonyms for a single term to the FTS index.
** Using this method, when tokenizing document text, the tokenizer
** provides multiple synonyms for each token. So that when a
** document such as "I won first place" is tokenized, entries are
** added to the FTS index for "i", "won", "first", "1st" and
** "place".
**
** This way, even if the tokenizer does not provide synonyms
** when tokenizing query text (it should not - to do would be
** inefficient), it doesn't matter if the user queries for
** 'first + place' or '1st + place', as there are entires in the
** FTS index corresponding to both forms of the first token.
** </ol>
**
** Whether it is parsing document or query text, any call to xToken that
** specifies a <i>tflags</i> argument with the FTS5_TOKEN_COLOCATED bit
** is considered to supply a synonym for the previous token. For example,
** when parsing the document "I won first place", a tokenizer that supports
** synonyms would call xToken() 5 times, as follows:
**
** <codeblock>
** xToken(pCtx, 0, "i", 1, 0, 1);
** xToken(pCtx, 0, "won", 3, 2, 5);
** xToken(pCtx, 0, "first", 5, 6, 11);
** xToken(pCtx, FTS5_TOKEN_COLOCATED, "1st", 3, 6, 11);
** xToken(pCtx, 0, "place", 5, 12, 17);
**</codeblock>
**
** It is an error to specify the FTS5_TOKEN_COLOCATED flag the first time
** xToken() is called. Multiple synonyms may be specified for a single token
** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence.
** There is no limit to the number of synonyms that may be provided for a
** single token.
**
** In many cases, method (1) above is the best approach. It does not add
** extra data to the FTS index or require FTS5 to query for multiple terms,
** so it is efficient in terms of disk space and query speed. However, it
** does not support prefix queries very well. If, as suggested above, the
** token "first" is subsituted for "1st" by the tokenizer, then the query:
**
** <codeblock>
** ... MATCH '1s*'</codeblock>
**
** will not match documents that contain the token "1st" (as the tokenizer
** will probably not map "1s" to any prefix of "first").
**
** For full prefix support, method (3) may be preferred. In this case,
** because the index contains entries for both "first" and "1st", prefix
** queries such as 'fi*' or '1s*' will match correctly. However, because
** extra entries are added to the FTS index, this method uses more space
** within the database.
**
** Method (2) offers a midpoint between (1) and (3). Using this method,
** a query such as '1s*' will match documents that contain the literal
** token "1st", but not "first" (assuming the tokenizer is not able to
** provide synonyms for prefixes). However, a non-prefix query like '1st'
** will match against "1st" and "first". This method does not require
** extra disk space, as no extra entries are added to the FTS index.
** On the other hand, it may require more CPU cycles to run MATCH queries,
** as separate queries of the FTS index are required for each synonym.
**
** When using methods (2) or (3), it is important that the tokenizer only
** provide synonyms when tokenizing document text (method (2)) or query
** text (method (3)), not both. Doing so will not cause any errors, but is
** inefficient.
*/
typedef struct Fts5Tokenizer Fts5Tokenizer;
typedef struct fts5_tokenizer fts5_tokenizer;
struct fts5_tokenizer {
int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
void (*xDelete)(Fts5Tokenizer*);
int (*xTokenize)(Fts5Tokenizer*,
void *pCtx,
int flags, /* Mask of FTS5_TOKENIZE_* flags */
const char *pText, int nText,
int (*xToken)(
void *pCtx, /* Copy of 2nd argument to xTokenize() */
int tflags, /* Mask of FTS5_TOKEN_* flags */
const char *pToken, /* Pointer to buffer containing token */
int nToken, /* Size of token in bytes */
int iStart, /* Byte offset of token within input text */
int iEnd /* Byte offset of end of token within input text */
)
);
};
/* Flags that may be passed as the third argument to xTokenize() */
#define FTS5_TOKENIZE_QUERY 0x0001
#define FTS5_TOKENIZE_PREFIX 0x0002
#define FTS5_TOKENIZE_DOCUMENT 0x0004
#define FTS5_TOKENIZE_AUX 0x0008
/* Flags that may be passed by the tokenizer implementation back to FTS5
** as the third argument to the supplied xToken callback. */
#define FTS5_TOKEN_COLOCATED 0x0001 /* Same position as prev. token */
/*
** END OF CUSTOM TOKENIZERS
*************************************************************************/
/*************************************************************************
** FTS5 EXTENSION REGISTRATION API
*/
typedef struct fts5_api fts5_api;
struct fts5_api {
int iVersion; /* Currently always set to 2 */
/* Create a new tokenizer */
int (*xCreateTokenizer)(
fts5_api *pApi,
const char *zName,
void *pContext,
fts5_tokenizer *pTokenizer,
void (*xDestroy)(void*)
);
/* Find an existing tokenizer */
int (*xFindTokenizer)(
fts5_api *pApi,
const char *zName,
void **ppContext,
fts5_tokenizer *pTokenizer
);
/* Create a new auxiliary function */
int (*xCreateFunction)(
fts5_api *pApi,
const char *zName,
void *pContext,
fts5_extension_function xFunction,
void (*xDestroy)(void*)
);
};
/*
** END OF REGISTRATION API
*************************************************************************/
#ifdef __cplusplus
} /* end of the 'extern "C"' block */
#endif
#endif /* _FTS5_H */

View File

@ -9,6 +9,7 @@
#include "nsAboutProtocolUtils.h"
#include "mozilla/ArrayUtils.h"
#include "nsDOMString.h"
#include "nsIProtocolHandler.h"
NS_IMPL_ISUPPORTS(nsAboutRedirector, nsIAboutModule)
@ -48,7 +49,7 @@ static RedirEntry kRedirMap[] = {
{ "crashes", "chrome://global/content/crashes.xhtml", 0 },
#endif
{
"credits", "http://www.mozilla.org/credits/",
"credits", "https://www.mozilla.org/credits/",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT
},
{
@ -143,12 +144,27 @@ nsAboutRedirector::NewChannel(nsIURI* aURI,
nsCOMPtr<nsIURI> tempURI;
rv = NS_NewURI(getter_AddRefs(tempURI), kRedirMap[i].url);
NS_ENSURE_SUCCESS(rv, rv);
// If tempURI links to an external URI (i.e. something other than
// chrome:// or resource://) then set the LOAD_REPLACE flag on the
// channel which forces the channel owner to reflect the displayed
// URL rather then being the systemPrincipal.
bool isUIResource = false;
rv = NS_URIChainHasFlags(tempURI, nsIProtocolHandler::URI_IS_UI_RESOURCE,
&isUIResource);
NS_ENSURE_SUCCESS(rv, rv);
nsLoadFlags loadFlags =
isUIResource ? static_cast<nsLoadFlags>(nsIChannel::LOAD_NORMAL)
: static_cast<nsLoadFlags>(nsIChannel::LOAD_REPLACE);
rv = NS_NewChannelInternal(getter_AddRefs(tempChannel),
tempURI,
aLoadInfo);
if (NS_FAILED(rv)) {
return rv;
}
aLoadInfo,
nullptr, // aLoadGroup
nullptr, // aCallbacks
loadFlags);
NS_ENSURE_SUCCESS(rv, rv);
tempChannel->SetOriginalURI(aURI);

View File

@ -184,12 +184,14 @@ void
AudioChannelService::Shutdown()
{
if (gAudioChannelService) {
if (IsParentProcess()) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(gAudioChannelService, "xpcom-shutdown");
obs->RemoveObserver(gAudioChannelService, "outer-window-destroyed");
if (IsParentProcess()) {
obs->RemoveObserver(gAudioChannelService, "ipc:content-shutdown");
obs->RemoveObserver(gAudioChannelService, "xpcom-shutdown");
obs->RemoveObserver(gAudioChannelService, "outer-window-destroyed");
#ifdef MOZ_WIDGET_GONK
// To monitor the volume settings based on audio channel.
obs->RemoveObserver(gAudioChannelService, "mozsettings-changed");
@ -216,12 +218,13 @@ AudioChannelService::AudioChannelService()
, mContentOrNormalChannel(false)
, mAnyChannel(false)
{
if (IsParentProcess()) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->AddObserver(this, "xpcom-shutdown", false);
obs->AddObserver(this, "outer-window-destroyed", false);
if (IsParentProcess()) {
obs->AddObserver(this, "ipc:content-shutdown", false);
obs->AddObserver(this, "xpcom-shutdown", false);
obs->AddObserver(this, "outer-window-destroyed", false);
#ifdef MOZ_WIDGET_GONK
// To monitor the volume settings based on audio channel.
obs->AddObserver(this, "mozsettings-changed", false);

View File

@ -400,7 +400,18 @@ nsContentIterator::Init(nsIDOMRange* aDOMRange)
if (endIsData || !endNode->HasChildren() || endIndx == 0) {
if (mPre) {
if (endNode->IsContent()) {
mLast = endNode->AsContent();
// If the end node is an empty element and the end offset is 0,
// the last element should be the previous node (i.e., shouldn't
// include the end node in the range).
if (!endIsData && !endNode->HasChildren() && !endIndx) {
mLast = GetPrevSibling(endNode);
if (!NodeIsInTraversalRange(mLast, mPre, startNode, startIndx,
endNode, endIndx)) {
mLast = nullptr;
}
} else {
mLast = endNode->AsContent();
}
} else {
// Not much else to do here...
mLast = nullptr;

View File

@ -3168,5 +3168,13 @@ DeprecationWarning(JSContext* aCx, JSObject* aObject,
}
}
bool
ObjectToOuterObjectValue(JSContext* cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JS::Value> vp)
{
JSObject* outer = JS_ObjectToOuterObject(cx, obj);
vp.setObject(*outer);
return true;
}
} // namespace dom
} // namespace mozilla

View File

@ -789,6 +789,9 @@ TryToOuterize(JSContext* cx, JS::MutableHandle<JS::Value> rval)
return true;
}
bool
ObjectToOuterObjectValue(JSContext* cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JS::Value> vp);
// Make sure to wrap the given string value into the right compartment, as
// needed.
MOZ_ALWAYS_INLINE

View File

@ -1333,10 +1333,6 @@ DOMInterfaces = {
'implicitJSContext': ['readHeapSnapshot', 'saveHeapSnapshot']
},
'TimeRanges': {
'wrapperCache': False
},
'TouchList': {
'headerFile': 'mozilla/dom/TouchEvent.h',
},

View File

@ -453,7 +453,7 @@ class CGDOMJSClass(CGThing):
nullptr, /* unwatch */
nullptr, /* getElements */
nullptr, /* enumerate */
JS_ObjectToOuterObject /* thisObject */
mozilla::dom::ObjectToOuterObjectValue /* thisValue */
}
""",
objectMoved=objectMovedHook)

View File

@ -15,6 +15,7 @@
#include "mozilla/dom/BluetoothMapParametersBinding.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/Endian.h"
#include "mozilla/dom/File.h"
#include "mozilla/RefPtr.h"
@ -279,7 +280,7 @@ BluetoothMapSmsManager::MasDataHandler(UnixSocketBuffer* aMessage)
return;
}
mRemoteMaxPacketLength = ((static_cast<int>(data[5]) << 8) | data[6]);
mRemoteMaxPacketLength = BigEndian::readUint16(&data[5]);
if (mRemoteMaxPacketLength < 255) {
BT_LOGR("Remote maximum packet length %d", mRemoteMaxPacketLength);
@ -713,26 +714,20 @@ BluetoothMapSmsManager::HandleSmsMmsFolderListing(const ObexHeaderSet& aHeader)
if (aHeader.GetAppParameter(Map::AppParametersTagId::MaxListCount,
buf, 64)) {
maxListCount = *((uint16_t *)buf);
// convert big endian to little endian
maxListCount = (maxListCount >> 8) | (maxListCount << 8);
maxListCount = BigEndian::readUint16(buf);
}
uint16_t startOffset = 0;
if (aHeader.GetAppParameter(Map::AppParametersTagId::StartOffset,
buf, 64)) {
startOffset = *((uint16_t *)buf);
// convert big endian to little endian
startOffset = (startOffset >> 8) | (startOffset << 8);
startOffset = BigEndian::readUint16(buf);
}
// Folder listing size
int foldersize = mCurrentFolder->GetSubFolderCount();
// Convert little endian to big endian
uint8_t folderListingSizeValue[2];
folderListingSizeValue[0] = (foldersize & 0xFF00) >> 8;
folderListingSizeValue[1] = (foldersize & 0x00FF);
BigEndian::writeUint16(&folderListingSizeValue[0], foldersize);
// Section 3.3.4 "GetResponse", IrOBEX 1.2
// [opcode:1][length:2][FolderListingSize:4][Headers:var] where
@ -786,18 +781,14 @@ BluetoothMapSmsManager::AppendBtNamedValueByTagId(
*/
switch (aTagId) {
case Map::AppParametersTagId::MaxListCount: {
uint16_t maxListCount = *((uint16_t *)buf);
// convert big endian to little endian
maxListCount = (maxListCount >> 8) | (maxListCount << 8);
uint16_t maxListCount = BigEndian::readUint16(buf);
BT_LOGR("max list count: %d", maxListCount);
AppendNamedValue(aValues, "maxListCount",
static_cast<uint32_t>(maxListCount));
break;
}
case Map::AppParametersTagId::StartOffset: {
uint16_t startOffset = *((uint16_t *)buf);
// convert big endian to little endian
startOffset = (startOffset >> 8) | (startOffset << 8);
uint16_t startOffset = BigEndian::readUint16(buf);
BT_LOGR("start offset : %d", startOffset);
AppendNamedValue(aValues, "startOffset",
static_cast<uint32_t>(startOffset));
@ -812,10 +803,8 @@ BluetoothMapSmsManager::AppendBtNamedValueByTagId(
case Map::AppParametersTagId::ParameterMask: {
/* Table 6.5, MAP 6.3.1. ParameterMask is Bit 16-31 Reserved for future
* use. The reserved bits shall be set to 0 by MCE and discarded by MSE.
* convert big endian to little endian
*/
uint32_t parameterMask = (buf[3] << 0) | (buf[2] << 8) |
(buf[1] << 16) | (buf[0] << 24);
uint32_t parameterMask = BigEndian::readUint32(buf);
BT_LOGR("msg parameterMask : %d", parameterMask);
AppendNamedValue(aValues, "parameterMask", parameterMask);
break;

View File

@ -13,6 +13,7 @@
#include "BluetoothUuid.h"
#include "mozilla/dom/BluetoothPbapParametersBinding.h"
#include "mozilla/Endian.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/RefPtr.h"
@ -537,7 +538,7 @@ BluetoothPbapManager::AppendNamedValueByTagId(
AppendNamedValue(aValues, "searchText", nsCString((char *) buf));
break;
case AppParameterTag::MaxListCount: {
uint16_t maxListCount = ReadLittleEndianUInt16(buf);
uint16_t maxListCount = BigEndian::readUint16(buf);
AppendNamedValue(aValues, "maxListCount",
static_cast<uint32_t>(maxListCount));
@ -549,7 +550,7 @@ BluetoothPbapManager::AppendNamedValueByTagId(
}
case AppParameterTag::ListStartOffset:
AppendNamedValue(aValues, "listStartOffset",
static_cast<uint32_t>(ReadLittleEndianUInt16(buf)));
static_cast<uint32_t>(BigEndian::readUint16(buf)));
break;
case AppParameterTag::PropertySelector:
AppendNamedValue(aValues, "propSelector", PackPropertiesMask(buf, 64));
@ -729,9 +730,7 @@ BluetoothPbapManager::PackPropertiesMask(uint8_t* aData, int aSize)
// the requested vCard objects. We only support bit 0~31 since the rest are
// reserved for future use or vendor specific properties.
// convert big endian to little endian
uint32_t x = (aData[7] << 0) | (aData[6] << 8) |
(aData[5] << 16) | (aData[4] << 24);
uint32_t x = BigEndian::readUint32(&aData[4]);
uint32_t count = 0;
while (x) {
@ -859,7 +858,8 @@ BluetoothPbapManager::ReplyToGet(uint16_t aPhonebookSize)
if (mPhonebookSizeRequired) {
// ---- Part 2: [headerId:1][length:2][PhonebookSize:4] ---- //
uint16_t pbSizeBigEndian = ConvertEndiannessUInt16(aPhonebookSize);
uint8_t phonebookSize[2];
BigEndian::writeUint16(&phonebookSize[0], aPhonebookSize);
// Section 6.2.1 "Application Parameters Header", PBAP 1.2
// appParameters: [headerId:1][length:2][PhonebookSize:4], where
@ -868,8 +868,8 @@ BluetoothPbapManager::ReplyToGet(uint16_t aPhonebookSize)
AppendAppParameter(appParameters,
sizeof(appParameters),
static_cast<uint8_t>(AppParameterTag::PhonebookSize),
(uint8_t*) &pbSizeBigEndian,
sizeof(pbSizeBigEndian));
phonebookSize,
sizeof(phonebookSize));
index += AppendHeaderAppParameters(&res[index],
mRemoteMaxPacketLength,

View File

@ -9,6 +9,7 @@
#include <unistd.h>
#include <sys/socket.h>
#include "BluetoothInterface.h"
#include "mozilla/Endian.h"
#include "nsClassHashtable.h"
BEGIN_BLUETOOTH_NAMESPACE
@ -243,18 +244,14 @@ int16_t
SocketMessageWatcher::ReadInt16(unsigned long aOffset) const
{
/* little-endian buffer */
return (static_cast<int16_t>(mBuf[aOffset + 1]) << 8) |
static_cast<int16_t>(mBuf[aOffset]);
return LittleEndian::readInt16(&mBuf[aOffset]);
}
int32_t
SocketMessageWatcher::ReadInt32(unsigned long aOffset) const
{
/* little-endian buffer */
return (static_cast<int32_t>(mBuf[aOffset + 3]) << 24) |
(static_cast<int32_t>(mBuf[aOffset + 2]) << 16) |
(static_cast<int32_t>(mBuf[aOffset + 1]) << 8) |
static_cast<int32_t>(mBuf[aOffset]);
return LittleEndian::readInt32(&mBuf[aOffset]);
}
void

View File

@ -604,16 +604,4 @@ InsertNamedValue(InfallibleTArray<BluetoothNamedValue>& aArray,
aArray.InsertElementAt(aIndex, BluetoothNamedValue(name, aValue));
}
uint16_t
ConvertEndiannessUInt16(uint16_t aValue)
{
return (aValue >> 8) | (aValue << 8);
}
uint16_t
ReadLittleEndianUInt16(const uint8_t* aBuf)
{
return ConvertEndiannessUInt16(*((uint16_t *) aBuf));
}
END_BLUETOOTH_NAMESPACE

View File

@ -272,20 +272,6 @@ void InsertNamedValue(InfallibleTArray<BluetoothNamedValue>& aArray,
uint8_t aIndex, const char* aName,
const BluetoothValue& aValue);
//
// Big/Little endianness conversion
//
/**
* Convert a big/little endian uint16_t value to little/big endian one.
*/
uint16_t ConvertEndiannessUInt16(uint16_t aValue);
/**
* Read an uint16_t from array and convert it to little endian one.
*/
uint16_t ReadLittleEndianUInt16(const uint8_t* aBuf);
END_BLUETOOTH_NAMESPACE
#endif // mozilla_dom_bluetooth_BluetoothUtils_h

View File

@ -1896,12 +1896,7 @@ BrowserElementChild.prototype = {
}
if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
let bgColor = 'transparent';
try {
bgColor = content.getComputedStyle(content.document.body)
.getPropertyValue('background-color');
} catch (e) {}
sendAsyncMsg('loadend', {backgroundColor: bgColor});
sendAsyncMsg('loadend');
switch (status) {
case Cr.NS_OK :

View File

@ -22,7 +22,7 @@ function runTest() {
var iframe = document.createElement('iframe');
iframe.setAttribute('mozbrowser', 'true');
iframe.id = 'iframe';
iframe.src = 'http://example.com/tests/dom/browser-element/mochitest/file_browserElement_LoadEvents.html';
iframe.src = browserElementTestHelpers.emptyPage1;
function loadstart(e) {
ok(e.isTrusted, 'Event should be trusted.');
@ -46,7 +46,6 @@ function runTest() {
ok(seenLoadStart, 'loadend after loadstart.');
ok(!seenLoadEnd, 'Just one loadend event.');
ok(seenLocationChange, 'loadend after locationchange.');
is(e.detail.backgroundColor, 'rgb(0, 128, 0)', 'Expected background color reported')
seenLoadEnd = true;
}
@ -100,7 +99,6 @@ function runTest2() {
seenLoadEnd = true;
ok(seenLoadStart, 'Load end after load start.');
ok(seenLocationChange, 'Load end after location change.');
is(e.detail.backgroundColor, 'transparent', 'Expected background color reported')
});
iframe.src = browserElementTestHelpers.emptyPage2;

View File

@ -1,14 +0,0 @@
<html>
<body style="background-color:green;">
<!-- Tests rely on the fact that there's an element in here called 'url' and
that there's visible text on the page. -->
Aloha! My URL is <span id='url'></span>.
<script>
document.getElementById('url').innerHTML = window.location;
</script>
</body>
</html>

View File

@ -95,7 +95,6 @@ support-files =
file_browserElement_ExecuteScript.html
file_browserElement_ForwardName.html
file_browserElement_FrameWrongURI.html
file_browserElement_LoadEvents.html
file_browserElement_Metachange.sjs
file_browserElement_NextPaint.html
file_browserElement_Open1.html

View File

@ -1521,7 +1521,7 @@ HTMLMediaElement::Seek(double aTime,
}
// Clamp the seek target to inside the seekable ranges.
RefPtr<dom::TimeRanges> seekable = new dom::TimeRanges();
RefPtr<dom::TimeRanges> seekable = new dom::TimeRanges(ToSupports(OwnerDoc()));
media::TimeIntervals seekableIntervals = mDecoder->GetSeekable();
if (seekableIntervals.IsInvalid()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
@ -1638,7 +1638,7 @@ NS_IMETHODIMP HTMLMediaElement::GetDuration(double* aDuration)
already_AddRefed<TimeRanges>
HTMLMediaElement::Seekable() const
{
RefPtr<TimeRanges> ranges = new TimeRanges();
RefPtr<TimeRanges> ranges = new TimeRanges(ToSupports(OwnerDoc()));
if (mDecoder && mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING) {
mDecoder->GetSeekable().ToTimeRanges(ranges);
}
@ -1662,7 +1662,7 @@ NS_IMETHODIMP HTMLMediaElement::GetPaused(bool* aPaused)
already_AddRefed<TimeRanges>
HTMLMediaElement::Played()
{
RefPtr<TimeRanges> ranges = new TimeRanges();
RefPtr<TimeRanges> ranges = new TimeRanges(ToSupports(OwnerDoc()));
uint32_t timeRangeCount = 0;
if (mPlayed) {
@ -2067,7 +2067,7 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
mDefaultPlaybackRate(1.0),
mPlaybackRate(1.0),
mPreservesPitch(true),
mPlayed(new TimeRanges),
mPlayed(new TimeRanges(ToSupports(OwnerDoc()))),
mCurrentPlayRangeStart(-1.0),
mBegun(false),
mLoadedDataFired(false),
@ -4477,7 +4477,7 @@ HTMLMediaElement::CopyInnerTo(Element* aDest)
already_AddRefed<TimeRanges>
HTMLMediaElement::Buffered() const
{
RefPtr<TimeRanges> ranges = new TimeRanges();
RefPtr<TimeRanges> ranges = new TimeRanges(ToSupports(OwnerDoc()));
if (mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING) {
if (mDecoder) {
media::TimeIntervals buffered = mDecoder->GetBuffered();

View File

@ -12,16 +12,27 @@
namespace mozilla {
namespace dom {
NS_IMPL_ISUPPORTS(TimeRanges, nsIDOMTimeRanges)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TimeRanges, mParent)
NS_IMPL_CYCLE_COLLECTING_ADDREF(TimeRanges)
NS_IMPL_CYCLE_COLLECTING_RELEASE(TimeRanges)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TimeRanges)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsIDOMTimeRanges)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
TimeRanges::TimeRanges()
: mParent(nullptr)
{
}
TimeRanges::TimeRanges(nsISupports* aParent)
: mParent(aParent)
{
MOZ_COUNT_CTOR(TimeRanges);
}
TimeRanges::~TimeRanges()
{
MOZ_COUNT_DTOR(TimeRanges);
}
NS_IMETHODIMP
@ -166,10 +177,16 @@ TimeRanges::Find(double aTime, double aTolerance /* = 0 */)
return NoIndex;
}
bool
TimeRanges::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
JSObject*
TimeRanges::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return TimeRangesBinding::Wrap(aCx, this, aGivenProto, aReflector);
return TimeRangesBinding::Wrap(aCx, this, aGivenProto);
}
nsISupports*
TimeRanges::GetParentObject() const
{
return mParent;
}
void

View File

@ -25,13 +25,16 @@ namespace dom {
// Implements media TimeRanges:
// http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#timeranges
class TimeRanges final : public nsIDOMTimeRanges
class TimeRanges final : public nsIDOMTimeRanges,
public nsWrapperCache
{
public:
NS_DECL_ISUPPORTS
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TimeRanges)
NS_DECL_NSIDOMTIMERANGES
TimeRanges();
explicit TimeRanges(nsISupports* aParent);
void Add(double aStart, double aEnd);
@ -50,7 +53,9 @@ public:
// Mutate this TimeRange to be the intersection of this and aOtherRanges.
void Intersection(const TimeRanges* aOtherRanges);
bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector);
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
nsISupports* GetParentObject() const;
uint32_t Length() const
{
@ -90,6 +95,8 @@ private:
nsAutoTArray<TimeRange,4> mRanges;
nsCOMPtr<nsISupports> mParent;
public:
typedef nsTArray<TimeRange>::index_type index_type;
static const index_type NoIndex = index_type(-1);

View File

@ -30,3 +30,9 @@ var tests = [
inputWithoutGrouping: "123456.78", value: 123456.78
},
];
var invalidTests = [
// Right now this will pass in a 'de' build, but not in the 'en' build that
// are used for testing. See bug .
// { desc: "Invalid German", langTag: "de", input: "12.34" }
];

View File

@ -49,11 +49,24 @@ function runTest(test) {
"') localization without grouping separator");
}
function runInvalidInputTest(test) {
elem.lang = test.langTag;
elem.value = 0;
elem.focus();
elem.select();
sendString(test.input);
is(elem.value, "", "Test " + test.desc + " ('" + test.langTag +
"') with invalid input: " + test.input);
}
function startTests() {
elem = document.getElementById("input");
for (var test of tests) {
runTest(test, elem);
}
for (var test of invalidTests) {
runInvalidInputTest(test, elem);
}
}
</script>

View File

@ -57,11 +57,26 @@ function runTest(test) {
checkIsInvalid(elem, `${desc} without grouping separator`);
}
function runInvalidInputTest(test) {
elem.lang = test.langTag;
gInvalid = false; // reset
var desc = `${test.desc} (lang='${test.langTag}', id='${elem.id}')`;
elem.value = 0;
elem.focus();
elem.select();
sendString(test.input);
checkIsInvalid(elem, `${desc} with invalid input ${test.input}`);
}
function startTests() {
elem = document.getElementById("input");
for (var test of tests) {
runTest(test);
}
for (var test of invalidTests) {
runInvalidInputTest(test);
}
elem = document.getElementById("requiredinput");
for (var test of tests) {
runTest(test);

View File

@ -874,7 +874,7 @@ protected:
// Counters related to decode and presentation of frames.
FrameStatistics mFrameStats;
RefPtr<VideoFrameContainer> mVideoFrameContainer;
const RefPtr<VideoFrameContainer> mVideoFrameContainer;
// Data needed to estimate playback data rate. The timeline used for
// this estimate is "decode time" (where the "current time" is the

View File

@ -249,12 +249,12 @@ MediaDecoderReader::GetBuffered()
}
RefPtr<MediaDecoderReader::MetadataPromise>
MediaDecoderReader::AsyncReadMetadataInternal()
MediaDecoderReader::AsyncReadMetadata()
{
typedef ReadMetadataFailureReason Reason;
MOZ_ASSERT(OnTaskQueue());
DECODER_LOG("MediaDecoderReader::AsyncReadMetadataInternal");
DECODER_LOG("MediaDecoderReader::AsyncReadMetadata");
// Attempt to read the metadata.
RefPtr<MetadataHolder> metadata = new MetadataHolder();

View File

@ -94,38 +94,9 @@ public:
// on failure.
virtual nsresult Init() { return NS_OK; }
RefPtr<MetadataPromise> AsyncReadMetadata()
{
return OnTaskQueue() ?
AsyncReadMetadataInternal() :
InvokeAsync(OwnerThread(), this, __func__,
&MediaDecoderReader::AsyncReadMetadataInternal);
}
// Release media resources they should be released in dormant state
// The reader can be made usable again by calling ReadMetadata().
void ReleaseMediaResources()
{
if (OnTaskQueue()) {
ReleaseMediaResourcesInternal();
return;
}
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
this, &MediaDecoderReader::ReleaseMediaResourcesInternal);
OwnerThread()->Dispatch(r.forget());
}
void DisableHardwareAcceleration()
{
if (OnTaskQueue()) {
DisableHardwareAccelerationInternal();
return;
}
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
this, &MediaDecoderReader::DisableHardwareAccelerationInternal);
OwnerThread()->Dispatch(r.forget());
}
virtual void ReleaseMediaResources() {};
// Breaks reference-counted cycles. Called during shutdown.
// WARNING: If you override this, you must call the base implementation
// in your override.
@ -185,6 +156,18 @@ public:
virtual bool HasAudio() = 0;
virtual bool HasVideo() = 0;
// The default implementation of AsyncReadMetadata is implemented in terms of
// synchronous ReadMetadata() calls. Implementations may also
// override AsyncReadMetadata to create a more proper async implementation.
virtual RefPtr<MetadataPromise> AsyncReadMetadata();
// Read header data for all bitstreams in the file. Fills aInfo with
// the data required to present the media, and optionally fills *aTags
// with tag metadata from the file.
// Returns NS_OK on success, or NS_ERROR_FAILURE on failure.
virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) { MOZ_CRASH(); }
// Fills aInfo with the latest cached data required to present the media,
// ReadUpdatedMetadata will always be called once ReadMetadata has succeeded.
virtual void ReadUpdatedMetadata(MediaInfo* aInfo) { };
@ -260,22 +243,6 @@ public:
virtual size_t SizeOfVideoQueueInFrames();
virtual size_t SizeOfAudioQueueInFrames();
private:
virtual void ReleaseMediaResourcesInternal() {}
virtual void DisableHardwareAccelerationInternal() {}
// Read header data for all bitstreams in the file. Fills aInfo with
// the data required to present the media, and optionally fills *aTags
// with tag metadata from the file.
// Returns NS_OK on success, or NS_ERROR_FAILURE on failure.
virtual nsresult ReadMetadata(MediaInfo*, MetadataTags**) { MOZ_CRASH(); }
// The default implementation of AsyncReadMetadataInternal is implemented in
// terms of synchronous ReadMetadata() calls. Implementations may also
// override AsyncReadMetadataInternal to create a more proper async
// implementation.
virtual RefPtr<MetadataPromise> AsyncReadMetadataInternal();
protected:
friend class TrackBuffer;
virtual void NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset) { }
@ -355,6 +322,8 @@ public:
// decoding.
virtual bool VideoIsHardwareAccelerated() const { return false; }
virtual void DisableHardwareAcceleration() {}
TimedMetadataEventSource& TimedMetadataEvent() {
return mTimedMetadataEvent;
}

View File

@ -1287,7 +1287,8 @@ MediaDecoderStateMachine::SetDormant(bool aDormant)
// that run after ResetDecode are supposed to run with a clean slate. We rely
// on that in other places (i.e. seeking), so it seems reasonable to rely on
// it here as well.
mReader->ReleaseMediaResources();
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(mReader, &MediaDecoderReader::ReleaseMediaResources);
DecodeTaskQueue()->Dispatch(r.forget());
} else if ((aDormant != true) && (mState == DECODER_STATE_DORMANT)) {
ScheduleStateMachine();
mDecodingFirstFrame = true;
@ -2280,10 +2281,11 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
case DECODER_STATE_DECODING_METADATA: {
if (!mMetadataRequest.Exists()) {
DECODER_LOG("Calling AsyncReadMetadata");
DECODER_LOG("Dispatching AsyncReadMetadata");
// Set mode to METADATA since we are about to read metadata.
mResource->SetReadMode(MediaCacheStream::MODE_METADATA);
mMetadataRequest.Begin(mReader->AsyncReadMetadata()
mMetadataRequest.Begin(InvokeAsync(DecodeTaskQueue(), mReader.get(), __func__,
&MediaDecoderReader::AsyncReadMetadata)
->Then(OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnMetadataRead,
&MediaDecoderStateMachine::OnMetadataNotRead));
@ -2482,7 +2484,9 @@ MediaDecoderStateMachine::CheckFrameValidity(VideoData* aData)
if (mReader->VideoIsHardwareAccelerated() &&
frameStats.GetPresentedFrames() > 60 &&
mCorruptFrames.mean() >= 2 /* 20% */) {
mReader->DisableHardwareAcceleration();
nsCOMPtr<nsIRunnable> task =
NS_NewRunnableMethod(mReader, &MediaDecoderReader::DisableHardwareAcceleration);
DecodeTaskQueue()->Dispatch(task.forget());
mCorruptFrames.clear();
gfxCriticalNote << "Too many dropped/corrupted frames, disabling DXVA";
}

View File

@ -243,7 +243,7 @@ MediaFormatReader::IsWaitingOnCDMResource() {
}
RefPtr<MediaDecoderReader::MetadataPromise>
MediaFormatReader::AsyncReadMetadataInternal()
MediaFormatReader::AsyncReadMetadata()
{
MOZ_ASSERT(OnTaskQueue());
@ -539,7 +539,7 @@ MediaFormatReader::GetDecoderData(TrackType aTrack)
}
void
MediaFormatReader::DisableHardwareAccelerationInternal()
MediaFormatReader::DisableHardwareAcceleration()
{
MOZ_ASSERT(OnTaskQueue());
if (HasVideo() && !mHardwareAccelerationDisabled) {
@ -1582,9 +1582,8 @@ MediaFormatReader::GetBuffered()
return intervals.Shift(media::TimeUnit::FromMicroseconds(-startTime));
}
void MediaFormatReader::ReleaseMediaResourcesInternal()
void MediaFormatReader::ReleaseMediaResources()
{
MOZ_ASSERT(OnTaskQueue());
// Before freeing a video codec, all video buffers needed to be released
// even from graphics pipeline.
if (mVideoFrameContainer) {

View File

@ -52,6 +52,8 @@ public:
return mAudio.mTrackDemuxer;
}
RefPtr<MetadataPromise> AsyncReadMetadata() override;
void ReadUpdatedMetadata(MediaInfo* aInfo) override;
RefPtr<SeekPromise>
@ -71,6 +73,9 @@ public:
virtual bool ForceZeroStartTime() const override;
// For Media Resource Management
void ReleaseMediaResources() override;
nsresult ResetDecode() override;
RefPtr<ShutdownPromise> Shutdown() override;
@ -79,6 +84,8 @@ public:
bool VideoIsHardwareAccelerated() const override;
void DisableHardwareAcceleration() override;
bool IsWaitForDataSupported() override { return true; }
RefPtr<WaitForDataPromise> WaitForData(MediaData::Type aType) override;
@ -435,12 +442,6 @@ private:
#if defined(READER_DORMANT_HEURISTIC)
const bool mDormantEnabled;
#endif
private:
// For Media Resource Management
void ReleaseMediaResourcesInternal() override;
void DisableHardwareAccelerationInternal() override;
RefPtr<MetadataPromise> AsyncReadMetadataInternal() override;
};
} // namespace mozilla

View File

@ -35,8 +35,8 @@ AndroidMediaReader::AndroidMediaReader(AbstractMediaDecoder *aDecoder,
{
}
nsresult
AndroidMediaReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
nsresult AndroidMediaReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags)
{
MOZ_ASSERT(OnTaskQueue());

View File

@ -64,6 +64,8 @@ public:
return true;
}
virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags);
virtual RefPtr<SeekPromise>
Seek(int64_t aTime, int64_t aEndTime) override;
@ -85,8 +87,6 @@ public:
RefPtr<Image> mImage;
};
private:
virtual nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags);
};
} // namespace mozilla

View File

@ -351,7 +351,8 @@ GetProperty(AudioFileStreamID aAudioFileStream,
nsresult
AppleMP3Reader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
AppleMP3Reader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags)
{
MOZ_ASSERT(OnTaskQueue());

View File

@ -31,6 +31,9 @@ public:
virtual bool HasAudio() override;
virtual bool HasVideo() override;
virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) override;
virtual RefPtr<SeekPromise>
Seek(int64_t aTime, int64_t aEndTime) override;
@ -47,11 +50,10 @@ protected:
virtual void NotifyDataArrivedInternal(uint32_t aLength,
int64_t aOffset) override;
public:
virtual bool IsMediaSeekable() override;
private:
virtual nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) override;
void SetupDecoder();
nsresult Read(uint32_t *aNumBytes, char *aData);

View File

@ -90,7 +90,8 @@ static const GUID CLSID_MPEG_LAYER_3_DECODER_FILTER =
{ 0x38BE3000, 0xDBF4, 0x11D0, {0x86, 0x0E, 0x00, 0xA0, 0x24, 0xCF, 0xEF, 0x6D} };
nsresult
DirectShowReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
DirectShowReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags)
{
MOZ_ASSERT(OnTaskQueue());
HRESULT hr;

View File

@ -50,6 +50,9 @@ public:
bool HasAudio() override;
bool HasVideo() override;
nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) override;
RefPtr<SeekPromise>
Seek(int64_t aTime, int64_t aEndTime) override;
@ -61,7 +64,6 @@ public:
bool IsMediaSeekable() override;
private:
nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) override;
// Notifies the filter graph that playback is complete. aStatus is
// the code to send to the filter graph. Always returns false, so

View File

@ -17,7 +17,6 @@
#ifdef XP_WIN
#include "windows.h"
#ifdef MOZ_SANDBOX
#include "mozilla/Scoped.h"
#include <intrin.h>
#include <assert.h>
#endif
@ -37,31 +36,6 @@
#include "sha256.h"
#endif
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
namespace {
// Scoped type used by Load
struct ScopedActCtxHandleTraits
{
typedef HANDLE type;
static type empty()
{
return INVALID_HANDLE_VALUE;
}
static void release(type aActCtxHandle)
{
if (aActCtxHandle != INVALID_HANDLE_VALUE) {
ReleaseActCtx(aActCtxHandle);
}
}
};
typedef mozilla::Scoped<ScopedActCtxHandleTraits> ScopedActCtxHandle;
} // namespace
#endif
namespace mozilla {
namespace gmp {
@ -146,11 +120,6 @@ static void SecureMemset(void* start, uint8_t value, size_t size)
}
#endif
// The RAII variable holding the activation context that we create before
// lowering the sandbox is getting optimized out.
#if defined(_MSC_VER)
#pragma optimize("g", off)
#endif
bool
GMPLoaderImpl::Load(const char* aUTF8LibPath,
uint32_t aUTF8LibPathLen,
@ -214,6 +183,15 @@ GMPLoaderImpl::Load(const char* aUTF8LibPath,
nodeId = std::string(aOriginSalt, aOriginSalt + aOriginSaltLen);
}
// Start the sandbox now that we've generated the device bound node id.
// This must happen after the node id is bound to the device id, as
// generating the device id requires privileges.
if (mSandboxStarter && !mSandboxStarter->Start(aUTF8LibPath)) {
return false;
}
// Load the GMP.
PRLibSpec libSpec;
#ifdef XP_WIN
int pathLen = MultiByteToWideChar(CP_UTF8, 0, aUTF8LibPath, -1, nullptr, 0);
if (pathLen == 0) {
@ -225,29 +203,6 @@ GMPLoaderImpl::Load(const char* aUTF8LibPath,
return false;
}
#ifdef MOZ_SANDBOX
// If the GMP DLL is a side-by-side assembly with static imports then the DLL
// loader will attempt to create an activation context which will fail because
// of the sandbox. If we create an activation context before we start the
// sandbox then this one will get picked up by the DLL loader.
ACTCTX actCtx = { sizeof(actCtx) };
actCtx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
actCtx.lpSource = widePath;
actCtx.lpResourceName = ISOLATIONAWARE_MANIFEST_RESOURCE_ID;
ScopedActCtxHandle actCtxHandle(CreateActCtx(&actCtx));
#endif
#endif
// Start the sandbox now that we've generated the device bound node id.
// This must happen after the node id is bound to the device id, as
// generating the device id requires privileges.
if (mSandboxStarter && !mSandboxStarter->Start(aUTF8LibPath)) {
return false;
}
// Load the GMP.
PRLibSpec libSpec;
#ifdef XP_WIN
libSpec.value.pathname_u = widePath;
libSpec.type = PR_LibSpec_PathnameU;
#else
@ -280,9 +235,6 @@ GMPLoaderImpl::Load(const char* aUTF8LibPath,
return true;
}
#if defined(_MSC_VER)
#pragma optimize("", on)
#endif
GMPErr
GMPLoaderImpl::GetAPI(const char* aAPIName,

View File

@ -127,9 +127,6 @@ IPDL_SOURCES += [
'PGMPVideoEncoder.ipdl',
]
if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
NO_VISIBILITY_FLAGS = True
# comment this out to use Unsafe Shmem for more performance
DEFINES['GMP_SAFE_SHMEM'] = True

View File

@ -72,7 +72,7 @@ static char const * const sDefaultCodecCaps[][2] = {
{"audio/mpeg", "audio/mpeg, layer=(int)3"}
};
static char const * const sPluginBlacklist[] = {
static char const * const sPluginBlockList[] = {
"flump3dec",
"h264parse",
};
@ -217,32 +217,32 @@ GstCaps* GStreamerFormatHelper::ConvertFormatsToCaps(const char* aMIMEType,
}
/* static */ bool
GStreamerFormatHelper::IsBlacklistEnabled()
GStreamerFormatHelper::IsBlockListEnabled()
{
static bool sBlacklistEnabled;
static bool sBlacklistEnabledCached = false;
static bool sBlockListEnabled;
static bool sBlockListEnabledCached = false;
if (!sBlacklistEnabledCached) {
Preferences::AddBoolVarCache(&sBlacklistEnabled,
if (!sBlockListEnabledCached) {
Preferences::AddBoolVarCache(&sBlockListEnabled,
"media.gstreamer.enable-blacklist", true);
sBlacklistEnabledCached = true;
sBlockListEnabledCached = true;
}
return sBlacklistEnabled;
return sBlockListEnabled;
}
/* static */ bool
GStreamerFormatHelper::IsPluginFeatureBlacklisted(GstPluginFeature *aFeature)
GStreamerFormatHelper::IsPluginFeatureBlocked(GstPluginFeature *aFeature)
{
if (!IsBlacklistEnabled()) {
if (!IsBlockListEnabled()) {
return false;
}
const gchar *factoryName =
gst_plugin_feature_get_name(aFeature);
for (unsigned int i = 0; i < G_N_ELEMENTS(sPluginBlacklist); i++) {
if (!strcmp(factoryName, sPluginBlacklist[i])) {
for (unsigned int i = 0; i < G_N_ELEMENTS(sPluginBlockList); i++) {
if (!strcmp(factoryName, sPluginBlockList[i])) {
LOG("rejecting disabled plugin %s", factoryName);
return true;
}
@ -268,7 +268,7 @@ static gboolean FactoryFilter(GstPluginFeature *aFeature, gpointer)
return
gst_plugin_feature_get_rank(aFeature) >= GST_RANK_MARGINAL &&
!GStreamerFormatHelper::IsPluginFeatureBlacklisted(aFeature);
!GStreamerFormatHelper::IsPluginFeatureBlocked(aFeature);
}
/**

View File

@ -29,8 +29,8 @@ class GStreamerFormatHelper {
bool CanHandleContainerCaps(GstCaps* aCaps);
bool CanHandleCodecCaps(GstCaps* aCaps);
static bool IsBlacklistEnabled();
static bool IsPluginFeatureBlacklisted(GstPluginFeature *aFeature);
static bool IsBlockListEnabled();
static bool IsPluginFeatureBlocked(GstPluginFeature *aFeature);
static GstCaps* ConvertFormatsToCaps(const char* aMIMEType,
const nsAString* aCodecs);

View File

@ -258,7 +258,7 @@ GValueArray *GStreamerReader::ElementFilter(GstURIDecodeBin *aBin,
GValue *value = &aFactories->values[i];
GstPluginFeature *factory = GST_PLUGIN_FEATURE(g_value_peek_pointer(value));
if (!GStreamerFormatHelper::IsPluginFeatureBlacklisted(factory)) {
if (!GStreamerFormatHelper::IsPluginFeatureBlocked(factory)) {
g_value_array_append(filtered, value);
}
}
@ -360,8 +360,8 @@ GStreamerReader::GetDataLength()
return streamLen - mDataOffset;
}
nsresult
GStreamerReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
nsresult GStreamerReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags)
{
MOZ_ASSERT(OnTaskQueue());
nsresult ret = NS_OK;
@ -1206,7 +1206,7 @@ void GStreamerReader::Eos(GstAppSink* aSink)
* This callback is called while the pipeline is automatically built, after a
* new element has been added to the pipeline. We use it to find the
* uridecodebin instance used by playbin and connect to it to apply our
* blacklist.
* block list.
*/
void
GStreamerReader::PlayElementAddedCb(GstBin *aBin, GstElement *aElement,
@ -1243,7 +1243,7 @@ GStreamerReader::ShouldAutoplugFactory(GstElementFactory* aFactory, GstCaps* aCa
/**
* This is called by uridecodebin (running inside playbin), after it has found
* candidate factories to continue decoding the stream. We apply the blacklist
* candidate factories to continue decoding the stream. We apply the block list
* here, disallowing known-crashy plugins.
*/
GValueArray*

View File

@ -46,6 +46,8 @@ public:
virtual bool DecodeAudioData() override;
virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
int64_t aTimeThreshold) override;
virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) override;
virtual RefPtr<SeekPromise>
Seek(int64_t aTime, int64_t aEndTime) override;
virtual media::TimeIntervals GetBuffered() override;
@ -68,7 +70,6 @@ public:
virtual bool IsMediaSeekable() override;
private:
virtual nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) override;
void ReadAndPushData(guint aLength);
RefPtr<layers::PlanarYCbCrImage> GetImageFromBuffer(GstBuffer* aBuffer);
@ -92,8 +93,8 @@ private:
/*
* We attach this callback to playbin so that when uridecodebin is
* constructed, we can then list for its autoplug-sort signal to blacklist
* the elements it can construct.
* constructed, we can then list for its autoplug-sort signal to block
* list the elements it can construct.
*/
static void ElementAddedCb(GstBin *aPlayBin,
GstElement *aElement,
@ -193,7 +194,7 @@ private:
static bool ShouldAutoplugFactory(GstElementFactory* aFactory, GstCaps* aCaps);
/* Called by decodebin during autoplugging. We use it to apply our
* container/codec blacklist.
* container/codec block list.
*/
static GValueArray* AutoplugSortCb(GstElement* aElement,
GstPad* aPad, GstCaps* aCaps,

View File

@ -118,19 +118,31 @@ SourceBuffer::SetTimestampOffset(double aTimestampOffset, ErrorResult& aRv)
}
}
already_AddRefed<TimeRanges>
TimeRanges*
SourceBuffer::GetBuffered(ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
// http://w3c.github.io/media-source/index.html#widl-SourceBuffer-buffered
// 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an InvalidStateError exception and abort these steps.
if (!IsAttached()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
media::TimeIntervals ranges = mContentManager->Buffered();
MSE_DEBUGV("ranges=%s", DumpTimeRanges(ranges).get());
RefPtr<dom::TimeRanges> tr = new dom::TimeRanges();
ranges.ToTimeRanges(tr);
return tr.forget();
bool rangeChanged = true;
media::TimeIntervals intersection = mContentManager->Buffered();
MSE_DEBUGV("intersection=%s", DumpTimeRanges(intersection).get());
if (mBuffered) {
media::TimeIntervals currentValue(mBuffered);
rangeChanged = (intersection != currentValue);
MSE_DEBUGV("currentValue=%s", DumpTimeRanges(currentValue).get());
}
// 5. If intersection ranges does not contain the exact same range information as the current value of this attribute, then update the current value of this attribute to intersection ranges.
if (rangeChanged) {
mBuffered = new TimeRanges(ToSupports(this));
intersection.ToTimeRanges(mBuffered);
}
// 6. Return the current value of this attribute.
return mBuffered;
}
media::TimeIntervals
@ -634,11 +646,13 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SourceBuffer)
manager->Detach();
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaSource)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBuffered)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SourceBuffer,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaSource)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBuffered)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_ADDREF_INHERITED(SourceBuffer, DOMEventTargetHelper)

View File

@ -147,7 +147,7 @@ public:
return mUpdating;
}
already_AddRefed<TimeRanges> GetBuffered(ErrorResult& aRv);
TimeRanges* GetBuffered(ErrorResult& aRv);
media::TimeIntervals GetTimeIntervals();
double TimestampOffset() const
@ -274,6 +274,8 @@ private:
MozPromiseRequestHolder<SourceBufferContentManager::AppendPromise> mPendingAppend;
const nsCString mType;
RefPtr<TimeRanges> mBuffered;
};
} // namespace dom

View File

@ -371,8 +371,8 @@ void OggReader::SetupMediaTracksInfo(const nsTArray<uint32_t>& aSerials)
}
}
nsresult
OggReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
nsresult OggReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags)
{
MOZ_ASSERT(OnTaskQueue());

View File

@ -69,6 +69,8 @@ public:
return mTheoraState != 0 && mTheoraState->mActive;
}
virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) override;
virtual RefPtr<SeekPromise>
Seek(int64_t aTime, int64_t aEndTime) override;
virtual media::TimeIntervals GetBuffered() override;
@ -76,8 +78,6 @@ public:
virtual bool IsMediaSeekable() override;
private:
virtual nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) override;
// TODO: DEPRECATED. This uses synchronous decoding.
// Stores the presentation time of the first frame we'd be able to play if
// we started playback at the current position. Returns the first video

View File

@ -284,10 +284,8 @@ MediaCodecReader::~MediaCodecReader()
}
void
MediaCodecReader::ReleaseMediaResourcesInternal()
MediaCodecReader::ReleaseMediaResources()
{
MOZ_ASSERT(OnTaskQueue());
// Stop the mSource because we are in the dormant state and the stop function
// will rewind the mSource to the beginning of the stream.
if (mVideoTrack.mSource != nullptr && !mVideoTrack.mSourceIsStopped) {
@ -660,7 +658,7 @@ MediaCodecReader::ParseDataSegment(const char* aBuffer,
}
RefPtr<MediaDecoderReader::MetadataPromise>
MediaCodecReader::AsyncReadMetadataInternal()
MediaCodecReader::AsyncReadMetadata()
{
MOZ_ASSERT(OnTaskQueue());

View File

@ -60,6 +60,9 @@ public:
MediaCodecReader(AbstractMediaDecoder* aDecoder);
virtual ~MediaCodecReader();
// Release media resources they should be released in dormant state
virtual void ReleaseMediaResources();
// Destroys the decoding state. The reader cannot be made usable again.
// This is different from ReleaseMediaResources() as Shutdown() is
// irreversible, whereas ReleaseMediaResources() is reversible.
@ -70,11 +73,8 @@ protected:
// all contents have been continuously parsed. (ex. total duration of some
// variable-bit-rate MP3 files.)
virtual void NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset) override;
virtual RefPtr<MediaDecoderReader::MetadataPromise>
AsyncReadMetadataInternal() override;
public:
// Flush the TaskQueue, flush MediaCodec and raise the mDiscontinuity.
virtual nsresult ResetDecode() override;
@ -89,6 +89,8 @@ public:
virtual bool HasAudio();
virtual bool HasVideo();
virtual RefPtr<MediaDecoderReader::MetadataPromise> AsyncReadMetadata() override;
// Moves the decode head to aTime microseconds. aStartTime and aEndTime
// denote the start and end times of the media in usecs, and aCurrentTime
// is the current playback position in microseconds.
@ -434,10 +436,6 @@ private:
nsTArray<ReleaseItem> mPendingReleaseItems;
NotifyDataArrivedFilter mFilter;
private:
// Release media resources they should be released in dormant state
virtual void ReleaseMediaResourcesInternal() override;
};
} // namespace mozilla

View File

@ -170,10 +170,8 @@ MediaOmxReader::Shutdown()
return p;
}
void MediaOmxReader::ReleaseMediaResourcesInternal()
void MediaOmxReader::ReleaseMediaResources()
{
MOZ_ASSERT(OnTaskQueue());
mMediaResourceRequest.DisconnectIfExists();
mMetadataPromise.RejectIfExists(ReadMetadataFailureReason::METADATA_ERROR, __func__);
@ -212,7 +210,7 @@ nsresult MediaOmxReader::InitOmxDecoder()
}
RefPtr<MediaDecoderReader::MetadataPromise>
MediaOmxReader::AsyncReadMetadataInternal()
MediaOmxReader::AsyncReadMetadata()
{
MOZ_ASSERT(OnTaskQueue());
EnsureActive();

View File

@ -72,10 +72,6 @@ public:
protected:
virtual void NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset) override;
virtual RefPtr<MediaDecoderReader::MetadataPromise>
AsyncReadMetadataInternal() override;
public:
virtual nsresult ResetDecode()
@ -99,6 +95,10 @@ public:
return mHasVideo;
}
virtual void ReleaseMediaResources() override;
virtual RefPtr<MediaDecoderReader::MetadataPromise> AsyncReadMetadata() override;
virtual RefPtr<SeekPromise>
Seek(int64_t aTime, int64_t aEndTime) override;
@ -118,8 +118,6 @@ private:
class ProcessCachedDataTask;
class NotifyDataArrivedRunnable;
virtual void ReleaseMediaResourcesInternal() override;
bool IsShutdown() {
MutexAutoLock lock(mShutdownMutex);
return mIsShutdown;

View File

@ -89,13 +89,13 @@ RtspMediaCodecReader::RequestVideoData(bool aSkipToNextKeyframe,
}
RefPtr<MediaDecoderReader::MetadataPromise>
RtspMediaCodecReader::AsyncReadMetadataInternal()
RtspMediaCodecReader::AsyncReadMetadata()
{
mRtspResource->DisablePlayoutDelay();
EnsureActive();
RefPtr<MediaDecoderReader::MetadataPromise> p =
MediaCodecReader::AsyncReadMetadataInternal();
MediaCodecReader::AsyncReadMetadata();
// Send a PAUSE to the RTSP server because the underlying media resource is
// not ready.

View File

@ -58,12 +58,12 @@ public:
// Disptach a DecodeAudioDataTask to decode audio data.
virtual RefPtr<AudioDataPromise> RequestAudioData() override;
virtual RefPtr<MediaDecoderReader::MetadataPromise> AsyncReadMetadata()
override;
virtual void HandleResourceAllocated() override;
private:
virtual RefPtr<MediaDecoderReader::MetadataPromise>
AsyncReadMetadataInternal() override;
// A pointer to RtspMediaResource for calling the Rtsp specific function.
// The lifetime of mRtspResource is controlled by MediaDecoder. MediaDecoder
// holds the MediaDecoderStateMachine and RtspMediaResource.

View File

@ -87,14 +87,14 @@ void RtspOmxReader::EnsureActive() {
}
RefPtr<MediaDecoderReader::MetadataPromise>
RtspOmxReader::AsyncReadMetadataInternal()
RtspOmxReader::AsyncReadMetadata()
{
// Send a PLAY command to the RTSP server before reading metadata.
// Because we might need some decoded samples to ensure we have configuration.
mRtspResource->DisablePlayoutDelay();
RefPtr<MediaDecoderReader::MetadataPromise> p =
MediaOmxReader::AsyncReadMetadataInternal();
MediaOmxReader::AsyncReadMetadata();
// Send a PAUSE to the RTSP server because the underlying media resource is
// not ready.

View File

@ -66,12 +66,12 @@ public:
virtual void SetIdle() override;
virtual RefPtr<MediaDecoderReader::MetadataPromise> AsyncReadMetadata()
override;
virtual void HandleResourceAllocated() override;
private:
virtual RefPtr<MediaDecoderReader::MetadataPromise>
AsyncReadMetadataInternal() override;
// A pointer to RtspMediaResource for calling the Rtsp specific function.
// The lifetime of mRtspResource is controlled by MediaDecoder. MediaDecoder
// holds the MediaDecoderStateMachine and RtspMediaResource.

View File

@ -39,7 +39,7 @@ GonkAudioDecoderManager::GonkAudioDecoderManager(const AudioInfo& aConfig)
: mAudioChannels(aConfig.mChannels)
, mAudioRate(aConfig.mRate)
, mAudioProfile(aConfig.mProfile)
, mAudioBuffer(nullptr)
, mAudioCompactor(mAudioQueue)
{
MOZ_COUNT_CTOR(GonkAudioDecoderManager);
MOZ_ASSERT(mAudioChannels);
@ -107,77 +107,94 @@ GonkAudioDecoderManager::InitMediaCodecProxy()
}
nsresult
GonkAudioDecoderManager::CreateAudioData(int64_t aStreamOffset, AudioData **v) {
if (!(mAudioBuffer != nullptr && mAudioBuffer->data() != nullptr)) {
GonkAudioDecoderManager::CreateAudioData(MediaBuffer* aBuffer, int64_t aStreamOffset)
{
if (!(aBuffer != nullptr && aBuffer->data() != nullptr)) {
GADM_LOG("Audio Buffer is not valid!");
return NS_ERROR_UNEXPECTED;
}
int64_t timeUs;
if (!mAudioBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
if (!aBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
return NS_ERROR_UNEXPECTED;
}
if (mAudioBuffer->range_length() == 0) {
if (aBuffer->range_length() == 0) {
// Some decoders may return spurious empty buffers that we just want to ignore
// quoted from Android's AwesomePlayer.cpp
ReleaseAudioBuffer();
return NS_ERROR_NOT_AVAILABLE;
}
if (mLastTime > timeUs) {
ReleaseAudioBuffer();
GADM_LOG("Output decoded sample time is revert. time=%lld", timeUs);
MOZ_ASSERT(false);
return NS_ERROR_NOT_AVAILABLE;
}
mLastTime = timeUs;
const uint8_t *data = static_cast<const uint8_t*>(mAudioBuffer->data());
size_t dataOffset = mAudioBuffer->range_offset();
size_t size = mAudioBuffer->range_length();
const uint8_t *data = static_cast<const uint8_t*>(aBuffer->data());
size_t dataOffset = aBuffer->range_offset();
size_t size = aBuffer->range_length();
nsAutoArrayPtr<AudioDataValue> buffer(new AudioDataValue[size/2]);
memcpy(buffer.get(), data+dataOffset, size);
uint32_t frames = size / (2 * mAudioChannels);
CheckedInt64 duration = FramesToUsecs(frames, mAudioRate);
if (!duration.isValid()) {
return NS_ERROR_UNEXPECTED;
}
RefPtr<AudioData> audioData = new AudioData(aStreamOffset,
timeUs,
duration.value(),
frames,
buffer.forget(),
mAudioChannels,
mAudioRate);
ReleaseAudioBuffer();
audioData.forget(v);
typedef AudioCompactor::NativeCopy OmxCopy;
mAudioCompactor.Push(aStreamOffset,
timeUs,
mAudioRate,
frames,
mAudioChannels,
OmxCopy(data+dataOffset,
size,
mAudioChannels));
return NS_OK;
}
class AutoReleaseAudioBuffer
{
public:
AutoReleaseAudioBuffer(MediaBuffer* aBuffer, MediaCodecProxy* aCodecProxy)
: mAudioBuffer(aBuffer)
, mCodecProxy(aCodecProxy)
{}
~AutoReleaseAudioBuffer()
{
if (mAudioBuffer) {
mCodecProxy->ReleaseMediaBuffer(mAudioBuffer);
}
}
private:
MediaBuffer* mAudioBuffer;
sp<MediaCodecProxy> mCodecProxy;
};
nsresult
GonkAudioDecoderManager::Output(int64_t aStreamOffset,
RefPtr<MediaData>& aOutData)
{
aOutData = nullptr;
if (mAudioQueue.GetSize() > 0) {
aOutData = mAudioQueue.PopFront();
return mAudioQueue.AtEndOfStream() ? NS_ERROR_ABORT : NS_OK;
}
status_t err;
err = mDecoder->Output(&mAudioBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US);
MediaBuffer* audioBuffer = nullptr;
err = mDecoder->Output(&audioBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US);
AutoReleaseAudioBuffer a(audioBuffer, mDecoder.get());
switch (err) {
case OK:
{
RefPtr<AudioData> data;
nsresult rv = CreateAudioData(aStreamOffset, getter_AddRefs(data));
if (rv == NS_ERROR_NOT_AVAILABLE) {
// Decoder outputs an empty video buffer, try again
return NS_ERROR_NOT_AVAILABLE;
} else if (rv != NS_OK || data == nullptr) {
return NS_ERROR_UNEXPECTED;
}
aOutData = data;
return NS_OK;
nsresult rv = CreateAudioData(audioBuffer, aStreamOffset);
NS_ENSURE_SUCCESS(rv, rv);
break;
}
case android::INFO_FORMAT_CHANGED:
{
@ -219,17 +236,11 @@ GonkAudioDecoderManager::Output(int64_t aStreamOffset,
case android::ERROR_END_OF_STREAM:
{
GADM_LOG("Got EOS frame!");
RefPtr<AudioData> data;
nsresult rv = CreateAudioData(aStreamOffset, getter_AddRefs(data));
if (rv == NS_ERROR_NOT_AVAILABLE) {
// For EOS, no need to do any thing.
return NS_ERROR_ABORT;
} else if (rv != NS_OK || data == nullptr) {
GADM_LOG("Failed to create audio data!");
return NS_ERROR_UNEXPECTED;
}
aOutData = data;
return NS_ERROR_ABORT;
nsresult rv = CreateAudioData(audioBuffer, aStreamOffset);
NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT);
MOZ_ASSERT(mAudioQueue.GetSize() > 0);
mAudioQueue.Finish();
break;
}
case -ETIMEDOUT:
{
@ -243,14 +254,22 @@ GonkAudioDecoderManager::Output(int64_t aStreamOffset,
}
}
return NS_OK;
if (mAudioQueue.GetSize() > 0) {
aOutData = mAudioQueue.PopFront();
// Return NS_ERROR_ABORT at the last sample.
return mAudioQueue.AtEndOfStream() ? NS_ERROR_ABORT : NS_OK;
}
return NS_ERROR_NOT_AVAILABLE;
}
void GonkAudioDecoderManager::ReleaseAudioBuffer() {
if (mAudioBuffer) {
mDecoder->ReleaseMediaBuffer(mAudioBuffer);
mAudioBuffer = nullptr;
}
nsresult
GonkAudioDecoderManager::Flush()
{
GADM_LOG("FLUSH<<<");
mAudioQueue.Reset();
GADM_LOG(">>>FLUSH");
return GonkDecoderManager::Flush();
}
} // namespace mozilla

View File

@ -7,6 +7,7 @@
#if !defined(GonkAudioDecoderManager_h_)
#define GonkAudioDecoderManager_h_
#include "AudioCompactor.h"
#include "mozilla/RefPtr.h"
#include "GonkMediaDataDecoder.h"
@ -30,19 +31,21 @@ public:
nsresult Output(int64_t aStreamOffset,
RefPtr<MediaData>& aOutput) override;
virtual nsresult Flush() override;
private:
bool InitMediaCodecProxy();
nsresult CreateAudioData(int64_t aStreamOffset,
AudioData** aOutData);
void ReleaseAudioBuffer();
nsresult CreateAudioData(MediaBuffer* aBuffer, int64_t aStreamOffset);
uint32_t mAudioChannels;
uint32_t mAudioRate;
const uint32_t mAudioProfile;
android::MediaBuffer* mAudioBuffer;
MediaQueue<AudioData> mAudioQueue;
AudioCompactor mAudioCompactor;
};
} // namespace mozilla

View File

@ -33,7 +33,7 @@ public:
nsresult Input(MediaRawData* aSample);
// Flush the queued sample.
nsresult Flush();
virtual nsresult Flush();
// Shutdown decoder and rejects the init promise.
virtual nsresult Shutdown();

View File

@ -218,7 +218,7 @@ MFTDecoder::Output(RefPtr<IMFSample>* aOutput)
}
if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
// Type change, probably geometric aperature change.
// Type change, probably geometric aperture change.
// Reconfigure decoder output type, so that GetOutputMediaType()
// returns the new type, and return the error code to caller.
// This is an expected failure, so don't warn on encountering it.

View File

@ -28,6 +28,7 @@ namespace mozilla {
static bool sDXVAEnabled = false;
static int sNumDecoderThreads = -1;
static bool sIsIntelDecoderEnabled = false;
static bool sLowLatencyMFTEnabled = false;
WMFDecoderModule::WMFDecoderModule()
: mWMFInitialized(false)
@ -68,6 +69,7 @@ WMFDecoderModule::Init()
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
sDXVAEnabled = gfxPlatform::GetPlatform()->CanUseHardwareVideoDecoding();
sIsIntelDecoderEnabled = Preferences::GetBool("media.webm.intel_decoder.enabled", false);
sLowLatencyMFTEnabled = Preferences::GetBool("media.wmf.low-latency.enabled", false);
SetNumOfDecoderThreads();
}
@ -78,6 +80,13 @@ WMFDecoderModule::GetNumDecoderThreads()
return sNumDecoderThreads;
}
/* static */
bool
WMFDecoderModule::LowLatencyMFTEnabled()
{
return sLowLatencyMFTEnabled;
}
nsresult
WMFDecoderModule::Startup()
{

View File

@ -41,6 +41,7 @@ public:
// Called from any thread, must call init first
static int GetNumDecoderThreads();
static bool LowLatencyMFTEnabled();
private:
bool mWMFInitialized;
};

View File

@ -216,12 +216,13 @@ WMFVideoMFTManager::InitInternal(bool aForceD3D9)
attr->GetUINT32(MF_SA_D3D_AWARE, &aware);
attr->SetUINT32(CODECAPI_AVDecNumWorkerThreads,
WMFDecoderModule::GetNumDecoderThreads());
hr = attr->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE);
if (SUCCEEDED(hr)) {
LOG("Enabling Low Latency Mode");
}
else {
LOG("Couldn't enable Low Latency Mode");
if (WMFDecoderModule::LowLatencyMFTEnabled()) {
hr = attr->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE);
if (SUCCEEDED(hr)) {
LOG("Enabling Low Latency Mode");
} else {
LOG("Couldn't enable Low Latency Mode");
}
}
}

View File

@ -32,8 +32,8 @@ nsresult RawReader::ResetDecode()
return MediaDecoderReader::ResetDecode();
}
nsresult
RawReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
nsresult RawReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags)
{
MOZ_ASSERT(OnTaskQueue());

View File

@ -36,6 +36,8 @@ public:
return true;
}
virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) override;
virtual RefPtr<SeekPromise>
Seek(int64_t aTime, int64_t aEndTime) override;
@ -44,7 +46,6 @@ public:
virtual bool IsMediaSeekable() override;
private:
virtual nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) override;
bool ReadFromResource(uint8_t *aBuf, uint32_t aLength);
RawVideoHeader mMetadata;

View File

@ -116,8 +116,8 @@ WaveReader::~WaveReader()
MOZ_COUNT_DTOR(WaveReader);
}
nsresult
WaveReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
nsresult WaveReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags)
{
MOZ_ASSERT(OnTaskQueue());

View File

@ -36,6 +36,8 @@ public:
return false;
}
virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) override;
virtual RefPtr<SeekPromise>
Seek(int64_t aTime, int64_t aEndTime) override;
@ -44,7 +46,6 @@ public:
virtual bool IsMediaSeekable() override;
private:
virtual nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) override;
bool ReadAll(char* aBuf, int64_t aSize, int64_t* aBytesRead = nullptr);
bool LoadRIFFChunk();
bool LoadFormatChunk(uint32_t aChunkSize);

View File

@ -227,10 +227,8 @@ void WebMReader::Cleanup()
}
RefPtr<MediaDecoderReader::MetadataPromise>
WebMReader::AsyncReadMetadataInternal()
WebMReader::AsyncReadMetadata()
{
MOZ_ASSERT(OnTaskQueue());
RefPtr<MetadataHolder> metadata = new MetadataHolder();
if (NS_FAILED(RetrieveWebMMetadata(&metadata->mInfo)) ||

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