Bug 1029098 support global sidebar state for users who do not turn on restore session state, r=felipe, a=sylvestre
authorShane Caraveo <scaraveo@mozilla.com>
Thu, 26 Jun 2014 18:35:34 -0700
changeset 207403 f2be42467a16dc3c6a1eff6ce3ab0283d5cb4768
parent 207402 a101306a4aa694fcaf410f6b04a9668dca43a593
child 207404 731a5e8831e6b7b9d325975fbeee35fd4497a5ca
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfelipe, sylvestre
bugs1029098
milestone32.0a2
Bug 1029098 support global sidebar state for users who do not turn on restore session state, r=felipe, a=sylvestre
browser/base/content/browser-social.js
browser/base/content/test/social/browser_social_window.js
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -86,16 +86,17 @@ SocialUI = {
     this._initialized = true;
   },
 
   // Called on window unload
   uninit: function SocialUI_uninit() {
     if (!this._initialized) {
       return;
     }
+    SocialSidebar.saveWindowState();
 
     Services.obs.removeObserver(this, "social:ambient-notification-changed");
     Services.obs.removeObserver(this, "social:profile-changed");
     Services.obs.removeObserver(this, "social:frameworker-error");
     Services.obs.removeObserver(this, "social:providers-changed");
     Services.obs.removeObserver(this, "social:provider-reload");
     Services.obs.removeObserver(this, "social:provider-enabled");
     Services.obs.removeObserver(this, "social:provider-disabled");
@@ -706,16 +707,21 @@ SocialSidebar = {
 
   // Whether the user has toggled the sidebar on (for windows where it can appear)
   get opened() {
     let broadcaster = document.getElementById("socialSidebarBroadcaster");
     return !broadcaster.hidden;
   },
 
   restoreWindowState: function() {
+    // Window state is used to allow different sidebar providers in each window.
+    // We also store the provider used in a pref as the default sidebar to
+    // maintain that state for users who do not restore window state. The
+    // existence of social.sidebar.provider means the sidebar is open with that
+    // provider.
     this._initialized = true;
     if (!this.canShow)
       return;
 
     if (Services.prefs.prefHasUserValue("social.provider.current")) {
       // "upgrade" when the first window opens if we have old prefs.  We get the
       // values from prefs this one time, window state will be saved when this
       // window is closed.
@@ -733,34 +739,54 @@ SocialSidebar = {
         "origin": origin
       };
       SessionStore.setWindowValue(window, "socialSidebar", JSON.stringify(data));
     }
 
     let data = SessionStore.getWindowValue(window, "socialSidebar");
     // if this window doesn't have it's own state, use the state from the opener
     if (!data && window.opener && !window.opener.closed) {
-      data = SessionStore.getWindowValue(window.opener, "socialSidebar");
+      try {
+        data = SessionStore.getWindowValue(window.opener, "socialSidebar");
+      } catch(e) {
+        // Window is not tracked, which happens on osx if the window is opened
+        // from the hidden window. That happens when you close the last window
+        // without quiting firefox, then open a new window.
+      }
     }
     if (data) {
       data = JSON.parse(data);
       document.getElementById("social-sidebar-browser").setAttribute("origin", data.origin);
       if (!data.hidden)
         this.show(data.origin);
+    } else if (Services.prefs.prefHasUserValue("social.sidebar.provider")) {
+      // no window state, use the global state if it is available
+      this.show(Services.prefs.getCharPref("social.sidebar.provider"));
     }
   },
 
   saveWindowState: function() {
     let broadcaster = document.getElementById("socialSidebarBroadcaster");
     let sidebarOrigin = document.getElementById("social-sidebar-browser").getAttribute("origin");
     let data = {
       "hidden": broadcaster.hidden,
       "origin": sidebarOrigin
     };
-    SessionStore.setWindowValue(window, "socialSidebar", JSON.stringify(data));
+
+    // Save a global state for users who do not restore state.
+    if (broadcaster.hidden)
+      Services.prefs.clearUserPref("social.sidebar.provider");
+    else
+      Services.prefs.setCharPref("social.sidebar.provider", sidebarOrigin);
+
+    try {
+      SessionStore.setWindowValue(window, "socialSidebar", JSON.stringify(data));
+    } catch(e) {
+      // window not tracked during uninit
+    }
   },
 
   setSidebarVisibilityState: function(aEnabled) {
     let sbrowser = document.getElementById("social-sidebar-browser");
     // it's possible we'll be called twice with aEnabled=false so let's
     // just assume we may often be called with the same state.
     if (aEnabled == sbrowser.docShellIsActive)
       return;
--- a/browser/base/content/test/social/browser_social_window.js
+++ b/browser/base/content/test/social/browser_social_window.js
@@ -25,27 +25,30 @@ function openWindowAndWaitForInit(parent
   createdWindows.push(w);
   Services.obs.addObserver(function providerSet(subject, topic, data) {
     Services.obs.removeObserver(providerSet, topic);
     info(topic + " observer was notified - continuing test");
     executeSoon(() => callback(w));
   }, topic, false);
 }
 
+function closeWindow(w, cb) {
+  waitForNotification("domwindowclosed", cb);
+  w.close();
+}
+
 function closeOneWindow(cb) {
   let w = createdWindows.pop();
-  if (!w) {
+  if (!w || w.closed) {
     cb();
     return;
   }
-  waitForCondition(function() w.closed,
-                   function() {
-                    info("window closed, " + createdWindows.length + " windows left");
-                    closeOneWindow(cb);
-                    }, "window did not close");
+  closeWindow(w, function() {
+    closeOneWindow(cb);
+  });
   w.close();
 }
 
 function postTestCleanup(cb) {
   closeOneWindow(cb);
 }
 
 let manifest = { // normal provider
@@ -121,16 +124,61 @@ let tests = {
               });
             });
           });
         }, "sidebar did not open");
       }, cbnext);
     }, cbnext);
   },
 
+  testGlobalState: function(cbnext) {
+    setManifestPref("social.manifest.test", manifest);
+    ok(!SocialSidebar.opened, "sidebar is closed initially");
+    ok(!Services.prefs.prefHasUserValue("social.sidebar.provider"), "global state unset");
+    // mimick no session state in opener so we exercise the global state via pref
+    SessionStore.deleteWindowValue(window, "socialSidebar");
+    ok(!SessionStore.getWindowValue(window, "socialSidebar"), "window state unset");
+    SocialService.addProvider(manifest, function() {
+      openWindowAndWaitForInit(window, function(w1) {
+        w1.SocialSidebar.show();
+        waitForCondition(function() w1.SocialSidebar.opened,
+                     function() {
+          ok(Services.prefs.prefHasUserValue("social.sidebar.provider"), "global state set");
+          ok(!SocialSidebar.opened, "1. main sidebar is still closed");
+          ok(w1.SocialSidebar.opened, "1. window sidebar is open");
+          closeWindow(w1, function() {
+            // this time, the global state should cause the sidebar to be opened
+            // in the new window
+            openWindowAndWaitForInit(window, function(w1) {
+              ok(!SocialSidebar.opened, "2. main sidebar is still closed");
+              ok(w1.SocialSidebar.opened, "2. window sidebar is open");
+              w1.SocialSidebar.hide();
+              ok(!w1.SocialSidebar.opened, "2. window sidebar is closed");
+              ok(!Services.prefs.prefHasUserValue("social.sidebar.provider"), "2. global state unset");
+              // global state should now be no sidebar gets opened on new window
+              closeWindow(w1, function() {
+                ok(!Services.prefs.prefHasUserValue("social.sidebar.provider"), "3. global state unset");
+                ok(!SocialSidebar.opened, "3. main sidebar is still closed");
+                openWindowAndWaitForInit(window, function(w1) {
+                  ok(!Services.prefs.prefHasUserValue("social.sidebar.provider"), "4. global state unset");
+                  ok(!SocialSidebar.opened, "4. main sidebar is still closed");
+                  ok(!w1.SocialSidebar.opened, "4. window sidebar is closed");
+                  SocialService.removeProvider(manifest.origin, function() {
+                    Services.prefs.clearUserPref("social.manifest.test");
+                    cbnext();
+                  });
+                });
+              });
+            });
+          });
+        });        
+      });
+    });
+  },
+
   // Check per window sidebar functionality, including migration from using
   // prefs to using session state, and state inheritance of windows (new windows
   // inherit state from the opener).
   testPerWindowSidebar: function(cbnext) {
     function finishCheck() {
       // disable social and re-check
       SocialService.removeProvider(manifest.origin, function() {
         SocialService.removeProvider(manifest2.origin, function() {