mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-24 02:35:41 +00:00
Merge m-c to b2ginbound, a=merge CLOSED TREE
This commit is contained in:
commit
268dd97805
@ -18,3 +18,6 @@ LOCAL_INCLUDES += [
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -275,7 +275,7 @@ var gTests = [
|
||||
Services.obs.removeObserver(searchObserver, "browser-search-engine-modified");
|
||||
});
|
||||
Services.search.addEngine("http://test:80/browser/browser/base/content/test/general/POSTSearchEngine.xml",
|
||||
Ci.nsISearchEngine.DATA_XML, null, false);
|
||||
null, null, false);
|
||||
return deferred.promise;
|
||||
}
|
||||
},
|
||||
@ -659,7 +659,7 @@ function promiseNewEngine(basename) {
|
||||
info("Waiting for engine to be added: " + basename);
|
||||
let addDeferred = Promise.defer();
|
||||
let url = getRootDirectory(gTestPath) + basename;
|
||||
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
|
||||
Services.search.addEngine(url, null, "", false, {
|
||||
onSuccess: function (engine) {
|
||||
info("Search engine added: " + basename);
|
||||
registerCleanupFunction(() => {
|
||||
|
@ -194,32 +194,32 @@ add_task(function* cycleSuggestions() {
|
||||
shiftKey: true,
|
||||
accelKey: true,
|
||||
};
|
||||
|
||||
|
||||
let state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers });
|
||||
checkState(state, "xfoo", ["xfoo", "xbar"], 0, aSelectedButtonIndex);
|
||||
|
||||
|
||||
state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers });
|
||||
checkState(state, "xbar", ["xfoo", "xbar"], 1, aSelectedButtonIndex);
|
||||
|
||||
|
||||
state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers });
|
||||
checkState(state, "x", ["xfoo", "xbar"], -1, aSelectedButtonIndex);
|
||||
|
||||
|
||||
state = yield msg("key", { key: "VK_DOWN", modifiers: modifiers });
|
||||
checkState(state, "xfoo", ["xfoo", "xbar"], 0, aSelectedButtonIndex);
|
||||
|
||||
|
||||
state = yield msg("key", { key: "VK_UP", modifiers: modifiers });
|
||||
checkState(state, "x", ["xfoo", "xbar"], -1, aSelectedButtonIndex);
|
||||
|
||||
|
||||
state = yield msg("key", { key: "VK_UP", modifiers: modifiers });
|
||||
checkState(state, "xbar", ["xfoo", "xbar"], 1, aSelectedButtonIndex);
|
||||
|
||||
|
||||
state = yield msg("key", { key: "VK_UP", modifiers: modifiers });
|
||||
checkState(state, "xfoo", ["xfoo", "xbar"], 0, aSelectedButtonIndex);
|
||||
|
||||
|
||||
state = yield msg("key", { key: "VK_UP", modifiers: modifiers });
|
||||
checkState(state, "x", ["xfoo", "xbar"], -1, aSelectedButtonIndex);
|
||||
});
|
||||
|
||||
|
||||
yield cycle();
|
||||
|
||||
// Repeat with a one-off selected.
|
||||
@ -689,7 +689,7 @@ function checkState(actualState, expectedInputVal, expectedSuggestions,
|
||||
if (expectedSelectedIdx == -1 && expectedSelectedButtonIdx != undefined) {
|
||||
expectedSelectedIdx = expectedSuggestions.length + expectedSelectedButtonIdx;
|
||||
}
|
||||
|
||||
|
||||
let expectedState = {
|
||||
selectedIndex: expectedSelectedIdx,
|
||||
numSuggestions: expectedSuggestions.length,
|
||||
@ -759,34 +759,15 @@ function setUpEngines() {
|
||||
let currentEngineName = Services.search.currentEngine.name;
|
||||
let currentEngines = Services.search.getVisibleEngines();
|
||||
info("Adding test search engines");
|
||||
let engine1 = yield promiseNewEngine(TEST_ENGINE_BASENAME);
|
||||
let engine2 = yield promiseNewEngine(TEST_ENGINE_2_BASENAME);
|
||||
let engine1 = yield promiseNewSearchEngine(TEST_ENGINE_BASENAME);
|
||||
let engine2 = yield promiseNewSearchEngine(TEST_ENGINE_2_BASENAME);
|
||||
Services.search.currentEngine = engine1;
|
||||
for (let engine of currentEngines) {
|
||||
Services.search.removeEngine(engine);
|
||||
}
|
||||
registerCleanupFunction(() => {
|
||||
Services.search.restoreDefaultEngines();
|
||||
Services.search.removeEngine(engine1);
|
||||
Services.search.removeEngine(engine2);
|
||||
Services.search.currentEngine = Services.search.getEngineByName(currentEngineName);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function promiseNewEngine(basename) {
|
||||
info("Waiting for engine to be added: " + basename);
|
||||
let addDeferred = Promise.defer();
|
||||
let url = getRootDirectory(gTestPath) + basename;
|
||||
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
|
||||
onSuccess: function (engine) {
|
||||
info("Search engine added: " + basename);
|
||||
addDeferred.resolve(engine);
|
||||
},
|
||||
onError: function (errCode) {
|
||||
ok(false, "addEngine failed with error code " + errCode);
|
||||
addDeferred.reject();
|
||||
},
|
||||
});
|
||||
return addDeferred.promise;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ function test() {
|
||||
});
|
||||
|
||||
Services.search.addEngine("http://test:80/browser/browser/base/content/test/general/POSTSearchEngine.xml",
|
||||
Ci.nsISearchEngine.DATA_XML, null, false);
|
||||
null, null, false);
|
||||
}
|
||||
|
||||
var gCurrTest;
|
||||
|
@ -65,6 +65,76 @@ function once(target, name) {
|
||||
});
|
||||
}
|
||||
|
||||
function fetchFile(uri) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", uri, true);
|
||||
xhr.onreadystatechange = function() {
|
||||
if (this.readyState != this.DONE) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
resolve(this.responseText);
|
||||
} catch (ex) {
|
||||
ok(false, `Script error reading ${uri}: ${ex}`);
|
||||
resolve("");
|
||||
}
|
||||
};
|
||||
xhr.onerror = error => {
|
||||
ok(false, `XHR error reading ${uri}: ${error}`);
|
||||
resolve("");
|
||||
};
|
||||
xhr.send(null);
|
||||
});
|
||||
}
|
||||
|
||||
var gChromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]
|
||||
.getService(Ci.nsIChromeRegistry);
|
||||
var gChromeMap = new Map();
|
||||
|
||||
function getBaseUriForChromeUri(chromeUri) {
|
||||
let chromeFile = chromeUri + "gobbledygooknonexistentfile.reallynothere";
|
||||
let uri = Services.io.newURI(chromeFile, null, null);
|
||||
let fileUri = gChromeReg.convertChromeURL(uri);
|
||||
return fileUri.resolve(".");
|
||||
}
|
||||
|
||||
function parseManifest(manifestUri) {
|
||||
return fetchFile(manifestUri.spec).then(data => {
|
||||
for (let line of data.split('\n')) {
|
||||
let [type, ...argv] = line.split(/\s+/);
|
||||
let component;
|
||||
if (type == "content" || type == "skin") {
|
||||
[component] = argv;
|
||||
} else {
|
||||
// skip unrelated lines
|
||||
continue;
|
||||
}
|
||||
let chromeUri = `chrome://${component}/${type}/`;
|
||||
gChromeMap.set(getBaseUriForChromeUri(chromeUri), chromeUri);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function convertToChromeUri(fileUri) {
|
||||
let baseUri = fileUri.spec;
|
||||
let path = "";
|
||||
while (true) {
|
||||
let slashPos = baseUri.lastIndexOf("/", baseUri.length - 2);
|
||||
if (slashPos < 0) {
|
||||
info(`File not accessible from chrome protocol: ${fileUri.path}`);
|
||||
return fileUri;
|
||||
}
|
||||
path = baseUri.slice(slashPos + 1) + path;
|
||||
baseUri = baseUri.slice(0, slashPos + 1);
|
||||
if (gChromeMap.has(baseUri)) {
|
||||
let chromeBaseUri = gChromeMap.get(baseUri);
|
||||
let chromeUri = `${chromeBaseUri}${path}`;
|
||||
return Services.io.newURI(chromeUri, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function messageIsCSSError(msg, innerWindowID, outerWindowID) {
|
||||
// Only care about CSS errors generated by our iframe:
|
||||
if ((msg instanceof Ci.nsIScriptError) &&
|
||||
@ -85,15 +155,11 @@ add_task(function checkAllTheCSS() {
|
||||
// This asynchronously produces a list of URLs (sadly, mostly sync on our
|
||||
// test infrastructure because it runs against jarfiles there, and
|
||||
// our zipreader APIs are all sync)
|
||||
let uris = yield generateURIsFromDirTree(appDir, ".css");
|
||||
let uris = yield generateURIsFromDirTree(appDir, [".css", ".manifest"]);
|
||||
|
||||
// Create a clean iframe to load all the files into. This needs to live at a
|
||||
// file or jar URI (depending on whether we're using a packaged build or not)
|
||||
// so that it's allowed to load other same-scheme URIs (i.e. the browser css).
|
||||
let resHandler = Services.io.getProtocolHandler("resource")
|
||||
.QueryInterface(Ci.nsISubstitutingProtocolHandler);
|
||||
let resURI = Services.io.newURI('resource://testing-common/resource_test_file.html', null, null);
|
||||
let testFile = resHandler.resolveURI(resURI);
|
||||
// chrome URI so that it's allowed to load and parse any styles.
|
||||
let testFile = getRootDirectory(gTestPath) + "dummy_page.html";
|
||||
let windowless = Services.appShell.createWindowlessBrowser();
|
||||
let iframe = windowless.document.createElementNS("http://www.w3.org/1999/xhtml", "html:iframe");
|
||||
windowless.document.documentElement.appendChild(iframe);
|
||||
@ -106,6 +172,20 @@ add_task(function checkAllTheCSS() {
|
||||
let innerWindowID = windowUtils.currentInnerWindowID;
|
||||
let outerWindowID = windowUtils.outerWindowID;
|
||||
|
||||
// Parse and remove all manifests from the list.
|
||||
// NOTE that this must be done before filtering out devtools paths
|
||||
// so that all chrome paths can be recorded.
|
||||
let manifestPromises = [];
|
||||
uris = uris.filter(uri => {
|
||||
if (uri.path.endsWith(".manifest")) {
|
||||
manifestPromises.push(parseManifest(uri));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
// Wait for all manifest to be parsed
|
||||
yield Promise.all(manifestPromises);
|
||||
|
||||
// We build a list of promises that get resolved when their respective
|
||||
// files have loaded and produced no errors.
|
||||
let allPromises = [];
|
||||
@ -133,7 +213,8 @@ add_task(function checkAllTheCSS() {
|
||||
linkEl.addEventListener("load", onLoad);
|
||||
linkEl.addEventListener("error", onError);
|
||||
linkEl.setAttribute("type", "text/css");
|
||||
linkEl.setAttribute("href", uri.spec);
|
||||
let chromeUri = convertToChromeUri(uri);
|
||||
linkEl.setAttribute("href", chromeUri.spec);
|
||||
allPromises.push(promiseForThisSpec.promise);
|
||||
doc.head.appendChild(linkEl);
|
||||
}
|
||||
|
@ -1033,8 +1033,7 @@ function promiseNewSearchEngine(basename) {
|
||||
return new Promise((resolve, reject) => {
|
||||
info("Waiting for engine to be added: " + basename);
|
||||
let url = getRootDirectory(gTestPath) + basename;
|
||||
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "",
|
||||
false, {
|
||||
Services.search.addEngine(url, null, "", false, {
|
||||
onSuccess: function (engine) {
|
||||
info("Search engine added: " + basename);
|
||||
registerCleanupFunction(() => Services.search.removeEngine(engine));
|
||||
|
@ -237,7 +237,7 @@ function promiseNewSearchEngine({name: basename, numLogos}) {
|
||||
// Wait for addEngine().
|
||||
let addDeferred = Promise.defer();
|
||||
let url = getRootDirectory(gTestPath) + basename;
|
||||
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
|
||||
Services.search.addEngine(url, null, "", false, {
|
||||
onSuccess: function (engine) {
|
||||
info("Search engine added: " + basename);
|
||||
gNewEngines.push(engine);
|
||||
|
@ -17,3 +17,6 @@ FINAL_LIBRARY = 'browsercomps'
|
||||
LOCAL_INCLUDES += [
|
||||
'../build',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -38,3 +38,6 @@ if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
# GTK2: Need to link with glib for GNOME shell service
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'gtk2', 'gtk3'):
|
||||
OS_LIBS += CONFIG['TK_LIBS']
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -21,3 +21,6 @@ FINAL_LIBRARY = 'browsercomps'
|
||||
LOCAL_INCLUDES += [
|
||||
'../build'
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -42,3 +42,6 @@ LOCAL_INCLUDES += [
|
||||
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ('Firefox', 'RSS Discovery and Preview')
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -930,6 +930,10 @@ loop.OTSdkDriver = (function() {
|
||||
this.dispatcher.dispatch(new sharedActions.ConnectionFailure({
|
||||
reason: FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA
|
||||
}));
|
||||
} else if (event.code === OT.ExceptionCodes.UNABLE_TO_PUBLISH) {
|
||||
// We need to log the message so that we can understand where the exception
|
||||
// is coming from. Potentially a temporary addition.
|
||||
this._notifyMetricsEvent("sdk.exception." + event.code + "." + event.message);
|
||||
} else {
|
||||
this._notifyMetricsEvent("sdk.exception." + event.code);
|
||||
}
|
||||
|
@ -1537,6 +1537,26 @@ describe("loop.OTSdkDriver", function () {
|
||||
}));
|
||||
});
|
||||
|
||||
describe("Unable to publish (not GetUserMedia)", function() {
|
||||
it("should notify metrics", function() {
|
||||
sdk.trigger("exception", {
|
||||
code: OT.ExceptionCodes.UNABLE_TO_PUBLISH,
|
||||
message: "Fake",
|
||||
title: "Connect Failed"
|
||||
});
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.ConnectionStatus({
|
||||
event: "sdk.exception." + OT.ExceptionCodes.UNABLE_TO_PUBLISH + ".Fake",
|
||||
state: "starting",
|
||||
connections: 0,
|
||||
sendStreams: 0,
|
||||
recvStreams: 0
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe("Unable to publish (GetUserMedia)", function() {
|
||||
it("should destroy the publisher", function() {
|
||||
sdk.trigger("exception", {
|
||||
|
@ -446,13 +446,11 @@
|
||||
if (target.engine) {
|
||||
this.currentEngine = target.engine;
|
||||
} else if (target.classList.contains("addengine-item")) {
|
||||
// We only detect OpenSearch files
|
||||
var type = Ci.nsISearchEngine.DATA_XML;
|
||||
// Select the installed engine if the installation succeeds
|
||||
var installCallback = {
|
||||
onSuccess: engine => this.currentEngine = engine
|
||||
}
|
||||
Services.search.addEngine(target.getAttribute("uri"), type,
|
||||
Services.search.addEngine(target.getAttribute("uri"), null,
|
||||
target.getAttribute("src"), false,
|
||||
installCallback);
|
||||
}
|
||||
@ -1432,8 +1430,7 @@
|
||||
Components.utils.reportError("Error adding search engine: " + errorCode);
|
||||
}
|
||||
}
|
||||
Services.search.addEngine(target.getAttribute("uri"),
|
||||
Ci.nsISearchEngine.DATA_XML,
|
||||
Services.search.addEngine(target.getAttribute("uri"), null,
|
||||
target.getAttribute("image"), false,
|
||||
installCallback);
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ support-files =
|
||||
head.js
|
||||
opensearch.html
|
||||
test.html
|
||||
testEngine.src
|
||||
testEngine.xml
|
||||
testEngine_diacritics.xml
|
||||
testEngine_dupe.xml
|
||||
|
@ -99,8 +99,7 @@ function* promiseSetEngine() {
|
||||
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
ss.addEngine("http://mochi.test:8888/browser/browser/components/search/test/426329.xml",
|
||||
Ci.nsISearchEngine.DATA_XML, "data:image/x-icon,%00",
|
||||
false);
|
||||
null, "data:image/x-icon,%00", false);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -24,8 +24,7 @@ function test() {
|
||||
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/483086-1.xml",
|
||||
Ci.nsISearchEngine.DATA_XML, "data:image/x-icon;%00",
|
||||
false);
|
||||
null, "data:image/x-icon;%00", false);
|
||||
}
|
||||
|
||||
function test2() {
|
||||
@ -37,7 +36,7 @@ function test2() {
|
||||
is(engine.searchForm, "http://example.com", "SearchForm is correct");
|
||||
gSS.removeEngine(engine);
|
||||
break;
|
||||
case "engine-removed":
|
||||
case "engine-removed":
|
||||
Services.obs.removeObserver(observer, "browser-search-engine-modified");
|
||||
finish();
|
||||
break;
|
||||
@ -46,6 +45,5 @@ function test2() {
|
||||
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/483086-2.xml",
|
||||
Ci.nsISearchEngine.DATA_XML, "data:image/x-icon;%00",
|
||||
false);
|
||||
null, "data:image/x-icon;%00", false);
|
||||
}
|
||||
|
@ -44,12 +44,11 @@ var gTests = [
|
||||
name: "Foo",
|
||||
alias: null,
|
||||
description: "Foo Search",
|
||||
searchForm: "http://mochi.test:8888/browser/browser/components/search/test/",
|
||||
type: Ci.nsISearchEngine.TYPE_OPENSEARCH
|
||||
searchForm: "http://mochi.test:8888/browser/browser/components/search/test/"
|
||||
},
|
||||
run: function () {
|
||||
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
|
||||
Ci.nsISearchEngine.DATA_XML, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
|
||||
null, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
|
||||
false);
|
||||
},
|
||||
added: function (engine) {
|
||||
@ -77,37 +76,6 @@ var gTests = [
|
||||
ok(currentEngine, "An engine is present.");
|
||||
isnot(currentEngine.name, this.engine.name, "Current engine reset after removal");
|
||||
|
||||
nextTest();
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "sherlock install",
|
||||
engine: {
|
||||
name: "Test Sherlock",
|
||||
alias: null,
|
||||
description: "Test Description",
|
||||
searchForm: "http://example.com/searchform",
|
||||
type: Ci.nsISearchEngine.TYPE_SHERLOCK
|
||||
},
|
||||
run: function () {
|
||||
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.src",
|
||||
Ci.nsISearchEngine.DATA_TEXT, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
|
||||
false);
|
||||
},
|
||||
added: function (engine) {
|
||||
ok(engine, "engine was added.");
|
||||
checkEngine(this.engine, engine);
|
||||
|
||||
let engineFromSS = gSS.getEngineByName(this.engine.name);
|
||||
is(engineFromSS, engine, "engine is obtainable via getEngineByName");
|
||||
|
||||
gSS.removeEngine(engine);
|
||||
},
|
||||
removed: function (engine) {
|
||||
let currentEngine = gSS.currentEngine;
|
||||
ok(currentEngine, "An engine is present.");
|
||||
isnot(currentEngine.name, this.engine.name, "Current engine reset after removal");
|
||||
|
||||
nextTest();
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ function test() {
|
||||
alias: null,
|
||||
description: "Amazon.com Search",
|
||||
searchForm: "https://www.amazon.com/exec/obidos/external-search/?field-keywords=&mode=blended&tag=mozilla-20&sourceid=Mozilla-search",
|
||||
type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
|
||||
hidden: false,
|
||||
wrappedJSObject: {
|
||||
queryCharset: "UTF-8",
|
||||
|
@ -40,7 +40,6 @@ function test() {
|
||||
alias: null,
|
||||
description: "Bing. Search by Microsoft.",
|
||||
searchForm: "https://www.bing.com/search?q=&pc=MOZI",
|
||||
type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
|
||||
hidden: false,
|
||||
wrappedJSObject: {
|
||||
queryCharset: "UTF-8",
|
||||
|
@ -31,8 +31,7 @@ function test() {
|
||||
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
ss.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine_mozsearch.xml",
|
||||
Ci.nsISearchEngine.DATA_XML, "data:image/x-icon,%00",
|
||||
false);
|
||||
null, "data:image/x-icon,%00", false);
|
||||
|
||||
function startTest() {
|
||||
contextMenu = document.getElementById("contentAreaContextMenu");
|
||||
|
@ -30,7 +30,6 @@ function test() {
|
||||
alias: null,
|
||||
description: "eBay - Online auctions",
|
||||
searchForm: "http://search.ebay.com/",
|
||||
type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
|
||||
hidden: false,
|
||||
wrappedJSObject: {
|
||||
queryCharset: "ISO-8859-1",
|
||||
|
@ -46,7 +46,6 @@ function test() {
|
||||
alias: null,
|
||||
description: "Google Search",
|
||||
searchForm: "https://www.google.com/search?q=&ie=utf-8&oe=utf-8",
|
||||
type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
|
||||
hidden: false,
|
||||
wrappedJSObject: {
|
||||
queryCharset: "UTF-8",
|
||||
|
@ -96,9 +96,7 @@ function test() {
|
||||
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
Services.search.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
|
||||
Ci.nsISearchEngine.DATA_XML,
|
||||
"data:image/x-icon,%00",
|
||||
false);
|
||||
null, "data:image/x-icon,%00", false);
|
||||
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ function promiseNewEngine(basename) {
|
||||
Services.search.init({
|
||||
onInitComplete: function() {
|
||||
let url = getRootDirectory(gTestPath) + basename;
|
||||
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
|
||||
Services.search.addEngine(url, null, "", false, {
|
||||
onSuccess: function (engine) {
|
||||
info("Search engine added: " + basename);
|
||||
resolve(engine);
|
||||
|
@ -51,8 +51,7 @@ function test() {
|
||||
ok(false, "failed to install engine: " + errorCode);
|
||||
}
|
||||
};
|
||||
Services.search.addEngine(engineURL + "426329.xml",
|
||||
Ci.nsISearchEngine.DATA_XML,
|
||||
Services.search.addEngine(engineURL + "426329.xml", null,
|
||||
"data:image/x-icon,%00", false, installCallback);
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,7 @@ function getString(key, ...params) {
|
||||
}
|
||||
|
||||
function AddSearchProvider(...args) {
|
||||
return gBrowser.addTab(ROOT + "webapi.html?AddSearchProvider:" + encodeURIComponent(JSON.stringify(args)));
|
||||
}
|
||||
|
||||
function addSearchEngine(...args) {
|
||||
return gBrowser.addTab(ROOT + "webapi.html?addSearchEngine:" + encodeURIComponent(JSON.stringify(args)));
|
||||
return gBrowser.addTab(ROOT + "webapi.html?" + encodeURIComponent(JSON.stringify(args)));
|
||||
}
|
||||
|
||||
function promiseDialogOpened() {
|
||||
@ -34,7 +30,7 @@ function promiseDialogOpened() {
|
||||
});
|
||||
}
|
||||
|
||||
add_task(function* test_working_AddSearchProvider() {
|
||||
add_task(function* test_working() {
|
||||
gBrowser.selectedTab = AddSearchProvider(ROOT + "testEngine.xml");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
@ -46,7 +42,7 @@ add_task(function* test_working_AddSearchProvider() {
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_HTTP_AddSearchProvider() {
|
||||
add_task(function* test_HTTP() {
|
||||
gBrowser.selectedTab = AddSearchProvider(ROOT.replace("http:", "HTTP:") + "testEngine.xml");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
@ -58,7 +54,7 @@ add_task(function* test_HTTP_AddSearchProvider() {
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_relative_AddSearchProvider() {
|
||||
add_task(function* test_relative() {
|
||||
gBrowser.selectedTab = AddSearchProvider("testEngine.xml");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
@ -70,7 +66,7 @@ add_task(function* test_relative_AddSearchProvider() {
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_invalid_AddSearchProvider() {
|
||||
add_task(function* test_invalid() {
|
||||
gBrowser.selectedTab = AddSearchProvider("z://foobar");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
@ -82,7 +78,7 @@ add_task(function* test_invalid_AddSearchProvider() {
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_missing_AddSearchProvider() {
|
||||
add_task(function* test_missing() {
|
||||
let url = ROOT + "foobar.xml";
|
||||
gBrowser.selectedTab = AddSearchProvider(url);
|
||||
|
||||
@ -94,88 +90,3 @@ add_task(function* test_missing_AddSearchProvider() {
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_working_addSearchEngine_xml() {
|
||||
gBrowser.selectedTab = addSearchEngine(ROOT + "testEngine.xml", "", "", "");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
|
||||
is(dialog.args.text, getString("addEngineConfirmation", "Foo", "example.com"),
|
||||
"Should have seen the right install message");
|
||||
dialog.document.documentElement.cancelDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_working_addSearchEngine_src() {
|
||||
gBrowser.selectedTab = addSearchEngine(ROOT + "testEngine.src", "", "", "");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
|
||||
is(dialog.args.text, getString("addEngineConfirmation", "Test Sherlock", "example.com"),
|
||||
"Should have seen the right install message");
|
||||
dialog.document.documentElement.cancelDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_relative_addSearchEngine_xml() {
|
||||
gBrowser.selectedTab = addSearchEngine("testEngine.xml", "", "", "");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
|
||||
is(dialog.args.text, getString("addEngineConfirmation", "Foo", "example.com"),
|
||||
"Should have seen the right install message");
|
||||
dialog.document.documentElement.cancelDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_relative_addSearchEngine_src() {
|
||||
gBrowser.selectedTab = addSearchEngine("testEngine.src", "", "", "");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
|
||||
is(dialog.args.text, getString("addEngineConfirmation", "Test Sherlock", "example.com"),
|
||||
"Should have seen the right install message");
|
||||
dialog.document.documentElement.cancelDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_invalid_addSearchEngine() {
|
||||
gBrowser.selectedTab = addSearchEngine("z://foobar", "", "", "");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "alert", "Should see the alert dialog.");
|
||||
is(dialog.args.text, getString("error_invalid_engine_msg", brandName),
|
||||
"Should have seen the right error message")
|
||||
dialog.document.documentElement.acceptDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_invalid_icon_addSearchEngine() {
|
||||
gBrowser.selectedTab = addSearchEngine(ROOT + "testEngine.src", "z://foobar", "", "");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "alert", "Should see the alert dialog.");
|
||||
is(dialog.args.text, getString("error_invalid_engine_msg", brandName),
|
||||
"Should have seen the right error message")
|
||||
dialog.document.documentElement.acceptDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_missing_addSearchEngine() {
|
||||
let url = ROOT + "foobar.xml";
|
||||
gBrowser.selectedTab = addSearchEngine(url, "", "", "");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "alert", "Should see the alert dialog.");
|
||||
is(dialog.args.text, getString("error_loading_engine_msg2", brandName, url),
|
||||
"Should have seen the right error message")
|
||||
dialog.document.documentElement.acceptDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
@ -30,7 +30,6 @@ function test() {
|
||||
alias: null,
|
||||
description: "Yahoo Search",
|
||||
searchForm: "https://search.yahoo.com/yhs/search?p=&ei=UTF-8&hspart=mozilla",
|
||||
type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
|
||||
hidden: false,
|
||||
wrappedJSObject: {
|
||||
queryCharset: "UTF-8",
|
||||
|
@ -146,7 +146,7 @@ function promiseNewEngine(basename, options = {}) {
|
||||
onInitComplete: function() {
|
||||
let url = getRootDirectory(gTestPath) + basename;
|
||||
let current = Services.search.currentEngine;
|
||||
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
|
||||
Services.search.addEngine(url, null, "", false, {
|
||||
onSuccess: function (engine) {
|
||||
info("Search engine added: " + basename);
|
||||
if (setAsCurrent) {
|
||||
|
@ -1,11 +0,0 @@
|
||||
<search
|
||||
name="Test Sherlock"
|
||||
description="Test Description"
|
||||
method="GET"
|
||||
searchform="http://example.com/searchform"
|
||||
action="http://example.com/action"
|
||||
queryCharset="UTF-8"
|
||||
>
|
||||
<input name="userParam" user>
|
||||
<input name="param" value="value">
|
||||
</search>
|
@ -4,14 +4,10 @@
|
||||
<head>
|
||||
<script>
|
||||
function installEngine() {
|
||||
var query = window.location.search.substring(1).split(":");
|
||||
var func = query[0];
|
||||
var args = JSON.parse(decodeURIComponent(query[1]));
|
||||
var query = window.location.search.substring(1);
|
||||
var args = JSON.parse(decodeURIComponent(query));
|
||||
|
||||
if (func == "AddSearchProvider")
|
||||
window.external.AddSearchProvider(...args);
|
||||
else if (func == "addSearchEngine")
|
||||
window.sidebar.addSearchEngine(...args);
|
||||
window.external.AddSearchProvider(...args);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
@ -52,3 +52,6 @@ CXXFLAGS += CONFIG['TK_CFLAGS']
|
||||
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ('Firefox', 'Shell Integration')
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -317,7 +317,7 @@ function waitForNewEngine(basename, numImages) {
|
||||
// Wait for addEngine().
|
||||
let addDeferred = Promise.defer();
|
||||
let url = getRootDirectory(gTestPath) + basename;
|
||||
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
|
||||
Services.search.addEngine(url, null, "", false, {
|
||||
onSuccess: function (engine) {
|
||||
info("Search engine added: " + basename);
|
||||
addDeferred.resolve(engine);
|
||||
|
@ -3,7 +3,7 @@
|
||||
* 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/. */
|
||||
|
||||
@import url("chrome://devtools/skin/themes/floating-scrollbars.css");
|
||||
@import url("floating-scrollbars.css");
|
||||
|
||||
scrollbar thumb {
|
||||
background-color: rgba(170,170,170,0.2) !important;
|
||||
|
@ -35,3 +35,6 @@ DevToolsModules(
|
||||
'protocol.js',
|
||||
'worker.js'
|
||||
)
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -35,3 +35,6 @@ FINAL_LIBRARY = 'xul'
|
||||
LOCAL_INCLUDES += [
|
||||
'/docshell/base'
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -32,3 +32,6 @@ LOCAL_INCLUDES += [
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['CLANG_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -38,3 +38,6 @@ LOCAL_INCLUDES += [
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -498,6 +498,11 @@ this.PermissionsTable = { geolocation: {
|
||||
privileged: ALLOW_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
"system-app-only-audio-channels-in-app": {
|
||||
app: DENY_ACTION,
|
||||
privileged: DENY_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
"killswitch": {
|
||||
app: DENY_ACTION,
|
||||
trusted: DENY_ACTION,
|
||||
|
@ -46,3 +46,7 @@ property FillOpacity
|
||||
// Push API
|
||||
method PushManager.subscribe
|
||||
method PushSubscription.unsubscribe
|
||||
|
||||
// window.sidebar.addSearchEngine
|
||||
attribute Window.sidebar
|
||||
method External.addSearchEngine
|
||||
|
@ -15,3 +15,6 @@ LOCAL_INCLUDES += [
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul-gtest'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -18,3 +18,6 @@ include('/ipc/chromium/chromium-config.mozbuild')
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -29,3 +29,6 @@ MOCHITEST_CHROME_MANIFESTS += ['tests/chrome.ini']
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -45,6 +45,24 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(BrowserElementAudioChannel,
|
||||
mTabParent,
|
||||
mBrowserElementAPI)
|
||||
|
||||
/* static */ already_AddRefed<BrowserElementAudioChannel>
|
||||
BrowserElementAudioChannel::Create(nsPIDOMWindow* aWindow,
|
||||
nsIFrameLoader* aFrameLoader,
|
||||
nsIBrowserElementAPI* aAPI,
|
||||
AudioChannel aAudioChannel,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsRefPtr<BrowserElementAudioChannel> ac =
|
||||
new BrowserElementAudioChannel(aWindow, aFrameLoader, aAPI, aAudioChannel);
|
||||
|
||||
aRv = ac->Initialize();
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ac.forget();
|
||||
}
|
||||
|
||||
BrowserElementAudioChannel::BrowserElementAudioChannel(
|
||||
nsPIDOMWindow* aWindow,
|
||||
nsIFrameLoader* aFrameLoader,
|
||||
@ -58,7 +76,6 @@ BrowserElementAudioChannel::BrowserElementAudioChannel(
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsInMainProcess();
|
||||
MOZ_ASSERT(mFrameLoader);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
@ -94,6 +111,20 @@ BrowserElementAudioChannel::~BrowserElementAudioChannel()
|
||||
nsresult
|
||||
BrowserElementAudioChannel::Initialize()
|
||||
{
|
||||
if (!mFrameLoader) {
|
||||
nsCOMPtr<nsPIDOMWindow> window = GetOwner();
|
||||
if (!window) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> topWindow;
|
||||
window->GetScriptableTop(getter_AddRefs(topWindow));
|
||||
|
||||
mFrameWindow = do_QueryInterface(topWindow);
|
||||
mFrameWindow = mFrameWindow->GetOuterWindow();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell;
|
||||
nsresult rv = mFrameLoader->GetDocShell(getter_AddRefs(docShell));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
@ -35,12 +35,12 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BrowserElementAudioChannel,
|
||||
DOMEventTargetHelper)
|
||||
|
||||
BrowserElementAudioChannel(nsPIDOMWindow* aWindow,
|
||||
nsIFrameLoader* aFrameLoader,
|
||||
nsIBrowserElementAPI* aAPI,
|
||||
AudioChannel aAudioChannel);
|
||||
|
||||
nsresult Initialize();
|
||||
static already_AddRefed<BrowserElementAudioChannel>
|
||||
Create(nsPIDOMWindow* aWindow,
|
||||
nsIFrameLoader* aFrameLoader,
|
||||
nsIBrowserElementAPI* aAPI,
|
||||
AudioChannel aAudioChannel,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// WebIDL methods
|
||||
|
||||
@ -60,8 +60,15 @@ public:
|
||||
IMPL_EVENT_HANDLER(activestatechanged);
|
||||
|
||||
private:
|
||||
BrowserElementAudioChannel(nsPIDOMWindow* aWindow,
|
||||
nsIFrameLoader* aFrameLoader,
|
||||
nsIBrowserElementAPI* aAPI,
|
||||
AudioChannel aAudioChannel);
|
||||
|
||||
~BrowserElementAudioChannel();
|
||||
|
||||
nsresult Initialize();
|
||||
|
||||
void ProcessStateChanged(const char16_t* aData);
|
||||
|
||||
nsCOMPtr<nsIFrameLoader> mFrameLoader;
|
||||
|
@ -12,6 +12,8 @@ var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/Microformats.js");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "acs",
|
||||
"@mozilla.org/audiochannel/service;1",
|
||||
@ -251,7 +253,8 @@ BrowserElementChild.prototype = {
|
||||
"set-audio-channel-volume": this._recvSetAudioChannelVolume,
|
||||
"get-audio-channel-muted": this._recvGetAudioChannelMuted,
|
||||
"set-audio-channel-muted": this._recvSetAudioChannelMuted,
|
||||
"get-is-audio-channel-active": this._recvIsAudioChannelActive
|
||||
"get-is-audio-channel-active": this._recvIsAudioChannelActive,
|
||||
"get-structured-data": this._recvGetStructuredData
|
||||
}
|
||||
|
||||
addMessageListener("browser-element-api:call", function(aMessage) {
|
||||
@ -1558,6 +1561,300 @@ BrowserElementChild.prototype = {
|
||||
sendAsyncMsg('got-set-input-method-active', msgData);
|
||||
},
|
||||
|
||||
_processMicroformatValue(field, value) {
|
||||
if (['node', 'resolvedNode', 'semanticType'].includes(field)) {
|
||||
return null;
|
||||
} else if (Array.isArray(value)) {
|
||||
var result = value.map(i => this._processMicroformatValue(field, i))
|
||||
.filter(i => i !== null);
|
||||
return result.length ? result : null;
|
||||
} else if (typeof value == 'string') {
|
||||
return value;
|
||||
} else if (typeof value == 'object' && value !== null) {
|
||||
return this._processMicroformatItem(value);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
// This function takes legacy Microformat data (hCard and hCalendar)
|
||||
// and produces the same result that the equivalent Microdata data
|
||||
// would produce.
|
||||
_processMicroformatItem(microformatData) {
|
||||
var result = {};
|
||||
|
||||
if (microformatData.semanticType == 'geo') {
|
||||
return microformatData.latitude + ';' + microformatData.longitude;
|
||||
}
|
||||
|
||||
if (microformatData.semanticType == 'hCard') {
|
||||
result.type = ["http://microformats.org/profile/hcard"];
|
||||
} else if (microformatData.semanticType == 'hCalendar') {
|
||||
result.type = ["http://microformats.org/profile/hcalendar#vevent"];
|
||||
}
|
||||
|
||||
for (let field of Object.getOwnPropertyNames(microformatData)) {
|
||||
var processed = this._processMicroformatValue(field, microformatData[field]);
|
||||
if (processed === null) {
|
||||
continue;
|
||||
}
|
||||
if (!result.properties) {
|
||||
result.properties = {};
|
||||
}
|
||||
if (Array.isArray(processed)) {
|
||||
result.properties[field] = processed;
|
||||
} else {
|
||||
result.properties[field] = [processed];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
_findItemProperties: function(node, properties, alreadyProcessed) {
|
||||
if (node.itemProp) {
|
||||
var value;
|
||||
|
||||
if (node.itemScope) {
|
||||
value = this._processItem(node, alreadyProcessed);
|
||||
} else {
|
||||
value = node.itemValue;
|
||||
}
|
||||
|
||||
for (let i = 0; i < node.itemProp.length; ++i) {
|
||||
var property = node.itemProp[i];
|
||||
if (!properties[property]) {
|
||||
properties[property] = [];
|
||||
}
|
||||
|
||||
properties[property].push(value);
|
||||
}
|
||||
}
|
||||
|
||||
if (!node.itemScope) {
|
||||
var childNodes = node.childNodes;
|
||||
for (var childNode of childNodes) {
|
||||
this._findItemProperties(childNode, properties, alreadyProcessed);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_processItem: function(node, alreadyProcessed = []) {
|
||||
if (alreadyProcessed.includes(node)) {
|
||||
return "ERROR";
|
||||
}
|
||||
|
||||
alreadyProcessed.push(node);
|
||||
|
||||
var result = {};
|
||||
|
||||
if (node.itemId) {
|
||||
result.id = node.itemId;
|
||||
}
|
||||
if (node.itemType) {
|
||||
result.type = [];
|
||||
for (let i = 0; i < node.itemType.length; ++i) {
|
||||
result.type.push(node.itemType[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var properties = {};
|
||||
|
||||
var childNodes = node.childNodes;
|
||||
for (var childNode of childNodes) {
|
||||
this._findItemProperties(childNode, properties, alreadyProcessed);
|
||||
}
|
||||
|
||||
if (node.itemRef) {
|
||||
for (let i = 0; i < node.itemRef.length; ++i) {
|
||||
var refNode = content.document.getElementById(node.itemRef[i]);
|
||||
this._findItemProperties(refNode, properties, alreadyProcessed);
|
||||
}
|
||||
}
|
||||
|
||||
result.properties = properties;
|
||||
return result;
|
||||
},
|
||||
|
||||
_recvGetStructuredData: function(data) {
|
||||
var result = {
|
||||
items: []
|
||||
};
|
||||
|
||||
var microdataItems = content.document.getItems();
|
||||
|
||||
for (let microdataItem of microdataItems) {
|
||||
result.items.push(this._processItem(microdataItem));
|
||||
}
|
||||
|
||||
var hCardItems = Microformats.get("hCard", content.document);
|
||||
for (let hCardItem of hCardItems) {
|
||||
if (!hCardItem.node.itemScope) { // If it's also marked with Microdata, ignore the Microformat
|
||||
result.items.push(this._processMicroformatItem(hCardItem));
|
||||
}
|
||||
}
|
||||
|
||||
var hCalendarItems = Microformats.get("hCalendar", content.document);
|
||||
for (let hCalendarItem of hCalendarItems) {
|
||||
if (!hCalendarItem.node.itemScope) { // If it's also marked with Microdata, ignore the Microformat
|
||||
result.items.push(this._processMicroformatItem(hCalendarItem));
|
||||
}
|
||||
}
|
||||
|
||||
var resultString = JSON.stringify(result);
|
||||
|
||||
sendAsyncMsg('got-structured-data', {
|
||||
id: data.json.id,
|
||||
successRv: resultString
|
||||
});
|
||||
},
|
||||
|
||||
_processMicroformatValue(field, value) {
|
||||
if (['node', 'resolvedNode', 'semanticType'].includes(field)) {
|
||||
return null;
|
||||
} else if (Array.isArray(value)) {
|
||||
var result = value.map(i => this._processMicroformatValue(field, i))
|
||||
.filter(i => i !== null);
|
||||
return result.length ? result : null;
|
||||
} else if (typeof value == 'string') {
|
||||
return value;
|
||||
} else if (typeof value == 'object' && value !== null) {
|
||||
return this._processMicroformatItem(value);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
// This function takes legacy Microformat data (hCard and hCalendar)
|
||||
// and produces the same result that the equivalent Microdata data
|
||||
// would produce.
|
||||
_processMicroformatItem(microformatData) {
|
||||
var result = {};
|
||||
|
||||
if (microformatData.semanticType == 'geo') {
|
||||
return microformatData.latitude + ';' + microformatData.longitude;
|
||||
}
|
||||
|
||||
if (microformatData.semanticType == 'hCard') {
|
||||
result.type = ["http://microformats.org/profile/hcard"];
|
||||
} else if (microformatData.semanticType == 'hCalendar') {
|
||||
result.type = ["http://microformats.org/profile/hcalendar#vevent"];
|
||||
}
|
||||
|
||||
for (let field of Object.getOwnPropertyNames(microformatData)) {
|
||||
var processed = this._processMicroformatValue(field, microformatData[field]);
|
||||
if (processed === null) {
|
||||
continue;
|
||||
}
|
||||
if (!result.properties) {
|
||||
result.properties = {};
|
||||
}
|
||||
if (Array.isArray(processed)) {
|
||||
result.properties[field] = processed;
|
||||
} else {
|
||||
result.properties[field] = [processed];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
_findItemProperties: function(node, properties, alreadyProcessed) {
|
||||
if (node.itemProp) {
|
||||
var value;
|
||||
|
||||
if (node.itemScope) {
|
||||
value = this._processItem(node, alreadyProcessed);
|
||||
} else {
|
||||
value = node.itemValue;
|
||||
}
|
||||
|
||||
for (let i = 0; i < node.itemProp.length; ++i) {
|
||||
var property = node.itemProp[i];
|
||||
if (!properties[property]) {
|
||||
properties[property] = [];
|
||||
}
|
||||
|
||||
properties[property].push(value);
|
||||
}
|
||||
}
|
||||
|
||||
if (!node.itemScope) {
|
||||
var childNodes = node.childNodes;
|
||||
for (var childNode of childNodes) {
|
||||
this._findItemProperties(childNode, properties, alreadyProcessed);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_processItem: function(node, alreadyProcessed = []) {
|
||||
if (alreadyProcessed.includes(node)) {
|
||||
return "ERROR";
|
||||
}
|
||||
|
||||
alreadyProcessed.push(node);
|
||||
|
||||
var result = {};
|
||||
|
||||
if (node.itemId) {
|
||||
result.id = node.itemId;
|
||||
}
|
||||
if (node.itemType) {
|
||||
result.type = [];
|
||||
for (let i = 0; i < node.itemType.length; ++i) {
|
||||
result.type.push(node.itemType[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var properties = {};
|
||||
|
||||
var childNodes = node.childNodes;
|
||||
for (var childNode of childNodes) {
|
||||
this._findItemProperties(childNode, properties, alreadyProcessed);
|
||||
}
|
||||
|
||||
if (node.itemRef) {
|
||||
for (let i = 0; i < node.itemRef.length; ++i) {
|
||||
var refNode = content.document.getElementById(node.itemRef[i]);
|
||||
this._findItemProperties(refNode, properties, alreadyProcessed);
|
||||
}
|
||||
}
|
||||
|
||||
result.properties = properties;
|
||||
return result;
|
||||
},
|
||||
|
||||
_recvGetStructuredData: function(data) {
|
||||
var result = {
|
||||
items: []
|
||||
};
|
||||
|
||||
var microdataItems = content.document.getItems();
|
||||
|
||||
for (let microdataItem of microdataItems) {
|
||||
result.items.push(this._processItem(microdataItem));
|
||||
}
|
||||
|
||||
var hCardItems = Microformats.get("hCard", content.document);
|
||||
for (let hCardItem of hCardItems) {
|
||||
if (!hCardItem.node.itemScope) { // If it's also marked with Microdata, ignore the Microformat
|
||||
result.items.push(this._processMicroformatItem(hCardItem));
|
||||
}
|
||||
}
|
||||
|
||||
var hCalendarItems = Microformats.get("hCalendar", content.document);
|
||||
for (let hCalendarItem of hCalendarItems) {
|
||||
if (!hCalendarItem.node.itemScope) { // If it's also marked with Microdata, ignore the Microformat
|
||||
result.items.push(this._processMicroformatItem(hCalendarItem));
|
||||
}
|
||||
}
|
||||
|
||||
var resultString = JSON.stringify(result);
|
||||
|
||||
sendAsyncMsg('got-structured-data', {
|
||||
id: data.json.id,
|
||||
successRv: resultString
|
||||
});
|
||||
},
|
||||
|
||||
// The docShell keeps a weak reference to the progress listener, so we need
|
||||
// to keep a strong ref to it ourselves.
|
||||
_progressListener: {
|
||||
|
@ -208,7 +208,8 @@ BrowserElementParent.prototype = {
|
||||
"got-set-audio-channel-volume": this._gotDOMRequestResult,
|
||||
"got-audio-channel-muted": this._gotDOMRequestResult,
|
||||
"got-set-audio-channel-muted": this._gotDOMRequestResult,
|
||||
"got-is-audio-channel-active": this._gotDOMRequestResult
|
||||
"got-is-audio-channel-active": this._gotDOMRequestResult,
|
||||
"got-structured-data": this._gotDOMRequestResult
|
||||
};
|
||||
|
||||
let mmSecuritySensitiveCalls = {
|
||||
@ -1033,6 +1034,8 @@ BrowserElementParent.prototype = {
|
||||
{audioChannel: aAudioChannel});
|
||||
},
|
||||
|
||||
getStructuredData: defineDOMRequestMethod('get-structured-data'),
|
||||
|
||||
/**
|
||||
* Called when the visibility of the window which owns this iframe changes.
|
||||
*/
|
||||
|
78
dom/browser-element/mochitest/async.js
Normal file
78
dom/browser-element/mochitest/async.js
Normal file
@ -0,0 +1,78 @@
|
||||
/* 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/. */
|
||||
|
||||
/*
|
||||
* This is an approximate implementation of ES7's async-await pattern.
|
||||
* see: https://github.com/tc39/ecmascript-asyncawait
|
||||
*
|
||||
* It allows for simple creation of async function and "tasks".
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* var myThinger = {
|
||||
* doAsynThing: async(function*(url){
|
||||
* var result = yield fetch(url);
|
||||
* return process(result);
|
||||
* });
|
||||
* }
|
||||
*
|
||||
* And Task-like things can be created as follows:
|
||||
*
|
||||
* var myTask = async(function*{
|
||||
* var result = yield fetch(url);
|
||||
* return result;
|
||||
* });
|
||||
* //returns a promise
|
||||
*
|
||||
* myTask().then(doSomethingElse);
|
||||
*
|
||||
*/
|
||||
|
||||
(function(exports) {
|
||||
"use strict";
|
||||
function async(func, self) {
|
||||
return function asyncFunction() {
|
||||
const functionArgs = Array.from(arguments);
|
||||
return new Promise(function(resolve, reject) {
|
||||
var gen;
|
||||
if (typeof func !== "function") {
|
||||
reject(new TypeError("Expected a Function."));
|
||||
}
|
||||
//not a generator, wrap it.
|
||||
if (func.constructor.name !== "GeneratorFunction") {
|
||||
gen = (function*() {
|
||||
return func.apply(self, functionArgs);
|
||||
}());
|
||||
} else {
|
||||
gen = func.apply(self, functionArgs);
|
||||
}
|
||||
try {
|
||||
step(gen.next(undefined));
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
|
||||
function step({value, done}) {
|
||||
if (done) {
|
||||
return resolve(value);
|
||||
}
|
||||
if (value instanceof Promise) {
|
||||
return value.then(
|
||||
result => step(gen.next(result)),
|
||||
error => {
|
||||
try {
|
||||
step(gen.throw(error));
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
).catch(err => reject(err));
|
||||
}
|
||||
step(gen.next(value));
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
exports.async = async;
|
||||
}(this || self));
|
@ -0,0 +1,111 @@
|
||||
/* Any copyright is dedicated to the public domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/*globals async, is, SimpleTest, browserElementTestHelpers*/
|
||||
|
||||
// Bug 119580 - getStructuredData tests
|
||||
'use strict';
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
const EMPTY_URL = 'file_empty.html';
|
||||
const MICRODATA_URL = 'file_microdata.html';
|
||||
const MICRODATA_ITEMREF_URL = 'file_microdata_itemref.html';
|
||||
const MICRODATA_BAD_ITEMREF_URL = 'file_microdata_bad_itemref.html';
|
||||
const MICROFORMATS_URL = 'file_microformats.html';
|
||||
|
||||
var test1 = async(function* () {
|
||||
var structuredData = yield requestStructuredData(EMPTY_URL);
|
||||
is(structuredData.items && structuredData.items.length, 0,
|
||||
'There should be 0 items.');
|
||||
});
|
||||
|
||||
var test2 = async(function* () {
|
||||
var structuredData = yield requestStructuredData(MICRODATA_URL);
|
||||
is(structuredData.items && structuredData.items.length, 2,
|
||||
'There should be two items.');
|
||||
is(structuredData.items[0].type[0], 'http://schema.org/Recipe',
|
||||
'Can get item type.');
|
||||
is(structuredData.items[0].properties['datePublished'][0], '2009-05-08',
|
||||
'Can get item property.');
|
||||
is(structuredData.items[1]
|
||||
.properties["aggregateRating"][0]
|
||||
.properties["ratingValue"][0],
|
||||
'4', 'Can get nested item property.');
|
||||
});
|
||||
|
||||
var test3 = async(function* () {
|
||||
var structuredData = yield requestStructuredData(MICROFORMATS_URL);
|
||||
is(structuredData.items && structuredData.items.length, 2,
|
||||
'There should be two items.');
|
||||
is(structuredData.items[0].type[0], 'http://microformats.org/profile/hcard',
|
||||
'Got hCard object.');
|
||||
is(structuredData.items[0]
|
||||
.properties["adr"][0]
|
||||
.properties["country-name"][0],
|
||||
'France', 'Can read hCard properties.');
|
||||
is(structuredData.items[0]
|
||||
.properties["adr"][0]
|
||||
.properties["type"]
|
||||
.includes('home') &&
|
||||
structuredData.items[0]
|
||||
.properties["adr"][0]
|
||||
.properties["type"]
|
||||
.includes('postal'),
|
||||
true, 'Property can contain multiple values.');
|
||||
is(structuredData.items[0]
|
||||
.properties["geo"][0],
|
||||
'48.816667;2.366667', 'Geo value is formatted as per WHATWG spec.');
|
||||
|
||||
is(structuredData.items[1].type[0],
|
||||
'http://microformats.org/profile/hcalendar#vevent',
|
||||
'Got hCalendar object.');
|
||||
is(structuredData.items[1]
|
||||
.properties["dtstart"][0],
|
||||
'2005-10-05', 'Can read hCalendar properties');
|
||||
});
|
||||
|
||||
var test4 = async(function* () {
|
||||
var structuredData = yield requestStructuredData(MICRODATA_ITEMREF_URL);
|
||||
is(structuredData.items[0].properties["license"][0],
|
||||
'http://www.opensource.org/licenses/mit-license.php', 'itemref works.');
|
||||
is(structuredData.items[1].properties["license"][0],
|
||||
'http://www.opensource.org/licenses/mit-license.php',
|
||||
'Two items can successfully share an itemref.');
|
||||
});
|
||||
|
||||
var test5 = async(function* () {
|
||||
var structuredData = yield requestStructuredData(MICRODATA_BAD_ITEMREF_URL);
|
||||
is(structuredData.items[0]
|
||||
.properties["band"][0]
|
||||
.properties["cycle"][0]
|
||||
.properties["band"][0],
|
||||
'ERROR', 'Cyclic reference should be detected as an error.');
|
||||
});
|
||||
|
||||
Promise
|
||||
.all([test1(), test2(), test3(), test4(), test5()])
|
||||
.then(SimpleTest.finish);
|
||||
|
||||
function requestStructuredData(url) {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
iframe.src = url;
|
||||
document.body.appendChild(iframe);
|
||||
return new Promise((resolve, reject) => {
|
||||
iframe.addEventListener('mozbrowserloadend', function loadend() {
|
||||
iframe.removeEventListener('mozbrowserloadend', loadend);
|
||||
SimpleTest.executeSoon(() => {
|
||||
var req = iframe.getStructuredData();
|
||||
req.onsuccess = (ev) => {
|
||||
document.body.removeChild(iframe);
|
||||
resolve(JSON.parse(req.result));
|
||||
};
|
||||
req.onerror = (ev) => {
|
||||
document.body.removeChild(iframe);
|
||||
reject(new Error(req.error));
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
70
dom/browser-element/mochitest/file_microdata.html
Normal file
70
dom/browser-element/mochitest/file_microdata.html
Normal file
@ -0,0 +1,70 @@
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<h1>This example is taken from <a href="https://schema.org/Recipe">https://schema.org/Recipe</a></h1>
|
||||
|
||||
<div itemscope itemtype="http://schema.org/Recipe">
|
||||
<span itemprop="name">Mom's World Famous Banana Bread</span> By <span itemprop="author">John Smith</span>,
|
||||
<meta itemprop="datePublished" content="2009-05-08">May 8, 2009
|
||||
<img itemprop="image" src="bananabread.jpg" alt="Banana bread on a plate" />
|
||||
<span itemprop="description">This classic banana bread recipe comes
|
||||
from my mom -- the walnuts add a nice texture and flavor to the banana
|
||||
bread.</span> Prep Time:
|
||||
<meta itemprop="prepTime" content="PT15M">15 minutes Cook time:
|
||||
<meta itemprop="cookTime" content="PT1H">1 hour Yield: <span itemprop="recipeYield">1 loaf</span>
|
||||
<div itemprop="nutrition" itemscope itemtype="http://schema.org/NutritionInformation">
|
||||
Nutrition facts:
|
||||
<span itemprop="calories">240 calories</span>,
|
||||
<span itemprop="fatContent">9 grams fat</span>
|
||||
</div>
|
||||
Ingredients: - <span itemprop="recipeIngredient">3 or 4 ripe bananas, smashed</span> - <span itemprop="recipeIngredient">1 egg</span> - <span itemprop="recipeIngredient">3/4 cup of sugar</span> ... Instructions:
|
||||
<span itemprop="recipeInstructions">
|
||||
Preheat the oven to 350 degrees. Mix in the ingredients in a bowl. Add
|
||||
the flour last. Pour the mixture into a loaf pan and bake for one hour.
|
||||
</span> 140 comments:
|
||||
<div itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter">
|
||||
<meta itemprop="interactionType" content="http://schema.org/CommentAction" />
|
||||
<meta itemprop="userInteractionCount" content="140" />
|
||||
</div>
|
||||
From Janel, May 5 -- thank you, great recipe! ...
|
||||
</div>
|
||||
|
||||
<h1>This example is taken from <a href="https://schema.org/Book">https://schema.org/Book</a></h1>
|
||||
|
||||
<div itemscope itemtype="http://schema.org/Book">
|
||||
<img itemprop="image" src="catcher-in-the-rye-book-cover.jpg" alt="cover art: red horse, city in background" />
|
||||
<span itemprop="name">The Catcher in the Rye</span> -
|
||||
<link itemprop="bookFormat" href="http://schema.org/Paperback">Mass Market Paperback by <a itemprop="author" href="/author/jd_salinger.html">J.D. Salinger</a>
|
||||
<div itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">
|
||||
<span itemprop="ratingValue">4</span> stars -
|
||||
<span itemprop="reviewCount">3077</span> reviews
|
||||
</div>
|
||||
<div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
|
||||
Price: <span itemprop="price" content="6.99">$6.99</span>
|
||||
<meta itemprop="priceCurrency" content="USD" />
|
||||
<link itemprop="availability" href="http://schema.org/InStock">In Stock
|
||||
</div>
|
||||
Product details
|
||||
<span itemprop="numberOfPages">224</span> pages Publisher: <span itemprop="publisher">Little, Brown, and Company</span> -
|
||||
<meta itemprop="datePublished" content="1991-05-01">May 1, 1991 Language: <span itemprop="inLanguage">English</span> ISBN-10:
|
||||
<span itemprop="isbn">0316769487</span> Reviews:
|
||||
<div itemprop="review" itemscope itemtype="http://schema.org/Review">
|
||||
<span itemprop="reviewRating">5</span> stars -
|
||||
<b>"<span itemprop="name">A masterpiece of literature</span>"</b> by
|
||||
<span itemprop="author">John Doe</span>, Written on
|
||||
<meta itemprop="datePublished" content="2006-05-04">May 4, 2006
|
||||
<span itemprop="reviewBody">I really enjoyed this book. It captures the essential
|
||||
challenge people face as they try make sense of their lives and grow to adulthood.</span>
|
||||
</div>
|
||||
<div itemprop="review" itemscope itemtype="http://schema.org/Review">
|
||||
<span itemprop="reviewRating">4</span> stars -
|
||||
<b>"<span itemprop="name">A good read.</span>" </b> by <span itemprop="author">Bob Smith</span>, Written on
|
||||
<meta itemprop="datePublished" content="2006-06-15">June 15, 2006
|
||||
<span itemprop="reviewBody">Catcher in the Rye is a fun book. It's a good book to read.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<h1>This example is taken from <a href="https://html.spec.whatwg.org/multipage/microdata.html">https://html.spec.whatwg.org/multipage/microdata.html</a>, and modified.</h1>
|
||||
|
||||
<div itemscope id="amanda" itemref="a b"></div>
|
||||
<p id="a">Name: <span itemprop="name">Amanda</span></p>
|
||||
<div id="b" itemprop="band" itemscope itemref="c"></div>
|
||||
<div id="c">
|
||||
<p>Band: <span itemprop="name">Jazz Band</span></p>
|
||||
<p>Size: <span itemprop="size">12</span> players</p>
|
||||
<span itemprop="cycle" itemscope itemref="b">This is an error.</span>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
23
dom/browser-element/mochitest/file_microdata_itemref.html
Normal file
23
dom/browser-element/mochitest/file_microdata_itemref.html
Normal file
@ -0,0 +1,23 @@
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<h1>This example is taken from <a href="https://html.spec.whatwg.org/multipage/microdata.html">https://html.spec.whatwg.org/multipage/microdata.html</a></h1>
|
||||
|
||||
<figure itemscope itemtype="http://n.whatwg.org/work" itemref="licenses">
|
||||
<img itemprop="work" src="images/house.jpeg" alt="A white house, boarded up, sits in a forest.">
|
||||
<figcaption itemprop="title">The house I found.</figcaption>
|
||||
</figure>
|
||||
<figure itemscope itemtype="http://n.whatwg.org/work" itemref="licenses">
|
||||
<img itemprop="work" src="images/mailbox.jpeg" alt="Outside the house is a mailbox. It has a leaflet inside.">
|
||||
<figcaption itemprop="title">The mailbox.</figcaption>
|
||||
</figure>
|
||||
<footer>
|
||||
<p id="licenses">All images licensed under the <a itemprop="license"
|
||||
href="http://www.opensource.org/licenses/mit-license.php">MIT
|
||||
license</a>.</p>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
50
dom/browser-element/mochitest/file_microformats.html
Normal file
50
dom/browser-element/mochitest/file_microformats.html
Normal file
@ -0,0 +1,50 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
</head>
|
||||
<body>
|
||||
<h1>This example is taken from <a href="http://microformats.org/wiki/hcard-examples">http://microformats.org/wiki/hcard-examples</a></h1>
|
||||
|
||||
<div class="vcard">
|
||||
<span class="fn n">
|
||||
<a class="url" href="http://t37.net">
|
||||
<span class="given-name">Fréderic</span>
|
||||
<span class="family-name">de Villamil</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="nickname">neuro</span>
|
||||
<a class="email" href="mailto:neuroNOSPAM@t37.net">
|
||||
<span class="type">pref</span><span>erred email</span>
|
||||
</a>
|
||||
<span class="org">Omatis</span>
|
||||
<span class="adr">
|
||||
<abbr class="type" title="dom">France</abbr>
|
||||
<span class="type">home</span> address
|
||||
<abbr class="type" title="postal">mail</abbr> and
|
||||
<abbr class="type" title="parcel">shipments</abbr>:
|
||||
<span class="street-address">12 rue Danton</span>
|
||||
<span class="locality">Le Kremlin-Bicetre</span>
|
||||
<span class="postal-code">94270</span>
|
||||
<span class="country-name">France</span>
|
||||
</span>
|
||||
<span class="geo">
|
||||
<abbr class="latitude" title="48.816667">N 48° 81.6667</abbr>
|
||||
<abbr class="longitude" title="2.366667">E 2° 36.6667</abbr>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h1>This example is taken from <a href="http://microformats.org/wiki/hCalendar">http://microformats.org/wiki/hCalendar</a></h1>
|
||||
|
||||
<div class="vevent">
|
||||
<a class="url" href="http://conferences.oreillynet.com/pub/w/40/program.html">
|
||||
http://conferences.oreillynet.com/pub/w/40/program.html
|
||||
</a>
|
||||
<span class="summary">Web 2.0 Conference</span>:
|
||||
<abbr class="dtstart" title="2005-10-05">October 5</abbr>-
|
||||
<abbr class="dtend" title="2005-10-07">7</abbr>,
|
||||
at the <span class="location">Argent Hotel, San Francisco, CA</span>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -12,6 +12,7 @@ support-files =
|
||||
browserElement_Find.js
|
||||
browserElement_OpenTab.js
|
||||
|
||||
[test_browserElement_oop_getStructuredData.html]
|
||||
[test_browserElement_oop_Viewmode.html]
|
||||
[test_browserElement_oop_ThemeColor.html]
|
||||
[test_browserElement_inproc_ErrorSecurity.html]
|
||||
|
@ -3,6 +3,7 @@ skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || deb
|
||||
support-files =
|
||||
../../../browser/base/content/test/general/audio.ogg
|
||||
../../../dom/media/test/short-video.ogv
|
||||
async.js
|
||||
browserElementTestHelpers.js
|
||||
browserElement_Alert.js
|
||||
browserElement_AlertInFrame.js
|
||||
@ -37,6 +38,7 @@ support-files =
|
||||
browserElement_FrameWrongURI.js
|
||||
browserElement_GetScreenshot.js
|
||||
browserElement_GetScreenshotDppx.js
|
||||
browserElement_getStructuredData.js
|
||||
browserElement_Iconchange.js
|
||||
browserElement_LoadEvents.js
|
||||
browserElement_Manifestchange.js
|
||||
@ -124,6 +126,11 @@ support-files =
|
||||
file_http_401_response.sjs
|
||||
file_http_407_response.sjs
|
||||
file_inputmethod.html
|
||||
file_microdata.html
|
||||
file_microdata_bad_itemref.html
|
||||
file_microdata_itemref.html
|
||||
file_microformats.html
|
||||
file_inputmethod.html
|
||||
file_post_request.html
|
||||
file_wyciwyg.html
|
||||
file_audio.html
|
||||
@ -232,3 +239,4 @@ disabled = bug 774100
|
||||
[test_browserElement_inproc_GetContentDimensions.html]
|
||||
[test_browserElement_inproc_AudioChannel.html]
|
||||
[test_browserElement_inproc_SetNFCFocus.html]
|
||||
[test_browserElement_inproc_getStructuredData.html]
|
||||
|
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Bug 1195801</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.8" src="async.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="browserElement_getStructuredData.js"></script>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Bug 1195801</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.8" src="async.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="browserElement_getStructuredData.js"></script>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -52,3 +52,6 @@ MOCHITEST_MANIFESTS += [
|
||||
'mochitest/mochitest.ini',
|
||||
'mochitest/priority/mochitest.ini',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -26,7 +26,7 @@ interface nsIBrowserElementNextPaintListener : nsISupports
|
||||
* Interface to the BrowserElementParent implementation. All methods
|
||||
* but setFrameLoader throw when the remote process is dead.
|
||||
*/
|
||||
[scriptable, uuid(56bd3e12-4a8b-422a-89fc-6dc25aa30aa2)]
|
||||
[scriptable, uuid(9946695c-1ed3-4abb-bc60-6f8947fd5641)]
|
||||
interface nsIBrowserElementAPI : nsISupports
|
||||
{
|
||||
const long FIND_CASE_SENSITIVE = 0;
|
||||
@ -100,4 +100,16 @@ interface nsIBrowserElementAPI : nsISupports
|
||||
void setNFCFocus(in boolean isFocus);
|
||||
|
||||
nsIDOMDOMRequest executeScript(in DOMString script, in jsval options);
|
||||
|
||||
/**
|
||||
* Returns a JSON string representing Microdata objects on the page.
|
||||
* Format is described at:
|
||||
* https://html.spec.whatwg.org/multipage/microdata.html#json
|
||||
*
|
||||
* Also contains hCard and hCalendar objects after converting them
|
||||
* to equivalent Microdata objects described at:
|
||||
* https://html.spec.whatwg.org/multipage/microdata.html#vcard
|
||||
* https://html.spec.whatwg.org/multipage/microdata.html#vevent
|
||||
*/
|
||||
nsIDOMDOMRequest getStructuredData();
|
||||
};
|
||||
|
@ -36,3 +36,6 @@ IPDL_SOURCES += [
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -45,3 +45,6 @@ MOCHITEST_MANIFESTS += [
|
||||
'test/mochitest.ini',
|
||||
]
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -45,3 +45,6 @@ MOCHITEST_MANIFESTS += [
|
||||
]
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -430,6 +430,13 @@ const kEventConstructors = {
|
||||
return e;
|
||||
},
|
||||
},
|
||||
ServiceWorkerMessageEvent: { create: function (aName, aProps) {
|
||||
var e = new ServiceWorkerMessageEvent("serviceworkermessageevent", { bubbles: aProps.bubbles,
|
||||
cancelable: aProps.cancelable, data: aProps.data, origin: aProps.origin,
|
||||
lastEventId: aProps.lastEventId, source: aProps.source });
|
||||
return e;
|
||||
},
|
||||
},
|
||||
SimpleGestureEvent: { create: function (aName, aProps) {
|
||||
var e = document.createEvent("simplegestureevent");
|
||||
e.initSimpleGestureEvent(aName, aProps.bubbles, aProps.cancelable,
|
||||
|
@ -41,3 +41,6 @@ include('/ipc/chromium/chromium-config.mozbuild')
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -30,3 +30,5 @@ LOCAL_INCLUDES += [
|
||||
'/dom/fmradio',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -32,3 +32,6 @@ LOCAL_INCLUDES += [
|
||||
'../system/gonk',
|
||||
]
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -54,3 +54,6 @@ CFLAGS += CONFIG['GLIB_CFLAGS']
|
||||
CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
CXXFLAGS += CONFIG['GLIB_CFLAGS']
|
||||
CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -51,3 +51,6 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/system/windows',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -2527,6 +2527,9 @@ HTMLInputElement::UpdateFileList()
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we (lazily) create a new Promise for GetFilesAndDirectories:
|
||||
mFilesAndDirectoriesPromise = nullptr;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -4884,6 +4887,15 @@ MakeOrReuseFileSystem(const nsAString& aNewLocalRootPath,
|
||||
already_AddRefed<Promise>
|
||||
HTMLInputElement::GetFilesAndDirectories(ErrorResult& aRv)
|
||||
{
|
||||
if (mType != NS_FORM_INPUT_FILE) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mFilesAndDirectoriesPromise) {
|
||||
return nsRefPtr<Promise>(mFilesAndDirectoriesPromise).forget();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = OwnerDoc()->GetScopeObject();
|
||||
MOZ_ASSERT(global);
|
||||
if (!global) {
|
||||
@ -4932,6 +4944,11 @@ HTMLInputElement::GetFilesAndDirectories(ErrorResult& aRv)
|
||||
|
||||
p->MaybeResolve(filesAndDirsSeq);
|
||||
|
||||
// Cache the Promise so that repeat getFilesAndDirectories() calls return
|
||||
// the same Promise and array of File and Directory objects until the user
|
||||
// picks different files/directories:
|
||||
mFilesAndDirectoriesPromise = p;
|
||||
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
|
@ -1285,6 +1285,7 @@ protected:
|
||||
#endif
|
||||
|
||||
nsRefPtr<FileList> mFileList;
|
||||
nsRefPtr<Promise> mFilesAndDirectoriesPromise;
|
||||
|
||||
nsString mStaticDocFileList;
|
||||
|
||||
|
@ -563,69 +563,84 @@ nsBrowserElement::GetAllowedAudioChannels(
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAppsService> appsService =
|
||||
do_GetService("@mozilla.org/AppsService;1");
|
||||
if (NS_WARN_IF(!appsService)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIApplication> app;
|
||||
aRv = appsService->GetAppByManifestURL(manifestURL, getter_AddRefs(app));
|
||||
GenerateAllowedAudioChannels(window, frameLoader, mBrowserElementAPI,
|
||||
manifestURL, mBrowserElementAudioChannels,
|
||||
aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Normal is always allowed.
|
||||
nsTArray<nsRefPtr<BrowserElementAudioChannel>> channels;
|
||||
aAudioChannels.AppendElements(mBrowserElementAudioChannels);
|
||||
}
|
||||
|
||||
nsRefPtr<BrowserElementAudioChannel> ac =
|
||||
new BrowserElementAudioChannel(window, frameLoader, mBrowserElementAPI,
|
||||
AudioChannel::Normal);
|
||||
/* static */ void
|
||||
nsBrowserElement::GenerateAllowedAudioChannels(
|
||||
nsPIDOMWindow* aWindow,
|
||||
nsIFrameLoader* aFrameLoader,
|
||||
nsIBrowserElementAPI* aAPI,
|
||||
const nsAString& aManifestURL,
|
||||
nsTArray<nsRefPtr<BrowserElementAudioChannel>>& aAudioChannels,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(aAudioChannels.IsEmpty());
|
||||
|
||||
aRv = ac->Initialize();
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIAppsService> appsService =
|
||||
do_GetService("@mozilla.org/AppsService;1");
|
||||
if (NS_WARN_IF(!appsService)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
channels.AppendElement(ac);
|
||||
nsCOMPtr<mozIApplication> app;
|
||||
aRv = appsService->GetAppByManifestURL(aManifestURL, getter_AddRefs(app));
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (app) {
|
||||
const nsAttrValue::EnumTable* audioChannelTable =
|
||||
AudioChannelService::GetAudioChannelTable();
|
||||
// Normal is always allowed.
|
||||
nsTArray<nsRefPtr<BrowserElementAudioChannel>> channels;
|
||||
|
||||
bool allowed;
|
||||
nsAutoCString permissionName;
|
||||
nsRefPtr<BrowserElementAudioChannel> ac =
|
||||
BrowserElementAudioChannel::Create(aWindow, aFrameLoader, aAPI,
|
||||
AudioChannel::Normal, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; audioChannelTable && audioChannelTable[i].tag; ++i) {
|
||||
permissionName.AssignASCII("audio-channel-");
|
||||
permissionName.AppendASCII(audioChannelTable[i].tag);
|
||||
channels.AppendElement(ac);
|
||||
|
||||
aRv = app->HasPermission(permissionName.get(), &allowed);
|
||||
if (app) {
|
||||
const nsAttrValue::EnumTable* audioChannelTable =
|
||||
AudioChannelService::GetAudioChannelTable();
|
||||
|
||||
bool allowed;
|
||||
nsAutoCString permissionName;
|
||||
|
||||
for (uint32_t i = 0; audioChannelTable && audioChannelTable[i].tag; ++i) {
|
||||
permissionName.AssignASCII("audio-channel-");
|
||||
permissionName.AppendASCII(audioChannelTable[i].tag);
|
||||
|
||||
aRv = app->HasPermission(permissionName.get(), &allowed);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (allowed) {
|
||||
nsRefPtr<BrowserElementAudioChannel> ac =
|
||||
BrowserElementAudioChannel::Create(aWindow, aFrameLoader, aAPI,
|
||||
(AudioChannel)audioChannelTable[i].value,
|
||||
aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (allowed) {
|
||||
nsRefPtr<BrowserElementAudioChannel> ac =
|
||||
new BrowserElementAudioChannel(window, frameLoader,
|
||||
mBrowserElementAPI,
|
||||
(AudioChannel)audioChannelTable[i].value);
|
||||
|
||||
aRv = ac->Initialize();
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
channels.AppendElement(ac);
|
||||
}
|
||||
channels.AppendElement(ac);
|
||||
}
|
||||
}
|
||||
|
||||
mBrowserElementAudioChannels.AppendElements(channels);
|
||||
}
|
||||
|
||||
aAudioChannels.AppendElements(mBrowserElementAudioChannels);
|
||||
aAudioChannels.SwapElements(channels);
|
||||
}
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
@ -747,4 +762,20 @@ nsBrowserElement::ExecuteScript(const nsAString& aScript,
|
||||
return req.forget().downcast<DOMRequest>();
|
||||
}
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
nsBrowserElement::GetStructuredData(ErrorResult& aRv)
|
||||
{
|
||||
NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
|
||||
|
||||
nsCOMPtr<nsIDOMDOMRequest> req;
|
||||
nsresult rv = mBrowserElementAPI->GetStructuredData(getter_AddRefs(req));
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return req.forget().downcast<DOMRequest>();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -112,9 +112,20 @@ public:
|
||||
const dom::BrowserElementExecuteScriptOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<dom::DOMRequest> GetStructuredData(ErrorResult& aRv);
|
||||
|
||||
void SetNFCFocus(bool isFocus,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// Helper
|
||||
static void GenerateAllowedAudioChannels(
|
||||
nsPIDOMWindow* aWindow,
|
||||
nsIFrameLoader* aFrameLoader,
|
||||
nsIBrowserElementAPI* aAPI,
|
||||
const nsAString& aManifestURL,
|
||||
nsTArray<nsRefPtr<dom::BrowserElementAudioChannel>>& aAudioChannels,
|
||||
ErrorResult& aRv);
|
||||
|
||||
protected:
|
||||
NS_IMETHOD_(already_AddRefed<nsFrameLoader>) GetFrameLoader() = 0;
|
||||
void InitBrowserElementAPI();
|
||||
|
@ -55,3 +55,6 @@ FINAL_LIBRARY = 'xul'
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/system/gonk',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -44,3 +44,6 @@ XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -20,3 +20,6 @@ FINAL_LIBRARY = 'xul'
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
|
||||
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -22,3 +22,6 @@ FINAL_LIBRARY = 'xul'
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -16,3 +16,5 @@ LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -25,3 +25,6 @@ LOCAL_INCLUDES += [
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -22,3 +22,6 @@ USE_STATIC_LIBS = True
|
||||
NO_VISIBILITY_FLAGS = True
|
||||
# Don't use STL wrappers; this isn't Gecko code
|
||||
DISABLE_STL_WRAPPING = True
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -24,3 +24,6 @@ USE_STATIC_LIBS = True
|
||||
NO_VISIBILITY_FLAGS = True
|
||||
# Don't use STL wrappers; this isn't Gecko code
|
||||
DISABLE_STL_WRAPPING = True
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -14,3 +14,6 @@ UNIFIED_SOURCES += [
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
@ -242,12 +242,20 @@ PlatformDecoderModule::CreateDecoder(const TrackInfo& aConfig,
|
||||
}
|
||||
|
||||
if (H264Converter::IsH264(aConfig)) {
|
||||
m = new H264Converter(this,
|
||||
nsRefPtr<H264Converter> h
|
||||
= new H264Converter(this,
|
||||
*aConfig.GetAsVideoInfo(),
|
||||
aLayersBackend,
|
||||
aImageContainer,
|
||||
aTaskQueue,
|
||||
callback);
|
||||
const nsresult rv = h->GetLastError();
|
||||
if (NS_SUCCEEDED(rv) || rv == NS_ERROR_NOT_INITIALIZED) {
|
||||
// The H264Converter either successfully created the wrapped decoder,
|
||||
// or there wasn't enough AVCC data to do so. Otherwise, there was some
|
||||
// problem, for example WMF DLLs were missing.
|
||||
m = h.forget();
|
||||
}
|
||||
} else if (!hasPlatformDecoder && VPXDecoder::IsVPX(aConfig.mMimeType)) {
|
||||
m = new VPXDecoder(*aConfig.GetAsVideoInfo(),
|
||||
aImageContainer,
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
|
||||
// Return true if mimetype is H.264.
|
||||
static bool IsH264(const TrackInfo& aConfig);
|
||||
nsresult GetLastError() const { return mLastError; }
|
||||
|
||||
private:
|
||||
// Will create the required MediaDataDecoder if need AVCC and we have a SPS NAL.
|
||||
|
@ -59,6 +59,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool* aFinished) override
|
||||
|
@ -235,8 +235,7 @@ public:
|
||||
// The number of frames consumed/produced depends on the amount of space
|
||||
// remaining in both the input and output buffer, and the playback rate (that
|
||||
// is, the ratio between the output samplerate and the input samplerate).
|
||||
void CopyFromInputBufferWithResampling(AudioNodeStream* aStream,
|
||||
AudioBlock* aOutput,
|
||||
void CopyFromInputBufferWithResampling(AudioBlock* aOutput,
|
||||
uint32_t aChannels,
|
||||
uint32_t* aOffsetWithinBlock,
|
||||
uint32_t aAvailableInOutput,
|
||||
@ -368,8 +367,7 @@ public:
|
||||
* This function knows when it needs to allocate the output buffer, and also
|
||||
* optimizes the case where it can avoid memory allocations.
|
||||
*/
|
||||
void CopyFromBuffer(AudioNodeStream* aStream,
|
||||
AudioBlock* aOutput,
|
||||
void CopyFromBuffer(AudioBlock* aOutput,
|
||||
uint32_t aChannels,
|
||||
uint32_t* aOffsetWithinBlock,
|
||||
StreamTime* aCurrentPosition,
|
||||
@ -380,7 +378,7 @@ public:
|
||||
std::min<StreamTime>(WEBAUDIO_BLOCK_SIZE - *aOffsetWithinBlock,
|
||||
mStop - *aCurrentPosition);
|
||||
if (mResampler) {
|
||||
CopyFromInputBufferWithResampling(aStream, aOutput, aChannels,
|
||||
CopyFromInputBufferWithResampling(aOutput, aChannels,
|
||||
aOffsetWithinBlock, availableInOutput,
|
||||
aCurrentPosition, aBufferMax);
|
||||
return;
|
||||
@ -434,7 +432,7 @@ public:
|
||||
return rate ? rate : mBufferSampleRate;
|
||||
}
|
||||
|
||||
void UpdateSampleRateIfNeeded(uint32_t aChannels)
|
||||
void UpdateSampleRateIfNeeded(uint32_t aChannels, StreamTime aStreamPosition)
|
||||
{
|
||||
float playbackRate;
|
||||
float detune;
|
||||
@ -442,12 +440,12 @@ public:
|
||||
if (mPlaybackRateTimeline.HasSimpleValue()) {
|
||||
playbackRate = mPlaybackRateTimeline.GetValue();
|
||||
} else {
|
||||
playbackRate = mPlaybackRateTimeline.GetValueAtTime(mSource->GetCurrentPosition());
|
||||
playbackRate = mPlaybackRateTimeline.GetValueAtTime(aStreamPosition);
|
||||
}
|
||||
if (mDetuneTimeline.HasSimpleValue()) {
|
||||
detune = mDetuneTimeline.GetValue();
|
||||
} else {
|
||||
detune = mDetuneTimeline.GetValueAtTime(mSource->GetCurrentPosition());
|
||||
detune = mDetuneTimeline.GetValueAtTime(aStreamPosition);
|
||||
}
|
||||
if (playbackRate <= 0 || mozilla::IsNaN(playbackRate)) {
|
||||
playbackRate = 1.0f;
|
||||
@ -460,6 +458,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool* aFinished) override
|
||||
@ -470,7 +469,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
StreamTime streamPosition = aStream->GetCurrentPosition();
|
||||
StreamTime streamPosition = aStream->GraphTimeToStreamTime(aFrom);
|
||||
// We've finished if we've gone past mStop, or if we're past mDuration when
|
||||
// looping is disabled.
|
||||
if (streamPosition >= mStop ||
|
||||
@ -482,7 +481,7 @@ public:
|
||||
|
||||
uint32_t channels = mBuffer ? mBuffer->GetChannels() : 0;
|
||||
|
||||
UpdateSampleRateIfNeeded(channels);
|
||||
UpdateSampleRateIfNeeded(channels, streamPosition);
|
||||
|
||||
uint32_t written = 0;
|
||||
while (written < WEBAUDIO_BLOCK_SIZE) {
|
||||
@ -503,10 +502,10 @@ public:
|
||||
if (mBufferPosition >= mLoopEnd) {
|
||||
mBufferPosition = mLoopStart;
|
||||
}
|
||||
CopyFromBuffer(aStream, aOutput, channels, &written, &streamPosition, mLoopEnd);
|
||||
CopyFromBuffer(aOutput, channels, &written, &streamPosition, mLoopEnd);
|
||||
} else {
|
||||
if (mBufferPosition < mBufferEnd || mRemainingResamplerTail) {
|
||||
CopyFromBuffer(aStream, aOutput, channels, &written, &streamPosition, mBufferEnd);
|
||||
CopyFromBuffer(aOutput, channels, &written, &streamPosition, mBufferEnd);
|
||||
} else {
|
||||
FillWithZeroes(aOutput, channels, &written, &streamPosition, STREAM_TIME_MAX);
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool* aFinished) override
|
||||
@ -241,6 +242,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool* aFinished) override
|
||||
|
@ -273,6 +273,7 @@ AudioBufferSumOfSquares(const float* aInput, uint32_t aLength)
|
||||
|
||||
void
|
||||
AudioNodeEngine::ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool* aFinished)
|
||||
|
@ -315,6 +315,7 @@ public:
|
||||
* call this again.
|
||||
*/
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool* aFinished);
|
||||
@ -323,7 +324,8 @@ public:
|
||||
* ProcessBlock() will be called later, and it then should not change
|
||||
* aOutput. This is used only for DelayNodeEngine in a feedback loop.
|
||||
*/
|
||||
virtual void ProduceBlockBeforeInput(AudioBlock* aOutput)
|
||||
virtual void ProduceBlockBeforeInput(GraphTime aFrom,
|
||||
AudioBlock* aOutput)
|
||||
{
|
||||
NS_NOTREACHED("ProduceBlockBeforeInput called on wrong engine\n");
|
||||
}
|
||||
|
@ -131,7 +131,6 @@ AudioNodeExternalInputStream::ProcessInput(GraphTime aFrom, GraphTime aTo,
|
||||
// Handle that.
|
||||
if (!IsEnabled() || mInputs.IsEmpty() || mPassThrough) {
|
||||
mLastChunks[0].SetNull(WEBAUDIO_BLOCK_SIZE);
|
||||
AdvanceOutputSegment();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -205,9 +204,6 @@ AudioNodeExternalInputStream::ProcessInput(GraphTime aFrom, GraphTime aTo,
|
||||
if (accumulateIndex == 0) {
|
||||
mLastChunks[0].SetNull(WEBAUDIO_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
// Using AudioNodeStream's AdvanceOutputSegment to push the media stream graph along with null data.
|
||||
AdvanceOutputSegment();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -513,12 +513,6 @@ AudioNodeStream::UpMixDownMixChunk(const AudioBlock* aChunk,
|
||||
void
|
||||
AudioNodeStream::ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags)
|
||||
{
|
||||
if (!mFinished) {
|
||||
EnsureTrack(AUDIO_TRACK);
|
||||
}
|
||||
// No more tracks will be coming
|
||||
mBuffer.AdvanceKnownTracksTime(STREAM_TIME_MAX);
|
||||
|
||||
uint16_t outputCount = mLastChunks.Length();
|
||||
MOZ_ASSERT(outputCount == std::max(uint16_t(1), mEngine->OutputCount()));
|
||||
|
||||
@ -547,7 +541,8 @@ AudioNodeStream::ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags)
|
||||
mLastChunks[0] = mInputChunks[0];
|
||||
} else {
|
||||
if (maxInputs <= 1 && outputCount <= 1) {
|
||||
mEngine->ProcessBlock(this, mInputChunks[0], &mLastChunks[0], &finished);
|
||||
mEngine->ProcessBlock(this, aFrom,
|
||||
mInputChunks[0], &mLastChunks[0], &finished);
|
||||
} else {
|
||||
mEngine->ProcessBlocksOnPorts(this, mInputChunks, mLastChunks, &finished);
|
||||
}
|
||||
@ -570,12 +565,17 @@ AudioNodeStream::ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags)
|
||||
|
||||
if (!mFinished) {
|
||||
// Don't output anything while finished
|
||||
AdvanceOutputSegment();
|
||||
if (mFlags & EXTERNAL_OUTPUT) {
|
||||
AdvanceOutputSegment();
|
||||
}
|
||||
if (mMarkAsFinishedAfterThisBlock && (aFlags & ALLOW_FINISH)) {
|
||||
// This stream was finished the last time that we looked at it, and all
|
||||
// of the depending streams have finished their output as well, so now
|
||||
// it's time to mark this stream as finished.
|
||||
FinishOutput();
|
||||
if (mFlags & EXTERNAL_OUTPUT) {
|
||||
FinishOutput();
|
||||
}
|
||||
FinishOnGraphThread();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -592,7 +592,7 @@ AudioNodeStream::ProduceOutputBeforeInput(GraphTime aFrom)
|
||||
if (!mIsActive) {
|
||||
mLastChunks[0].SetNull(WEBAUDIO_BLOCK_SIZE);
|
||||
} else {
|
||||
mEngine->ProduceBlockBeforeInput(&mLastChunks[0]);
|
||||
mEngine->ProduceBlockBeforeInput(aFrom, &mLastChunks[0]);
|
||||
NS_ASSERTION(mLastChunks[0].GetDuration() == WEBAUDIO_BLOCK_SIZE,
|
||||
"Invalid WebAudio chunk size");
|
||||
if (mDisabledTrackIDs.Contains(static_cast<TrackID>(AUDIO_TRACK))) {
|
||||
@ -605,9 +605,12 @@ void
|
||||
AudioNodeStream::AdvanceOutputSegment()
|
||||
{
|
||||
StreamBuffer::Track* track = EnsureTrack(AUDIO_TRACK);
|
||||
// No more tracks will be coming
|
||||
mBuffer.AdvanceKnownTracksTime(STREAM_TIME_MAX);
|
||||
|
||||
AudioSegment* segment = track->Get<AudioSegment>();
|
||||
|
||||
if (mFlags & EXTERNAL_OUTPUT) {
|
||||
if (!mLastChunks[0].IsNull()) {
|
||||
segment->AppendAndConsumeChunk(mLastChunks[0].AsMutableChunk());
|
||||
} else {
|
||||
segment->AppendNullData(mLastChunks[0].GetDuration());
|
||||
@ -623,23 +626,11 @@ AudioNodeStream::AdvanceOutputSegment()
|
||||
}
|
||||
}
|
||||
|
||||
StreamTime
|
||||
AudioNodeStream::GetCurrentPosition()
|
||||
{
|
||||
NS_ASSERTION(!mFinished, "Don't create another track after finishing");
|
||||
return EnsureTrack(AUDIO_TRACK)->Get<AudioSegment>()->GetDuration();
|
||||
}
|
||||
|
||||
void
|
||||
AudioNodeStream::FinishOutput()
|
||||
{
|
||||
if (IsFinishedOnGraphThread()) {
|
||||
return;
|
||||
}
|
||||
|
||||
StreamBuffer::Track* track = EnsureTrack(AUDIO_TRACK);
|
||||
track->SetEnded();
|
||||
FinishOnGraphThread();
|
||||
|
||||
for (uint32_t j = 0; j < mListeners.Length(); ++j) {
|
||||
MediaStreamListener* l = mListeners[j];
|
||||
|
@ -122,7 +122,6 @@ public:
|
||||
* the output. This is used only for DelayNodeEngine in a feedback loop.
|
||||
*/
|
||||
void ProduceOutputBeforeInput(GraphTime aFrom);
|
||||
StreamTime GetCurrentPosition();
|
||||
bool IsAudioParamStream() const
|
||||
{
|
||||
return mAudioParamStream;
|
||||
|
@ -138,6 +138,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool* aFinished) override
|
||||
@ -186,7 +187,7 @@ public:
|
||||
uint32_t numberOfChannels = mBiquads.Length();
|
||||
aOutput->AllocateChannels(numberOfChannels);
|
||||
|
||||
StreamTime pos = aStream->GetCurrentPosition();
|
||||
StreamTime pos = aStream->GraphTimeToStreamTime(aFrom);
|
||||
|
||||
double freq = mFrequency.GetValueAtTime(pos);
|
||||
double q = mQ.GetValueAtTime(pos);
|
||||
|
@ -102,6 +102,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool* aFinished) override
|
||||
|
@ -76,6 +76,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool* aFinished) override
|
||||
@ -115,13 +116,13 @@ public:
|
||||
// Skip output update if mLastChunks has already been set by
|
||||
// ProduceBlockBeforeInput() when in a cycle.
|
||||
if (!mHaveProducedBeforeInput) {
|
||||
UpdateOutputBlock(aOutput, 0.0);
|
||||
UpdateOutputBlock(aFrom, aOutput, 0.0);
|
||||
}
|
||||
mHaveProducedBeforeInput = false;
|
||||
mBuffer.NextBlock();
|
||||
}
|
||||
|
||||
void UpdateOutputBlock(AudioBlock* aOutput, double minDelay)
|
||||
void UpdateOutputBlock(GraphTime aFrom, AudioBlock* aOutput, double minDelay)
|
||||
{
|
||||
double maxDelay = mMaxDelay;
|
||||
double sampleRate = mSource->SampleRate();
|
||||
@ -138,7 +139,7 @@ public:
|
||||
// Compute the delay values for the duration of the input AudioChunk
|
||||
// If this DelayNode is in a cycle, make sure the delay value is at least
|
||||
// one block.
|
||||
StreamTime tick = mSource->GetCurrentPosition();
|
||||
StreamTime tick = mSource->GraphTimeToStreamTime(aFrom);
|
||||
float values[WEBAUDIO_BLOCK_SIZE];
|
||||
mDelay.GetValuesAtTime(tick, values,WEBAUDIO_BLOCK_SIZE);
|
||||
|
||||
@ -153,12 +154,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ProduceBlockBeforeInput(AudioBlock* aOutput) override
|
||||
virtual void ProduceBlockBeforeInput(GraphTime aFrom,
|
||||
AudioBlock* aOutput) override
|
||||
{
|
||||
if (mLeftOverData <= 0) {
|
||||
aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
|
||||
} else {
|
||||
UpdateOutputBlock(aOutput, WEBAUDIO_BLOCK_SIZE);
|
||||
UpdateOutputBlock(aFrom, aOutput, WEBAUDIO_BLOCK_SIZE);
|
||||
}
|
||||
mHaveProducedBeforeInput = true;
|
||||
}
|
||||
|
@ -93,6 +93,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool* aFinished) override
|
||||
@ -110,7 +111,7 @@ public:
|
||||
aInput.ChannelCount());
|
||||
}
|
||||
|
||||
StreamTime pos = aStream->GetCurrentPosition();
|
||||
StreamTime pos = aStream->GraphTimeToStreamTime(aFrom);
|
||||
mCompressor->setParameterValue(DynamicsCompressor::ParamThreshold,
|
||||
mThreshold.GetValueAtTime(pos));
|
||||
mCompressor->setParameterValue(DynamicsCompressor::ParamKnee,
|
||||
|
@ -59,6 +59,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool* aFinished) override
|
||||
@ -84,7 +85,7 @@ public:
|
||||
aOutput->AllocateChannels(aInput.ChannelCount());
|
||||
|
||||
// Compute the gain values for the duration of the input AudioChunk
|
||||
StreamTime tick = aStream->GetCurrentPosition();
|
||||
StreamTime tick = aStream->GraphTimeToStreamTime(aFrom);
|
||||
float computedGain[WEBAUDIO_BLOCK_SIZE];
|
||||
mGain.GetValuesAtTime(tick, computedGain, WEBAUDIO_BLOCK_SIZE);
|
||||
|
||||
|
@ -286,13 +286,14 @@ public:
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool* aFinished) override
|
||||
{
|
||||
MOZ_ASSERT(mSource == aStream, "Invalid source stream");
|
||||
|
||||
StreamTime ticks = aStream->GetCurrentPosition();
|
||||
StreamTime ticks = aStream->GraphTimeToStreamTime(aFrom);
|
||||
if (mStart == -1) {
|
||||
ComputeSilence(aOutput);
|
||||
return;
|
||||
|
@ -135,6 +135,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool *aFinished) override
|
||||
|
@ -280,6 +280,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool* aFinished) override
|
||||
@ -328,7 +329,7 @@ public:
|
||||
*aOutput = mSharedBuffers->GetOutputBuffer();
|
||||
|
||||
if (mInputWriteIndex >= mBufferSize) {
|
||||
SendBuffersToMainThread(aStream);
|
||||
SendBuffersToMainThread(aStream, aFrom);
|
||||
mInputWriteIndex -= mBufferSize;
|
||||
}
|
||||
}
|
||||
@ -359,12 +360,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void SendBuffersToMainThread(AudioNodeStream* aStream)
|
||||
void SendBuffersToMainThread(AudioNodeStream* aStream, GraphTime aFrom)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
// we now have a full input buffer ready to be sent to the main thread.
|
||||
StreamTime playbackTick = mSource->GetCurrentPosition();
|
||||
StreamTime playbackTick = mSource->GraphTimeToStreamTime(aFrom);
|
||||
// Add the duration of the current sample
|
||||
playbackTick += WEBAUDIO_BLOCK_SIZE;
|
||||
// Add the delay caused by the main thread
|
||||
|
@ -109,6 +109,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
const AudioBlock& aInput,
|
||||
AudioBlock* aOutput,
|
||||
bool *aFinished) override
|
||||
@ -146,7 +147,7 @@ public:
|
||||
bool onLeft[WEBAUDIO_BLOCK_SIZE];
|
||||
|
||||
float values[WEBAUDIO_BLOCK_SIZE];
|
||||
StreamTime tick = aStream->GetCurrentPosition();
|
||||
StreamTime tick = aStream->GraphTimeToStreamTime(aFrom);
|
||||
mPan.GetValuesAtTime(tick, values, WEBAUDIO_BLOCK_SIZE);
|
||||
|
||||
for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user