mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 891225 implement new provider status buttons, r=markh
This commit is contained in:
parent
e7e23e3306
commit
dafd27215e
@ -37,6 +37,10 @@ SocialUI = {
|
|||||||
Services.obs.addObserver(this, "social:provider-set", false);
|
Services.obs.addObserver(this, "social:provider-set", false);
|
||||||
Services.obs.addObserver(this, "social:providers-changed", false);
|
Services.obs.addObserver(this, "social:providers-changed", false);
|
||||||
Services.obs.addObserver(this, "social:provider-reload", false);
|
Services.obs.addObserver(this, "social:provider-reload", false);
|
||||||
|
Services.obs.addObserver(this, "social:provider-installed", false);
|
||||||
|
Services.obs.addObserver(this, "social:provider-uninstalled", false);
|
||||||
|
Services.obs.addObserver(this, "social:provider-enabled", false);
|
||||||
|
Services.obs.addObserver(this, "social:provider-disabled", false);
|
||||||
|
|
||||||
Services.prefs.addObserver("social.sidebar.open", this, false);
|
Services.prefs.addObserver("social.sidebar.open", this, false);
|
||||||
Services.prefs.addObserver("social.toast-notifications.enabled", this, false);
|
Services.prefs.addObserver("social.toast-notifications.enabled", this, false);
|
||||||
@ -62,6 +66,10 @@ SocialUI = {
|
|||||||
Services.obs.removeObserver(this, "social:provider-set");
|
Services.obs.removeObserver(this, "social:provider-set");
|
||||||
Services.obs.removeObserver(this, "social:providers-changed");
|
Services.obs.removeObserver(this, "social:providers-changed");
|
||||||
Services.obs.removeObserver(this, "social:provider-reload");
|
Services.obs.removeObserver(this, "social:provider-reload");
|
||||||
|
Services.obs.removeObserver(this, "social:provider-installed");
|
||||||
|
Services.obs.removeObserver(this, "social:provider-uninstalled");
|
||||||
|
Services.obs.removeObserver(this, "social:provider-enabled");
|
||||||
|
Services.obs.removeObserver(this, "social:provider-disabled");
|
||||||
|
|
||||||
Services.prefs.removeObserver("social.sidebar.open", this);
|
Services.prefs.removeObserver("social.sidebar.open", this);
|
||||||
Services.prefs.removeObserver("social.toast-notifications.enabled", this);
|
Services.prefs.removeObserver("social.toast-notifications.enabled", this);
|
||||||
@ -76,6 +84,18 @@ SocialUI = {
|
|||||||
// manually :(
|
// manually :(
|
||||||
try {
|
try {
|
||||||
switch (topic) {
|
switch (topic) {
|
||||||
|
case "social:provider-installed":
|
||||||
|
SocialStatus.setPosition(data);
|
||||||
|
break;
|
||||||
|
case "social:provider-uninstalled":
|
||||||
|
SocialStatus.removePosition(data);
|
||||||
|
break;
|
||||||
|
case "social:provider-enabled":
|
||||||
|
SocialStatus.populateToolbarPalette();
|
||||||
|
break;
|
||||||
|
case "social:provider-disabled":
|
||||||
|
SocialStatus.removeProvider(data);
|
||||||
|
break;
|
||||||
case "social:provider-reload":
|
case "social:provider-reload":
|
||||||
// if the reloaded provider is our current provider, fall through
|
// if the reloaded provider is our current provider, fall through
|
||||||
// to social:provider-set so the ui will be reset
|
// to social:provider-set so the ui will be reset
|
||||||
@ -98,6 +118,7 @@ SocialUI = {
|
|||||||
SocialSidebar.update();
|
SocialSidebar.update();
|
||||||
SocialMark.update();
|
SocialMark.update();
|
||||||
SocialToolbar.update();
|
SocialToolbar.update();
|
||||||
|
SocialStatus.populateToolbarPalette();
|
||||||
SocialMenu.populate();
|
SocialMenu.populate();
|
||||||
break;
|
break;
|
||||||
case "social:providers-changed":
|
case "social:providers-changed":
|
||||||
@ -106,10 +127,12 @@ SocialUI = {
|
|||||||
// and the multi-provider menu
|
// and the multi-provider menu
|
||||||
SocialToolbar.populateProviderMenus();
|
SocialToolbar.populateProviderMenus();
|
||||||
SocialShare.populateProviderMenu();
|
SocialShare.populateProviderMenu();
|
||||||
|
SocialStatus.populateToolbarPalette();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Provider-specific notifications
|
// Provider-specific notifications
|
||||||
case "social:ambient-notification-changed":
|
case "social:ambient-notification-changed":
|
||||||
|
SocialStatus.updateNotification(data);
|
||||||
if (this._matchesCurrentProvider(data)) {
|
if (this._matchesCurrentProvider(data)) {
|
||||||
SocialToolbar.updateButton();
|
SocialToolbar.updateButton();
|
||||||
SocialMenu.populate();
|
SocialMenu.populate();
|
||||||
@ -1056,6 +1079,15 @@ SocialToolbar = {
|
|||||||
Services.prefs.clearUserPref(CACHE_PREF_NAME);
|
Services.prefs.clearUserPref(CACHE_PREF_NAME);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the provider uses the new SocialStatus button, then they do not get
|
||||||
|
// to use the ambient icons in the old toolbar button. Since the status
|
||||||
|
// button depends on multiple workers, if not enabled we will ignore this
|
||||||
|
// limitation. That allows a provider to migrate to the new functionality
|
||||||
|
// once we enable multiple workers.
|
||||||
|
if (Social.provider.statusURL && Social.allowMultipleWorkers)
|
||||||
|
return;
|
||||||
|
|
||||||
let icons = Social.provider.ambientNotificationIcons;
|
let icons = Social.provider.ambientNotificationIcons;
|
||||||
let iconNames = Object.keys(icons);
|
let iconNames = Object.keys(icons);
|
||||||
|
|
||||||
@ -1154,9 +1186,8 @@ SocialToolbar = {
|
|||||||
socialToolbarItem.insertBefore(toolbarButtons, SocialMark.button);
|
socialToolbarItem.insertBefore(toolbarButtons, SocialMark.button);
|
||||||
|
|
||||||
for (let frame of createdFrames) {
|
for (let frame of createdFrames) {
|
||||||
if (frame.socialErrorListener) {
|
if (frame.socialErrorListener)
|
||||||
frame.socialErrorListener.remove();
|
frame.socialErrorListener.remove();
|
||||||
}
|
|
||||||
if (frame.docShell) {
|
if (frame.docShell) {
|
||||||
frame.docShell.isActive = false;
|
frame.docShell.isActive = false;
|
||||||
Social.setErrorListener(frame, this.setPanelErrorMessage.bind(this));
|
Social.setErrorListener(frame, this.setPanelErrorMessage.bind(this));
|
||||||
@ -1201,11 +1232,10 @@ SocialToolbar = {
|
|||||||
|
|
||||||
panel.addEventListener("popupshown", function onpopupshown() {
|
panel.addEventListener("popupshown", function onpopupshown() {
|
||||||
panel.removeEventListener("popupshown", onpopupshown);
|
panel.removeEventListener("popupshown", onpopupshown);
|
||||||
// This attribute is needed on both the button and the
|
// The "open" attribute is needed on both the button and the containing
|
||||||
// containing toolbaritem since the buttons on OS X have
|
// toolbaritem since the buttons on OS X have moz-appearance:none, while
|
||||||
// moz-appearance:none, while their container gets
|
// their container gets moz-appearance:toolbarbutton due to the way that
|
||||||
// moz-appearance:toolbarbutton due to the way that toolbar buttons
|
// toolbar buttons get combined on OS X.
|
||||||
// get combined on OS X.
|
|
||||||
aToolbarButton.setAttribute("open", "true");
|
aToolbarButton.setAttribute("open", "true");
|
||||||
aToolbarButton.parentNode.setAttribute("open", "true");
|
aToolbarButton.parentNode.setAttribute("open", "true");
|
||||||
notificationFrame.docShell.isActive = true;
|
notificationFrame.docShell.isActive = true;
|
||||||
@ -1392,4 +1422,353 @@ SocialSidebar = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this helper class is used by removable/customizable buttons to handle
|
||||||
|
// location persistence and insertion into palette and/or toolbars
|
||||||
|
|
||||||
|
// When a provider is installed we show all their UI so the user will see the
|
||||||
|
// functionality of what they installed. The user can later customize the UI,
|
||||||
|
// moving buttons around or off the toolbar.
|
||||||
|
//
|
||||||
|
// To make this happen, on install we add a button id to the navbar currentset.
|
||||||
|
// On enabling the provider (happens just after install) we insert the button
|
||||||
|
// into the toolbar as well. The button is then persisted on restart (assuming
|
||||||
|
// it was not removed).
|
||||||
|
//
|
||||||
|
// When a provider is disabled, we do not remove the buttons from currentset.
|
||||||
|
// That way, if the provider is re-enabled during the same session, the buttons
|
||||||
|
// will reappear where they were before. When a provider is uninstalled, we make
|
||||||
|
// sure that the id is removed from currentset.
|
||||||
|
//
|
||||||
|
// On startup, we insert the buttons of any enabled provider into either the
|
||||||
|
// apropriate toolbar or the palette.
|
||||||
|
function ToolbarHelper(type, createButtonFn) {
|
||||||
|
this._createButton = createButtonFn;
|
||||||
|
this._type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolbarHelper.prototype = {
|
||||||
|
idFromOrgin: function(origin) {
|
||||||
|
return this._type + "-" + origin;
|
||||||
|
},
|
||||||
|
|
||||||
|
// find a button either in the document or the palette
|
||||||
|
_getExistingButton: function(id) {
|
||||||
|
let button = document.getElementById(id);
|
||||||
|
if (button)
|
||||||
|
return button;
|
||||||
|
let palette = document.getElementById("navigator-toolbox").palette;
|
||||||
|
let paletteItem = palette.firstChild;
|
||||||
|
while (paletteItem) {
|
||||||
|
if (paletteItem.id == id)
|
||||||
|
return paletteItem;
|
||||||
|
paletteItem = paletteItem.nextSibling;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
setPersistentPosition: function(id) {
|
||||||
|
// called when a provider is installed. add provider buttons to nav-bar
|
||||||
|
let toolbar = document.getElementById("nav-bar");
|
||||||
|
// first startups will not have a currentset attribute, always rely on
|
||||||
|
// currentSet since it will be derived from the defaultset in that case.
|
||||||
|
let currentset = toolbar.currentSet;
|
||||||
|
if (currentset == "__empty")
|
||||||
|
currentset = []
|
||||||
|
else
|
||||||
|
currentset = currentset.split(",");
|
||||||
|
if (currentset.indexOf(id) >= 0)
|
||||||
|
return;
|
||||||
|
// we do not set toolbar.currentSet since that will try to add the button,
|
||||||
|
// and we have not added it yet (happens on provider being enabled)
|
||||||
|
currentset.push(id);
|
||||||
|
toolbar.setAttribute("currentset", currentset.join(","));
|
||||||
|
document.persist(toolbar.id, "currentset");
|
||||||
|
},
|
||||||
|
|
||||||
|
removeProviderButton: function(origin) {
|
||||||
|
// this will remove the button from the palette or the toolbar
|
||||||
|
let button = this._getExistingButton(this.idFromOrgin(origin));
|
||||||
|
if (button)
|
||||||
|
button.parentNode.removeChild(button);
|
||||||
|
},
|
||||||
|
|
||||||
|
removePersistence: function(id) {
|
||||||
|
let persisted = document.querySelectorAll("*[currentset]");
|
||||||
|
for (let pent of persisted) {
|
||||||
|
// the button will have been removed, but left in the currentset attribute
|
||||||
|
// in case the user re-enables (e.g. undo in addon manager). So we only
|
||||||
|
// check the attribute here.
|
||||||
|
let currentset = pent.getAttribute("currentset").split(",");
|
||||||
|
|
||||||
|
let pos = currentset.indexOf(id);
|
||||||
|
if (pos >= 0) {
|
||||||
|
currentset.splice(pos, 1);
|
||||||
|
pent.setAttribute("currentset", currentset.join(","));
|
||||||
|
document.persist(pent.id, "currentset");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// if social is entirely disabled, we need to clear the palette, but leave
|
||||||
|
// the persisted id's in place
|
||||||
|
clearPalette: function() {
|
||||||
|
[this.removeProviderButton(p.origin) for (p of Social.providers)];
|
||||||
|
},
|
||||||
|
|
||||||
|
// should be called on startup of each window, otherwise the addon manager
|
||||||
|
// listener will handle new activations, or enable/disabling of a provider
|
||||||
|
// XXX we currently call more regularly, will fix during refactoring
|
||||||
|
populatePalette: function() {
|
||||||
|
if (!Social.enabled) {
|
||||||
|
this.clearPalette();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let persisted = document.querySelectorAll("*[currentset]");
|
||||||
|
let persistedById = {};
|
||||||
|
for (let pent of persisted) {
|
||||||
|
let pset = pent.getAttribute("currentset").split(',');
|
||||||
|
for (let id of pset)
|
||||||
|
persistedById[id] = pent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create any buttons that do not exist yet if they have been persisted
|
||||||
|
// as a part of the UI (otherwise they belong in the palette).
|
||||||
|
for (let provider of Social.providers) {
|
||||||
|
let id = this.idFromOrgin(provider.origin);
|
||||||
|
if (this._getExistingButton(id))
|
||||||
|
return;
|
||||||
|
let button = this._createButton(provider);
|
||||||
|
if (button && persistedById.hasOwnProperty(id)) {
|
||||||
|
let parent = persistedById[id];
|
||||||
|
let pset = persistedById[id].getAttribute("currentset").split(',');
|
||||||
|
let pi = pset.indexOf(id) + 1;
|
||||||
|
let next = document.getElementById(pset[pi]);
|
||||||
|
parent.insertItem(id, next, null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SocialStatus = {
|
||||||
|
populateToolbarPalette: function() {
|
||||||
|
if (!Social.allowMultipleWorkers)
|
||||||
|
return;
|
||||||
|
this._toolbarHelper.populatePalette();
|
||||||
|
},
|
||||||
|
|
||||||
|
setPosition: function(origin) {
|
||||||
|
if (!Social.allowMultipleWorkers)
|
||||||
|
return;
|
||||||
|
// this is called during install, before the provider is enabled so we have
|
||||||
|
// to use the manifest rather than the provider instance as we do elsewhere.
|
||||||
|
let manifest = Social.getManifestByOrigin(origin);
|
||||||
|
if (!manifest.statusURL)
|
||||||
|
return;
|
||||||
|
let tbh = this._toolbarHelper;
|
||||||
|
tbh.setPersistentPosition(tbh.idFromOrgin(origin));
|
||||||
|
},
|
||||||
|
|
||||||
|
removePosition: function(origin) {
|
||||||
|
if (!Social.allowMultipleWorkers)
|
||||||
|
return;
|
||||||
|
let tbh = this._toolbarHelper;
|
||||||
|
tbh.removePersistence(tbh.idFromOrgin(origin));
|
||||||
|
},
|
||||||
|
|
||||||
|
removeProvider: function(origin) {
|
||||||
|
if (!Social.allowMultipleWorkers)
|
||||||
|
return;
|
||||||
|
this._toolbarHelper.removeProviderButton(origin);
|
||||||
|
},
|
||||||
|
|
||||||
|
get _toolbarHelper() {
|
||||||
|
delete this._toolbarHelper;
|
||||||
|
this._toolbarHelper = new ToolbarHelper("social-status-button", this._createButton.bind(this));
|
||||||
|
return this._toolbarHelper;
|
||||||
|
},
|
||||||
|
|
||||||
|
get _dynamicResizer() {
|
||||||
|
delete this._dynamicResizer;
|
||||||
|
this._dynamicResizer = new DynamicResizeWatcher();
|
||||||
|
return this._dynamicResizer;
|
||||||
|
},
|
||||||
|
|
||||||
|
_createButton: function(provider) {
|
||||||
|
if (!provider.statusURL)
|
||||||
|
return null;
|
||||||
|
let palette = document.getElementById("navigator-toolbox").palette;
|
||||||
|
let button = document.createElement("toolbarbutton");
|
||||||
|
button.setAttribute("class", "toolbarbutton-1 social-status-button");
|
||||||
|
button.setAttribute("type", "badged");
|
||||||
|
button.setAttribute("removable", "true");
|
||||||
|
button.setAttribute("image", provider.iconURL);
|
||||||
|
button.setAttribute("label", provider.name);
|
||||||
|
button.setAttribute("tooltiptext", provider.name);
|
||||||
|
button.setAttribute("origin", provider.origin);
|
||||||
|
button.setAttribute("oncommand", "SocialStatus.showPopup(this);");
|
||||||
|
button.setAttribute("id", this._toolbarHelper.idFromOrgin(provider.origin));
|
||||||
|
palette.appendChild(button);
|
||||||
|
return button;
|
||||||
|
},
|
||||||
|
|
||||||
|
// status panels are one-per button per-process, we swap the docshells between
|
||||||
|
// windows when necessary
|
||||||
|
_attachNotificatonPanel: function(aButton, provider) {
|
||||||
|
let panel = document.getElementById("social-notification-panel");
|
||||||
|
panel.hidden = !SocialUI.enabled;
|
||||||
|
let notificationFrameId = "social-status-" + provider.origin;
|
||||||
|
let frame = document.getElementById(notificationFrameId);
|
||||||
|
|
||||||
|
if (!frame) {
|
||||||
|
frame = SharedFrame.createFrame(
|
||||||
|
notificationFrameId, /* frame name */
|
||||||
|
panel, /* parent */
|
||||||
|
{
|
||||||
|
"type": "content",
|
||||||
|
"mozbrowser": "true",
|
||||||
|
"class": "social-panel-frame",
|
||||||
|
"id": notificationFrameId,
|
||||||
|
"tooltip": "aHTMLTooltip",
|
||||||
|
|
||||||
|
// work around bug 793057 - by making the panel roughly the final size
|
||||||
|
// we are more likely to have the anchor in the correct position.
|
||||||
|
"style": "width: " + PANEL_MIN_WIDTH + "px;",
|
||||||
|
|
||||||
|
"origin": provider.origin,
|
||||||
|
"src": provider.statusURL
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (frame.socialErrorListener)
|
||||||
|
frame.socialErrorListener.remove();
|
||||||
|
if (frame.docShell) {
|
||||||
|
frame.docShell.isActive = false;
|
||||||
|
Social.setErrorListener(frame, this.setPanelErrorMessage.bind(this));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
frame.setAttribute("origin", provider.origin);
|
||||||
|
SharedFrame.updateURL(notificationFrameId, provider.statusURL);
|
||||||
|
}
|
||||||
|
aButton.setAttribute("notificationFrameId", notificationFrameId);
|
||||||
|
},
|
||||||
|
|
||||||
|
updateNotification: function(origin) {
|
||||||
|
if (!Social.allowMultipleWorkers)
|
||||||
|
return;
|
||||||
|
let provider = Social._getProviderFromOrigin(origin);
|
||||||
|
let button = document.getElementById(this._toolbarHelper.idFromOrgin(provider.origin));
|
||||||
|
if (button) {
|
||||||
|
// we only grab the first notification, ignore all others
|
||||||
|
let icons = provider.ambientNotificationIcons;
|
||||||
|
let iconNames = Object.keys(icons);
|
||||||
|
let notif = icons[iconNames[0]];
|
||||||
|
if (!notif) {
|
||||||
|
button.setAttribute("badge", "");
|
||||||
|
button.setAttribute("aria-label", "");
|
||||||
|
button.setAttribute("tooltiptext", "");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.style.listStyleImage = "url(" + notif.iconURL || provider.iconURL + ")";
|
||||||
|
button.setAttribute("tooltiptext", notif.label);
|
||||||
|
|
||||||
|
let badge = notif.counter || "";
|
||||||
|
button.setAttribute("badge", badge);
|
||||||
|
let ariaLabel = notif.label;
|
||||||
|
// if there is a badge value, we must use a localizable string to insert it.
|
||||||
|
if (badge)
|
||||||
|
ariaLabel = gNavigatorBundle.getFormattedString("social.aria.toolbarButtonBadgeText",
|
||||||
|
[ariaLabel, badge]);
|
||||||
|
button.setAttribute("aria-label", ariaLabel);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
showPopup: function(aToolbarButton) {
|
||||||
|
if (!Social.allowMultipleWorkers)
|
||||||
|
return;
|
||||||
|
// attach our notification panel if necessary
|
||||||
|
let origin = aToolbarButton.getAttribute("origin");
|
||||||
|
let provider = Social._getProviderFromOrigin(origin);
|
||||||
|
this._attachNotificatonPanel(aToolbarButton, provider);
|
||||||
|
|
||||||
|
let panel = document.getElementById("social-notification-panel");
|
||||||
|
let notificationFrameId = aToolbarButton.getAttribute("notificationFrameId");
|
||||||
|
let notificationFrame = document.getElementById(notificationFrameId);
|
||||||
|
|
||||||
|
let wasAlive = SharedFrame.isGroupAlive(notificationFrameId);
|
||||||
|
SharedFrame.setOwner(notificationFrameId, notificationFrame);
|
||||||
|
|
||||||
|
// Clear dimensions on all browsers so the panel size will
|
||||||
|
// only use the selected browser.
|
||||||
|
let frameIter = panel.firstElementChild;
|
||||||
|
while (frameIter) {
|
||||||
|
frameIter.collapsed = (frameIter != notificationFrame);
|
||||||
|
frameIter = frameIter.nextElementSibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dispatchPanelEvent(name) {
|
||||||
|
let evt = notificationFrame.contentDocument.createEvent("CustomEvent");
|
||||||
|
evt.initCustomEvent(name, true, true, {});
|
||||||
|
notificationFrame.contentDocument.documentElement.dispatchEvent(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
let dynamicResizer = this._dynamicResizer;
|
||||||
|
panel.addEventListener("popuphidden", function onpopuphiding() {
|
||||||
|
panel.removeEventListener("popuphidden", onpopuphiding);
|
||||||
|
aToolbarButton.removeAttribute("open");
|
||||||
|
dynamicResizer.stop();
|
||||||
|
notificationFrame.docShell.isActive = false;
|
||||||
|
dispatchPanelEvent("socialFrameHide");
|
||||||
|
});
|
||||||
|
|
||||||
|
panel.addEventListener("popupshown", function onpopupshown() {
|
||||||
|
panel.removeEventListener("popupshown", onpopupshown);
|
||||||
|
// This attribute is needed on both the button and the
|
||||||
|
// containing toolbaritem since the buttons on OS X have
|
||||||
|
// moz-appearance:none, while their container gets
|
||||||
|
// moz-appearance:toolbarbutton due to the way that toolbar buttons
|
||||||
|
// get combined on OS X.
|
||||||
|
aToolbarButton.setAttribute("open", "true");
|
||||||
|
notificationFrame.docShell.isActive = true;
|
||||||
|
notificationFrame.docShell.isAppTab = true;
|
||||||
|
if (notificationFrame.contentDocument.readyState == "complete" && wasAlive) {
|
||||||
|
dynamicResizer.start(panel, notificationFrame);
|
||||||
|
dispatchPanelEvent("socialFrameShow");
|
||||||
|
} else {
|
||||||
|
// first time load, wait for load and dispatch after load
|
||||||
|
notificationFrame.addEventListener("load", function panelBrowserOnload(e) {
|
||||||
|
notificationFrame.removeEventListener("load", panelBrowserOnload, true);
|
||||||
|
dynamicResizer.start(panel, notificationFrame);
|
||||||
|
dispatchPanelEvent("socialFrameShow");
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let navBar = document.getElementById("nav-bar");
|
||||||
|
let anchor = navBar.getAttribute("mode") == "text" ?
|
||||||
|
document.getAnonymousElementByAttribute(aToolbarButton, "class", "toolbarbutton-text") :
|
||||||
|
document.getAnonymousElementByAttribute(aToolbarButton, "class", "toolbarbutton-badge-container");
|
||||||
|
// Bug 849216 - open the popup in a setTimeout so we avoid the auto-rollup
|
||||||
|
// handling from preventing it being opened in some cases.
|
||||||
|
setTimeout(function() {
|
||||||
|
panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, false);
|
||||||
|
}, 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
setPanelErrorMessage: function(aNotificationFrame) {
|
||||||
|
if (!aNotificationFrame)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let src = aNotificationFrame.getAttribute("src");
|
||||||
|
aNotificationFrame.removeAttribute("src");
|
||||||
|
aNotificationFrame.webNavigation.loadURI("about:socialerror?mode=tryAgainOnly&url=" +
|
||||||
|
encodeURIComponent(src),
|
||||||
|
null, null, null, null);
|
||||||
|
let panel = aNotificationFrame.parentNode;
|
||||||
|
sizeSocialPanelToContent(panel, aNotificationFrame);
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -31,6 +31,7 @@ MOCHITEST_BROWSER_FILES = \
|
|||||||
browser_social_multiprovider.js \
|
browser_social_multiprovider.js \
|
||||||
browser_social_multiworker.js \
|
browser_social_multiworker.js \
|
||||||
browser_social_errorPage.js \
|
browser_social_errorPage.js \
|
||||||
|
browser_social_status.js \
|
||||||
browser_social_window.js \
|
browser_social_window.js \
|
||||||
social_activate.html \
|
social_activate.html \
|
||||||
social_activate_iframe.html \
|
social_activate_iframe.html \
|
||||||
|
@ -50,9 +50,10 @@ function installListener(next, aManifest) {
|
|||||||
let expectEvent = "onInstalling";
|
let expectEvent = "onInstalling";
|
||||||
let prefname = getManifestPrefname(aManifest);
|
let prefname = getManifestPrefname(aManifest);
|
||||||
// wait for the actual removal to call next
|
// wait for the actual removal to call next
|
||||||
SocialService.registerProviderListener(function providerListener(topic, data) {
|
SocialService.registerProviderListener(function providerListener(topic, origin, providers) {
|
||||||
if (topic == "provider-removed") {
|
if (topic == "provider-disabled") {
|
||||||
SocialService.unregisterProviderListener(providerListener);
|
SocialService.unregisterProviderListener(providerListener);
|
||||||
|
is(origin, aManifest.origin, "provider disabled");
|
||||||
executeSoon(next);
|
executeSoon(next);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -295,14 +296,15 @@ var tests = {
|
|||||||
Social.enabled = true;
|
Social.enabled = true;
|
||||||
|
|
||||||
// watch for the provider-update and test the new version
|
// watch for the provider-update and test the new version
|
||||||
SocialService.registerProviderListener(function providerListener(topic, data) {
|
SocialService.registerProviderListener(function providerListener(topic, origin, providers) {
|
||||||
if (topic != "provider-update")
|
if (topic != "provider-update")
|
||||||
return;
|
return;
|
||||||
|
is(origin, addonManifest.origin, "provider updated")
|
||||||
SocialService.unregisterProviderListener(providerListener);
|
SocialService.unregisterProviderListener(providerListener);
|
||||||
Services.prefs.clearUserPref("social.whitelist");
|
Services.prefs.clearUserPref("social.whitelist");
|
||||||
let provider = Social._getProviderFromOrigin(addonManifest.origin);
|
let provider = Social._getProviderFromOrigin(origin);
|
||||||
is(provider.manifest.version, 2, "manifest version is 2");
|
is(provider.manifest.version, 2, "manifest version is 2");
|
||||||
Social.uninstallProvider(addonManifest.origin, function() {
|
Social.uninstallProvider(origin, function() {
|
||||||
gBrowser.removeTab(tab);
|
gBrowser.removeTab(tab);
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
@ -155,14 +155,15 @@ var tests = {
|
|||||||
setManifestPref("social.manifest.blocked", manifest_bad);
|
setManifestPref("social.manifest.blocked", manifest_bad);
|
||||||
try {
|
try {
|
||||||
SocialService.addProvider(manifest_bad, function(provider) {
|
SocialService.addProvider(manifest_bad, function(provider) {
|
||||||
// the act of blocking should cause a 'provider-removed' notification
|
// the act of blocking should cause a 'provider-disabled' notification
|
||||||
// from SocialService.
|
// from SocialService.
|
||||||
SocialService.registerProviderListener(function providerListener(topic) {
|
SocialService.registerProviderListener(function providerListener(topic, origin, providers) {
|
||||||
if (topic != "provider-removed")
|
if (topic != "provider-disabled")
|
||||||
return;
|
return;
|
||||||
SocialService.unregisterProviderListener(providerListener);
|
SocialService.unregisterProviderListener(providerListener);
|
||||||
|
is(origin, provider.origin, "provider disabled");
|
||||||
SocialService.getProvider(provider.origin, function(p) {
|
SocialService.getProvider(provider.origin, function(p) {
|
||||||
ok(p==null, "blocklisted provider removed");
|
ok(p == null, "blocklisted provider disabled");
|
||||||
Services.prefs.clearUserPref("social.manifest.blocked");
|
Services.prefs.clearUserPref("social.manifest.blocked");
|
||||||
resetBlocklist(finish);
|
resetBlocklist(finish);
|
||||||
});
|
});
|
||||||
|
@ -19,6 +19,13 @@ function test() {
|
|||||||
|
|
||||||
var tests = {
|
var tests = {
|
||||||
testStatusIcons: function(next) {
|
testStatusIcons: function(next) {
|
||||||
|
let icon = {
|
||||||
|
name: "testIcon",
|
||||||
|
iconURL: "chrome://browser/skin/Info.png",
|
||||||
|
contentPanel: "https://example.com/browser/browser/base/content/test/social/social_panel.html",
|
||||||
|
counter: 1
|
||||||
|
};
|
||||||
|
|
||||||
let iconsReady = false;
|
let iconsReady = false;
|
||||||
let gotSidebarMessage = false;
|
let gotSidebarMessage = false;
|
||||||
|
|
||||||
@ -71,7 +78,7 @@ var tests = {
|
|||||||
ok(true, "got sidebar message");
|
ok(true, "got sidebar message");
|
||||||
gotSidebarMessage = true;
|
gotSidebarMessage = true;
|
||||||
// load a status panel
|
// load a status panel
|
||||||
port.postMessage({topic: "test-ambient-notification"});
|
port.postMessage({topic: "test-ambient-notification", data: icon});
|
||||||
checkNext();
|
checkNext();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
220
browser/base/content/test/social/browser_social_status.js
Normal file
220
browser/base/content/test/social/browser_social_status.js
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
|
||||||
|
|
||||||
|
let manifest = { // builtin provider
|
||||||
|
name: "provider example.com",
|
||||||
|
origin: "https://example.com",
|
||||||
|
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
|
||||||
|
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||||
|
iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
|
||||||
|
};
|
||||||
|
let manifest2 = { // used for testing install
|
||||||
|
name: "provider test1",
|
||||||
|
origin: "https://test1.example.com",
|
||||||
|
workerURL: "https://test1.example.com/browser/browser/base/content/test/social/social_worker.js",
|
||||||
|
statusURL: "https://test1.example.com/browser/browser/base/content/test/social/social_panel.html",
|
||||||
|
iconURL: "https://test1.example.com/browser/browser/base/content/test/moz.png",
|
||||||
|
version: 1
|
||||||
|
};
|
||||||
|
let manifest3 = { // used for testing install
|
||||||
|
name: "provider test2",
|
||||||
|
origin: "https://test2.example.com",
|
||||||
|
sidebarURL: "https://test2.example.com/browser/browser/base/content/test/social/social_sidebar.html",
|
||||||
|
iconURL: "https://test2.example.com/browser/browser/base/content/test/moz.png",
|
||||||
|
version: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function openWindowAndWaitForInit(callback) {
|
||||||
|
let topic = "browser-delayed-startup-finished";
|
||||||
|
let w = OpenBrowserWindow();
|
||||||
|
Services.obs.addObserver(function providerSet(subject, topic, data) {
|
||||||
|
Services.obs.removeObserver(providerSet, topic);
|
||||||
|
executeSoon(() => callback(w));
|
||||||
|
}, topic, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
waitForExplicitFinish();
|
||||||
|
|
||||||
|
Services.prefs.setBoolPref("social.allowMultipleWorkers", true);
|
||||||
|
let toolbar = document.getElementById("nav-bar");
|
||||||
|
let currentsetAtStart = toolbar.currentSet;
|
||||||
|
info("tb0 "+currentsetAtStart);
|
||||||
|
runSocialTestWithProvider(manifest, function () {
|
||||||
|
runSocialTests(tests, undefined, undefined, function () {
|
||||||
|
Services.prefs.clearUserPref("social.remote-install.enabled");
|
||||||
|
// just in case the tests failed, clear these here as well
|
||||||
|
Services.prefs.clearUserPref("social.allowMultipleWorkers");
|
||||||
|
Services.prefs.clearUserPref("social.whitelist");
|
||||||
|
|
||||||
|
// This post-test test ensures that a new window maintains the same
|
||||||
|
// toolbar button set as when we started. That means our insert/removal of
|
||||||
|
// persistent id's is working correctly
|
||||||
|
is(currentsetAtStart, toolbar.currentSet, "toolbar currentset unchanged");
|
||||||
|
openWindowAndWaitForInit(function(w1) {
|
||||||
|
checkSocialUI(w1);
|
||||||
|
// Sometimes the new window adds other buttons to currentSet that are
|
||||||
|
// outside the scope of what we're checking. So we verify that all
|
||||||
|
// buttons from startup are in currentSet for a new window, and that the
|
||||||
|
// provider buttons are properly removed. (e.g on try, window-controls
|
||||||
|
// was not present in currentsetAtStart, but present on the second
|
||||||
|
// window)
|
||||||
|
let tb1 = w1.document.getElementById("nav-bar");
|
||||||
|
info("tb0 "+toolbar.currentSet);
|
||||||
|
info("tb1 "+tb1.currentSet);
|
||||||
|
let startupSet = Set(toolbar.currentSet.split(','));
|
||||||
|
let newSet = Set(tb1.currentSet.split(','));
|
||||||
|
let intersect = Set([x for (x of startupSet) if (newSet.has(x))]);
|
||||||
|
info("intersect "+intersect);
|
||||||
|
let difference = Set([x for (x of newSet) if (!startupSet.has(x))]);
|
||||||
|
info("difference "+difference);
|
||||||
|
is(startupSet.size, intersect.size, "new window toolbar same as old");
|
||||||
|
// verify that our provider buttons are not in difference
|
||||||
|
let id = SocialStatus._toolbarHelper.idFromOrgin(manifest2.origin);
|
||||||
|
ok(!difference.has(id), "status button not persisted at end");
|
||||||
|
w1.close();
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var tests = {
|
||||||
|
testNoButtonOnInstall: function(next) {
|
||||||
|
// we expect the addon install dialog to appear, we need to accept the
|
||||||
|
// install from the dialog.
|
||||||
|
info("Waiting for install dialog");
|
||||||
|
let panel = document.getElementById("servicesInstall-notification");
|
||||||
|
PopupNotifications.panel.addEventListener("popupshown", function onpopupshown() {
|
||||||
|
PopupNotifications.panel.removeEventListener("popupshown", onpopupshown);
|
||||||
|
info("servicesInstall-notification panel opened");
|
||||||
|
panel.button.click();
|
||||||
|
})
|
||||||
|
|
||||||
|
let id = "social-status-button-" + manifest3.origin;
|
||||||
|
let toolbar = document.getElementById("nav-bar");
|
||||||
|
let currentset = toolbar.getAttribute("currentset").split(',');
|
||||||
|
ok(currentset.indexOf(id) < 0, "button is not part of currentset at start");
|
||||||
|
|
||||||
|
let activationURL = manifest3.origin + "/browser/browser/base/content/test/social/social_activate.html"
|
||||||
|
addTab(activationURL, function(tab) {
|
||||||
|
let doc = tab.linkedBrowser.contentDocument;
|
||||||
|
Social.installProvider(doc, manifest3, function(addonManifest) {
|
||||||
|
// enable the provider so we know the button would have appeared
|
||||||
|
SocialService.addBuiltinProvider(manifest3.origin, function(provider) {
|
||||||
|
ok(provider, "provider is installed");
|
||||||
|
currentset = toolbar.getAttribute("currentset").split(',');
|
||||||
|
ok(currentset.indexOf(id) < 0, "button was not added to currentset");
|
||||||
|
Social.uninstallProvider(manifest3.origin, function() {
|
||||||
|
gBrowser.removeTab(tab);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
testButtonOnInstall: function(next) {
|
||||||
|
// we expect the addon install dialog to appear, we need to accept the
|
||||||
|
// install from the dialog.
|
||||||
|
info("Waiting for install dialog");
|
||||||
|
let panel = document.getElementById("servicesInstall-notification");
|
||||||
|
PopupNotifications.panel.addEventListener("popupshown", function onpopupshown() {
|
||||||
|
PopupNotifications.panel.removeEventListener("popupshown", onpopupshown);
|
||||||
|
info("servicesInstall-notification panel opened");
|
||||||
|
panel.button.click();
|
||||||
|
})
|
||||||
|
|
||||||
|
let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html"
|
||||||
|
addTab(activationURL, function(tab) {
|
||||||
|
let doc = tab.linkedBrowser.contentDocument;
|
||||||
|
Social.installProvider(doc, manifest2, function(addonManifest) {
|
||||||
|
// at this point, we should have a button id in the currentset for our provider
|
||||||
|
let id = "social-status-button-" + manifest2.origin;
|
||||||
|
let toolbar = document.getElementById("nav-bar");
|
||||||
|
|
||||||
|
waitForCondition(function() {
|
||||||
|
let currentset = toolbar.getAttribute("currentset").split(',');
|
||||||
|
return currentset.indexOf(id) >= 0;
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
// no longer need the tab
|
||||||
|
gBrowser.removeTab(tab);
|
||||||
|
next();
|
||||||
|
}, "status button added to currentset");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
testButtonOnEnable: function(next) {
|
||||||
|
// enable the provider now
|
||||||
|
SocialService.addBuiltinProvider(manifest2.origin, function(provider) {
|
||||||
|
ok(provider, "provider is installed");
|
||||||
|
let id = "social-status-button-" + manifest2.origin;
|
||||||
|
waitForCondition(function() { return document.getElementById(id) },
|
||||||
|
next, "button exists after enabling social");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
testStatusPanel: function(next) {
|
||||||
|
let icon = {
|
||||||
|
name: "testIcon",
|
||||||
|
iconURL: "chrome://browser/skin/Info.png",
|
||||||
|
counter: 1
|
||||||
|
};
|
||||||
|
// click on panel to open and wait for visibility
|
||||||
|
let provider = Social._getProviderFromOrigin(manifest2.origin);
|
||||||
|
let id = "social-status-button-" + provider.origin;
|
||||||
|
let btn = document.getElementById(id)
|
||||||
|
ok(btn, "got a status button");
|
||||||
|
let port = provider.getWorkerPort();
|
||||||
|
|
||||||
|
port.onmessage = function (e) {
|
||||||
|
let topic = e.data.topic;
|
||||||
|
switch (topic) {
|
||||||
|
case "test-init-done":
|
||||||
|
ok(true, "test-init-done received");
|
||||||
|
ok(provider.profile.userName, "profile was set by test worker");
|
||||||
|
btn.click();
|
||||||
|
break;
|
||||||
|
case "got-social-panel-visibility":
|
||||||
|
ok(true, "got the panel message " + e.data.result);
|
||||||
|
if (e.data.result == "shown") {
|
||||||
|
let panel = document.getElementById("social-notification-panel");
|
||||||
|
panel.hidePopup();
|
||||||
|
} else {
|
||||||
|
port.postMessage({topic: "test-ambient-notification", data: icon});
|
||||||
|
port.close();
|
||||||
|
waitForCondition(function() { return btn.getAttribute("badge"); },
|
||||||
|
function() {
|
||||||
|
is(btn.style.listStyleImage, "url(\"" + icon.iconURL + "\")", "notification icon updated");
|
||||||
|
next();
|
||||||
|
}, "button updated by notification");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
port.postMessage({topic: "test-init"});
|
||||||
|
},
|
||||||
|
testButtonOnDisable: function(next) {
|
||||||
|
// enable the provider now
|
||||||
|
let provider = Social._getProviderFromOrigin(manifest2.origin);
|
||||||
|
ok(provider, "provider is installed");
|
||||||
|
SocialService.removeProvider(manifest2.origin, function() {
|
||||||
|
let id = "social-status-button-" + manifest2.origin;
|
||||||
|
waitForCondition(function() { return !document.getElementById(id) },
|
||||||
|
next, "button does not exist after disabling the provider");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
testButtonOnUninstall: function(next) {
|
||||||
|
Social.uninstallProvider(manifest2.origin, function() {
|
||||||
|
// test that the button is no longer persisted
|
||||||
|
let id = "social-status-button-" + manifest2.origin;
|
||||||
|
let toolbar = document.getElementById("nav-bar");
|
||||||
|
let currentset = toolbar.getAttribute("currentset").split(',');
|
||||||
|
is(currentset.indexOf(id), -1, "button no longer in currentset");
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -177,7 +177,7 @@ function runSocialTests(tests, cbPreTest, cbPostTest, cbFinish) {
|
|||||||
cbPostTest(runNextTest);
|
cbPostTest(runNextTest);
|
||||||
}
|
}
|
||||||
cbPreTest(function() {
|
cbPreTest(function() {
|
||||||
is(providersAtStart, Social.providers.length, "pre-test: no new providers left enabled");
|
info("pre-test: starting with " + Social.providers.length + " providers");
|
||||||
info("sub-test " + name + " starting");
|
info("sub-test " + name + " starting");
|
||||||
try {
|
try {
|
||||||
func.call(tests, cleanupAndRunNextTest);
|
func.call(tests, cleanupAndRunNextTest);
|
||||||
|
@ -14,6 +14,7 @@ var data = {
|
|||||||
// at least one of these must be defined
|
// at least one of these must be defined
|
||||||
"sidebarURL": "/browser/browser/base/content/test/social/social_sidebar.html",
|
"sidebarURL": "/browser/browser/base/content/test/social/social_sidebar.html",
|
||||||
"workerURL": "/browser/browser/base/content/test/social/social_worker.js",
|
"workerURL": "/browser/browser/base/content/test/social/social_worker.js",
|
||||||
|
"statusURL": "/browser/browser/base/content/test/social/social_panel.html",
|
||||||
|
|
||||||
// should be available for display purposes
|
// should be available for display purposes
|
||||||
"description": "A short paragraph about this provider",
|
"description": "A short paragraph about this provider",
|
||||||
|
@ -119,13 +119,7 @@ onconnect = function(e) {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "test-ambient-notification":
|
case "test-ambient-notification":
|
||||||
let icon = {
|
apiPort.postMessage({topic: "social.ambient-notification", data: event.data.data});
|
||||||
name: "testIcon",
|
|
||||||
iconURL: "chrome://browser/skin/Info.png",
|
|
||||||
contentPanel: "https://example.com/browser/browser/base/content/test/social/social_panel.html",
|
|
||||||
counter: 1
|
|
||||||
};
|
|
||||||
apiPort.postMessage({topic: "social.ambient-notification", data: icon});
|
|
||||||
break;
|
break;
|
||||||
case "test-isVisible":
|
case "test-isVisible":
|
||||||
sidebarPort.postMessage({topic: "test-isVisible"});
|
sidebarPort.postMessage({topic: "test-isVisible"});
|
||||||
|
@ -169,24 +169,28 @@ this.Social = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register an observer for changes to the provider list
|
// Register an observer for changes to the provider list
|
||||||
SocialService.registerProviderListener(function providerListener(topic, data) {
|
SocialService.registerProviderListener(function providerListener(topic, origin, providers) {
|
||||||
// An engine change caused by adding/removing a provider should notify.
|
// An engine change caused by adding/removing a provider should notify.
|
||||||
// any providers we receive are enabled in the AddonsManager
|
// any providers we receive are enabled in the AddonsManager
|
||||||
if (topic == "provider-added" || topic == "provider-removed") {
|
if (topic == "provider-installed" || topic == "provider-uninstalled") {
|
||||||
Social._updateProviderCache(data);
|
// installed/uninstalled do not send the providers param
|
||||||
|
Services.obs.notifyObservers(null, "social:" + topic, origin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (topic == "provider-enabled" || topic == "provider-disabled") {
|
||||||
|
Social._updateProviderCache(providers);
|
||||||
Social._updateWorkerState(true);
|
Social._updateWorkerState(true);
|
||||||
Services.obs.notifyObservers(null, "social:providers-changed", null);
|
Services.obs.notifyObservers(null, "social:providers-changed", null);
|
||||||
|
Services.obs.notifyObservers(null, "social:" + topic, origin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (topic == "provider-update") {
|
if (topic == "provider-update") {
|
||||||
// a provider has self-updated its manifest, we need to update our cache
|
// a provider has self-updated its manifest, we need to update our cache
|
||||||
// and reload the provider.
|
// and reload the provider.
|
||||||
let provider = data;
|
Social._updateProviderCache(providers);
|
||||||
SocialService.getOrderedProviderList(function(providers) {
|
let provider = Social._getProviderFromOrigin(origin);
|
||||||
Social._updateProviderCache(providers);
|
provider.reload();
|
||||||
provider.reload();
|
Services.obs.notifyObservers(null, "social:providers-changed", null);
|
||||||
Services.obs.notifyObservers(null, "social:providers-changed", null);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -259,6 +263,10 @@ this.Social = {
|
|||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getManifestByOrigin: function(origin) {
|
||||||
|
return SocialService.getManifestByOrigin(origin);
|
||||||
|
},
|
||||||
|
|
||||||
installProvider: function(doc, data, installCallback) {
|
installProvider: function(doc, data, installCallback) {
|
||||||
SocialService.installProvider(doc, data, installCallback);
|
SocialService.installProvider(doc, data, installCallback);
|
||||||
},
|
},
|
||||||
|
@ -62,14 +62,6 @@ let SocialServiceInternal = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getManifestByOrigin: function(origin) {
|
|
||||||
for (let manifest of SocialServiceInternal.manifests) {
|
|
||||||
if (origin == manifest.origin) {
|
|
||||||
return manifest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
getManifestPrefname: function(origin) {
|
getManifestPrefname: function(origin) {
|
||||||
// Retrieve the prefname for a given origin/manifest.
|
// Retrieve the prefname for a given origin/manifest.
|
||||||
// If no existing pref, return a generated prefname.
|
// If no existing pref, return a generated prefname.
|
||||||
@ -391,7 +383,7 @@ this.SocialService = {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let manifest = SocialServiceInternal.getManifestByOrigin(origin);
|
let manifest = SocialService.getManifestByOrigin(origin);
|
||||||
if (manifest) {
|
if (manifest) {
|
||||||
let addon = new AddonWrapper(manifest);
|
let addon = new AddonWrapper(manifest);
|
||||||
AddonManagerPrivate.callAddonListeners("onEnabling", addon, false);
|
AddonManagerPrivate.callAddonListeners("onEnabling", addon, false);
|
||||||
@ -416,7 +408,7 @@ this.SocialService = {
|
|||||||
ActiveProviders.add(provider.origin);
|
ActiveProviders.add(provider.origin);
|
||||||
|
|
||||||
this.getOrderedProviderList(function (providers) {
|
this.getOrderedProviderList(function (providers) {
|
||||||
this._notifyProviderListeners("provider-added", providers);
|
this._notifyProviderListeners("provider-enabled", provider.origin, providers);
|
||||||
if (onDone)
|
if (onDone)
|
||||||
onDone(provider);
|
onDone(provider);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
@ -429,7 +421,7 @@ this.SocialService = {
|
|||||||
throw new Error("SocialService.removeProvider: no provider with origin " + origin + " exists!");
|
throw new Error("SocialService.removeProvider: no provider with origin " + origin + " exists!");
|
||||||
|
|
||||||
let provider = SocialServiceInternal.providers[origin];
|
let provider = SocialServiceInternal.providers[origin];
|
||||||
let manifest = SocialServiceInternal.getManifestByOrigin(origin);
|
let manifest = SocialService.getManifestByOrigin(origin);
|
||||||
let addon = manifest && new AddonWrapper(manifest);
|
let addon = manifest && new AddonWrapper(manifest);
|
||||||
if (addon) {
|
if (addon) {
|
||||||
AddonManagerPrivate.callAddonListeners("onDisabling", addon, false);
|
AddonManagerPrivate.callAddonListeners("onDisabling", addon, false);
|
||||||
@ -450,7 +442,7 @@ this.SocialService = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.getOrderedProviderList(function (providers) {
|
this.getOrderedProviderList(function (providers) {
|
||||||
this._notifyProviderListeners("provider-removed", providers);
|
this._notifyProviderListeners("provider-disabled", origin, providers);
|
||||||
if (onDone)
|
if (onDone)
|
||||||
onDone();
|
onDone();
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
@ -471,6 +463,15 @@ this.SocialService = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getManifestByOrigin: function(origin) {
|
||||||
|
for (let manifest of SocialServiceInternal.manifests) {
|
||||||
|
if (origin == manifest.origin) {
|
||||||
|
return manifest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
// Returns an array of installed providers, sorted by frecency
|
// Returns an array of installed providers, sorted by frecency
|
||||||
getOrderedProviderList: function(onDone) {
|
getOrderedProviderList: function(onDone) {
|
||||||
SocialServiceInternal.orderedProviders(onDone);
|
SocialServiceInternal.orderedProviders(onDone);
|
||||||
@ -488,10 +489,10 @@ this.SocialService = {
|
|||||||
this._providerListeners.delete(listener);
|
this._providerListeners.delete(listener);
|
||||||
},
|
},
|
||||||
|
|
||||||
_notifyProviderListeners: function (topic, data) {
|
_notifyProviderListeners: function (topic, origin, providers) {
|
||||||
for (let [listener, ] of this._providerListeners) {
|
for (let [listener, ] of this._providerListeners) {
|
||||||
try {
|
try {
|
||||||
listener(topic, data);
|
listener(topic, origin, providers);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
Components.utils.reportError("SocialService: provider listener threw an exception: " + ex);
|
Components.utils.reportError("SocialService: provider listener threw an exception: " + ex);
|
||||||
}
|
}
|
||||||
@ -499,7 +500,7 @@ this.SocialService = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_manifestFromData: function(type, data, principal) {
|
_manifestFromData: function(type, data, principal) {
|
||||||
let sameOriginRequired = ['workerURL', 'sidebarURL', 'shareURL'];
|
let sameOriginRequired = ['workerURL', 'sidebarURL', 'shareURL', 'statusURL'];
|
||||||
|
|
||||||
if (type == 'directory') {
|
if (type == 'directory') {
|
||||||
// directory provided manifests must have origin in manifest, use that
|
// directory provided manifests must have origin in manifest, use that
|
||||||
@ -517,8 +518,9 @@ this.SocialService = {
|
|||||||
// iconURL and name are required
|
// iconURL and name are required
|
||||||
// iconURL may be a different origin (CDN or data url support) if this is
|
// iconURL may be a different origin (CDN or data url support) if this is
|
||||||
// a whitelisted or directory listed provider
|
// a whitelisted or directory listed provider
|
||||||
if (!data['workerURL'] && !data['sidebarURL'] && !data['shareURL']) {
|
let providerHasFeatures = [url for (url of sameOriginRequired) if (data[url])].length > 0;
|
||||||
Cu.reportError("SocialService.manifestFromData manifest missing required workerURL or sidebarURL.");
|
if (!providerHasFeatures) {
|
||||||
|
Cu.reportError("SocialService.manifestFromData manifest missing required urls.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!data['name'] || !data['iconURL']) {
|
if (!data['name'] || !data['iconURL']) {
|
||||||
@ -596,7 +598,10 @@ this.SocialService = {
|
|||||||
aAddon.userDisabled = false;
|
aAddon.userDisabled = false;
|
||||||
}
|
}
|
||||||
schedule(function () {
|
schedule(function () {
|
||||||
this._installProvider(aDOMDocument, data, installCallback);
|
this._installProvider(aDOMDocument, data, aManifest => {
|
||||||
|
this._notifyProviderListeners("provider-installed", aManifest.origin);
|
||||||
|
installCallback(aManifest);
|
||||||
|
});
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
@ -661,7 +666,7 @@ this.SocialService = {
|
|||||||
* have knowledge of the currently selected provider here, we will notify
|
* have knowledge of the currently selected provider here, we will notify
|
||||||
* the front end to deal with any reload.
|
* the front end to deal with any reload.
|
||||||
*/
|
*/
|
||||||
updateProvider: function(aUpdateOrigin, aManifest, aCallback) {
|
updateProvider: function(aUpdateOrigin, aManifest) {
|
||||||
let originUri = Services.io.newURI(aUpdateOrigin, null, null);
|
let originUri = Services.io.newURI(aUpdateOrigin, null, null);
|
||||||
let principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(originUri);
|
let principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(originUri);
|
||||||
let installType = this.getOriginActivationType(aUpdateOrigin);
|
let installType = this.getOriginActivationType(aUpdateOrigin);
|
||||||
@ -682,13 +687,15 @@ this.SocialService = {
|
|||||||
let provider = new SocialProvider(manifest);
|
let provider = new SocialProvider(manifest);
|
||||||
SocialServiceInternal.providers[provider.origin] = provider;
|
SocialServiceInternal.providers[provider.origin] = provider;
|
||||||
// update the cache and ui, reload provider if necessary
|
// update the cache and ui, reload provider if necessary
|
||||||
this._notifyProviderListeners("provider-update", provider);
|
this.getOrderedProviderList(providers => {
|
||||||
|
this._notifyProviderListeners("provider-update", provider.origin, providers);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
uninstallProvider: function(origin, aCallback) {
|
uninstallProvider: function(origin, aCallback) {
|
||||||
let manifest = SocialServiceInternal.getManifestByOrigin(origin);
|
let manifest = SocialService.getManifestByOrigin(origin);
|
||||||
let addon = new AddonWrapper(manifest);
|
let addon = new AddonWrapper(manifest);
|
||||||
addon.uninstall(aCallback);
|
addon.uninstall(aCallback);
|
||||||
}
|
}
|
||||||
@ -720,6 +727,7 @@ function SocialProvider(input) {
|
|||||||
this.workerURL = input.workerURL;
|
this.workerURL = input.workerURL;
|
||||||
this.sidebarURL = input.sidebarURL;
|
this.sidebarURL = input.sidebarURL;
|
||||||
this.shareURL = input.shareURL;
|
this.shareURL = input.shareURL;
|
||||||
|
this.statusURL = input.statusURL;
|
||||||
this.origin = input.origin;
|
this.origin = input.origin;
|
||||||
let originUri = Services.io.newURI(input.origin, null, null);
|
let originUri = Services.io.newURI(input.origin, null, null);
|
||||||
this.principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(originUri);
|
this.principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(originUri);
|
||||||
@ -766,7 +774,7 @@ SocialProvider.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
get manifest() {
|
get manifest() {
|
||||||
return SocialServiceInternal.getManifestByOrigin(this.origin);
|
return SocialService.getManifestByOrigin(this.origin);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Reference to a workerAPI object for this provider. Null if the provider has
|
// Reference to a workerAPI object for this provider. Null if the provider has
|
||||||
@ -1012,7 +1020,7 @@ function getPrefnameFromOrigin(origin) {
|
|||||||
function AddonInstaller(sourceURI, aManifest, installCallback) {
|
function AddonInstaller(sourceURI, aManifest, installCallback) {
|
||||||
aManifest.updateDate = Date.now();
|
aManifest.updateDate = Date.now();
|
||||||
// get the existing manifest for installDate
|
// get the existing manifest for installDate
|
||||||
let manifest = SocialServiceInternal.getManifestByOrigin(aManifest.origin);
|
let manifest = SocialService.getManifestByOrigin(aManifest.origin);
|
||||||
let isNewInstall = !manifest;
|
let isNewInstall = !manifest;
|
||||||
if (manifest && manifest.installDate)
|
if (manifest && manifest.installDate)
|
||||||
aManifest.installDate = manifest.installDate;
|
aManifest.installDate = manifest.installDate;
|
||||||
@ -1088,6 +1096,7 @@ var SocialAddonProvider = {
|
|||||||
Services.prefs.clearUserPref(getPrefnameFromOrigin(aAddon.manifest.origin));
|
Services.prefs.clearUserPref(getPrefnameFromOrigin(aAddon.manifest.origin));
|
||||||
aAddon.pendingOperations -= AddonManager.PENDING_UNINSTALL;
|
aAddon.pendingOperations -= AddonManager.PENDING_UNINSTALL;
|
||||||
AddonManagerPrivate.callAddonListeners("onUninstalled", aAddon);
|
AddonManagerPrivate.callAddonListeners("onUninstalled", aAddon);
|
||||||
|
SocialService._notifyProviderListeners("provider-uninstalled", aAddon.manifest.origin);
|
||||||
if (aCallback)
|
if (aCallback)
|
||||||
schedule(aCallback);
|
schedule(aCallback);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user