зеркало из 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);
|
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
|
// if providerOrigin is undefined, we use the last-used provider, or the
|
||||||
// current/default provider. The provider selection in the share panel
|
// current/default provider. The provider selection in the share panel
|
||||||
// will call sharePage with an origin for us to switch to.
|
// 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
|
// 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
|
// define at least url. If it is undefined, we're sharing the current url in
|
||||||
// the browser tab.
|
// 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;
|
gBrowser.currentURI;
|
||||||
if (!this.canSharePage(sharedURI))
|
if (!this.canSharePage(sharedURI))
|
||||||
return;
|
return;
|
||||||
|
@ -628,7 +629,6 @@ SocialShare = {
|
||||||
// endpoints (e.g. oexchange) that do not support additional
|
// endpoints (e.g. oexchange) that do not support additional
|
||||||
// socialapi functionality. One tweak is that we shoot an event
|
// socialapi functionality. One tweak is that we shoot an event
|
||||||
// containing the open graph data.
|
// containing the open graph data.
|
||||||
let pageData = graphData ? graphData : this.currentShare;
|
|
||||||
if (!pageData || sharedURI == gBrowser.currentURI) {
|
if (!pageData || sharedURI == gBrowser.currentURI) {
|
||||||
pageData = OpenGraphBuilder.getData(gBrowser);
|
pageData = OpenGraphBuilder.getData(gBrowser);
|
||||||
if (graphData) {
|
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;
|
this.currentShare = pageData;
|
||||||
|
|
||||||
let shareEndpoint = OpenGraphBuilder.generateEndpointURL(provider.shareURL, pageData);
|
let shareEndpoint = OpenGraphBuilder.generateEndpointURL(provider.shareURL, pageData);
|
||||||
|
@ -1353,10 +1357,10 @@ SocialMarks = {
|
||||||
return this._toolbarHelper;
|
return this._toolbarHelper;
|
||||||
},
|
},
|
||||||
|
|
||||||
markLink: function(aOrigin, aUrl) {
|
markLink: function(aOrigin, aUrl, aTarget) {
|
||||||
// find the button for this provider, and open it
|
// find the button for this provider, and open it
|
||||||
let id = this._toolbarHelper.idFromOrigin(aOrigin);
|
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) {
|
markLink: function CM_markLink(origin) {
|
||||||
// send link to social, if it is the page url linkURI will be null
|
// 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() {
|
shareLink: function CM_shareLink() {
|
||||||
SocialShare.sharePage(null, { url: this.linkURI.spec });
|
SocialShare.sharePage(null, { url: this.linkURI.spec }, this.target);
|
||||||
},
|
},
|
||||||
|
|
||||||
shareImage: function CM_shareImage() {
|
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() {
|
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) {
|
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() {
|
savePageAs: function CM_savePageAs() {
|
||||||
|
|
|
@ -147,6 +147,7 @@
|
||||||
|
|
||||||
<method name="loadPanel">
|
<method name="loadPanel">
|
||||||
<parameter name="pageData"/>
|
<parameter name="pageData"/>
|
||||||
|
<parameter name="target"/>
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
let provider = this.provider;
|
let provider = this.provider;
|
||||||
let panel = this.panel;
|
let panel = this.panel;
|
||||||
|
@ -157,7 +158,13 @@
|
||||||
panel.appendChild(this.content);
|
panel.appendChild(this.content);
|
||||||
|
|
||||||
let URLTemplate = provider.markURL;
|
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);
|
let endpoint = OpenGraphBuilder.generateEndpointURL(URLTemplate, this.pageData);
|
||||||
|
|
||||||
// setup listeners
|
// setup listeners
|
||||||
|
@ -248,6 +255,7 @@
|
||||||
|
|
||||||
<method name="markLink">
|
<method name="markLink">
|
||||||
<parameter name="aUrl"/>
|
<parameter name="aUrl"/>
|
||||||
|
<parameter name="aTarget"/>
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
if (!aUrl) {
|
if (!aUrl) {
|
||||||
this.markCurrentPage(true);
|
this.markCurrentPage(true);
|
||||||
|
@ -259,7 +267,7 @@
|
||||||
// link, etc. inside the page. We also "update" the iframe to the
|
// link, etc. inside the page. We also "update" the iframe to the
|
||||||
// previous url when it is closed.
|
// previous url when it is closed.
|
||||||
this.content.setAttribute("src", "about:blank");
|
this.content.setAttribute("src", "about:blank");
|
||||||
this.loadPanel({ url: aUrl });
|
this.loadPanel({ url: aUrl }, aTarget);
|
||||||
this.openPanel(true);
|
this.openPanel(true);
|
||||||
]]></body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
|
@ -9,6 +9,7 @@ support-files =
|
||||||
opengraph/shortlink_linkrel.html
|
opengraph/shortlink_linkrel.html
|
||||||
opengraph/shorturl_link.html
|
opengraph/shorturl_link.html
|
||||||
opengraph/shorturl_linkrel.html
|
opengraph/shorturl_linkrel.html
|
||||||
|
microdata.html
|
||||||
share.html
|
share.html
|
||||||
social_activate.html
|
social_activate.html
|
||||||
social_activate_iframe.html
|
social_activate_iframe.html
|
||||||
|
|
|
@ -170,5 +170,76 @@ var tests = {
|
||||||
}
|
}
|
||||||
port.postMessage({topic: "test-init"});
|
port.postMessage({topic: "test-init"});
|
||||||
executeSoon(runOneTest);
|
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) {
|
testButtonOnDisable: function(next) {
|
||||||
// enable the provider now
|
// enable the provider now
|
||||||
let provider = Social._getProviderFromOrigin(manifest2.origin);
|
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);
|
shareData = JSON.parse(e.detail);
|
||||||
updateTextNode(document.getElementById("shared"), shareData.url);
|
updateTextNode(document.getElementById("shared"), shareData.url);
|
||||||
socialMarkUpdate(true);
|
socialMarkUpdate(true);
|
||||||
|
var port = navigator.mozSocial.getWorker().port;
|
||||||
|
port.postMessage({topic: "share-data-message", result: shareData});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -498,7 +498,7 @@ this.OpenGraphBuilder = {
|
||||||
return endpointURL;
|
return endpointURL;
|
||||||
},
|
},
|
||||||
|
|
||||||
getData: function(browser) {
|
getData: function(browser, target) {
|
||||||
let res = {
|
let res = {
|
||||||
url: this._validateURL(browser, browser.currentURI.spec),
|
url: this._validateURL(browser, browser.currentURI.spec),
|
||||||
title: browser.contentDocument.title,
|
title: browser.contentDocument.title,
|
||||||
|
@ -507,9 +507,14 @@ this.OpenGraphBuilder = {
|
||||||
this._getMetaData(browser, res);
|
this._getMetaData(browser, res);
|
||||||
this._getLinkData(browser, res);
|
this._getLinkData(browser, res);
|
||||||
this._getPageData(browser, res);
|
this._getPageData(browser, res);
|
||||||
|
res.microdata = this.getMicrodata(browser, target);
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getMicrodata: function (browser, target) {
|
||||||
|
return getMicrodata(browser.contentDocument, target);
|
||||||
|
},
|
||||||
|
|
||||||
_getMetaData: function(browser, o) {
|
_getMetaData: function(browser, o) {
|
||||||
// query for standardized meta data
|
// query for standardized meta data
|
||||||
let els = browser.contentDocument
|
let els = browser.contentDocument
|
||||||
|
@ -522,7 +527,14 @@ this.OpenGraphBuilder = {
|
||||||
if (!value)
|
if (!value)
|
||||||
continue;
|
continue;
|
||||||
value = unescapeService.unescape(value.trim());
|
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 "title":
|
||||||
case "og:title":
|
case "og:title":
|
||||||
o.title = value;
|
o.title = value;
|
||||||
|
@ -577,6 +589,19 @@ this.OpenGraphBuilder = {
|
||||||
case "image_src":
|
case "image_src":
|
||||||
o.previews.push(url);
|
o.previews.push(url);
|
||||||
break;
|
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;
|
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;
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче