зеркало из https://github.com/mozilla/gecko-dev.git
Bug 926417 add microdata support for share/marks, r=markh, r=felipe
This commit is contained in:
Родитель
01345e59a4
Коммит
a69c426a8e
|
@ -600,7 +600,7 @@ SocialShare = {
|
|||
sizeSocialPanelToContent(this.panel, iframe);
|
||||
},
|
||||
|
||||
sharePage: function(providerOrigin, graphData) {
|
||||
sharePage: function(providerOrigin, graphData, target) {
|
||||
// if providerOrigin is undefined, we use the last-used provider, or the
|
||||
// current/default provider. The provider selection in the share panel
|
||||
// will call sharePage with an origin for us to switch to.
|
||||
|
@ -619,7 +619,8 @@ SocialShare = {
|
|||
// in mozSocial API, or via nsContentMenu calls. If it is present, it MUST
|
||||
// define at least url. If it is undefined, we're sharing the current url in
|
||||
// the browser tab.
|
||||
let sharedURI = graphData ? Services.io.newURI(graphData.url, null, null) :
|
||||
let pageData = graphData ? graphData : this.currentShare;
|
||||
let sharedURI = pageData ? Services.io.newURI(pageData.url, null, null) :
|
||||
gBrowser.currentURI;
|
||||
if (!this.canSharePage(sharedURI))
|
||||
return;
|
||||
|
@ -628,7 +629,6 @@ SocialShare = {
|
|||
// endpoints (e.g. oexchange) that do not support additional
|
||||
// socialapi functionality. One tweak is that we shoot an event
|
||||
// containing the open graph data.
|
||||
let pageData = graphData ? graphData : this.currentShare;
|
||||
if (!pageData || sharedURI == gBrowser.currentURI) {
|
||||
pageData = OpenGraphBuilder.getData(gBrowser);
|
||||
if (graphData) {
|
||||
|
@ -638,6 +638,10 @@ SocialShare = {
|
|||
}
|
||||
}
|
||||
}
|
||||
// if this is a share of a selected item, get any microdata
|
||||
if (!pageData.microdata && target) {
|
||||
pageData.microdata = OpenGraphBuilder.getMicrodata(gBrowser, target);
|
||||
}
|
||||
this.currentShare = pageData;
|
||||
|
||||
let shareEndpoint = OpenGraphBuilder.generateEndpointURL(provider.shareURL, pageData);
|
||||
|
@ -1353,10 +1357,10 @@ SocialMarks = {
|
|||
return this._toolbarHelper;
|
||||
},
|
||||
|
||||
markLink: function(aOrigin, aUrl) {
|
||||
markLink: function(aOrigin, aUrl, aTarget) {
|
||||
// find the button for this provider, and open it
|
||||
let id = this._toolbarHelper.idFromOrigin(aOrigin);
|
||||
document.getElementById(id).markLink(aUrl);
|
||||
document.getElementById(id).markLink(aUrl, aTarget);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1591,22 +1591,22 @@ nsContextMenu.prototype = {
|
|||
},
|
||||
markLink: function CM_markLink(origin) {
|
||||
// send link to social, if it is the page url linkURI will be null
|
||||
SocialMarks.markLink(origin, this.linkURI ? this.linkURI.spec : null);
|
||||
SocialMarks.markLink(origin, this.linkURI ? this.linkURI.spec : null, this.target);
|
||||
},
|
||||
shareLink: function CM_shareLink() {
|
||||
SocialShare.sharePage(null, { url: this.linkURI.spec });
|
||||
SocialShare.sharePage(null, { url: this.linkURI.spec }, this.target);
|
||||
},
|
||||
|
||||
shareImage: function CM_shareImage() {
|
||||
SocialShare.sharePage(null, { url: this.imageURL, previews: [ this.mediaURL ] });
|
||||
SocialShare.sharePage(null, { url: this.imageURL, previews: [ this.mediaURL ] }, this.target);
|
||||
},
|
||||
|
||||
shareVideo: function CM_shareVideo() {
|
||||
SocialShare.sharePage(null, { url: this.mediaURL, source: this.mediaURL });
|
||||
SocialShare.sharePage(null, { url: this.mediaURL, source: this.mediaURL }, this.target);
|
||||
},
|
||||
|
||||
shareSelect: function CM_shareSelect(selection) {
|
||||
SocialShare.sharePage(null, { url: this.browser.currentURI.spec, text: selection });
|
||||
SocialShare.sharePage(null, { url: this.browser.currentURI.spec, text: selection }, this.target);
|
||||
},
|
||||
|
||||
savePageAs: function CM_savePageAs() {
|
||||
|
|
|
@ -147,6 +147,7 @@
|
|||
|
||||
<method name="loadPanel">
|
||||
<parameter name="pageData"/>
|
||||
<parameter name="target"/>
|
||||
<body><![CDATA[
|
||||
let provider = this.provider;
|
||||
let panel = this.panel;
|
||||
|
@ -157,7 +158,13 @@
|
|||
panel.appendChild(this.content);
|
||||
|
||||
let URLTemplate = provider.markURL;
|
||||
this.pageData = pageData || OpenGraphBuilder.getData(gBrowser);
|
||||
pageData = pageData || OpenGraphBuilder.getData(gBrowser);
|
||||
// if this is a share of a selected item, get any microdata
|
||||
if (!pageData.microdata && target) {
|
||||
pageData.microdata = OpenGraphBuilder.getMicrodata(gBrowser, target);
|
||||
}
|
||||
this.pageData = pageData;
|
||||
|
||||
let endpoint = OpenGraphBuilder.generateEndpointURL(URLTemplate, this.pageData);
|
||||
|
||||
// setup listeners
|
||||
|
@ -248,6 +255,7 @@
|
|||
|
||||
<method name="markLink">
|
||||
<parameter name="aUrl"/>
|
||||
<parameter name="aTarget"/>
|
||||
<body><![CDATA[
|
||||
if (!aUrl) {
|
||||
this.markCurrentPage(true);
|
||||
|
@ -259,7 +267,7 @@
|
|||
// link, etc. inside the page. We also "update" the iframe to the
|
||||
// previous url when it is closed.
|
||||
this.content.setAttribute("src", "about:blank");
|
||||
this.loadPanel({ url: aUrl });
|
||||
this.loadPanel({ url: aUrl }, aTarget);
|
||||
this.openPanel(true);
|
||||
]]></body>
|
||||
</method>
|
||||
|
|
|
@ -9,6 +9,7 @@ support-files =
|
|||
opengraph/shortlink_linkrel.html
|
||||
opengraph/shorturl_link.html
|
||||
opengraph/shorturl_linkrel.html
|
||||
microdata.html
|
||||
share.html
|
||||
social_activate.html
|
||||
social_activate_iframe.html
|
||||
|
|
|
@ -170,5 +170,76 @@ var tests = {
|
|||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
executeSoon(runOneTest);
|
||||
},
|
||||
testShareMicrodata: function(next) {
|
||||
SocialService.addProvider(manifest, function(provider) {
|
||||
let port = provider.getWorkerPort();
|
||||
let target, testTab;
|
||||
|
||||
let expecting = JSON.stringify({
|
||||
"url": "https://example.com/browser/browser/base/content/test/social/microdata.html",
|
||||
"title": "My Blog",
|
||||
"previews": [],
|
||||
"microdata": {
|
||||
"items": [{
|
||||
"types": ["http://schema.org/BlogPosting"],
|
||||
"properties": {
|
||||
"headline": ["Progress report"],
|
||||
"datePublished": ["2013-08-29"],
|
||||
"url": ["https://example.com/browser/browser/base/content/test/social/microdata.html?comments=0"],
|
||||
"comment": [{
|
||||
"types": ["http://schema.org/UserComments"],
|
||||
"properties": {
|
||||
"url": ["https://example.com/browser/browser/base/content/test/social/microdata.html#c1"],
|
||||
"creator": [{
|
||||
"types": ["http://schema.org/Person"],
|
||||
"properties": {
|
||||
"name": ["Greg"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"commentTime": ["2013-08-29"]
|
||||
}
|
||||
}, {
|
||||
"types": ["http://schema.org/UserComments"],
|
||||
"properties": {
|
||||
"url": ["https://example.com/browser/browser/base/content/test/social/microdata.html#c2"],
|
||||
"creator": [{
|
||||
"types": ["http://schema.org/Person"],
|
||||
"properties": {
|
||||
"name": ["Charlotte"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"commentTime": ["2013-08-29"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-share-data-message":
|
||||
is(JSON.stringify(e.data.result), expecting, "microdata data ok");
|
||||
gBrowser.removeTab(testTab);
|
||||
SocialService.removeProvider(manifest.origin, next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
|
||||
let url = "https://example.com/browser/browser/base/content/test/social/microdata.html"
|
||||
addTab(url, function(tab) {
|
||||
testTab = tab;
|
||||
let doc = tab.linkedBrowser.contentDocument;
|
||||
target = doc.getElementById("simple-hcard");
|
||||
SocialShare.sharePage(manifest.origin, null, target);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -280,6 +280,56 @@ var tests = {
|
|||
});
|
||||
},
|
||||
|
||||
testMarkMicrodata: function(next) {
|
||||
let provider = Social._getProviderFromOrigin(manifest2.origin);
|
||||
let port = provider.getWorkerPort();
|
||||
let target, testTab;
|
||||
|
||||
// browser_share tests microdata on the full page, this is testing a
|
||||
// specific target element.
|
||||
let expecting = JSON.stringify({
|
||||
"url": "https://example.com/browser/browser/base/content/test/social/microdata.html",
|
||||
"microdata": {
|
||||
"items": [{
|
||||
"types": ["http://schema.org/UserComments"],
|
||||
"properties": {
|
||||
"url": ["https://example.com/browser/browser/base/content/test/social/microdata.html#c2"],
|
||||
"creator": [{
|
||||
"types": ["http://schema.org/Person"],
|
||||
"properties": {
|
||||
"name": ["Charlotte"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"commentTime": ["2013-08-29"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-share-data-message":
|
||||
is(JSON.stringify(e.data.result), expecting, "microdata data ok");
|
||||
gBrowser.removeTab(testTab);
|
||||
port.close();
|
||||
next();
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
|
||||
let url = "https://example.com/browser/browser/base/content/test/social/microdata.html"
|
||||
addTab(url, function(tab) {
|
||||
testTab = tab;
|
||||
let doc = tab.linkedBrowser.contentDocument;
|
||||
target = doc.getElementById("test-comment");
|
||||
SocialMarks.markLink(manifest2.origin, url, target);
|
||||
});
|
||||
},
|
||||
|
||||
testButtonOnDisable: function(next) {
|
||||
// enable the provider now
|
||||
let provider = Social._getProviderFromOrigin(manifest2.origin);
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE HTML>
|
||||
<head>
|
||||
<title>My Blog</title>
|
||||
</head>
|
||||
<body>
|
||||
<article itemscope itemtype="http://schema.org/BlogPosting">
|
||||
<header>
|
||||
<h1 itemprop="headline">Progress report</h1>
|
||||
<p><time itemprop="datePublished" datetime="2013-08-29">today</time></p>
|
||||
<link itemprop="url" href="?comments=0">
|
||||
</header>
|
||||
<p>All in all, he's doing well with his swim lessons. The biggest thing was he had trouble
|
||||
putting his head in, but we got it down.</p>
|
||||
<section>
|
||||
<h1>Comments</h1>
|
||||
<article itemprop="comment" itemscope itemtype="http://schema.org/UserComments" id="c1">
|
||||
<link itemprop="url" href="#c1">
|
||||
<footer>
|
||||
<p>Posted by: <span itemprop="creator" itemscope itemtype="http://schema.org/Person">
|
||||
<span itemprop="name">Greg</span>
|
||||
</span></p>
|
||||
<p><time itemprop="commentTime" datetime="2013-08-29">15 minutes ago</time></p>
|
||||
</footer>
|
||||
<p>Ha!</p>
|
||||
</article>
|
||||
<article id="test-comment" itemprop="comment" itemscope itemtype="http://schema.org/UserComments" id="c2">
|
||||
<link itemprop="url" href="#c2">
|
||||
<footer>
|
||||
<p>Posted by: <span itemprop="creator" itemscope itemtype="http://schema.org/Person">
|
||||
<span itemprop="name">Charlotte</span>
|
||||
</span></p>
|
||||
<p><time itemprop="commentTime" datetime="2013-08-29">5 minutes ago</time></p>
|
||||
</footer>
|
||||
<p>When you say "we got it down"...</p>
|
||||
</article>
|
||||
</section>
|
||||
</article>
|
||||
</body>
|
|
@ -34,6 +34,8 @@
|
|||
shareData = JSON.parse(e.detail);
|
||||
updateTextNode(document.getElementById("shared"), shareData.url);
|
||||
socialMarkUpdate(true);
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "share-data-message", result: shareData});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -498,7 +498,7 @@ this.OpenGraphBuilder = {
|
|||
return endpointURL;
|
||||
},
|
||||
|
||||
getData: function(browser) {
|
||||
getData: function(browser, target) {
|
||||
let res = {
|
||||
url: this._validateURL(browser, browser.currentURI.spec),
|
||||
title: browser.contentDocument.title,
|
||||
|
@ -507,9 +507,14 @@ this.OpenGraphBuilder = {
|
|||
this._getMetaData(browser, res);
|
||||
this._getLinkData(browser, res);
|
||||
this._getPageData(browser, res);
|
||||
res.microdata = this.getMicrodata(browser, target);
|
||||
return res;
|
||||
},
|
||||
|
||||
getMicrodata: function (browser, target) {
|
||||
return getMicrodata(browser.contentDocument, target);
|
||||
},
|
||||
|
||||
_getMetaData: function(browser, o) {
|
||||
// query for standardized meta data
|
||||
let els = browser.contentDocument
|
||||
|
@ -522,7 +527,14 @@ this.OpenGraphBuilder = {
|
|||
if (!value)
|
||||
continue;
|
||||
value = unescapeService.unescape(value.trim());
|
||||
switch (el.getAttribute("property") || el.getAttribute("name")) {
|
||||
let key = el.getAttribute("property") || el.getAttribute("name");
|
||||
if (!key)
|
||||
continue;
|
||||
// There are a wide array of possible meta tags, expressing articles,
|
||||
// products, etc. so all meta tags are passed through but we touch up the
|
||||
// most common attributes.
|
||||
o[key] = value;
|
||||
switch (key) {
|
||||
case "title":
|
||||
case "og:title":
|
||||
o.title = value;
|
||||
|
@ -577,6 +589,19 @@ this.OpenGraphBuilder = {
|
|||
case "image_src":
|
||||
o.previews.push(url);
|
||||
break;
|
||||
case "alternate":
|
||||
// expressly for oembed support but we're liberal here and will let
|
||||
// other alternate links through. oembed defines an href, supplied by
|
||||
// the site, where you can fetch additional meta data about a page.
|
||||
// We'll let the client fetch the oembed data themselves, but they
|
||||
// need the data from this link.
|
||||
if (!o.alternate)
|
||||
o.alternate = [];
|
||||
o.alternate.push({
|
||||
"type": el.getAttribute("type"),
|
||||
"href": el.getAttribute("href"),
|
||||
"title": el.getAttribute("title")
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -610,3 +635,43 @@ this.OpenGraphBuilder = {
|
|||
return l;
|
||||
}
|
||||
};
|
||||
|
||||
// getMicrodata (and getObject) based on wg algorythm to convert microdata to json
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/microdata-2.html#json
|
||||
function getMicrodata(document, target) {
|
||||
|
||||
function _getObject(item) {
|
||||
let result = {};
|
||||
if (item.itemType.length)
|
||||
result.types = [i for (i of item.itemType)];
|
||||
if (item.itemId)
|
||||
result.itemId = item.itemid;
|
||||
if (item.properties.length)
|
||||
result.properties = {};
|
||||
for (let elem of item.properties) {
|
||||
let value;
|
||||
if (elem.itemScope)
|
||||
value = _getObject(elem);
|
||||
else if (elem.itemValue)
|
||||
value = elem.itemValue;
|
||||
// handle mis-formatted microdata
|
||||
else if (elem.hasAttribute("content"))
|
||||
value = elem.getAttribute("content");
|
||||
|
||||
for (let prop of elem.itemProp) {
|
||||
if (!result.properties[prop])
|
||||
result.properties[prop] = [];
|
||||
result.properties[prop].push(value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
let result = { items: [] };
|
||||
let elms = target ? [target] : document.getItems();
|
||||
for (let el of elms) {
|
||||
if (el.itemScope)
|
||||
result.items.push(_getObject(el));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче