Bug 983481 - Open a post activation landing page. r=markh, a=lsblakk
authorShane Caraveo <scaraveo@mozilla.com>
Wed, 30 Apr 2014 12:08:23 -0700
changeset 192243 315f0fda0470
parent 192242 bbac2a994298
child 192244 d7abd8044d61
push id3540
push userryanvm@gmail.com
push date2014-05-09 15:08 +0000
Treeherderresults
reviewersmarkh, lsblakk
bugs983481
milestone30.0
Bug 983481 - Open a post activation landing page. r=markh, a=lsblakk
browser/base/content/browser-social.js
browser/base/content/test/social/browser.ini
browser/base/content/test/social/browser_social_activation.js
browser/base/content/test/social/social_activate.html
browser/base/content/test/social/social_postActivation.html
toolkit/components/social/SocialService.jsm
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -228,16 +228,19 @@ SocialUI = {
         return;
       }
     }
     Social.installProvider(targetDoc, data, function(manifest) {
       Social.activateFromOrigin(manifest.origin, function(provider) {
         if (provider.sidebarURL) {
           SocialSidebar.show(provider.origin);
         }
+        if (provider.postActivationURL) {
+          openUILinkIn(provider.postActivationURL, "tab");
+        }
       });
     });
   },
 
   showLearnMore: function() {
     let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "social-api";
     openUILinkIn(url, "tab");
   },
--- a/browser/base/content/test/social/browser.ini
+++ b/browser/base/content/test/social/browser.ini
@@ -11,16 +11,17 @@ support-files =
   share.html
   social_activate.html
   social_activate_iframe.html
   social_chat.html
   social_crash_content_helper.js
   social_flyout.html
   social_mark.html
   social_panel.html
+  social_postActivation.html
   social_sidebar.html
   social_sidebar_empty.html
   social_window.html
   social_worker.js
   unchecked.jpg
 
 [browser_addons.js]
 [browser_blocklist.js]
--- a/browser/base/content/test/social/browser_social_activation.js
+++ b/browser/base/content/test/social/browser_social_activation.js
@@ -85,19 +85,22 @@ function activateIFrameProvider(domain, 
 
 function waitForProviderLoad(cb) {
   Services.obs.addObserver(function providerSet(subject, topic, data) {
     Services.obs.removeObserver(providerSet, "social:provider-enabled");
     info("social:provider-enabled observer was notified");
     waitForCondition(function() {
       let sbrowser = document.getElementById("social-sidebar-browser");
       let provider = SocialSidebar.provider;
+      let postActivation = provider && gBrowser.contentDocument.location.href == provider.origin + "/browser/browser/base/content/test/social/social_postActivation.html";
+
       return provider &&
              provider.profile &&
              provider.profile.displayName &&
+             postActivation &&
              sbrowser.docShellIsActive;
     }, function() {
       // executeSoon to let the browser UI observers run first
       executeSoon(cb);
     },
     "waitForProviderLoad: provider profile was not set");
   }, "social:provider-enabled", false);
 }
@@ -285,23 +288,28 @@ var tests = {
     gBrowser.selectedBrowser.addEventListener("load", function tabLoad() {
       gBrowser.selectedBrowser.removeEventListener("load", tabLoad, true);
       let browser = blanktab.linkedBrowser;
       is(browser.currentURI.spec, "about:addons", "about:addons should load into blank tab.");
 
       let prefname = addBuiltinManifest(gProviders[0]);
       activateOneProvider(gProviders[0], true, function() {
         info("first activation completed");
+        is(gBrowser.contentDocument.location.href, gProviders[0].origin + "/browser/browser/base/content/test/social/social_postActivation.html");
+        gBrowser.removeTab(gBrowser.selectedTab);
+        is(gBrowser.contentDocument.location.href, gProviders[0].origin + "/browser/browser/base/content/test/social/social_activate.html");
         gBrowser.removeTab(gBrowser.selectedTab);
         tabsToRemove.pop();
         // uninstall the provider
         clickAddonRemoveButton(blanktab, function(addon) {
           checkSocialUI();
           activateOneProvider(gProviders[0], true, function() {
             info("second activation completed");
+            is(gBrowser.contentDocument.location.href, gProviders[0].origin + "/browser/browser/base/content/test/social/social_postActivation.html");
+            gBrowser.removeTab(gBrowser.selectedTab);
 
             // after closing the addons tab, verify provider is still installed
             gBrowser.tabContainer.addEventListener("TabClose", function onTabClose() {
               gBrowser.tabContainer.removeEventListener("TabClose", onTabClose);
               AddonManager.getAddonsByTypes(["service"], function(aAddons) {
                 is(aAddons.length, 1, "there can be only one");
                 Services.prefs.clearUserPref("social.whitelist");
                 resetBuiltinManifestPref(prefname);
--- a/browser/base/content/test/social/social_activate.html
+++ b/browser/base/content/test/social/social_activate.html
@@ -10,16 +10,17 @@ var data = {
   "iconURL": "chrome://branding/content/icon16.png",
   "icon32URL": "chrome://branding/content/favicon32.png",
   "icon64URL": "chrome://branding/content/icon64.png",
 
   // at least one of these must be defined
   "sidebarURL": "/browser/browser/base/content/test/social/social_sidebar.html",
   "workerURL": "/browser/browser/base/content/test/social/social_worker.js",
   "statusURL": "/browser/browser/base/content/test/social/social_panel.html",
+  "postActivationURL": "/browser/browser/base/content/test/social/social_postActivation.html",
 
   // should be available for display purposes
   "description": "A short paragraph about this provider",
   "author": "Shane Caraveo, Mozilla",
 
   // optional
   "version": 1
 }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/social/social_postActivation.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+	<title>Post-Activation test</title>
+</head>
+
+<body>
+
+Post Activation landing page
+
+</body>
+</html>
--- a/toolkit/components/social/SocialService.jsm
+++ b/toolkit/components/social/SocialService.jsm
@@ -496,49 +496,54 @@ this.SocialService = {
         listener(topic, origin, providers);
       } catch (ex) {
         Components.utils.reportError("SocialService: provider listener threw an exception: " + ex);
       }
     }
   },
 
   _manifestFromData: function(type, data, principal) {
-    let sameOriginRequired = ['workerURL', 'sidebarURL', 'shareURL', 'statusURL', 'markURL'];
+    let featureURLs = ['workerURL', 'sidebarURL', 'shareURL', 'statusURL', 'markURL'];
+    let resolveURLs = featureURLs.concat(['postActivationURL']);
 
     if (type == 'directory') {
       // directory provided manifests must have origin in manifest, use that
       if (!data['origin']) {
         Cu.reportError("SocialService.manifestFromData directory service provided manifest without origin.");
         return null;
       }
       let URI = Services.io.newURI(data.origin, null, null);
       principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(URI);
     }
     // force/fixup origin
     data.origin = principal.origin;
 
-    // workerURL, sidebarURL is required and must be same-origin
     // iconURL and name are required
     // iconURL may be a different origin (CDN or data url support) if this is
     // a whitelisted or directory listed provider
-    let providerHasFeatures = [url for (url of sameOriginRequired) if (data[url])].length > 0;
+    let providerHasFeatures = [url for (url of featureURLs) if (data[url])].length > 0;
     if (!providerHasFeatures) {
       Cu.reportError("SocialService.manifestFromData manifest missing required urls.");
       return null;
     }
     if (!data['name'] || !data['iconURL']) {
       Cu.reportError("SocialService.manifestFromData manifest missing name or iconURL.");
       return null;
     }
-    for (let url of sameOriginRequired) {
+    for (let url of resolveURLs) {
       if (data[url]) {
         try {
-          data[url] = Services.io.newURI(principal.URI.resolve(data[url]), null, null).spec;
+          let resolved = Services.io.newURI(principal.URI.resolve(data[url]), null, null);
+          if (!(resolved.schemeIs("http") || resolved.schemeIs("https"))) {
+            Cu.reportError("SocialService.manifestFromData unsupported scheme '" + resolved.scheme + "' for " + principal.origin);
+            return null;
+          }
+          data[url] = resolved.spec;
         } catch(e) {
-          Cu.reportError("SocialService.manifestFromData same-origin missmatch in manifest for " + principal.origin);
+          Cu.reportError("SocialService.manifestFromData unable to resolve '" + url + "' for " + principal.origin);
           return null;
         }
       }
     }
     return data;
   },
 
   _getChromeWindow: function(aWindow) {
@@ -732,16 +737,17 @@ function SocialProvider(input) {
   this.icon64URL = input.icon64URL;
   this.workerURL = input.workerURL;
   this.sidebarURL = input.sidebarURL;
   this.shareURL = input.shareURL;
   this.statusURL = input.statusURL;
   this.markURL = input.markURL;
   this.markedIcon = input.markedIcon;
   this.unmarkedIcon = input.unmarkedIcon;
+  this.postActivationURL = input.postActivationURL;
   this.origin = input.origin;
   let originUri = Services.io.newURI(input.origin, null, null);
   this.principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(originUri);
   this.ambientNotificationIcons = {};
   this.errorState = null;
   this.frecency = 0;
 
   let activationType = getOriginActivationType(input.origin);