Backed out changeset b9b23b61401f (bug 1273203) for breaking many tests. r=backout

This commit is contained in:
Sebastian Hengst 2016-05-18 10:38:17 +02:00
Родитель 2a25239773
Коммит 51ba720edc
12 изменённых файлов: 478 добавлений и 0 удалений

Просмотреть файл

@ -26,6 +26,7 @@ const METHODS = {
findNext: {},
clearMatch: {},
executeScript: { alwaysFails: true }, // needs browser:universalxss
getStructuredData: {},
getWebManifest: {},
mute: {},
unmute: {},

Просмотреть файл

@ -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");
Cu.import("resource://gre/modules/ExtensionContent.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "acs",
@ -283,6 +285,7 @@ BrowserElementChild.prototype = {
"get-audio-channel-muted": this._recvGetAudioChannelMuted,
"set-audio-channel-muted": this._recvSetAudioChannelMuted,
"get-is-audio-channel-active": this._recvIsAudioChannelActive,
"get-structured-data": this._recvGetStructuredData,
"get-web-manifest": this._recvGetWebManifest,
}
@ -1543,6 +1546,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: {

Просмотреть файл

@ -389,6 +389,7 @@ BrowserElementParent.prototype = {
"got-audio-channel-muted": this._gotDOMRequestResult,
"got-set-audio-channel-muted": this._gotDOMRequestResult,
"got-is-audio-channel-active": this._gotDOMRequestResult,
"got-structured-data": this._gotDOMRequestResult,
"got-web-manifest": this._gotDOMRequestResult,
};
@ -1207,6 +1208,8 @@ BrowserElementParent.prototype = {
return req;
},
getStructuredData: defineDOMRequestMethod('get-structured-data'),
getWebManifest: defineDOMRequestMethod('get-web-manifest'),
/**
* Called when the visibility of the window which owns this iframe changes.

Просмотреть файл

@ -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));
};
});
});
});
}

Просмотреть файл

@ -14,6 +14,7 @@ support-files =
[test_browserElement_oop_AudioChannelSeeking.html]
tags = audiochannel
[test_browserElement_oop_getStructuredData.html]
[test_browserElement_oop_Viewmode.html]
[test_browserElement_oop_ThemeColor.html]
[test_browserElement_inproc_ErrorSecurity.html]

Просмотреть файл

@ -41,6 +41,7 @@ support-files =
browserElement_FrameWrongURI.js
browserElement_GetScreenshot.js
browserElement_GetScreenshotDppx.js
browserElement_getStructuredData.js
browserElement_getWebManifest.js
browserElement_Iconchange.js
browserElement_LoadEvents.js
@ -264,6 +265,7 @@ tags = audiochannel
[test_browserElement_inproc_AudioChannel_nested.html]
tags = audiochannel
[test_browserElement_inproc_SetNFCFocus.html]
[test_browserElement_inproc_getStructuredData.html]
[test_browserElement_inproc_OpenWindowEmpty.html]
skip-if = (toolkit == 'gonk') # Test doesn't work on B2G emulator
[test_browserElement_inproc_ActiveStateChangeOnChangingMutedOrVolume.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>

Просмотреть файл

@ -110,4 +110,16 @@ interface nsIBrowserElementAPI : nsISupports
* http://w3c.github.io/manifest/
*/
nsIDOMDOMRequest getWebManifest();
/**
* 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();
};

Просмотреть файл

@ -785,6 +785,22 @@ 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>();
}
already_AddRefed<DOMRequest>
nsBrowserElement::GetWebManifest(ErrorResult& aRv)
{

Просмотреть файл

@ -112,6 +112,8 @@ public:
const dom::BrowserElementExecuteScriptOptions& aOptions,
ErrorResult& aRv);
already_AddRefed<dom::DOMRequest> GetStructuredData(ErrorResult& aRv);
already_AddRefed<dom::DOMRequest> GetWebManifest(ErrorResult& aRv);
void SetNFCFocus(bool isFocus,

Просмотреть файл

@ -175,6 +175,11 @@ interface BrowserElementPrivileged {
DOMRequest executeScript(DOMString script,
optional BrowserElementExecuteScriptOptions options);
[Throws,
Pref="dom.mozBrowserFramesEnabled",
CheckAllPermissions="browser"]
DOMRequest getStructuredData();
[Throws,
Pref="dom.mozBrowserFramesEnabled",
CheckAllPermissions="browser"]