mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-06 07:48:38 +09:00
Revert "Remove the Social API"
This commit is contained in:
parent
d7e628ffa5
commit
aa52f6bd53
52 changed files with 2895 additions and 16 deletions
|
|
@ -1118,6 +1118,13 @@ pref("pdfjs.previousHandler.alwaysAskBeforeHandling", false);
|
|||
// (This is intentionally on the high side; see bug 746055.)
|
||||
pref("image.mem.max_decoded_image_kb", 256000);
|
||||
|
||||
pref("social.sidebar.unload_timeout_ms", 10000);
|
||||
|
||||
// Activation from inside of share panel is possible if activationPanelEnabled
|
||||
// is true. Pref'd off for release while usage testing is done through beta.
|
||||
pref("social.share.activationPanelEnabled", true);
|
||||
pref("social.shareDirectory", "https://activations.cdn.mozilla.net/sharePanel.html");
|
||||
|
||||
// Block insecure active content on https pages
|
||||
pref("security.mixed_content.block_active_content", true);
|
||||
|
||||
|
|
|
|||
60
browser/base/content/aboutProviderDirectory.xhtml
Normal file
60
browser/base/content/aboutProviderDirectory.xhtml
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % htmlDTD
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"DTD/xhtml1-strict.dtd">
|
||||
%htmlDTD;
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
|
||||
%brandDTD;
|
||||
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
|
||||
%browserDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&social.directory.label;</title>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://browser/skin/aboutProviderDirectory.css"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="activation-link" hidden="true">
|
||||
<div id="message-box">
|
||||
<p>&social.directory.text;</p>
|
||||
</div>
|
||||
<div id="button-box">
|
||||
<button onclick="openDirectory()">&social.directory.button;</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="activation" hidden="true">
|
||||
<p>&social.directory.introText;</p>
|
||||
<div><iframe id="activation-frame"/></div>
|
||||
<p><a class="link" onclick="openDirectory()">&social.directory.viewmore.text;</a></p>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script type="text/javascript;version=1.8"><![CDATA[
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function openDirectory() {
|
||||
let url = Services.prefs.getCharPref("social.directories").split(',')[0];
|
||||
window.open(url);
|
||||
window.close();
|
||||
}
|
||||
|
||||
if (Services.prefs.getBoolPref("social.share.activationPanelEnabled")) {
|
||||
let url = Services.prefs.getCharPref("social.shareDirectory");
|
||||
document.getElementById("activation-frame").setAttribute("src", url);
|
||||
document.getElementById("activation").removeAttribute("hidden");
|
||||
} else {
|
||||
document.getElementById("activation-link").removeAttribute("hidden");
|
||||
}
|
||||
]]></script>
|
||||
</html>
|
||||
111
browser/base/content/aboutSocialError.xhtml
Normal file
111
browser/base/content/aboutSocialError.xhtml
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % htmlDTD
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"DTD/xhtml1-strict.dtd">
|
||||
%htmlDTD;
|
||||
<!ENTITY % netErrorDTD SYSTEM "chrome://global/locale/netError.dtd">
|
||||
%netErrorDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&loadError.label;</title>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/aboutNetError.css" type="text/css" media="all" />
|
||||
<link rel="stylesheet" type="text/css" media="all" href="chrome://browser/skin/aboutSocialError.css"/>
|
||||
<link rel="icon" type="image/png" id="favicon" href="chrome://global/skin/icons/warning-16.png"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="errorPageContainer">
|
||||
|
||||
<!-- Error Title -->
|
||||
<div id="errorTitle">
|
||||
<p id="errorShortDescText" >foo</p>
|
||||
</div>
|
||||
|
||||
<div id="button-box">
|
||||
<button id="btnTryAgain" onclick="tryAgainButton()"/>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script type="text/javascript;version=1.8"><![CDATA[
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/Social.jsm");
|
||||
|
||||
let config = {
|
||||
tryAgainCallback: reloadProvider
|
||||
}
|
||||
|
||||
function parseQueryString() {
|
||||
let searchParams = new URLSearchParams(document.documentURI.split("?")[1]);
|
||||
let mode = searchParams.get("mode");
|
||||
config.origin = searchParams.get("origin");
|
||||
let encodedURL = searchParams.get("url");
|
||||
let url = decodeURIComponent(encodedURL);
|
||||
// directory does not have origin set, in that case use the url origin for
|
||||
// the error message.
|
||||
if (!config.origin) {
|
||||
let URI = Services.io.newURI(url, null, null);
|
||||
config.origin =
|
||||
Services.scriptSecurityManager.createCodebasePrincipal(URI, {}).origin;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case "compactInfo":
|
||||
document.getElementById("btnTryAgain").style.display = 'none';
|
||||
break;
|
||||
case "tryAgainOnly":
|
||||
//intentional fall-through
|
||||
case "tryAgain":
|
||||
config.tryAgainCallback = loadQueryURL;
|
||||
config.queryURL = url;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function setUpStrings() {
|
||||
let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
|
||||
let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||
|
||||
let productName = brandBundle.GetStringFromName("brandShortName");
|
||||
let provider = Social._getProviderFromOrigin(config.origin);
|
||||
let providerName = provider ? provider.name : config.origin;
|
||||
|
||||
// Sets up the error message
|
||||
let msg = browserBundle.formatStringFromName("social.error.message", [productName, providerName], 2);
|
||||
document.getElementById("errorShortDescText").textContent = msg;
|
||||
|
||||
// Sets up the buttons' labels and accesskeys
|
||||
let btnTryAgain = document.getElementById("btnTryAgain");
|
||||
btnTryAgain.textContent = browserBundle.GetStringFromName("social.error.tryAgain.label");
|
||||
btnTryAgain.accessKey = browserBundle.GetStringFromName("social.error.tryAgain.accesskey");
|
||||
}
|
||||
|
||||
function tryAgainButton() {
|
||||
config.tryAgainCallback();
|
||||
}
|
||||
|
||||
function loadQueryURL() {
|
||||
window.location.href = config.queryURL;
|
||||
}
|
||||
|
||||
function reloadProvider() {
|
||||
let provider = Social._getProviderFromOrigin(config.origin);
|
||||
provider.reload();
|
||||
}
|
||||
|
||||
parseQueryString();
|
||||
setUpStrings();
|
||||
]]></script>
|
||||
</html>
|
||||
|
|
@ -85,6 +85,10 @@
|
|||
label="&bookmarkThisLinkCmd.label;"
|
||||
accesskey="&bookmarkThisLinkCmd.accesskey;"
|
||||
oncommand="gContextMenu.bookmarkLink();"/>
|
||||
<menuitem id="context-sharelink"
|
||||
label="&shareLink.label;"
|
||||
accesskey="&shareLink.accesskey;"
|
||||
oncommand="gContextMenu.shareLink();"/>
|
||||
<menuitem id="context-savelink"
|
||||
label="&saveLinkCmd.label;"
|
||||
accesskey="&saveLinkCmd.accesskey;"
|
||||
|
|
@ -208,6 +212,10 @@
|
|||
label="&saveImageCmd.label;"
|
||||
accesskey="&saveImageCmd.accesskey;"
|
||||
oncommand="gContextMenu.saveMedia();"/>
|
||||
<menuitem id="context-shareimage"
|
||||
label="&shareImage.label;"
|
||||
accesskey="&shareImage.accesskey;"
|
||||
oncommand="gContextMenu.shareImage();"/>
|
||||
<menuitem id="context-sendimage"
|
||||
label="&emailImageCmd.label;"
|
||||
accesskey="&emailImageCmd.accesskey;"
|
||||
|
|
@ -229,6 +237,10 @@
|
|||
label="&saveVideoCmd.label;"
|
||||
accesskey="&saveVideoCmd.accesskey;"
|
||||
oncommand="gContextMenu.saveMedia();"/>
|
||||
<menuitem id="context-sharevideo"
|
||||
label="&shareVideo.label;"
|
||||
accesskey="&shareVideo.accesskey;"
|
||||
oncommand="gContextMenu.shareVideo();"/>
|
||||
<menuitem id="context-saveaudio"
|
||||
label="&saveAudioCmd.label;"
|
||||
accesskey="&saveAudioCmd.accesskey;"
|
||||
|
|
@ -259,6 +271,10 @@
|
|||
accesskey="&hidePluginCmd.accesskey;"
|
||||
oncommand="gContextMenu.hidePlugin();"/>
|
||||
<menuseparator id="context-sep-ctp"/>
|
||||
<menuitem id="context-sharepage"
|
||||
label="&sharePageCmd.label;"
|
||||
accesskey="&sharePageCmd.accesskey;"
|
||||
oncommand="SocialShare.sharePage();"/>
|
||||
<menuitem id="context-savepage"
|
||||
label="&savePageCmd.label;"
|
||||
accesskey="&savePageCmd.accesskey2;"
|
||||
|
|
@ -318,6 +334,10 @@
|
|||
<menupopup id="context-sendlinktodevice-popup"
|
||||
onpopupshowing="gFxAccounts.populateSendTabToDevicesMenu(event.target, gContextMenu.linkURL, gContextMenu.linkTextStr);"/>
|
||||
</menu>
|
||||
<menuitem id="context-shareselect"
|
||||
label="&shareSelect.label;"
|
||||
accesskey="&shareSelect.accesskey;"
|
||||
oncommand="gContextMenu.shareSelect();"/>
|
||||
<menuseparator id="frame-sep"/>
|
||||
<menu id="frame" label="&thisFrameMenu.label;" accesskey="&thisFrameMenu.accesskey;">
|
||||
<menupopup>
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@
|
|||
oncommand="OpenBrowserWindow({private: true});" reserved="true"/>
|
||||
<command id="History:UndoCloseTab" oncommand="undoCloseTab();"/>
|
||||
<command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
|
||||
<command id="Social:SharePage" oncommand="SocialShare.sharePage();"/>
|
||||
<command id="Social:Addons" oncommand="BrowserOpenAddonsMgr('addons://list/service');"/>
|
||||
</commandset>
|
||||
|
||||
<commandset id="placesCommands">
|
||||
|
|
@ -115,6 +117,7 @@
|
|||
</commandset>
|
||||
|
||||
<broadcasterset id="mainBroadcasterSet">
|
||||
<broadcaster id="Social:PageShareable" disabled="true"/>
|
||||
<broadcaster id="viewBookmarksSidebar" autoCheck="false" label="&bookmarksButton.label;"
|
||||
type="checkbox" group="sidebar" sidebarurl="chrome://browser/content/bookmarks/bookmarksPanel.xul"
|
||||
oncommand="SidebarUI.toggle('viewBookmarksSidebar');"/>
|
||||
|
|
|
|||
503
browser/base/content/browser-social.js
Normal file
503
browser/base/content/browser-social.js
Normal file
|
|
@ -0,0 +1,503 @@
|
|||
/* 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/. */
|
||||
|
||||
// the "exported" symbols
|
||||
var SocialUI,
|
||||
SocialShare,
|
||||
SocialActivationListener;
|
||||
|
||||
(function() {
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "OpenGraphBuilder", function() {
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/Social.jsm", tmp);
|
||||
return tmp.OpenGraphBuilder;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "DynamicResizeWatcher", function() {
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/Social.jsm", tmp);
|
||||
return tmp.DynamicResizeWatcher;
|
||||
});
|
||||
|
||||
SocialUI = {
|
||||
_initialized: false,
|
||||
|
||||
// Called on delayed startup to initialize the UI
|
||||
init: function SocialUI_init() {
|
||||
if (this._initialized) {
|
||||
return;
|
||||
}
|
||||
let mm = window.getGroupMessageManager("social");
|
||||
mm.loadFrameScript("chrome://browser/content/content.js", true);
|
||||
mm.loadFrameScript("chrome://browser/content/social-content.js", true);
|
||||
|
||||
Services.obs.addObserver(this, "social:providers-changed", false);
|
||||
|
||||
CustomizableUI.addListener(this);
|
||||
SocialActivationListener.init();
|
||||
|
||||
Social.init().then((update) => {
|
||||
if (update)
|
||||
this._providersChanged();
|
||||
});
|
||||
|
||||
this._initialized = true;
|
||||
},
|
||||
|
||||
// Called on window unload
|
||||
uninit: function SocialUI_uninit() {
|
||||
if (!this._initialized) {
|
||||
return;
|
||||
}
|
||||
Services.obs.removeObserver(this, "social:providers-changed");
|
||||
|
||||
CustomizableUI.removeListener(this);
|
||||
SocialActivationListener.uninit();
|
||||
|
||||
this._initialized = false;
|
||||
},
|
||||
|
||||
observe: function SocialUI_observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "social:providers-changed":
|
||||
this._providersChanged();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_providersChanged: function() {
|
||||
SocialShare.populateProviderMenu();
|
||||
},
|
||||
|
||||
showLearnMore: function() {
|
||||
let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "social-api";
|
||||
openUILinkIn(url, "tab");
|
||||
},
|
||||
|
||||
closeSocialPanelForLinkTraversal: function (target, linkNode) {
|
||||
// No need to close the panel if this traversal was not retargeted
|
||||
if (target == "" || target == "_self")
|
||||
return;
|
||||
|
||||
// Check to see whether this link traversal was in a social panel
|
||||
let win = linkNode.ownerGlobal;
|
||||
let container = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler;
|
||||
let containerParent = container.parentNode;
|
||||
if (containerParent.classList.contains("social-panel") &&
|
||||
containerParent instanceof Ci.nsIDOMXULPopupElement) {
|
||||
// allow the link traversal to finish before closing the panel
|
||||
setTimeout(() => {
|
||||
containerParent.hidePopup();
|
||||
}, 0);
|
||||
}
|
||||
},
|
||||
|
||||
get _chromeless() {
|
||||
// Is this a popup window that doesn't want chrome shown?
|
||||
let docElem = document.documentElement;
|
||||
// extrachrome is not restored during session restore, so we need
|
||||
// to check for the toolbar as well.
|
||||
let chromeless = docElem.getAttribute("chromehidden").includes("extrachrome") ||
|
||||
docElem.getAttribute('chromehidden').includes("toolbar");
|
||||
// This property is "fixed" for a window, so avoid doing the check above
|
||||
// multiple times...
|
||||
delete this._chromeless;
|
||||
this._chromeless = chromeless;
|
||||
return chromeless;
|
||||
},
|
||||
|
||||
get enabled() {
|
||||
// Returns whether social is enabled *for this window*.
|
||||
if (this._chromeless)
|
||||
return false;
|
||||
return Social.providers.length > 0;
|
||||
},
|
||||
|
||||
canSharePage: function(aURI) {
|
||||
return (aURI && (aURI.schemeIs('http') || aURI.schemeIs('https')));
|
||||
},
|
||||
|
||||
onCustomizeEnd: function(aWindow) {
|
||||
if (aWindow != window)
|
||||
return;
|
||||
// customization mode gets buttons out of sync with command updating, fix
|
||||
// the disabled state
|
||||
let canShare = this.canSharePage(gBrowser.currentURI);
|
||||
let shareButton = SocialShare.shareButton;
|
||||
if (shareButton) {
|
||||
if (canShare) {
|
||||
shareButton.removeAttribute("disabled")
|
||||
} else {
|
||||
shareButton.setAttribute("disabled", "true")
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// called on tab/urlbar/location changes and after customization. Update
|
||||
// anything that is tab specific.
|
||||
updateState: function() {
|
||||
goSetCommandEnabled("Social:PageShareable", this.canSharePage(gBrowser.currentURI));
|
||||
}
|
||||
}
|
||||
|
||||
// message manager handlers
|
||||
SocialActivationListener = {
|
||||
init: function() {
|
||||
messageManager.addMessageListener("Social:Activation", this);
|
||||
},
|
||||
uninit: function() {
|
||||
messageManager.removeMessageListener("Social:Activation", this);
|
||||
},
|
||||
receiveMessage: function(aMessage) {
|
||||
let data = aMessage.json;
|
||||
let browser = aMessage.target;
|
||||
data.window = window;
|
||||
// if the source if the message is the share panel, we do a one-click
|
||||
// installation. The source of activations is controlled by the
|
||||
// social.directories preference
|
||||
let options;
|
||||
if (browser == SocialShare.iframe && Services.prefs.getBoolPref("social.share.activationPanelEnabled")) {
|
||||
options = { bypassContentCheck: true, bypassInstallPanel: true };
|
||||
}
|
||||
|
||||
Social.installProvider(data, function(manifest) {
|
||||
Social.activateFromOrigin(manifest.origin, function(provider) {
|
||||
if (provider.shareURL) {
|
||||
// Ensure that the share button is somewhere usable.
|
||||
// SocialShare.shareButton may return null if it is in the menu-panel
|
||||
// and has never been visible, so we check the widget directly. If
|
||||
// there is no area for the widget we move it into the toolbar.
|
||||
let widget = CustomizableUI.getWidget("social-share-button");
|
||||
// If the panel is already open, we can be sure that the provider can
|
||||
// already be accessed, possibly anchored to another toolbar button.
|
||||
// In that case we don't move the widget.
|
||||
if (!widget.areaType && SocialShare.panel.state != "open") {
|
||||
CustomizableUI.addWidgetToArea("social-share-button", CustomizableUI.AREA_NAVBAR);
|
||||
// Ensure correct state.
|
||||
SocialUI.onCustomizeEnd(window);
|
||||
}
|
||||
|
||||
// make this new provider the selected provider. If the panel hasn't
|
||||
// been opened, we need to make the frame first.
|
||||
SocialShare._createFrame();
|
||||
SocialShare.iframe.setAttribute('src', 'data:text/plain;charset=utf8,');
|
||||
SocialShare.iframe.setAttribute('origin', provider.origin);
|
||||
// get the right button selected
|
||||
SocialShare.populateProviderMenu();
|
||||
if (SocialShare.panel.state == "open") {
|
||||
SocialShare.sharePage(provider.origin);
|
||||
}
|
||||
}
|
||||
if (provider.postActivationURL) {
|
||||
// if activated from an open share panel, we load the landing page in
|
||||
// a background tab
|
||||
gBrowser.loadOneTab(provider.postActivationURL, {inBackground: SocialShare.panel.state == "open"});
|
||||
}
|
||||
});
|
||||
}, options);
|
||||
}
|
||||
}
|
||||
|
||||
SocialShare = {
|
||||
get _dynamicResizer() {
|
||||
delete this._dynamicResizer;
|
||||
this._dynamicResizer = new DynamicResizeWatcher();
|
||||
return this._dynamicResizer;
|
||||
},
|
||||
|
||||
// Share panel may be attached to the overflow or menu button depending on
|
||||
// customization, we need to manage open state of the anchor.
|
||||
get anchor() {
|
||||
let widget = CustomizableUI.getWidget("social-share-button");
|
||||
return widget.forWindow(window).anchor;
|
||||
},
|
||||
// Holds the anchor node in use whilst the panel is open, because it may vary.
|
||||
_currentAnchor: null,
|
||||
|
||||
get panel() {
|
||||
return document.getElementById("social-share-panel");
|
||||
},
|
||||
|
||||
get iframe() {
|
||||
// panel.firstChild is our toolbar hbox, panel.lastChild is the iframe
|
||||
// container hbox used for an interstitial "loading" graphic
|
||||
return this.panel.lastChild.firstChild;
|
||||
},
|
||||
|
||||
uninit: function () {
|
||||
if (this.iframe) {
|
||||
let mm = this.messageManager;
|
||||
mm.removeMessageListener("PageVisibility:Show", this);
|
||||
mm.removeMessageListener("PageVisibility:Hide", this);
|
||||
mm.removeMessageListener("Social:DOMWindowClose", this);
|
||||
this.iframe.removeEventListener("load", this);
|
||||
this.iframe.remove();
|
||||
}
|
||||
},
|
||||
|
||||
_createFrame: function() {
|
||||
let panel = this.panel;
|
||||
if (this.iframe)
|
||||
return;
|
||||
this.panel.hidden = false;
|
||||
// create and initialize the panel for this window
|
||||
let iframe = document.createElement("browser");
|
||||
iframe.setAttribute("type", "content");
|
||||
iframe.setAttribute("class", "social-share-frame");
|
||||
iframe.setAttribute("context", "contentAreaContextMenu");
|
||||
iframe.setAttribute("tooltip", "aHTMLTooltip");
|
||||
iframe.setAttribute("disableglobalhistory", "true");
|
||||
iframe.setAttribute("flex", "1");
|
||||
iframe.setAttribute("message", "true");
|
||||
iframe.setAttribute("messagemanagergroup", "social");
|
||||
panel.lastChild.appendChild(iframe);
|
||||
let mm = this.messageManager;
|
||||
mm.addMessageListener("PageVisibility:Show", this);
|
||||
mm.addMessageListener("PageVisibility:Hide", this);
|
||||
mm.sendAsyncMessage("Social:SetErrorURL",
|
||||
{ template: "about:socialerror?mode=compactInfo&origin=%{origin}&url=%{url}" });
|
||||
iframe.addEventListener("load", this, true);
|
||||
mm.addMessageListener("Social:DOMWindowClose", this);
|
||||
|
||||
this.populateProviderMenu();
|
||||
},
|
||||
|
||||
get messageManager() {
|
||||
// The xbl bindings for the iframe may not exist yet, so we can't
|
||||
// access iframe.messageManager directly - but can get at it with this dance.
|
||||
return this.iframe.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader.messageManager;
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
let iframe = this.iframe;
|
||||
switch(aMessage.name) {
|
||||
case "PageVisibility:Show":
|
||||
SocialShare._dynamicResizer.start(iframe.parentNode, iframe);
|
||||
break;
|
||||
case "PageVisibility:Hide":
|
||||
SocialShare._dynamicResizer.stop();
|
||||
break;
|
||||
case "Social:DOMWindowClose":
|
||||
this.panel.hidePopup();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent: function(event) {
|
||||
switch (event.type) {
|
||||
case "load": {
|
||||
this.iframe.parentNode.removeAttribute("loading");
|
||||
if (this.currentShare)
|
||||
SocialShare.messageManager.sendAsyncMessage("Social:OpenGraphData", this.currentShare);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getSelectedProvider: function() {
|
||||
let provider;
|
||||
let lastProviderOrigin = this.iframe && this.iframe.getAttribute("origin");
|
||||
if (lastProviderOrigin) {
|
||||
provider = Social._getProviderFromOrigin(lastProviderOrigin);
|
||||
}
|
||||
return provider;
|
||||
},
|
||||
|
||||
createTooltip: function(event) {
|
||||
let tt = event.target;
|
||||
let provider = Social._getProviderFromOrigin(tt.triggerNode.getAttribute("origin"));
|
||||
tt.firstChild.setAttribute("value", provider.name);
|
||||
tt.lastChild.setAttribute("value", provider.origin);
|
||||
},
|
||||
|
||||
populateProviderMenu: function() {
|
||||
if (!this.iframe)
|
||||
return;
|
||||
let providers = Social.providers.filter(p => p.shareURL);
|
||||
let hbox = document.getElementById("social-share-provider-buttons");
|
||||
// remove everything before the add-share-provider button (which should also
|
||||
// be lastChild if any share providers were added)
|
||||
let addButton = document.getElementById("add-share-provider");
|
||||
while (hbox.lastChild != addButton) {
|
||||
hbox.removeChild(hbox.lastChild);
|
||||
}
|
||||
let selectedProvider = this.getSelectedProvider();
|
||||
for (let provider of providers) {
|
||||
let button = document.createElement("toolbarbutton");
|
||||
button.setAttribute("class", "toolbarbutton-1 share-provider-button");
|
||||
button.setAttribute("type", "radio");
|
||||
button.setAttribute("group", "share-providers");
|
||||
button.setAttribute("image", provider.iconURL);
|
||||
button.setAttribute("tooltip", "share-button-tooltip");
|
||||
button.setAttribute("origin", provider.origin);
|
||||
button.setAttribute("label", provider.name);
|
||||
button.setAttribute("oncommand", "SocialShare.sharePage(this.getAttribute('origin'));");
|
||||
if (provider == selectedProvider) {
|
||||
this.defaultButton = button;
|
||||
}
|
||||
hbox.appendChild(button);
|
||||
}
|
||||
if (!this.defaultButton) {
|
||||
this.defaultButton = addButton;
|
||||
}
|
||||
this.defaultButton.setAttribute("checked", "true");
|
||||
},
|
||||
|
||||
get shareButton() {
|
||||
// web-panels (bookmark/sidebar) don't include customizableui, so
|
||||
// nsContextMenu fails when accessing shareButton, breaking
|
||||
// browser_bug409481.js.
|
||||
if (!window.CustomizableUI)
|
||||
return null;
|
||||
let widget = CustomizableUI.getWidget("social-share-button");
|
||||
if (!widget || !widget.areaType)
|
||||
return null;
|
||||
return widget.forWindow(window).node;
|
||||
},
|
||||
|
||||
_onclick: function() {
|
||||
Services.telemetry.getHistogramById("SOCIAL_PANEL_CLICKS").add(0);
|
||||
},
|
||||
|
||||
onShowing: function() {
|
||||
(this._currentAnchor || this.anchor).setAttribute("open", "true");
|
||||
this.iframe.addEventListener("click", this._onclick, true);
|
||||
},
|
||||
|
||||
onHidden: function() {
|
||||
(this._currentAnchor || this.anchor).removeAttribute("open");
|
||||
this._currentAnchor = null;
|
||||
this.iframe.docShellIsActive = false;
|
||||
this.iframe.removeEventListener("click", this._onclick, true);
|
||||
this.iframe.setAttribute("src", "data:text/plain;charset=utf8,");
|
||||
// make sure that the frame is unloaded after it is hidden
|
||||
this.messageManager.sendAsyncMessage("Social:ClearFrame");
|
||||
this.currentShare = null;
|
||||
// share panel use is over, purge any history
|
||||
this.iframe.purgeSessionHistory();
|
||||
},
|
||||
|
||||
sharePage: function(providerOrigin, graphData, target, anchor) {
|
||||
// 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.
|
||||
this._createFrame();
|
||||
let iframe = this.iframe;
|
||||
|
||||
// graphData is an optional param that either defines the full set of data
|
||||
// to be shared, or partial data about the current page. It is set by a call
|
||||
// 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 pageData = graphData ? graphData : this.currentShare;
|
||||
let sharedURI = pageData ? Services.io.newURI(pageData.url, null, null) :
|
||||
gBrowser.currentURI;
|
||||
if (!SocialUI.canSharePage(sharedURI))
|
||||
return;
|
||||
|
||||
let browserMM = gBrowser.selectedBrowser.messageManager;
|
||||
|
||||
// the point of this action type is that we can use existing share
|
||||
// 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 _dataFn;
|
||||
if (!pageData || sharedURI == gBrowser.currentURI) {
|
||||
browserMM.addMessageListener("PageMetadata:PageDataResult", _dataFn = (msg) => {
|
||||
browserMM.removeMessageListener("PageMetadata:PageDataResult", _dataFn);
|
||||
let pageData = msg.json;
|
||||
if (graphData) {
|
||||
// overwrite data retreived from page with data given to us as a param
|
||||
for (let p in graphData) {
|
||||
pageData[p] = graphData[p];
|
||||
}
|
||||
}
|
||||
this.sharePage(providerOrigin, pageData, target, anchor);
|
||||
});
|
||||
browserMM.sendAsyncMessage("PageMetadata:GetPageData", null, { target });
|
||||
return;
|
||||
}
|
||||
// if this is a share of a selected item, get any microformats
|
||||
if (!pageData.microformats && target) {
|
||||
browserMM.addMessageListener("PageMetadata:MicroformatsResult", _dataFn = (msg) => {
|
||||
browserMM.removeMessageListener("PageMetadata:MicroformatsResult", _dataFn);
|
||||
pageData.microformats = msg.data;
|
||||
this.sharePage(providerOrigin, pageData, target, anchor);
|
||||
});
|
||||
browserMM.sendAsyncMessage("PageMetadata:GetMicroformats", null, { target });
|
||||
return;
|
||||
}
|
||||
this.currentShare = pageData;
|
||||
|
||||
let provider;
|
||||
if (providerOrigin)
|
||||
provider = Social._getProviderFromOrigin(providerOrigin);
|
||||
else
|
||||
provider = this.getSelectedProvider();
|
||||
if (!provider || !provider.shareURL) {
|
||||
this.showDirectory(anchor);
|
||||
return;
|
||||
}
|
||||
// check the menu button
|
||||
let hbox = document.getElementById("social-share-provider-buttons");
|
||||
let btn = hbox.querySelector("[origin='" + provider.origin + "']");
|
||||
if (btn)
|
||||
btn.checked = true;
|
||||
|
||||
let shareEndpoint = OpenGraphBuilder.generateEndpointURL(provider.shareURL, pageData);
|
||||
|
||||
this._dynamicResizer.stop();
|
||||
let size = provider.getPageSize("share");
|
||||
if (size) {
|
||||
// let the css on the share panel define width, but height
|
||||
// calculations dont work on all sites, so we allow that to be
|
||||
// defined.
|
||||
delete size.width;
|
||||
}
|
||||
|
||||
// if we've already loaded this provider/page share endpoint, we don't want
|
||||
// to add another load event listener.
|
||||
let endpointMatch = shareEndpoint == iframe.getAttribute("src");
|
||||
if (endpointMatch) {
|
||||
this._dynamicResizer.start(iframe.parentNode, iframe, size);
|
||||
iframe.docShellIsActive = true;
|
||||
SocialShare.messageManager.sendAsyncMessage("Social:OpenGraphData", this.currentShare);
|
||||
} else {
|
||||
iframe.parentNode.setAttribute("loading", "true");
|
||||
}
|
||||
// if the user switched between share providers we do not want that history
|
||||
// available.
|
||||
iframe.purgeSessionHistory();
|
||||
|
||||
// always ensure that origin belongs to the endpoint
|
||||
let uri = Services.io.newURI(shareEndpoint, null, null);
|
||||
iframe.setAttribute("origin", provider.origin);
|
||||
iframe.setAttribute("src", shareEndpoint);
|
||||
this._openPanel(anchor);
|
||||
},
|
||||
|
||||
showDirectory: function(anchor) {
|
||||
this._createFrame();
|
||||
let iframe = this.iframe;
|
||||
if (iframe.getAttribute("src") == "about:providerdirectory")
|
||||
return;
|
||||
iframe.removeAttribute("origin");
|
||||
iframe.parentNode.setAttribute("loading", "true");
|
||||
|
||||
iframe.setAttribute("src", "about:providerdirectory");
|
||||
this._openPanel(anchor);
|
||||
},
|
||||
|
||||
_openPanel: function(anchor) {
|
||||
this._currentAnchor = anchor || this.anchor;
|
||||
anchor = document.getAnonymousElementByAttribute(this._currentAnchor, "class", "toolbarbutton-icon");
|
||||
this.panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, false);
|
||||
Services.telemetry.getHistogramById("SOCIAL_TOOLBAR_BUTTONS").add(0);
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
|
|
@ -933,6 +933,11 @@ html|*#gcli-output-frame,
|
|||
transition: none;
|
||||
}
|
||||
|
||||
panelview > .social-panel-frame {
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Translation */
|
||||
notification[value="translation"] {
|
||||
-moz-binding: url("chrome://browser/content/translation-infobar.xml#translationbar");
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ Cu.import("resource://gre/modules/NotificationDB.jsm");
|
|||
["ShortcutUtils", "resource://gre/modules/ShortcutUtils.jsm"],
|
||||
["SimpleServiceDiscovery", "resource://gre/modules/SimpleServiceDiscovery.jsm"],
|
||||
["SitePermissions", "resource:///modules/SitePermissions.jsm"],
|
||||
["Social", "resource:///modules/Social.jsm"],
|
||||
["TabCrashHandler", "resource:///modules/ContentCrashHandlers.jsm"],
|
||||
["Task", "resource://gre/modules/Task.jsm"],
|
||||
["TelemetryStopwatch", "resource://gre/modules/TelemetryStopwatch.jsm"],
|
||||
|
|
@ -1409,6 +1410,8 @@ var gBrowserInit = {
|
|||
// Enable the Restore Last Session command if needed
|
||||
RestoreLastSessionObserver.init();
|
||||
|
||||
SocialUI.init();
|
||||
|
||||
// Start monitoring slow add-ons
|
||||
AddonWatcher.init();
|
||||
|
||||
|
|
@ -1539,6 +1542,7 @@ var gBrowserInit = {
|
|||
|
||||
gPrefService.removeObserver(ctrlTab.prefName, ctrlTab);
|
||||
ctrlTab.uninit();
|
||||
SocialUI.uninit();
|
||||
gBrowserThumbnails.uninit();
|
||||
FullZoom.destroy();
|
||||
|
||||
|
|
@ -4300,7 +4304,9 @@ var XULBrowserWindow = {
|
|||
|
||||
// Called before links are navigated to to allow us to retarget them if needed.
|
||||
onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
|
||||
return BrowserUtils.onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab);
|
||||
let target = BrowserUtils.onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab);
|
||||
SocialUI.closeSocialPanelForLinkTraversal(target, linkNode);
|
||||
return target;
|
||||
},
|
||||
|
||||
// Check whether this URI should load in the current process
|
||||
|
|
@ -4481,6 +4487,8 @@ var XULBrowserWindow = {
|
|||
|
||||
gIdentityHandler.onLocationChange();
|
||||
|
||||
SocialUI.updateState();
|
||||
|
||||
UITour.onLocationChange(location);
|
||||
|
||||
gTabletModePageCounter.inc();
|
||||
|
|
|
|||
|
|
@ -268,6 +268,27 @@
|
|||
<box id="UITourHighlight"></box>
|
||||
</panel>
|
||||
|
||||
<panel id="social-share-panel"
|
||||
class="social-panel"
|
||||
type="arrow"
|
||||
orient="vertical"
|
||||
onpopupshowing="SocialShare.onShowing()"
|
||||
onpopuphidden="SocialShare.onHidden()"
|
||||
hidden="true">
|
||||
<hbox class="social-share-toolbar">
|
||||
<toolbarbutton id="manage-share-providers" class="share-provider-button"
|
||||
tooltiptext="&social.addons.label;"
|
||||
oncommand="BrowserOpenAddonsMgr('addons://list/service');
|
||||
this.parentNode.parentNode.hidePopup();"/>
|
||||
<arrowscrollbox id="social-share-provider-buttons" orient="horizontal" flex="1" pack="end">
|
||||
<toolbarbutton id="add-share-provider" class="share-provider-button" type="radio"
|
||||
group="share-providers" tooltiptext="&findShareServices.label;"
|
||||
oncommand="SocialShare.showDirectory()"/>
|
||||
</arrowscrollbox>
|
||||
</hbox>
|
||||
<hbox id="share-container" flex="1"/>
|
||||
</panel>
|
||||
|
||||
<menupopup id="toolbar-context-menu"
|
||||
onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('viewToolbarsMenuSeparator'));">
|
||||
<menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
|
||||
|
|
@ -405,6 +426,11 @@
|
|||
#endif
|
||||
</tooltip>
|
||||
|
||||
<tooltip id="share-button-tooltip" onpopupshowing="SocialShare.createTooltip(event);">
|
||||
<label class="tooltip-label"/>
|
||||
<label class="tooltip-label"/>
|
||||
</tooltip>
|
||||
|
||||
#include popup-notifications.inc
|
||||
|
||||
#include ../../components/customizableui/content/panelUI.inc.xul
|
||||
|
|
|
|||
|
|
@ -698,6 +698,37 @@ var PageMetadataMessenger = {
|
|||
}
|
||||
PageMetadataMessenger.init();
|
||||
|
||||
addEventListener("ActivateSocialFeature", function (aEvent) {
|
||||
let document = content.document;
|
||||
let dwu = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
if (!dwu.isHandlingUserInput) {
|
||||
Cu.reportError("attempt to activate provider without user input from " + document.nodePrincipal.origin);
|
||||
return;
|
||||
}
|
||||
|
||||
let node = aEvent.target;
|
||||
let ownerDocument = node.ownerDocument;
|
||||
let data = node.getAttribute("data-service");
|
||||
if (data) {
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
} catch (e) {
|
||||
Cu.reportError("Social Service manifest parse error: " + e);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Cu.reportError("Social Service manifest not available");
|
||||
return;
|
||||
}
|
||||
|
||||
sendAsyncMessage("Social:Activation", {
|
||||
url: ownerDocument.location.href,
|
||||
origin: ownerDocument.nodePrincipal.origin,
|
||||
manifest: data
|
||||
});
|
||||
}, true, true);
|
||||
|
||||
addMessageListener("ContextMenu:SaveVideoFrameAsImage", (message) => {
|
||||
let video = message.objects.target;
|
||||
let canvas = content.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
|
|
|
|||
|
|
@ -174,15 +174,15 @@ nsContextMenu.prototype = {
|
|||
initNavigationItems: function CM_initNavigationItems() {
|
||||
var shouldShow = !(this.isContentSelected || this.onLink || this.onImage ||
|
||||
this.onCanvas || this.onVideo || this.onAudio ||
|
||||
this.onTextInput);
|
||||
this.onTextInput || this.onSocial);
|
||||
this.showItem("context-navigation", shouldShow);
|
||||
this.showItem("context-sep-navigation", shouldShow);
|
||||
|
||||
let stopped = XULBrowserWindow.stopCommand.getAttribute("disabled") == "true";
|
||||
|
||||
let stopReloadItem = "";
|
||||
if (shouldShow) {
|
||||
stopReloadItem = (stopped) ? "reload" : "stop";
|
||||
if (shouldShow || this.onSocial) {
|
||||
stopReloadItem = (stopped || this.onSocial) ? "reload" : "stop";
|
||||
}
|
||||
|
||||
this.showItem("context-reload", stopReloadItem == "reload");
|
||||
|
|
@ -249,7 +249,7 @@ nsContextMenu.prototype = {
|
|||
this.onImage || this.onCanvas ||
|
||||
this.onVideo || this.onAudio ||
|
||||
this.onLink || this.onTextInput);
|
||||
var showInspect = gPrefService.getBoolPref("devtools.inspector.enabled");
|
||||
var showInspect = !this.onSocial && gPrefService.getBoolPref("devtools.inspector.enabled");
|
||||
this.showItem("context-viewsource", shouldShow);
|
||||
this.showItem("context-viewinfo", shouldShow);
|
||||
this.showItem("inspect-separator", showInspect);
|
||||
|
|
@ -306,11 +306,12 @@ nsContextMenu.prototype = {
|
|||
let bookmarkPage = document.getElementById("context-bookmarkpage");
|
||||
this.showItem(bookmarkPage,
|
||||
!(this.isContentSelected || this.onTextInput || this.onLink ||
|
||||
this.onImage || this.onVideo || this.onAudio || this.onCanvas));
|
||||
this.onImage || this.onVideo || this.onAudio || this.onSocial ||
|
||||
this.onCanvas));
|
||||
bookmarkPage.setAttribute("tooltiptext", bookmarkPage.getAttribute("buttontooltiptext"));
|
||||
|
||||
this.showItem("context-bookmarklink", (this.onLink && !this.onMailtoLink) ||
|
||||
this.onPlainTextLink);
|
||||
this.showItem("context-bookmarklink", (this.onLink && !this.onMailtoLink &&
|
||||
!this.onSocial) || this.onPlainTextLink);
|
||||
this.showItem("context-keywordfield",
|
||||
this.onTextInput && this.onKeywordField);
|
||||
this.showItem("frame", this.inFrame);
|
||||
|
|
@ -348,6 +349,19 @@ nsContextMenu.prototype = {
|
|||
this.onTextInput && !this.onNumeric && top.gBidiUI);
|
||||
this.showItem("context-bidi-page-direction-toggle",
|
||||
!this.onTextInput && top.gBidiUI);
|
||||
|
||||
// SocialShare
|
||||
let shareButton = SocialShare.shareButton;
|
||||
let shareEnabled = shareButton && !shareButton.disabled && !this.onSocial;
|
||||
let pageShare = shareEnabled && !(this.isContentSelected ||
|
||||
this.onTextInput || this.onLink || this.onImage ||
|
||||
this.onVideo || this.onAudio || this.onCanvas);
|
||||
this.showItem("context-sharepage", pageShare);
|
||||
this.showItem("context-shareselect", shareEnabled && this.isContentSelected);
|
||||
this.showItem("context-sharelink", shareEnabled && (this.onLink || this.onPlainTextLink) && !this.onMailtoLink);
|
||||
this.showItem("context-shareimage", shareEnabled && this.onImage);
|
||||
this.showItem("context-sharevideo", shareEnabled && this.onVideo);
|
||||
this.setItemAttr("context-sharevideo", "disabled", !this.mediaURL || this.mediaURL.startsWith("blob:"));
|
||||
},
|
||||
|
||||
initSpellingItems: function() {
|
||||
|
|
@ -667,6 +681,7 @@ nsContextMenu.prototype = {
|
|||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.outerWindowID;
|
||||
}
|
||||
this.onSocial = !!this.browser.getAttribute("origin");
|
||||
|
||||
// Check if we are in a synthetic document (stand alone image, video, etc.).
|
||||
this.inSyntheticDoc = ownerDoc.mozSyntheticDocument;
|
||||
|
|
@ -1711,6 +1726,22 @@ nsContextMenu.prototype = {
|
|||
mm.sendAsyncMessage("ContextMenu:BookmarkFrame", null, { target: this.target });
|
||||
},
|
||||
|
||||
shareLink: function CM_shareLink() {
|
||||
SocialShare.sharePage(null, { url: this.linkURI.spec }, this.target);
|
||||
},
|
||||
|
||||
shareImage: function CM_shareImage() {
|
||||
SocialShare.sharePage(null, { url: this.imageURL, previews: [ this.mediaURL ] }, this.target);
|
||||
},
|
||||
|
||||
shareVideo: function CM_shareVideo() {
|
||||
SocialShare.sharePage(null, { url: this.mediaURL, source: this.mediaURL }, this.target);
|
||||
},
|
||||
|
||||
shareSelect: function CM_shareSelect() {
|
||||
SocialShare.sharePage(null, { url: this.browser.currentURI.spec, text: this.textSelected }, this.target);
|
||||
},
|
||||
|
||||
savePageAs: function CM_savePageAs() {
|
||||
saveBrowser(this.browser);
|
||||
},
|
||||
|
|
@ -1825,7 +1856,7 @@ nsContextMenu.prototype = {
|
|||
_getTelemetryPageContextInfo: function() {
|
||||
let rv = [];
|
||||
for (let k of ["isContentSelected", "onLink", "onImage", "onCanvas", "onVideo", "onAudio",
|
||||
"onTextInput"]) {
|
||||
"onTextInput", "onSocial"]) {
|
||||
if (this[k]) {
|
||||
rv.push(k.replace(/^(?:is|on)(.)/, (match, firstLetter) => firstLetter.toLowerCase()));
|
||||
}
|
||||
|
|
|
|||
172
browser/base/content/social-content.js
Normal file
172
browser/base/content/social-content.js
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* 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 content script is intended for use by iframes in the share panel. */
|
||||
|
||||
var {interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// social frames are always treated as app tabs
|
||||
docShell.isAppTab = true;
|
||||
|
||||
addEventListener("DOMContentLoaded", function(event) {
|
||||
if (event.target != content.document)
|
||||
return;
|
||||
// Some share panels (e.g. twitter and facebook) check content.opener, and if
|
||||
// it doesn't exist they act like they are in a browser tab. We want them to
|
||||
// act like they are in a dialog (which is the typical case).
|
||||
if (content && !content.opener) {
|
||||
content.opener = content;
|
||||
}
|
||||
hookWindowClose();
|
||||
disableDialogs();
|
||||
});
|
||||
|
||||
addMessageListener("Social:OpenGraphData", (message) => {
|
||||
let ev = new content.CustomEvent("OpenGraphData", { detail: JSON.stringify(message.data) });
|
||||
content.dispatchEvent(ev);
|
||||
});
|
||||
|
||||
addMessageListener("Social:ClearFrame", () => {
|
||||
docShell.createAboutBlankContentViewer(null);
|
||||
});
|
||||
|
||||
addEventListener("DOMWindowClose", (evt) => {
|
||||
// preventDefault stops the default window.close() function being called,
|
||||
// which doesn't actually close anything but causes things to get into
|
||||
// a bad state (an internal 'closed' flag is set and debug builds start
|
||||
// asserting as the window is used.).
|
||||
// None of the windows we inject this API into are suitable for this
|
||||
// default close behaviour, so even if we took no action above, we avoid
|
||||
// the default close from doing anything.
|
||||
evt.preventDefault();
|
||||
|
||||
// Tells the SocialShare class to close the panel
|
||||
sendAsyncMessage("Social:DOMWindowClose");
|
||||
});
|
||||
|
||||
function hookWindowClose() {
|
||||
// Allow scripts to close the "window". Because we are in a panel and not
|
||||
// in a full dialog, the DOMWindowClose listener above will only receive the
|
||||
// event if we do this.
|
||||
let dwu = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
dwu.allowScriptsToClose();
|
||||
}
|
||||
|
||||
function disableDialogs() {
|
||||
let windowUtils = content.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils);
|
||||
windowUtils.disableDialogs();
|
||||
}
|
||||
|
||||
// Error handling class used to listen for network errors in the social frames
|
||||
// and replace them with a social-specific error page
|
||||
const SocialErrorListener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener,
|
||||
Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference,
|
||||
Ci.nsISupports]),
|
||||
|
||||
defaultTemplate: "about:socialerror?mode=tryAgainOnly&url=%{url}&origin=%{origin}",
|
||||
urlTemplate: null,
|
||||
|
||||
init() {
|
||||
addMessageListener("Social:SetErrorURL", this);
|
||||
let webProgress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebProgress);
|
||||
webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_REQUEST |
|
||||
Ci.nsIWebProgress.NOTIFY_LOCATION);
|
||||
},
|
||||
|
||||
receiveMessage(message) {
|
||||
switch (message.name) {
|
||||
case "Social:SetErrorURL":
|
||||
// Either a url or null to reset to default template.
|
||||
this.urlTemplate = message.data.template;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
setErrorPage() {
|
||||
// if this is about:providerdirectory, use the directory iframe
|
||||
let frame = docShell.chromeEventHandler;
|
||||
let origin = frame.getAttribute("origin");
|
||||
let src = frame.getAttribute("src");
|
||||
if (src == "about:providerdirectory") {
|
||||
frame = content.document.getElementById("activation-frame");
|
||||
src = frame.getAttribute("src");
|
||||
}
|
||||
|
||||
let url = this.urlTemplate || this.defaultTemplate;
|
||||
url = url.replace("%{url}", encodeURIComponent(src));
|
||||
url = url.replace("%{origin}", encodeURIComponent(origin));
|
||||
if (frame != docShell.chromeEventHandler) {
|
||||
// Unable to access frame.docShell here. This is our own frame and doesn't
|
||||
// provide reload, so we'll just set the src.
|
||||
frame.setAttribute("src", url);
|
||||
} else {
|
||||
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
webNav.loadURI(url, null, null, null, null);
|
||||
}
|
||||
sendAsyncMessage("Social:ErrorPageNotify", {
|
||||
origin: origin,
|
||||
url: src
|
||||
});
|
||||
},
|
||||
|
||||
onStateChange(aWebProgress, aRequest, aState, aStatus) {
|
||||
let failure = false;
|
||||
if ((aState & Ci.nsIWebProgressListener.STATE_IS_REQUEST))
|
||||
return;
|
||||
if ((aState & Ci.nsIWebProgressListener.STATE_STOP)) {
|
||||
if (aRequest instanceof Ci.nsIHttpChannel) {
|
||||
try {
|
||||
// Change the frame to an error page on 4xx (client errors)
|
||||
// and 5xx (server errors). responseStatus throws if it is not set.
|
||||
failure = aRequest.responseStatus >= 400 &&
|
||||
aRequest.responseStatus < 600;
|
||||
} catch (e) {
|
||||
failure = aStatus != Components.results.NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calling cancel() will raise some OnStateChange notifications by itself,
|
||||
// so avoid doing that more than once
|
||||
if (failure && aStatus != Components.results.NS_BINDING_ABORTED) {
|
||||
// if tp is enabled and we get a failure, ignore failures (ie. STATE_STOP)
|
||||
// on child resources since they *may* have been blocked. We don't have an
|
||||
// easy way to know if a particular url is blocked by TP, only that
|
||||
// something was.
|
||||
if (docShell.hasTrackingContentBlocked) {
|
||||
let frame = docShell.chromeEventHandler;
|
||||
let src = frame.getAttribute("src");
|
||||
if (aRequest && aRequest.name != src) {
|
||||
Cu.reportError("SocialErrorListener ignoring blocked content error for " + aRequest.name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
aRequest.cancel(Components.results.NS_BINDING_ABORTED);
|
||||
this.setErrorPage();
|
||||
}
|
||||
},
|
||||
|
||||
onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {
|
||||
if (aRequest && aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) {
|
||||
aRequest.cancel(Components.results.NS_BINDING_ABORTED);
|
||||
this.setErrorPage();
|
||||
}
|
||||
},
|
||||
|
||||
onProgressChange() {},
|
||||
onStatusChange() {},
|
||||
onSecurityChange() {},
|
||||
};
|
||||
|
||||
SocialErrorListener.init();
|
||||
|
|
@ -64,6 +64,8 @@ browser.jar:
|
|||
|
||||
content/browser/aboutRobots-icon.png (content/aboutRobots-icon.png)
|
||||
content/browser/aboutRobots-widget-left.png (content/aboutRobots-widget-left.png)
|
||||
content/browser/aboutSocialError.xhtml (content/aboutSocialError.xhtml)
|
||||
content/browser/aboutProviderDirectory.xhtml (content/aboutProviderDirectory.xhtml)
|
||||
content/browser/aboutTabCrashed.css (content/aboutTabCrashed.css)
|
||||
content/browser/aboutTabCrashed.js (content/aboutTabCrashed.js)
|
||||
content/browser/aboutTabCrashed.xhtml (content/aboutTabCrashed.xhtml)
|
||||
|
|
@ -89,6 +91,7 @@ browser.jar:
|
|||
content/browser/browser-safebrowsing.js (content/browser-safebrowsing.js)
|
||||
#endif
|
||||
content/browser/browser-sidebar.js (content/browser-sidebar.js)
|
||||
content/browser/browser-social.js (content/browser-social.js)
|
||||
* content/browser/browser-syncui.js (content/browser-syncui.js)
|
||||
* content/browser/browser-tabPreviews.xml (content/browser-tabPreviews.xml)
|
||||
#ifdef CAN_DRAW_IN_TITLEBAR
|
||||
|
|
@ -100,6 +103,7 @@ browser.jar:
|
|||
content/browser/browser-trackingprotection.js (content/browser-trackingprotection.js)
|
||||
* content/browser/tab-content.js (content/tab-content.js)
|
||||
content/browser/content.js (content/content.js)
|
||||
content/browser/social-content.js (content/social-content.js)
|
||||
content/browser/defaultthemes/1.footer.jpg (content/defaultthemes/1.footer.jpg)
|
||||
content/browser/defaultthemes/1.header.jpg (content/defaultthemes/1.header.jpg)
|
||||
content/browser/defaultthemes/1.icon.jpg (content/defaultthemes/1.icon.jpg)
|
||||
|
|
|
|||
|
|
@ -56,6 +56,16 @@ static RedirEntry kRedirMap[] = {
|
|||
nsIAboutModule::ALLOW_SCRIPT |
|
||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT
|
||||
},
|
||||
{
|
||||
"socialerror", "chrome://browser/content/aboutSocialError.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT |
|
||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT
|
||||
},
|
||||
{
|
||||
"providerdirectory", "chrome://browser/content/aboutProviderDirectory.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT |
|
||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT
|
||||
},
|
||||
{
|
||||
"tabcrashed", "chrome://browser/content/aboutTabCrashed.xhtml",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
|
|||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "blocked", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
#endif
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "certerror", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "socialerror", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "providerdirectory", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "tabcrashed", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "feeds", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "privatebrowsing", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
|
|
|
|||
|
|
@ -556,6 +556,47 @@ const CustomizableWidgets = [
|
|||
clearSubview(sidebarItems);
|
||||
fillSubviewFromMenuItems([...menu.children], sidebarItems);
|
||||
}
|
||||
}, {
|
||||
id: "social-share-button",
|
||||
// custom build our button so we can attach to the share command
|
||||
type: "custom",
|
||||
onBuild: function(aDocument) {
|
||||
let node = aDocument.createElementNS(kNSXUL, "toolbarbutton");
|
||||
node.setAttribute("id", this.id);
|
||||
node.classList.add("toolbarbutton-1");
|
||||
node.classList.add("chromeclass-toolbar-additional");
|
||||
node.setAttribute("label", CustomizableUI.getLocalizedProperty(this, "label"));
|
||||
node.setAttribute("tooltiptext", CustomizableUI.getLocalizedProperty(this, "tooltiptext"));
|
||||
node.setAttribute("removable", "true");
|
||||
node.setAttribute("observes", "Social:PageShareable");
|
||||
node.setAttribute("command", "Social:SharePage");
|
||||
|
||||
let listener = {
|
||||
onWidgetAdded: (aWidgetId) => {
|
||||
if (aWidgetId != this.id)
|
||||
return;
|
||||
|
||||
Services.obs.notifyObservers(null, "social:" + this.id + "-added", null);
|
||||
},
|
||||
|
||||
onWidgetRemoved: aWidgetId => {
|
||||
if (aWidgetId != this.id)
|
||||
return;
|
||||
|
||||
Services.obs.notifyObservers(null, "social:" + this.id + "-removed", null);
|
||||
},
|
||||
|
||||
onWidgetInstanceRemoved: (aWidgetId, aDoc) => {
|
||||
if (aWidgetId != this.id || aDoc != aDocument)
|
||||
return;
|
||||
|
||||
CustomizableUI.removeListener(listener);
|
||||
}
|
||||
};
|
||||
CustomizableUI.addListener(listener);
|
||||
|
||||
return node;
|
||||
}
|
||||
}, {
|
||||
id: "add-ons-button",
|
||||
shortcutId: "key_openAddons",
|
||||
|
|
|
|||
|
|
@ -240,6 +240,8 @@
|
|||
onclick="PanelUI.hide();"/>
|
||||
</panelview>
|
||||
|
||||
<panelview id="PanelUI-socialapi" flex="1"/>
|
||||
|
||||
<panelview id="PanelUI-feeds" flex="1" oncommand="FeedHandler.subscribeToFeed(null, event);">
|
||||
<label value="&feedsMenu2.label;" class="panel-subview-header"/>
|
||||
</panelview>
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ divide the following different context menu situations:
|
|||
- ``canvas`` if the user opened the context menu on a canvas (that isn't a link);
|
||||
- ``media`` if the user opened the context menu on an HTML video or audio element;
|
||||
- ``input`` if the user opened the context menu on a text input element;
|
||||
- ``social`` if the user opened the context menu inside a social frame;
|
||||
- ``other`` for all other openings of the content menu;
|
||||
|
||||
Each of these objects (if they exist) then gets a "withcustom" and/or a "withoutcustom" property
|
||||
|
|
|
|||
|
|
@ -163,7 +163,22 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
|||
<!ENTITY bookmarkThisPageCmd.label "Bookmark This Page">
|
||||
<!ENTITY editThisBookmarkCmd.label "Edit This Bookmark">
|
||||
<!ENTITY bookmarkThisPageCmd.commandkey "d">
|
||||
|
||||
<!-- LOCALIZATION NOTE (findShareServices.label):
|
||||
- Use the unicode ellipsis char, \u2026,
|
||||
- or use "..." if \u2026 doesn't suit traditions in your locale. -->
|
||||
<!ENTITY findShareServices.label "Find more Share services…">
|
||||
<!ENTITY sharePageCmd.label "Share This Page">
|
||||
<!ENTITY sharePageCmd.commandkey "S">
|
||||
<!ENTITY sharePageCmd.accesskey "s">
|
||||
<!-- LOCALIZATION NOTE (shareLink.accesskey): must be different than the following share access keys -->
|
||||
<!ENTITY shareLink.label "Share This Link">
|
||||
<!ENTITY shareLink.accesskey "h">
|
||||
<!ENTITY shareImage.label "Share This Image">
|
||||
<!ENTITY shareImage.accesskey "r">
|
||||
<!ENTITY shareSelect.label "Share Selection">
|
||||
<!ENTITY shareSelect.accesskey "r">
|
||||
<!ENTITY shareVideo.label "Share This Video">
|
||||
<!ENTITY shareVideo.accesskey "r">
|
||||
<!ENTITY feedsMenu2.label "Subscribe to This Page">
|
||||
<!ENTITY subscribeToPageMenupopup.label "Subscribe to This Page">
|
||||
<!ENTITY subscribeToPageMenuitem.label "Subscribe to This Page…">
|
||||
|
|
@ -765,6 +780,14 @@ you can use these alternative items. Otherwise, their values should be empty. -
|
|||
<!ENTITY syncReAuthItem.accesskey "R">
|
||||
<!ENTITY syncToolbarButton.label "Sync">
|
||||
|
||||
<!ENTITY social.addons.label "Manage Services…">
|
||||
|
||||
<!ENTITY social.directory.label "Activations Directory">
|
||||
<!ENTITY social.directory.text "You can activate Share services from the directory.">
|
||||
<!ENTITY social.directory.button "Take me there!">
|
||||
<!ENTITY social.directory.introText "Click on a service to add it to &brandShortName;.">
|
||||
<!ENTITY social.directory.viewmore.text "View More">
|
||||
|
||||
<!ENTITY customizeMode.menuAndToolbars.header2 "Additional Tools and Features">
|
||||
<!ENTITY customizeMode.menuAndToolbars.empty "Want more tools?">
|
||||
<!ENTITY customizeMode.menuAndToolbars.emptyLink "Choose from thousands of add-ons">
|
||||
|
|
|
|||
|
|
@ -453,6 +453,29 @@ processHang.button_debug.accessKey = D
|
|||
# LOCALIZATION NOTE (fullscreenButton.tooltip): %S is the keyboard shortcut for full screen
|
||||
fullscreenButton.tooltip=Display the window in full screen (%S)
|
||||
|
||||
service.toolbarbutton.label=Services
|
||||
service.toolbarbutton.tooltiptext=Services
|
||||
|
||||
# LOCALIZATION NOTE (social.install.description): %1$S is the hostname of the social provider, %2$S is brandShortName (e.g. Firefox)
|
||||
service.install.description=Would you like to enable services from %1$S to display in your %2$S toolbar and sidebar?
|
||||
service.install.ok.label=Enable Services
|
||||
service.install.ok.accesskey=E
|
||||
|
||||
# LOCALIZATION NOTE (social.markpageMenu.label): %S is the name of the social provider
|
||||
social.markpageMenu.label=Save Page to %S
|
||||
# LOCALIZATION NOTE (social.marklinkMenu.label): %S is the name of the social provider
|
||||
social.marklinkMenu.label=Save Link to %S
|
||||
|
||||
# LOCALIZATION NOTE (social.error.message): %1$S is brandShortName (e.g. Firefox), %2$S is the name of the social provider
|
||||
social.error.message=%1$S is unable to connect with %2$S right now.
|
||||
social.error.tryAgain.label=Try Again
|
||||
social.error.tryAgain.accesskey=T
|
||||
social.error.closeSidebar.label=Close This Sidebar
|
||||
social.error.closeSidebar.accesskey=C
|
||||
|
||||
# LOCALIZATION NOTE: %1$S is the label for the toolbar button, %2$S is the associated badge numbering that the social provider may provide.
|
||||
social.aria.toolbarButtonBadgeText=%1$S (%2$S)
|
||||
|
||||
# LOCALIZATION NOTE (getUserMedia.shareCamera.message, getUserMedia.shareMicrophone.message,
|
||||
# getUserMedia.shareScreen.message, getUserMedia.shareCameraAndMicrophone.message,
|
||||
# getUserMedia.shareScreenAndMicrophone.message, getUserMedia.shareCameraAndAudioCapture.message,
|
||||
|
|
|
|||
|
|
@ -95,6 +95,9 @@ quit-button.tooltiptext.linux2 = Quit %1$S (%2$S)
|
|||
# %2$S is the keyboard shortcut
|
||||
quit-button.tooltiptext.mac = Quit %1$S (%2$S)
|
||||
|
||||
social-share-button.label = Share This Page
|
||||
social-share-button.tooltiptext = Share this page
|
||||
|
||||
panic-button.label = Forget
|
||||
panic-button.tooltiptext = Forget about some browsing history
|
||||
|
||||
|
|
|
|||
|
|
@ -694,7 +694,7 @@ this.BrowserUITelemetry = {
|
|||
"spell-undo-add-to-dictionary", "openlinkincurrent", "openlinkintab",
|
||||
"openlink",
|
||||
// "openlinkprivate" intentionally omitted for privacy reasons. See bug 1176391.
|
||||
"bookmarklink", "savelink",
|
||||
"bookmarklink", "sharelink", "savelink",
|
||||
"marklinkMenu", "copyemail", "copylink", "media-play", "media-pause",
|
||||
"media-mute", "media-unmute", "media-playbackrate",
|
||||
"media-playbackrate-050x", "media-playbackrate-100x",
|
||||
|
|
@ -702,12 +702,12 @@ this.BrowserUITelemetry = {
|
|||
"media-showcontrols", "media-hidecontrols",
|
||||
"video-fullscreen", "leave-dom-fullscreen",
|
||||
"reloadimage", "viewimage", "viewvideo", "copyimage-contents", "copyimage",
|
||||
"copyvideourl", "copyaudiourl", "saveimage", "sendimage",
|
||||
"copyvideourl", "copyaudiourl", "saveimage", "shareimage", "sendimage",
|
||||
"setDesktopBackground", "viewimageinfo", "viewimagedesc", "savevideo",
|
||||
"saveaudio", "video-saveimage", "sendvideo", "sendaudio",
|
||||
"ctp-play", "ctp-hide", "savepage", "pocket", "markpageMenu",
|
||||
"sharevideo", "saveaudio", "video-saveimage", "sendvideo", "sendaudio",
|
||||
"ctp-play", "ctp-hide", "sharepage", "savepage", "pocket", "markpageMenu",
|
||||
"viewbgimage", "undo", "cut", "copy", "paste", "delete", "selectall",
|
||||
"keywordfield", "searchselect", "frame", "showonlythisframe",
|
||||
"keywordfield", "searchselect", "shareselect", "frame", "showonlythisframe",
|
||||
"openframeintab", "openframe", "reloadframe", "bookmarkframe", "saveframe",
|
||||
"printframe", "viewframesource", "viewframeinfo",
|
||||
"viewpartialsource-selection", "viewpartialsource-mathml",
|
||||
|
|
|
|||
272
browser/modules/Social.jsm
Normal file
272
browser/modules/Social.jsm
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Social", "OpenGraphBuilder",
|
||||
"DynamicResizeWatcher", "sizeSocialPanelToContent"];
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
const Cu = Components.utils;
|
||||
|
||||
// The minimum sizes for the auto-resize panel code, minimum size necessary to
|
||||
// properly show the error page in the panel.
|
||||
const PANEL_MIN_HEIGHT = 190;
|
||||
const PANEL_MIN_WIDTH = 330;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
|
||||
"resource:///modules/CustomizableUI.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SocialService",
|
||||
"resource:///modules/SocialService.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PageMetadata",
|
||||
"resource://gre/modules/PageMetadata.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/Promise.jsm");
|
||||
|
||||
|
||||
this.Social = {
|
||||
initialized: false,
|
||||
lastEventReceived: 0,
|
||||
providers: [],
|
||||
_disabledForSafeMode: false,
|
||||
|
||||
init: function Social_init() {
|
||||
this._disabledForSafeMode = Services.appinfo.inSafeMode && this.enabled;
|
||||
let deferred = Promise.defer();
|
||||
|
||||
if (this.initialized) {
|
||||
deferred.resolve(true);
|
||||
return deferred.promise;
|
||||
}
|
||||
this.initialized = true;
|
||||
// if SocialService.hasEnabledProviders, retreive the providers so the
|
||||
// front-end can generate UI
|
||||
if (SocialService.hasEnabledProviders) {
|
||||
// Retrieve the current set of providers, and set the current provider.
|
||||
SocialService.getOrderedProviderList(function (providers) {
|
||||
Social._updateProviderCache(providers);
|
||||
Social._updateEnabledState(SocialService.enabled);
|
||||
deferred.resolve(false);
|
||||
});
|
||||
} else {
|
||||
deferred.resolve(false);
|
||||
}
|
||||
|
||||
// Register an observer for changes to the provider list
|
||||
SocialService.registerProviderListener(function providerListener(topic, origin, providers) {
|
||||
// An engine change caused by adding/removing a provider should notify.
|
||||
// any providers we receive are enabled in the AddonsManager
|
||||
if (topic == "provider-installed" || topic == "provider-uninstalled") {
|
||||
// installed/uninstalled do not send the providers param
|
||||
Services.obs.notifyObservers(null, "social:" + topic, origin);
|
||||
return;
|
||||
}
|
||||
if (topic == "provider-enabled") {
|
||||
Social._updateProviderCache(providers);
|
||||
Social._updateEnabledState(true);
|
||||
Services.obs.notifyObservers(null, "social:" + topic, origin);
|
||||
return;
|
||||
}
|
||||
if (topic == "provider-disabled") {
|
||||
// a provider was removed from the list of providers, update states
|
||||
Social._updateProviderCache(providers);
|
||||
Social._updateEnabledState(providers.length > 0);
|
||||
Services.obs.notifyObservers(null, "social:" + topic, origin);
|
||||
return;
|
||||
}
|
||||
if (topic == "provider-update") {
|
||||
// a provider has self-updated its manifest, we need to update our cache
|
||||
// and reload the provider.
|
||||
Social._updateProviderCache(providers);
|
||||
let provider = Social._getProviderFromOrigin(origin);
|
||||
provider.reload();
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
_updateEnabledState: function(enable) {
|
||||
for (let p of Social.providers) {
|
||||
p.enabled = enable;
|
||||
}
|
||||
},
|
||||
|
||||
// Called to update our cache of providers and set the current provider
|
||||
_updateProviderCache: function (providers) {
|
||||
this.providers = providers;
|
||||
Services.obs.notifyObservers(null, "social:providers-changed", null);
|
||||
},
|
||||
|
||||
get enabled() {
|
||||
return !this._disabledForSafeMode && this.providers.length > 0;
|
||||
},
|
||||
|
||||
_getProviderFromOrigin: function (origin) {
|
||||
for (let p of this.providers) {
|
||||
if (p.origin == origin) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
getManifestByOrigin: function(origin) {
|
||||
return SocialService.getManifestByOrigin(origin);
|
||||
},
|
||||
|
||||
installProvider: function(data, installCallback, options={}) {
|
||||
SocialService.installProvider(data, installCallback, options);
|
||||
},
|
||||
|
||||
uninstallProvider: function(origin, aCallback) {
|
||||
SocialService.uninstallProvider(origin, aCallback);
|
||||
},
|
||||
|
||||
// Activation functionality
|
||||
activateFromOrigin: function (origin, callback) {
|
||||
// It's OK if the provider has already been activated - we still get called
|
||||
// back with it.
|
||||
SocialService.enableProvider(origin, callback);
|
||||
}
|
||||
};
|
||||
|
||||
function sizeSocialPanelToContent(panel, iframe, requestedSize) {
|
||||
let doc = iframe.contentDocument;
|
||||
if (!doc || !doc.body) {
|
||||
return;
|
||||
}
|
||||
// We need an element to use for sizing our panel. See if the body defines
|
||||
// an id for that element, otherwise use the body itself.
|
||||
let body = doc.body;
|
||||
let docEl = doc.documentElement;
|
||||
let bodyId = body.getAttribute("contentid");
|
||||
if (bodyId) {
|
||||
body = doc.getElementById(bodyId) || doc.body;
|
||||
}
|
||||
// offsetHeight/Width don't include margins, so account for that.
|
||||
let cs = doc.defaultView.getComputedStyle(body);
|
||||
let width = Math.max(PANEL_MIN_WIDTH, docEl.offsetWidth);
|
||||
let height = Math.max(PANEL_MIN_HEIGHT, docEl.offsetHeight);
|
||||
// if the panel is preloaded prior to being shown, cs will be null. in that
|
||||
// case use the minimum size for the panel until it is shown.
|
||||
if (cs) {
|
||||
let computedHeight = parseInt(cs.marginTop) + body.offsetHeight + parseInt(cs.marginBottom);
|
||||
height = Math.max(computedHeight, height);
|
||||
let computedWidth = parseInt(cs.marginLeft) + body.offsetWidth + parseInt(cs.marginRight);
|
||||
width = Math.max(computedWidth, width);
|
||||
}
|
||||
|
||||
// if our scrollHeight is still larger than the iframe, the css calculations
|
||||
// above did not work for this site, increase the height. This can happen if
|
||||
// the site increases its height for additional UI.
|
||||
if (docEl.scrollHeight > iframe.boxObject.height)
|
||||
height = docEl.scrollHeight;
|
||||
|
||||
// if a size was defined in the manifest use it as a minimum
|
||||
if (requestedSize) {
|
||||
if (requestedSize.height)
|
||||
height = Math.max(height, requestedSize.height);
|
||||
if (requestedSize.width)
|
||||
width = Math.max(width, requestedSize.width);
|
||||
}
|
||||
|
||||
// add the extra space used by the panel (toolbar, borders, etc) if the iframe
|
||||
// has been loaded
|
||||
if (iframe.boxObject.width && iframe.boxObject.height) {
|
||||
// add extra space the panel needs if any
|
||||
width += panel.boxObject.width - iframe.boxObject.width;
|
||||
height += panel.boxObject.height - iframe.boxObject.height;
|
||||
}
|
||||
|
||||
// using panel.sizeTo will ignore css transitions, set size via style
|
||||
if (Math.abs(panel.boxObject.width - width) >= 2)
|
||||
panel.style.width = width + "px";
|
||||
if (Math.abs(panel.boxObject.height - height) >= 2)
|
||||
panel.style.height = height + "px";
|
||||
}
|
||||
|
||||
function DynamicResizeWatcher() {
|
||||
this._mutationObserver = null;
|
||||
}
|
||||
|
||||
DynamicResizeWatcher.prototype = {
|
||||
start: function DynamicResizeWatcher_start(panel, iframe, requestedSize) {
|
||||
this.stop(); // just in case...
|
||||
let doc = iframe.contentDocument;
|
||||
this._mutationObserver = new iframe.contentWindow.MutationObserver((mutations) => {
|
||||
sizeSocialPanelToContent(panel, iframe, requestedSize);
|
||||
});
|
||||
// Observe anything that causes the size to change.
|
||||
let config = {attributes: true, characterData: true, childList: true, subtree: true};
|
||||
this._mutationObserver.observe(doc, config);
|
||||
// and since this may be setup after the load event has fired we do an
|
||||
// initial resize now.
|
||||
sizeSocialPanelToContent(panel, iframe, requestedSize);
|
||||
},
|
||||
stop: function DynamicResizeWatcher_stop() {
|
||||
if (this._mutationObserver) {
|
||||
try {
|
||||
this._mutationObserver.disconnect();
|
||||
} catch (ex) {
|
||||
// may get "TypeError: can't access dead object" which seems strange,
|
||||
// but doesn't seem to indicate a real problem, so ignore it...
|
||||
}
|
||||
this._mutationObserver = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.OpenGraphBuilder = {
|
||||
generateEndpointURL: function(URLTemplate, pageData) {
|
||||
// support for existing oexchange style endpoints by supporting their
|
||||
// querystring arguments. parse the query string template and do
|
||||
// replacements where necessary the query names may be different than ours,
|
||||
// so we could see u=%{url} or url=%{url}
|
||||
let [endpointURL, queryString] = URLTemplate.split("?");
|
||||
let query = {};
|
||||
if (queryString) {
|
||||
queryString.split('&').forEach(function (val) {
|
||||
let [name, value] = val.split('=');
|
||||
let p = /%\{(.+)\}/.exec(value);
|
||||
if (!p) {
|
||||
// preserve non-template query vars
|
||||
query[name] = value;
|
||||
} else if (pageData[p[1]]) {
|
||||
if (p[1] == "previews")
|
||||
query[name] = pageData[p[1]][0];
|
||||
else
|
||||
query[name] = pageData[p[1]];
|
||||
} else if (p[1] == "body") {
|
||||
// build a body for emailers
|
||||
let body = "";
|
||||
if (pageData.title)
|
||||
body += pageData.title + "\n\n";
|
||||
if (pageData.description)
|
||||
body += pageData.description + "\n\n";
|
||||
if (pageData.text)
|
||||
body += pageData.text + "\n\n";
|
||||
body += pageData.url;
|
||||
query["body"] = body;
|
||||
}
|
||||
});
|
||||
// if the url template doesn't have title and no text was provided, add the title as the text.
|
||||
if (!query.text && !query.title && pageData.title) {
|
||||
query.text = pageData.title;
|
||||
}
|
||||
}
|
||||
var str = [];
|
||||
for (let p in query)
|
||||
str.push(p + "=" + encodeURIComponent(query[p]));
|
||||
if (str.length)
|
||||
endpointURL = endpointURL + "?" + str.join("&");
|
||||
return endpointURL;
|
||||
},
|
||||
};
|
||||
1097
browser/modules/SocialService.jsm
Normal file
1097
browser/modules/SocialService.jsm
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -35,6 +35,8 @@ EXTRA_JS_MODULES += [
|
|||
'Sanitizer.jsm',
|
||||
'SelfSupportBackend.jsm',
|
||||
'SitePermissions.jsm',
|
||||
'Social.jsm',
|
||||
'SocialService.jsm',
|
||||
'TransientPrefs.jsm',
|
||||
'URLBarZoom.jsm',
|
||||
'webrtcUI.jsm',
|
||||
|
|
|
|||
|
|
@ -1172,6 +1172,56 @@ html|span.ac-emphasize-text-url {
|
|||
-moz-image-region: rect(0, 48px, 16px, 32px);
|
||||
}
|
||||
|
||||
/* social share panel */
|
||||
%include ../shared/social/social.inc.css
|
||||
|
||||
.social-share-frame {
|
||||
border-top: 1px solid #f8f8f8;
|
||||
width: 756px;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
#share-container {
|
||||
min-width: 756px;
|
||||
background-color: white;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
#share-container[loading] {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/pendingpaint.png);
|
||||
}
|
||||
#share-container > browser {
|
||||
transition: opacity 150ms ease-in-out;
|
||||
opacity: 1;
|
||||
}
|
||||
#share-container[loading] > browser {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.social-share-toolbar {
|
||||
border-bottom: 1px solid #dedede;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
#social-share-provider-buttons {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.share-provider-button {
|
||||
padding: 5px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.share-provider-button > .toolbarbutton-text {
|
||||
display: none;
|
||||
}
|
||||
.share-provider-button > .toolbarbutton-icon {
|
||||
width: 16px;
|
||||
min-height: 16px;
|
||||
max-height: 16px;
|
||||
}
|
||||
|
||||
/* bookmarks menu-button */
|
||||
|
||||
#bookmarks-menu-button[cui-areatype="toolbar"] > .toolbarbutton-menubutton-dropmarker {
|
||||
|
|
|
|||
|
|
@ -49,6 +49,14 @@
|
|||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
/* subviewbutton entries for social sidebars have images that come from external
|
||||
/* sources, and are not guaranteed to be the size we want, so force the size on
|
||||
/* those icons. */
|
||||
toolbarbutton.social-provider-menuitem > .toolbarbutton-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.subviewbutton:-moz-any([image],[targetURI],.cui-withicon, .restoreallitem, .bookmark-item)[checked="true"] > .toolbarbutton-icon {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,6 +81,10 @@ browser.jar:
|
|||
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||
* skin/classic/browser/preferences/in-content/dialog.css (preferences/in-content/dialog.css)
|
||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||
skin/classic/browser/social/services-16.png (social/services-16.png)
|
||||
skin/classic/browser/social/services-64.png (social/services-64.png)
|
||||
skin/classic/browser/social/share-button.png (social/share-button.png)
|
||||
skin/classic/browser/social/share-button-active.png (social/share-button-active.png)
|
||||
skin/classic/browser/tabbrowser/alltabs.png (tabbrowser/alltabs.png)
|
||||
skin/classic/browser/tabbrowser/alltabs-inverted.png (tabbrowser/alltabs-inverted.png)
|
||||
skin/classic/browser/tabbrowser/newtab.svg (tabbrowser/newtab.svg)
|
||||
|
|
|
|||
|
|
@ -808,6 +808,10 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-ic
|
|||
-moz-image-region: rect(18px, 288px, 36px, 270px);
|
||||
}
|
||||
|
||||
#social-share-button@toolbarButtonPressed@ {
|
||||
-moz-image-region: rect(18px, 306px, 36px, 288px);
|
||||
}
|
||||
|
||||
#characterencoding-button@toolbarButtonPressed@ {
|
||||
-moz-image-region: rect(18px, 324px, 36px, 306px);
|
||||
}
|
||||
|
|
@ -963,6 +967,10 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-ic
|
|||
-moz-image-region: rect(36px, 576px, 72px, 540px);
|
||||
}
|
||||
|
||||
#social-share-button@toolbarButtonPressed@ {
|
||||
-moz-image-region: rect(36px, 612px, 72px, 576px);
|
||||
}
|
||||
|
||||
#characterencoding-button@toolbarButtonPressed@ {
|
||||
-moz-image-region: rect(36px, 648px, 72px, 612px);
|
||||
}
|
||||
|
|
@ -2021,6 +2029,59 @@ html|span.ac-emphasize-text-url {
|
|||
-moz-image-region: rect(0, 48px, 16px, 32px);
|
||||
}
|
||||
|
||||
/* social share panel */
|
||||
.social-share-frame {
|
||||
border-top: 1px solid #f8f8f8;
|
||||
min-width: 756px;
|
||||
height: 150px;
|
||||
/* we resize our panels dynamically, make it look nice */
|
||||
}
|
||||
|
||||
#share-container {
|
||||
min-width: 756px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
#share-container[loading] {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/pendingpaint.png);
|
||||
}
|
||||
#share-container > browser {
|
||||
transition: opacity 150ms ease-in-out;
|
||||
opacity: 1;
|
||||
}
|
||||
#share-container[loading] > browser {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#manage-share-providers {
|
||||
-moz-image-region: rect(18px, 468px, 36px, 450px);
|
||||
}
|
||||
|
||||
.social-share-toolbar {
|
||||
border-bottom: 1px solid #dedede;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
#social-share-provider-buttons {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.share-provider-button {
|
||||
padding: 5px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.share-provider-button > .toolbarbutton-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.share-provider-button > .toolbarbutton-icon {
|
||||
width: 16px;
|
||||
min-height: 16px;
|
||||
max-height: 16px;
|
||||
}
|
||||
|
||||
/* BOOKMARKING PANEL */
|
||||
#editBookmarkPanelStarIcon {
|
||||
list-style-image: url("chrome://browser/skin/places/starred48.png");
|
||||
|
|
@ -3121,6 +3182,33 @@ menulist.translate-infobar-element > .menulist-dropmarker {
|
|||
border-radius: 1px;
|
||||
}
|
||||
|
||||
/* Share */
|
||||
%include ../shared/social/social.inc.css
|
||||
|
||||
#social-share-panel {
|
||||
min-height: 100px;
|
||||
min-width: 300px;
|
||||
transition: height .3s ease-in-out, width .3s ease-in-out;
|
||||
}
|
||||
|
||||
#share-container,
|
||||
.social-share-frame {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: inherit;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: inherit;
|
||||
}
|
||||
|
||||
#social-share-panel > .social-share-toolbar {
|
||||
border-top-left-radius: inherit;
|
||||
border-top-right-radius: inherit;
|
||||
}
|
||||
|
||||
#social-share-provider-buttons {
|
||||
border-top-left-radius: inherit;
|
||||
border-top-right-radius: inherit;
|
||||
}
|
||||
|
||||
/* Customization mode */
|
||||
|
||||
%include ../shared/customizableui/customizeMode.inc.css
|
||||
|
|
|
|||
|
|
@ -124,6 +124,10 @@ browser.jar:
|
|||
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||
* skin/classic/browser/preferences/in-content/dialog.css (preferences/in-content/dialog.css)
|
||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||
skin/classic/browser/social/services-16.png (social/services-16.png)
|
||||
skin/classic/browser/social/services-16@2x.png (social/services-16@2x.png)
|
||||
skin/classic/browser/social/services-64.png (social/services-64.png)
|
||||
skin/classic/browser/social/services-64@2x.png (social/services-64@2x.png)
|
||||
skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon.png (tabbrowser/alltabs-box-bkgnd-icon.png)
|
||||
skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon-inverted.png (tabbrowser/alltabs-box-bkgnd-icon-inverted.png)
|
||||
skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon-inverted@2x.png (tabbrowser/alltabs-box-bkgnd-icon-inverted@2x.png)
|
||||
|
|
|
|||
30
browser/themes/shared/aboutProviderDirectory.css
Normal file
30
browser/themes/shared/aboutProviderDirectory.css
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
%include aboutSocialError.css
|
||||
|
||||
body {
|
||||
width: 310px;
|
||||
margin: 1em auto;
|
||||
}
|
||||
|
||||
#message-box {
|
||||
margin-top: 2em;
|
||||
background: url('chrome://global/skin/icons/information-24.png') no-repeat left 4px;
|
||||
padding-inline-start: 30px;
|
||||
}
|
||||
|
||||
#activation-frame {
|
||||
border: none;
|
||||
margin: 0;
|
||||
width: 310px;
|
||||
height: 200px;
|
||||
}
|
||||
#activation > p {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
line-height: 2em;
|
||||
}
|
||||
.link {
|
||||
text-decoration: none;
|
||||
color: -moz-nativehyperlinktext;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
% Note that zoom-reset-button is a bit different since it doesn't use an image and thus has the image with display: none.
|
||||
%define nestedButtons #zoom-out-button, #zoom-reset-button, #zoom-in-button, #cut-button, #copy-button, #paste-button
|
||||
%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #fullscreen-button, #sync-button, #feed-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button, #sidebar-button, @nestedButtons@, #e10s-button, #panic-button, #webide-button, #containers-panelmenu
|
||||
%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #fullscreen-button, #sync-button, #feed-button, #social-share-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button, #sidebar-button, @nestedButtons@, #e10s-button, #panic-button, #webide-button, #containers-panelmenu
|
||||
|
||||
%ifdef XP_MACOSX
|
||||
% Prior to 10.7 there wasn't a native fullscreen button so we use #restore-button to exit fullscreen
|
||||
|
|
|
|||
|
|
@ -951,6 +951,7 @@ panelview .toolbarbutton-1,
|
|||
.subviewbutton,
|
||||
.widget-overflow-list .toolbarbutton-1,
|
||||
.panelUI-grid .toolbarbutton-1 > .toolbarbutton-menubutton-button,
|
||||
.share-provider-button,
|
||||
.toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton {
|
||||
-moz-appearance: none;
|
||||
padding: 0 6px;
|
||||
|
|
@ -963,6 +964,7 @@ panelview .toolbarbutton-1,
|
|||
panelview .toolbarbutton-1,
|
||||
.subviewbutton,
|
||||
.widget-overflow-list .toolbarbutton-1,
|
||||
.share-provider-button,
|
||||
.toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton {
|
||||
border-width: 1px;
|
||||
}
|
||||
|
|
@ -1036,6 +1038,7 @@ panelview .toolbarbutton-1@buttonStateHover@,
|
|||
toolbarbutton.subviewbutton@buttonStateHover@,
|
||||
menu.subviewbutton@menuStateHover@,
|
||||
menuitem.subviewbutton@menuStateHover@,
|
||||
.share-provider-button@buttonStateHover@:not([checked="true"]),
|
||||
.widget-overflow-list .toolbarbutton-1@buttonStateHover@,
|
||||
.toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton@buttonStateHover@ {
|
||||
background-color: var(--arrowpanel-dimmed);
|
||||
|
|
@ -1050,6 +1053,7 @@ panelview .toolbarbutton-1:-moz-any(@buttonStateActive@,[checked=true]),
|
|||
toolbarbutton.subviewbutton@buttonStateActive@,
|
||||
menu.subviewbutton@menuStateActive@,
|
||||
menuitem.subviewbutton@menuStateActive@,
|
||||
.share-provider-button:-moz-any(@buttonStateActive@,[checked=true]),
|
||||
.widget-overflow-list .toolbarbutton-1@buttonStateActive@,
|
||||
.toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton@buttonStateActive@ {
|
||||
background-color: var(--arrowpanel-dimmed-further);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@
|
|||
skin/classic/browser/aboutNetError.css (../shared/aboutNetError.css)
|
||||
skin/classic/browser/blockedSite.css (../shared/blockedSite.css)
|
||||
skin/classic/browser/error-pages.css (../shared/error-pages.css)
|
||||
* skin/classic/browser/aboutProviderDirectory.css (../shared/aboutProviderDirectory.css)
|
||||
* skin/classic/browser/aboutSessionRestore.css (../shared/aboutSessionRestore.css)
|
||||
skin/classic/browser/aboutSocialError.css (../shared/aboutSocialError.css)
|
||||
skin/classic/browser/aboutTabCrashed.css (../shared/aboutTabCrashed.css)
|
||||
skin/classic/browser/aboutWelcomeBack.css (../shared/aboutWelcomeBack.css)
|
||||
skin/classic/browser/content-contextmenu.svg (../shared/content-contextmenu.svg)
|
||||
|
|
@ -63,6 +65,7 @@
|
|||
* skin/classic/browser/identity-icon.svg (../shared/identity-block/identity-icon.svg)
|
||||
skin/classic/browser/info.svg (../shared/info.svg)
|
||||
* skin/classic/browser/menuPanel.svg (../shared/menuPanel.svg)
|
||||
* skin/classic/browser/menuPanel-small.svg (../shared/menuPanel-small.svg)
|
||||
* skin/classic/browser/notification-icons.svg (../shared/notification-icons.svg)
|
||||
* skin/classic/browser/tracking-protection-16.svg (../shared/identity-block/tracking-protection-16.svg)
|
||||
skin/classic/browser/newtab/close.png (../shared/newtab/close.png)
|
||||
|
|
@ -97,6 +100,8 @@
|
|||
skin/classic/browser/search-indicator-magnifying-glass.svg (../shared/search/search-indicator-magnifying-glass.svg)
|
||||
skin/classic/browser/search-arrow-go.svg (../shared/search/search-arrow-go.svg)
|
||||
skin/classic/browser/gear.svg (../shared/search/gear.svg)
|
||||
skin/classic/browser/social/gear_default.png (../shared/social/gear_default.png)
|
||||
skin/classic/browser/social/gear_clicked.png (../shared/social/gear_clicked.png)
|
||||
skin/classic/browser/tabbrowser/connecting.png (../shared/tabbrowser/connecting.png)
|
||||
skin/classic/browser/tabbrowser/connecting@2x.png (../shared/tabbrowser/connecting@2x.png)
|
||||
skin/classic/browser/tabbrowser/crashed.svg (../shared/tabbrowser/crashed.svg)
|
||||
|
|
|
|||
16
browser/themes/shared/menuPanel-small.svg
Normal file
16
browser/themes/shared/menuPanel-small.svg
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="96" height="16" viewBox="0 0 96 16"
|
||||
class="fieldtext">
|
||||
#include icon-colors.inc.svg
|
||||
|
||||
<path id="placeholder" d="M8,16a8,8,0,1,1,8-8A8,8,0,0,1,8,16ZM12,4H4v8h8V4ZM5,9.939V6.061L6.939,8ZM9.939,11H6.061L8,9.061ZM11,11h0Zm0-4.939V9.939L9.061,8ZM11,5h0ZM6.061,5H9.939L8,6.939Z"/>
|
||||
<path id="cut" d="M29.63,15a2.426,2.426,0,0,1-2.282-1.277c-0.761-1.109-1.694-2.488-1.694-2.488S25,10.329,24.549,9.623a1.05,1.05,0,0,0-1.106-.538S20.6,4.437,20.124,3.706C19.465,2.689,20.7,1,20.7,1l4.4,7.044a19.333,19.333,0,0,0,1.867,2.286c0.519,0.4,1.382-.373,2.8.908C31.7,12.984,31.048,15,29.63,15ZM29.423,12.11c-0.933-1.042-1.728-.908-1.936-0.639a2.093,2.093,0,0,0,.38,1.748,1.612,1.612,0,0,0,1.383.74C29.838,13.959,30.356,13.153,29.423,12.11ZM25.582,7.372L24.4,5.6,27.276,1s1.233,1.69.575,2.708C27.568,4.142,26.445,5.967,25.582,7.372Zm-4.576,2.956A12.482,12.482,0,0,0,22.43,8.645l0.826,1.239c-0.428.65-.937,1.352-0.937,1.352s-0.933,1.378-1.694,2.488A2.426,2.426,0,0,1,18.344,15c-1.417,0-2.074-2.017-.138-3.765C19.624,9.956,20.487,10.732,21.006,10.329ZM18.551,12.11c-0.933,1.042-.415,1.849.173,1.849a1.612,1.612,0,0,0,1.383-.74,2.093,2.093,0,0,0,.38-1.748C20.28,11.2,19.485,11.068,18.551,12.11Z"/>
|
||||
<path id="copy" d="M46,15H40a1,1,0,0,1-1-1V6a1,1,0,0,1,1-1h4.953C45,5,47,6.984,47,7.047V14A1,1,0,0,1,46,15ZM44,6V8h2ZM38,4.886V11H34a1,1,0,0,1-1-1V2a1,1,0,0,1,1-1h4.953C39,1,41,2.985,41,3.047v1.34H38.5A0.5,0.5,0,0,0,38,4.886ZM38,2V4h2Z"/>
|
||||
<path id="paste" d="M59.5,15h-7A1.5,1.5,0,0,1,51,13.5v-9A1.5,1.5,0,0,1,52.5,3H54a2,2,0,1,1,4,0h1.5A1.5,1.5,0,0,1,61,4.5v9A1.5,1.5,0,0,1,59.5,15ZM58.682,4L57.61,3.5a1.613,1.613,0,0,0-3.219,0L53.318,4,52.781,5h6.437ZM58.82,5.688H54.074L51.059,7.428l2.849,4.935,6.574-3.8Z"/>
|
||||
<rect id="zoomOut" x="67" y="7" width="10" height="2"/>
|
||||
<path id="zoomIn" d="M93,9H89v4H87V9H83V7h4V3h2V7h4V9Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
|
|
@ -63,6 +63,11 @@ toolbarpaletteitem[place="palette"] > #feed-button {
|
|||
-moz-image-region: rect(0px, 416px, 32px, 384px);
|
||||
}
|
||||
|
||||
#social-share-button[cui-areatype="menu-panel"],
|
||||
toolbarpaletteitem[place="palette"] > #social-share-button {
|
||||
-moz-image-region: rect(0px, 448px, 32px, 416px);
|
||||
}
|
||||
|
||||
#characterencoding-button[cui-areatype="menu-panel"],
|
||||
toolbarpaletteitem[place="palette"] > #characterencoding-button {
|
||||
-moz-image-region: rect(0px, 480px, 32px, 448px);
|
||||
|
|
@ -171,3 +176,8 @@ toolbarpaletteitem[place="palette"] > #zoom-controls > #zoom-in-button {
|
|||
-moz-image-region: rect(0px, 96px, 16px, 80px);
|
||||
}
|
||||
|
||||
#add-share-provider {
|
||||
list-style-image: url(chrome://browser/skin/menuPanel-small.svg);
|
||||
-moz-image-region: rect(0px, 96px, 16px, 80px);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -271,6 +271,28 @@ html|*#webRTC-previewVideo {
|
|||
}
|
||||
}
|
||||
|
||||
/* SOCIAL API */
|
||||
|
||||
.popup-notification-icon[popupid="servicesInstall"] {
|
||||
list-style-image: url(chrome://browser/skin/social/services-64.png);
|
||||
}
|
||||
|
||||
.service-icon {
|
||||
list-style-image: url(chrome://browser/skin/social/services-16.png);
|
||||
}
|
||||
|
||||
%ifdef XP_MACOSX
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.popup-notification-icon[popupid="servicesInstall"] {
|
||||
list-style-image: url(chrome://browser/skin/social/services-64@2x.png);
|
||||
}
|
||||
|
||||
.service-icon {
|
||||
list-style-image: url(chrome://browser/skin/social/services-16@2x.png);
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
/* TRANSLATION */
|
||||
|
||||
.translation-icon {
|
||||
|
|
|
|||
BIN
browser/themes/shared/social/gear_clicked.png
Normal file
BIN
browser/themes/shared/social/gear_clicked.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
BIN
browser/themes/shared/social/gear_default.png
Normal file
BIN
browser/themes/shared/social/gear_default.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
23
browser/themes/shared/social/social.inc.css
Normal file
23
browser/themes/shared/social/social.inc.css
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
%if 0
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
%endif
|
||||
|
||||
#manage-share-providers {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar.png");
|
||||
-moz-image-region: rect(0, 468px, 18px, 450px);
|
||||
}
|
||||
|
||||
#manage-share-providers > .toolbarbutton-icon {
|
||||
min-height: 18px;
|
||||
min-width: 18px;
|
||||
}
|
||||
|
||||
.social-panel > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 0;
|
||||
}
|
||||
/* fixup corners for share panel */
|
||||
.social-panel > .social-panel-frame {
|
||||
border-radius: inherit;
|
||||
}
|
||||
|
|
@ -64,6 +64,10 @@ toolbar[brighttext] #bookmarks-menu-button > .toolbarbutton-menubutton-dropmarke
|
|||
-moz-image-region: rect(0, 288px, 18px, 270px);
|
||||
}
|
||||
|
||||
#social-share-button[cui-areatype="toolbar"] {
|
||||
-moz-image-region: rect(0px, 306px, 18px, 288px);
|
||||
}
|
||||
|
||||
#characterencoding-button[cui-areatype="toolbar"]{
|
||||
-moz-image-region: rect(0, 324px, 18px, 306px);
|
||||
}
|
||||
|
|
@ -238,6 +242,10 @@ toolbar[brighttext] #bookmarks-menu-button > .toolbarbutton-menubutton-dropmarke
|
|||
-moz-image-region: rect(0, 576px, 36px, 540px);
|
||||
}
|
||||
|
||||
#social-share-button[cui-areatype="toolbar"] {
|
||||
-moz-image-region: rect(0, 612px, 36px, 576px);
|
||||
}
|
||||
|
||||
#characterencoding-button[cui-areatype="toolbar"] {
|
||||
-moz-image-region: rect(0, 648px, 36px, 612px);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1874,6 +1874,81 @@ html|span.ac-emphasize-text-url {
|
|||
-moz-image-region: rect(0, 48px, 16px, 32px);
|
||||
}
|
||||
|
||||
/* social share panel */
|
||||
%include ../shared/social/social.inc.css
|
||||
|
||||
.social-panel-frame {
|
||||
border-radius: inherit;
|
||||
}
|
||||
|
||||
.social-share-frame {
|
||||
min-width: 756px;
|
||||
height: 150px;
|
||||
}
|
||||
#share-container {
|
||||
min-width: 756px;
|
||||
background-color: white;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
#share-container[loading] {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/pendingpaint.png);
|
||||
}
|
||||
#share-container > browser {
|
||||
transition: opacity 150ms ease-in-out;
|
||||
opacity: 1;
|
||||
}
|
||||
#share-container[loading] > browser {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.social-share-toolbar {
|
||||
border-bottom: 1px solid #e2e5e8;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
#social-share-provider-buttons {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.share-provider-button {
|
||||
padding: 5px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.share-provider-button > .toolbarbutton-text {
|
||||
display: none;
|
||||
}
|
||||
.share-provider-button > .toolbarbutton-icon {
|
||||
width: 16px;
|
||||
min-height: 16px;
|
||||
max-height: 16px;
|
||||
}
|
||||
|
||||
#social-share-panel {
|
||||
min-height: 100px;
|
||||
min-width: 766px;
|
||||
}
|
||||
|
||||
#share-container,
|
||||
.social-share-frame {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: inherit;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: inherit;
|
||||
}
|
||||
|
||||
#social-share-panel > .social-share-toolbar {
|
||||
border-top-left-radius: inherit;
|
||||
border-top-right-radius: inherit;
|
||||
}
|
||||
|
||||
#social-share-provider-buttons {
|
||||
border-top-left-radius: inherit;
|
||||
border-top-right-radius: inherit;
|
||||
}
|
||||
|
||||
/* bookmarks menu-button */
|
||||
|
||||
#nav-bar #bookmarks-menu-button[cui-areatype="toolbar"]:not([overflowedItem=true]) > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {
|
||||
|
|
|
|||
|
|
@ -97,6 +97,14 @@ menuitem[type="checkbox"].subviewbutton {
|
|||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
/* subviewbutton entries for social sidebars have images that come from external
|
||||
/* sources, and are not guaranteed to be the size we want, so force the size on
|
||||
/* those icons. */
|
||||
toolbarbutton.social-provider-menuitem > .toolbarbutton-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.subviewbutton:-moz-any([image],[targetURI],.cui-withicon, .restoreallitem, .bookmark-item)[checked="true"] > .toolbarbutton-icon {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,6 +133,8 @@ browser.jar:
|
|||
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||
* skin/classic/browser/preferences/in-content/dialog.css (preferences/in-content/dialog.css)
|
||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||
skin/classic/browser/social/services-16.png (social/services-16.png)
|
||||
skin/classic/browser/social/services-64.png (social/services-64.png)
|
||||
skin/classic/browser/tabbrowser/newtab.svg (tabbrowser/newtab.svg)
|
||||
skin/classic/browser/tabbrowser/newtab-XPVista7.svg (tabbrowser/newtab-XPVista7.svg)
|
||||
skin/classic/browser/tabbrowser/newtab-inverted.svg (tabbrowser/newtab-inverted.svg)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue