Bug 808215 - Disable social API in private windows for per-window Private Browsing builds. r=jaws,mixedpuppy

--HG--
rename : browser/base/content/test/social/browser_social.js => browser/base/content/test/social/browser_social_globalPB.js
This commit is contained in:
Mark Hammond 2013-01-24 21:14:36 +11:00
parent 4c2b124e68
commit 1311d8b627
9 changed files with 218 additions and 41 deletions

View File

@ -18,6 +18,11 @@ let SocialUI = {
Services.obs.addObserver(this, "social:recommend-info-changed", false);
Services.obs.addObserver(this, "social:frameworker-error", false);
Services.obs.addObserver(this, "social:provider-set", false);
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
// this observer is necessary so things are also correctly updated
// when per-window PB isn't active
Services.obs.addObserver(this, "private-browsing", false);
#endif
Services.prefs.addObserver("social.sidebar.open", this, false);
Services.prefs.addObserver("social.toast-notifications.enabled", this, false);
@ -41,6 +46,9 @@ let SocialUI = {
Services.obs.removeObserver(this, "social:recommend-info-changed");
Services.obs.removeObserver(this, "social:frameworker-error");
Services.obs.removeObserver(this, "social:provider-set");
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
Services.obs.removeObserver(this, "private-browsing");
#endif
Services.prefs.removeObserver("social.sidebar.open", this);
Services.prefs.removeObserver("social.toast-notifications.enabled", this);
@ -120,7 +128,7 @@ let SocialUI = {
}
break;
case "social:frameworker-error":
if (Social.provider && Social.provider.origin == data) {
if (this.enabled && Social.provider.origin == data) {
SocialSidebar.setSidebarErrorMessage("frameworker-error");
}
break;
@ -132,6 +140,14 @@ let SocialUI = {
SocialToolbar.updateButton();
}
break;
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
case "private-browsing":
this._updateEnabledState();
this._updateActiveUI();
SocialToolbar.init();
break;
#endif
}
} catch (e) {
Components.utils.reportError(e + "\n" + e.stack);
@ -155,8 +171,15 @@ let SocialUI = {
},
_updateActiveUI: function SocialUI_updateActiveUI() {
// The "active" UI isn't dependent on there being a provider, just on
// social being "active" (but also chromeless/PB)
let enabled = Social.active && !this._chromeless
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
&& !PrivateBrowsingUtils.isWindowPrivate(window)
#endif
;
let broadcaster = document.getElementById("socialActiveBroadcaster");
broadcaster.hidden = !Social.active;
broadcaster.hidden = !enabled;
if (!Social.provider)
return;
@ -172,7 +195,7 @@ let SocialUI = {
"social.turnOn.accesskey");
toggleCommand.setAttribute("label", label);
toggleCommand.setAttribute("accesskey", accesskey);
toggleCommand.setAttribute("hidden", Social.active ? "false" : "true");
toggleCommand.setAttribute("hidden", enabled ? "false" : "true");
},
_updateMenuItems: function () {
@ -203,6 +226,11 @@ let SocialUI = {
if (whitelist.split(",").indexOf(providerOrigin) == -1)
return;
// If we are in PB mode, we silently do nothing (bug 829404 exists to
// do something sensible here...)
if (PrivateBrowsingUtils.isWindowPrivate(window))
return;
// If the last event was received < 1s ago, ignore this one
let now = Date.now();
if (now - Social.lastEventReceived < 1000)
@ -285,7 +313,30 @@ let SocialUI = {
if (confirmationIndex == 0) {
Social.deactivateFromOrigin(Social.provider.origin);
}
}
},
get _chromeless() {
// Is this a popup window that doesn't want chrome shown?
let docElem = document.documentElement;
let chromeless = docElem.getAttribute("chromehidden").indexOf("extrachrome") >= 0;
// 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
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|| PrivateBrowsingUtils.isWindowPrivate(window)
#endif
)
return false;
return !!(Social.active && Social.provider && Social.provider.enabled);
},
}
let SocialChatBar = {
@ -295,11 +346,7 @@ let SocialChatBar = {
// Whether the chatbar is available for this window. Note that in full-screen
// mode chats are available, but not shown.
get isAvailable() {
if (!Social.haveLoggedInUser())
return false;
let docElem = document.documentElement;
let chromeless = docElem.getAttribute("chromehidden").indexOf("extrachrome") >= 0;
return Social.uiVisible && !chromeless;
return SocialUI.enabled && Social.haveLoggedInUser();
},
// Does this chatbar have any chats (whether minimized, collapsed or normal)
get hasChats() {
@ -394,7 +441,7 @@ let SocialFlyout = {
_createFrame: function() {
let panel = this.panel;
if (!Social.provider || panel.firstChild)
if (!SocialUI.enabled || panel.firstChild)
return;
// create and initialize the panel for this window
let iframe = document.createElement("iframe");
@ -471,7 +518,7 @@ let SocialFlyout = {
// Hide any other social panels that may be open.
document.getElementById("social-notification-panel").hidePopup();
if (!Social.provider)
if (!SocialUI.enabled)
return;
let panel = this.panel;
if (!panel.firstChild)
@ -537,7 +584,7 @@ let SocialShareButton = {
// changes, via updateProvider)
updateProfileInfo: function SSB_updateProfileInfo() {
let profileRow = document.getElementById("unsharePopupHeader");
let profile = Social.provider.profile;
let profile = SocialUI.enabled ? Social.provider.profile : null;
if (profile && profile.displayName) {
profileRow.hidden = false;
let portrait = document.getElementById("socialUserPortrait");
@ -569,7 +616,7 @@ let SocialShareButton = {
updateButtonHiddenState: function SSB_updateButtonHiddenState() {
let shareButton = this.shareButton;
if (shareButton)
shareButton.hidden = !Social.uiVisible || Social.provider.recommendInfo == null ||
shareButton.hidden = !SocialUI.enabled || Social.provider.recommendInfo == null ||
!Social.haveLoggedInUser() ||
!this.canSharePage(gBrowser.currentURI);
@ -635,7 +682,7 @@ let SocialShareButton = {
let shareButton = this.shareButton;
let currentPageShared = shareButton && !shareButton.hidden && Social.isPageShared(gBrowser.currentURI);
let recommendInfo = Social.provider ? Social.provider.recommendInfo : null;
let recommendInfo = SocialUI.enabled ? Social.provider.recommendInfo : null;
// Provide a11y-friendly notification of share.
let status = document.getElementById("share-button-status");
if (status) {
@ -677,10 +724,10 @@ var SocialMenu = {
let separator = document.getElementById("socialAmbientMenuSeparator");
separator.hidden = true;
if (!Social.uiVisible)
let provider = SocialUI.enabled ? Social.provider : null;
if (!provider)
return;
let provider = Social.provider;
let iconNames = Object.keys(provider.ambientNotificationIcons);
for (let name of iconNames) {
let icon = provider.ambientNotificationIcons[name];
@ -718,7 +765,7 @@ var SocialToolbar = {
// Called when the Social.provider changes
updateProvider: function () {
if (!Social.provider)
if (!SocialUI.enabled)
return;
this.button.style.listStyleImage = "url(" + Social.provider.iconURL + ")";
this.button.setAttribute("label", Social.provider.name);
@ -736,7 +783,7 @@ var SocialToolbar = {
// socialActiveBroadcaster is responsible for that.
updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() {
let tbi = document.getElementById("social-toolbar-item");
let socialEnabled = Social.uiVisible;
let socialEnabled = SocialUI.enabled;
for (let className of ["social-statusarea-separator", "social-statusarea-user"]) {
for (let element of document.getElementsByClassName(className))
element.hidden = !socialEnabled;
@ -792,7 +839,7 @@ var SocialToolbar = {
const CACHE_PREF_NAME = "social.cached.ambientNotificationIcons";
// provider.profile == undefined means no response yet from the provider
// to tell us whether the user is logged in or not.
if (!provider.enabled ||
if (!SocialUI.enabled ||
(!Social.haveLoggedInUser() && provider.profile !== undefined)) {
// Either no enabled provider, or there is a provider and it has
// responded with a profile and the user isn't loggedin. The icons
@ -1004,8 +1051,8 @@ var SocialToolbar = {
while (providerMenuSep.previousSibling.nodeName == "menuitem") {
menu.removeChild(providerMenuSep.previousSibling);
}
// only show a selection if there is more than one
if (!Social.enabled || providers.length < 2) {
// only show a selection if enabled and there is more than one
if (!SocialUI.enabled || Social.providers.length < 2) {
providerMenuSep.hidden = true;
return;
}
@ -1046,15 +1093,7 @@ var SocialSidebar = {
// Whether the sidebar can be shown for this window.
get canShow() {
return Social.uiVisible && Social.provider.sidebarURL && !this.chromeless;
},
// Whether this is a "chromeless window" (e.g. popup window). We don't show
// the sidebar in these windows.
get chromeless() {
let docElem = document.documentElement;
return docElem.getAttribute('disablechrome') ||
docElem.getAttribute('chromehidden').contains("toolbar");
return SocialUI.enabled && Social.provider.sidebarURL;
},
// Whether the user has toggled the sidebar on (for windows where it can appear)

View File

@ -29,9 +29,13 @@ _BROWSER_FILES = \
social_worker.js \
$(NULL)
ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
_BROWSER_FILES += \
browser_social.js \
browser_social_perwindowPB.js \
$(NULL)
else
_BROWSER_FILES += \
browser_social_globalPB.js \
$(NULL)
endif

View File

@ -0,0 +1,82 @@
/* 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/. */
function openTab(win, url, callback) {
let newTab = win.gBrowser.addTab(url);
let tabBrowser = win.gBrowser.getBrowserForTab(newTab);
tabBrowser.addEventListener("load", function tabLoadListener() {
tabBrowser.removeEventListener("load", tabLoadListener, true);
win.gBrowser.selectedTab = newTab;
callback(newTab);
}, true)
}
// Tests for per-window private browsing.
function openPBWindow(callback) {
let w = OpenBrowserWindow({private: true});
w.addEventListener("load", function loadListener() {
w.removeEventListener("load", loadListener);
openTab(w, "http://example.com", function() {
callback(w);
});
});
}
function postAndReceive(port, postTopic, receiveTopic, callback) {
port.onmessage = function(e) {
if (e.data.topic == receiveTopic)
callback();
}
port.postMessage({topic: postTopic});
}
function test() {
waitForExplicitFinish();
let manifest = { // normal provider
name: "provider 1",
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/social/moz.png"
};
runSocialTestWithProvider(manifest, function (finishcb) {
openTab(window, "http://example.com", function(newTab) {
runSocialTests(tests, undefined, undefined, function() {
window.gBrowser.removeTab(newTab);
finishcb();
});
});
});
}
var tests = {
testPrivateBrowsing: function(next) {
let port = Social.provider.getWorkerPort();
ok(port, "provider has a port");
postAndReceive(port, "test-init", "test-init-done", function() {
// social features should all be enabled in the existing window.
info("checking main window ui");
ok(window.SocialUI.enabled, "social is enabled in normal window");
checkSocialUI(window);
// open a new private-window
openPBWindow(function(pbwin) {
// The provider should remain alive.
postAndReceive(port, "ping", "pong", function() {
// the new window should have no social features at all.
info("checking private window ui");
ok(!pbwin.SocialUI.enabled, "social is disabled in a PB window");
checkSocialUI(pbwin);
// but they should all remain enabled in the initial window
info("checking main window ui");
ok(window.SocialUI.enabled, "social is still enabled in normal window");
checkSocialUI(window);
// that's all folks...
pbwin.close();
next();
})
});
});
},
}

View File

@ -148,3 +148,36 @@ function runSocialTests(tests, cbPreTest, cbPostTest, cbFinish) {
}
runNextTest();
}
// A fairly large hammer which checks all aspects of the SocialUI for
// internal consistency.
function checkSocialUI(win) {
let win = win || window;
let doc = win.document;
let provider = Social.provider;
let enabled = win.SocialUI.enabled;
function isbool(a, b, msg) {
is(!!a, !!b, msg);
}
isbool(win.SocialSidebar.canShow, enabled, "social sidebar active?");
if (enabled)
isbool(win.SocialSidebar.opened, enabled, "social sidebar open?");
isbool(win.SocialChatBar.isAvailable, enabled && Social.haveLoggedInUser(), "chatbar available?");
isbool(!win.SocialChatBar.chatbar.hidden, enabled && Social.haveLoggedInUser(), "chatbar visible?");
isbool(!win.SocialShareButton.shareButton.hidden, enabled && provider.recommendInfo, "share button visible?");
isbool(!doc.getElementById("social-toolbar-item").hidden, enabled, "toolbar items visible?");
if (enabled)
todo_is(win.SocialToolbar.button.style.listStyleImage, 'url("' + provider.iconURL + '")', "Bug 821262 - toolbar button has provider icon");
// and for good measure, check all the social commands.
// Social:Remove - never disabled directly but parent nodes are
isbool(!doc.getElementById("Social:Toggle").hidden, enabled, "Social:Toggle visible?");
// Until bug 821262 is fixed, ToggleNotifications might not be updated correctly...
// isbool(!doc.getElementById("Social:ToggleNotifications").hidden, enabled, "Bug 821262 - Social:ToggleNotifications visible?");
isbool(!doc.getElementById("Social:FocusChat").hidden, enabled && Social.haveLoggedInUser(), "Social:FocusChat visible?");
isbool(doc.getElementById("Social:FocusChat").getAttribute("disabled"), enabled ? "false" : "true", "Social:FocusChat disabled?");
is(doc.getElementById("Social:SharePage").getAttribute("disabled"), enabled && provider.recommendInfo ? "false" : "true", "Social:SharePage visible?");
// broadcasters.
isbool(!doc.getElementById("socialActiveBroadcaster").hidden, enabled, "socialActiveBroadcaster hidden?");
}

View File

@ -22,14 +22,17 @@ EXTRA_JS_MODULES = \
offlineAppCache.jsm \
SignInToWebsite.jsm \
TelemetryTimestamps.jsm \
Social.jsm \
webappsUI.jsm \
webrtcUI.jsm \
KeywordURLResetPrompter.jsm \
SharedFrame.jsm \
$(NULL)
EXTRA_PP_JS_MODULES = RecentWindow.jsm
EXTRA_PP_JS_MODULES = \
RecentWindow.jsm \
Social.jsm \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
EXTRA_JS_MODULES += \

View File

@ -84,7 +84,9 @@ this.Social = {
}
if (!this._addedObservers) {
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
Services.obs.addObserver(this, "private-browsing", false);
#endif
Services.obs.addObserver(this, "social:pref-changed", false);
this._addedObservers = true;
}
@ -131,6 +133,7 @@ this.Social = {
},
observe: function(aSubject, aTopic, aData) {
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
if (aTopic == "private-browsing") {
if (aData == "enter") {
this._enabledBeforePrivateBrowsing = this.enabled;
@ -144,7 +147,9 @@ this.Social = {
this.enabled = false;
this.enabled = this._enabledBeforePrivateBrowsing;
}
} else if (aTopic == "social:pref-changed") {
} else
#endif
if (aTopic == "social:pref-changed") {
// Make sure our provider's enabled state matches the overall state of the
// social components.
if (this.provider)
@ -152,10 +157,6 @@ this.Social = {
}
},
get uiVisible() {
return this.provider && this.provider.enabled;
},
set enabled(val) {
SocialService.enabled = val;
},

View File

@ -15,6 +15,9 @@ EXTRA_JS_MODULES = \
MessagePortWorker.js \
SocialService.jsm \
WorkerAPI.jsm \
$(NULL)
EXTRA_PP_JS_MODULES = \
MozSocialAPI.jsm \
$(NULL)

View File

@ -8,6 +8,9 @@ Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "SocialService", "resource://gre/modules/SocialService.jsm");
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", "resource://gre/modules/PrivateBrowsingUtils.jsm");
#endif
this.EXPORTED_SYMBOLS = ["MozSocialAPI", "openChatWindow"];
@ -40,7 +43,11 @@ this.MozSocialAPI = {
function injectController(doc, topic, data) {
try {
let window = doc.defaultView;
if (!window)
if (!window
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|| !PrivateBrowsingUtils.isWindowPrivate(window)
#endif
)
return;
// Do not attempt to load the API into about: error pages
@ -228,7 +235,12 @@ function getChromeWindow(contentWin) {
}
function isWindowGoodForChats(win) {
return win.SocialChatBar && win.SocialChatBar.isAvailable;
return win.SocialChatBar
&& win.SocialChatBar.isAvailable
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
&& !PrivateBrowsingUtils.isWindowPrivate(win)
#endif
;
}
function findChromeWindowForChats(preferredWindow) {