Bug 653108 - Scratchpad is tied to the tab it was first run in; r=mihai.sucan,sdwilsh
authorRob Campbell <rcampbell@mozilla.com>
Sat, 21 May 2011 08:59:23 -0300
changeset 69848 ca4df27501e4c37cd28bd31b4c378763e5d17d35
parent 69847 2a10e886f3d7a4f43511ba88179bd440cf65b078
child 69849 ccc461a5e51e16aaf9eddd8dcbcded6e1be0bdae
push idunknown
push userunknown
push dateunknown
reviewersmihai.sucan, sdwilsh
bugs653108
milestone6.0a1
Bug 653108 - Scratchpad is tied to the tab it was first run in; r=mihai.sucan,sdwilsh
browser/base/content/scratchpad.js
browser/base/content/test/Makefile.in
browser/base/content/test/browser_scratchpad_tab_switch.js
browser/locales/en-US/chrome/browser/scratchpad.properties
--- a/browser/base/content/scratchpad.js
+++ b/browser/base/content/scratchpad.js
@@ -124,34 +124,39 @@ var Scratchpad = {
   /**
    * Cached Cu.Sandbox object for the active tab content window object.
    */
   _contentSandbox: null,
 
   /**
    * Get the Cu.Sandbox object for the active tab content window object. Note
    * that the returned object is cached for later reuse. The cached object is
-   * kept only for the current browser window and it is reset for each context
-   * switch or navigator:browser window switch.
+   * kept only for the current location in the current tab of the current
+   * browser window and it is reset for each context switch,
+   * navigator:browser window switch, tab switch or navigation.
    */
   get contentSandbox()
   {
     if (!this.browserWindow) {
       Cu.reportError(this.strings.
                      GetStringFromName("browserWindow.unavailable"));
       return;
     }
 
     if (!this._contentSandbox ||
-        this.browserWindow != this._previousBrowserWindow) {
+        this.browserWindow != this._previousBrowserWindow ||
+        this._previousBrowser != this.gBrowser.selectedBrowser ||
+        this._previousLocation != this.gBrowser.contentWindow.location.href) {
       let contentWindow = this.gBrowser.selectedBrowser.contentWindow;
       this._contentSandbox = new Cu.Sandbox(contentWindow,
         { sandboxPrototype: contentWindow, wantXrays: false });
 
       this._previousBrowserWindow = this.browserWindow;
+      this._previousBrowser = this.gBrowser.selectedBrowser;
+      this._previousLocation = contentWindow.location.href;
     }
 
     return this._contentSandbox;
   },
 
   /**
    * Cached Cu.Sandbox object for the most recently active navigator:browser
    * chrome window object.
@@ -553,42 +558,44 @@ var Scratchpad = {
   /**
    * Set the current execution context to be the active tab content window.
    */
   setContentContext: function SP_setContentContext()
   {
     let content = document.getElementById("sp-menu-content");
     document.getElementById("sp-menu-browser").removeAttribute("checked");
     content.setAttribute("checked", true);
+    this.executionContext = SCRATCHPAD_CONTEXT_CONTENT;
     this.statusbarStatus.label = content.getAttribute("label");
-    this.executionContext = SCRATCHPAD_CONTEXT_CONTENT;
     this.resetContext();
   },
 
   /**
    * Set the current execution context to be the most recent chrome window.
    */
   setBrowserContext: function SP_setBrowserContext()
   {
-    let chrome = document.getElementById("sp-menu-browser");
+    let browser = document.getElementById("sp-menu-browser");
     document.getElementById("sp-menu-content").removeAttribute("checked");
-    chrome.setAttribute("checked", true);
-    this.statusbarStatus.label = chrome.getAttribute("label");
+    browser.setAttribute("checked", true);
     this.executionContext = SCRATCHPAD_CONTEXT_BROWSER;
+    this.statusbarStatus.label = browser.getAttribute("label");
     this.resetContext();
   },
 
   /**
    * Reset the cached Cu.Sandbox object for the current context.
    */
   resetContext: function SP_resetContext()
   {
     this._chromeSandbox = null;
     this._contentSandbox = null;
     this._previousWindow = null;
+    this._previousBrowser = null;
+    this._previousLocation = null;
   },
 
   /**
    * Gets the ID of the outer window of the given DOM window object.
    *
    * @param nsIDOMWindow aWindow
    * @return integer
    *         the outer window ID
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -189,16 +189,17 @@ endif
                  browser_inspector_scrolling.js \
                  browser_inspector_store.js \
                  browser_inspector_tab_switch.js \
                  browser_inspector_treePanel_output.js \
                  browser_inspector_treePanel_input.html \
                  browser_inspector_treePanel_result.html \
                  browser_scratchpad_initialization.js \
                  browser_scratchpad_contexts.js \
+                 browser_scratchpad_tab_switch.js \
                  browser_scratchpad_execute_print.js \
                  browser_scratchpad_inspect.js \
                  browser_scratchpad_files.js \
                  browser_scratchpad_ui.js \
                  browser_scratchpad_bug_646070_chrome_context_pref.js \
                  browser_overflowScroll.js \
                  browser_pageInfo.js \
                  browser_page_style_menu.js \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_scratchpad_tab_switch.js
@@ -0,0 +1,111 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Reference to the Scratchpad chrome window object.
+let gScratchpadWindow;
+let tab1;
+let tab2;
+let sp;
+
+function test()
+{
+  waitForExplicitFinish();
+
+  tab1 = gBrowser.addTab();
+  gBrowser.selectedTab = tab1;
+  gBrowser.selectedBrowser.addEventListener("load", function() {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+
+    tab2 = gBrowser.addTab();
+    gBrowser.selectedTab = tab2;
+    gBrowser.selectedBrowser.addEventListener("load", function() {
+      gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+      gScratchpadWindow = Scratchpad.openScratchpad();
+      gScratchpadWindow.addEventListener("load", runTests, false);
+    }, true);
+    content.location = "data:text/html,test context switch in Scratchpad tab 2";
+  }, true);
+
+  content.location = "data:text/html,test context switch in Scratchpad tab 1";
+}
+
+function runTests()
+{
+  gScratchpadWindow.removeEventListener("load", runTests, true);
+
+  sp = gScratchpadWindow.Scratchpad;
+
+  let contentMenu = gScratchpadWindow.document.getElementById("sp-menu-content");
+  let browserMenu = gScratchpadWindow.document.getElementById("sp-menu-browser");
+  let statusbar = sp.statusbarStatus;
+
+  ok(contentMenu, "found #sp-menu-content");
+  ok(browserMenu, "found #sp-menu-browser");
+  ok(statusbar, "found Scratchpad.statusbarStatus");
+
+  sp.setContentContext();
+
+  is(sp.executionContext, gScratchpadWindow.SCRATCHPAD_CONTEXT_CONTENT,
+     "executionContext is content");
+
+  is(contentMenu.getAttribute("checked"), "true",
+     "content menuitem is checked");
+
+  ok(!browserMenu.hasAttribute("checked"),
+     "chrome menuitem is not checked");
+
+  is(statusbar.getAttribute("label"), contentMenu.getAttribute("label"),
+     "statusbar label is correct");
+
+  ok(sp.textbox, "textbox exists");
+  sp.textbox.value = "window.foosbug653108 = 'aloha';";
+
+  ok(!content.wrappedJSObject.foosbug653108,
+     "no content.foosbug653108");
+
+  sp.run();
+
+  is(content.wrappedJSObject.foosbug653108, "aloha",
+     "content.foosbug653108 has been set");
+
+  gBrowser.tabContainer.addEventListener("TabSelect", runTests2, true);
+  gBrowser.selectedTab = tab1;
+}
+
+function runTests2() {
+  gBrowser.tabContainer.removeEventListener("TabSelect", runTests2, true);
+
+  ok(!window.foosbug653108, "no window.foosbug653108");
+
+  sp.textbox.value = "window.foosbug653108";
+  let result = sp.run();
+
+  isnot(result, "aloha", "window.foosbug653108 is not aloha");
+
+  sp.textbox.value = "window.foosbug653108 = 'ahoyhoy';";
+  sp.run();
+
+  is(content.wrappedJSObject.foosbug653108, "ahoyhoy",
+     "content.foosbug653108 has been set 2");
+
+  gBrowser.selectedBrowser.addEventListener("load", runTests3, true);
+  content.location = "data:text/html,test context switch in Scratchpad location 2";
+}
+
+function runTests3() {
+  gBrowser.selectedBrowser.removeEventListener("load", runTests3, true);
+  // Check that the sandbox is not cached.
+
+  sp.textbox.value = "typeof foosbug653108;";
+  is(sp.run()[1], "undefined", "global variable does not exist");
+
+  gScratchpadWindow.close();
+  gScratchpadWindow = null;
+  tab1 = null;
+  tab2 = null;
+  sp = null;
+  gBrowser.removeCurrentTab();
+  gBrowser.removeCurrentTab();
+  finish();
+}
--- a/browser/locales/en-US/chrome/browser/scratchpad.properties
+++ b/browser/locales/en-US/chrome/browser/scratchpad.properties
@@ -23,8 +23,9 @@ openFile.failed=Failed to read the file.
 
 # LOCALIZATION NOTE  (saveFileAs): This is the file picker title, when you save
 # a file in Scratchpad.
 saveFileAs=Save File As
 
 # LOCALIZATION NOTE  (saveFile.failed): This is the message displayed when file
 # save fails.
 saveFile.failed=The file save operation failed.
+