bug 484188 - Port browser-chrome mochitests from browser/base/content to SeaMonkey, r=Neil
authorRobert Kaiser <kairo@kairo.at>
Fri, 10 Apr 2009 13:20:24 +0200
changeset 2371 671042296bda8f1769b0ebac7afca1eae2672aad
parent 2370 6310cc51872bcaab0d4ff2fb9da80414d596f516
child 2372 39818eecd89706d7e844813842a68234259d8628
push id1923
push userkairo@kairo.at
push dateFri, 10 Apr 2009 11:22:15 +0000
treeherdercomm-central@671042296bda [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersNeil
bugs484188
bug 484188 - Port browser-chrome mochitests from browser/base/content to SeaMonkey, r=Neil
suite/browser/navigator.js
suite/browser/pageinfo/pageInfo.js
suite/browser/test/Makefile.in
suite/browser/test/browser/browser_bug413915.js
suite/browser/test/browser/browser_bug427559.js
suite/browser/test/browser/browser_bug462289.js
suite/browser/test/browser/browser_ctrlTab.js
suite/browser/test/browser/browser_feed_tab.js
suite/browser/test/browser/browser_page_style_menu.js
suite/browser/test/browser/browser_pluginnotification.js
suite/browser/test/browser/browser_scope.js
suite/browser/test/browser/feed_tab.html
suite/browser/test/browser/page_style_sample.html
suite/browser/test/browser/plugin_both.html
suite/browser/test/browser/plugin_both2.html
suite/browser/test/browser/plugin_test.html
suite/browser/test/browser/plugin_unknown.html
--- a/suite/browser/navigator.js
+++ b/suite/browser/navigator.js
@@ -1684,20 +1684,20 @@ function BrowserViewSourceOfURL(url, cha
              "_blank",
              "all,dialog=no",
              url, charset, pageCookie);
 }
 
 // doc=null for regular page info, doc=owner document for frame info.
 function BrowserPageInfo(doc, initialTab)
 {
-  window.openDialog("chrome://navigator/content/pageinfo/pageInfo.xul",
-                    "_blank",
-                    "chrome,dialog=no",
-                    {doc: doc, initialTab: initialTab});
+  return window.openDialog("chrome://navigator/content/pageinfo/pageInfo.xul",
+                           "_blank",
+                           "chrome,dialog=no",
+                           {doc: doc, initialTab: initialTab});
 }
 
 function hiddenWindowStartup()
 {
   // focus the hidden window
   window.focus();
 
   // Disable menus which are not appropriate
--- a/suite/browser/pageinfo/pageInfo.js
+++ b/suite/browser/pageinfo/pageInfo.js
@@ -334,16 +334,19 @@ function onLoadPageInfo()
   var initialTab = "generalTab";
   if ("arguments" in window && window.arguments.length >= 1 &&
        window.arguments[0] && window.arguments[0].initialTab)
     initialTab = window.arguments[0].initialTab;
   var tabbox = document.getElementById("tabbox");
   initialTab = document.getElementById(initialTab) || document.getElementById("generalTab");
   tabbox.selectedTab = initialTab;
   tabbox.selectedTab.focus();
+  Components.classes["@mozilla.org/observer-service;1"]
+            .getService(Components.interfaces.nsIObserverService)
+            .notifyObservers(window, "page-info-dialog-loaded", null);
 }
 
 function onUnloadPageInfo()
 {
   // Remove the observer, only if there is at least 1 image.
   if (gImageView.data.length != 0) {
     Components.classes["@mozilla.org/observer-service;1"]
               .getService(Components.interfaces.nsIObserverService)
--- a/suite/browser/test/Makefile.in
+++ b/suite/browser/test/Makefile.in
@@ -44,10 +44,31 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =	test_feed_discovery.html \
 		feed_discovery.html \
 		test_bug395533.html \
 		bug395533-data.txt \
 		$(NULL)
 
+_BROWSER_FILES = browser_bug413915.js \
+                 browser_bug427559.js \
+                 browser_page_style_menu.js \
+                 page_style_sample.html \
+                 browser_feed_tab.js \
+                 feed_tab.html \
+                 browser_pluginnotification.js \
+                 plugin_unknown.html \
+                 plugin_test.html \
+                 plugin_both.html \
+                 plugin_both2.html \
+                 browser_scope.js \
+    $(NULL)
+
+ifeq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+_BROWSER_FILES += browser_bug462289.js
+endif
+
 libs:: $(addprefix mochitest/, $(_TEST_FILES))
 	$(INSTALL) $(foreach f,$^,"$f") $(MOZDEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
+
+libs:: $(addprefix browser/, $(_BROWSER_FILES))
+	$(INSTALL) $(foreach f,$^,"$f") $(MOZDEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/suite/browser/test/browser/browser_bug413915.js
@@ -0,0 +1,62 @@
+function test() {
+  var ioserv = Components.classes["@mozilla.org/network/io-service;1"].
+               getService(Components.interfaces.nsIIOService);
+  var exampleUri = ioserv.newURI("http://example.com/", null, null);
+  var secman = Components.classes["@mozilla.org/scriptsecuritymanager;1"].
+               getService(Components.interfaces.nsIScriptSecurityManager);
+  var principal = secman.getCodebasePrincipal(exampleUri);
+
+  function testIsFeed(aTitle, aHref, aType, aKnown) {
+    var link = { title: aTitle, href: aHref, type: aType };
+    return isValidFeed(link, principal, aKnown);
+  }
+
+  var href = "http://example.com/feed/";
+  var atomType = "application/atom+xml";
+  var funkyAtomType = " aPPLICAtion/Atom+XML ";
+  var rssType = "application/rss+xml";
+  var funkyRssType = " Application/RSS+XML  ";
+  var rdfType = "application/rdf+xml";
+  var texmlType = "text/xml";
+  var appxmlType = "application/xml";
+  var noRss = "Foo";
+  var rss = "RSS";
+
+  // things that should be valid
+  ok(testIsFeed(noRss, href, atomType, false) == atomType,
+     "detect Atom feed");
+  ok(testIsFeed(noRss, href, funkyAtomType, false) == atomType,
+     "clean up and detect Atom feed");
+  ok(testIsFeed(noRss, href, rssType, false) == rssType,
+     "detect RSS feed");
+  ok(testIsFeed(noRss, href, funkyRssType, false) == rssType,
+     "clean up and detect RSS feed");
+
+  // things that should not be feeds
+  ok(testIsFeed(noRss, href, rdfType, false) == null,
+     "should not detect RDF non-feed");
+  ok(testIsFeed(rss, href, rdfType, false) == null,
+     "should not detect RDF feed from type and title");
+  ok(testIsFeed(noRss, href, texmlType, false) == null,
+     "should not detect text/xml non-feed");
+  ok(testIsFeed(rss, href, texmlType, false) == null,
+     "should not detect text/xml feed from type and title");
+  ok(testIsFeed(noRss, href, appxmlType, false) == null,
+     "should not detect application/xml non-feed");
+  ok(testIsFeed(rss, href, appxmlType, false) == null,
+     "should not detect application/xml feed from type and title");
+
+  // security check only, returns cleaned up type or "application/rss+xml"
+  ok(testIsFeed(noRss, href, atomType, true) == atomType,
+     "feed security check should return Atom type");
+  ok(testIsFeed(noRss, href, funkyAtomType, true) == atomType,
+     "feed security check should return cleaned up Atom type");
+  ok(testIsFeed(noRss, href, rssType, true) == rssType,
+     "feed security check should return RSS type");
+  ok(testIsFeed(noRss, href, funkyRssType, true) == rssType,
+     "feed security check should return cleaned up RSS type");
+  ok(testIsFeed(noRss, href, "", true) == rssType,
+     "feed security check without type should return RSS type");
+  ok(testIsFeed(noRss, href, "garbage", true) == "garbage",
+     "feed security check with garbage type should return garbage");
+}
new file mode 100644
--- /dev/null
+++ b/suite/browser/test/browser/browser_bug427559.js
@@ -0,0 +1,77 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Firefox Browser Test Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Edward Lee <edward.lee@engineering.uiuc.edu>.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Test bug 427559 to make sure focused elements that are no longer on the page
+ * will have focus transferred to the window when changing tabs back to that
+ * tab with the now-gone element.
+ */
+
+// Default focus on a button and have it kill itself on blur
+let testPage = 'data:text/html,<body><button onblur="this.parentNode.removeChild(this);"><script>document.body.firstChild.focus();</script></body>';
+
+function test() {
+  waitForExplicitFinish();
+
+  // Prepare the test tab
+  let testTab = gBrowser.addTab();
+  gBrowser.selectedTab = testTab;
+  let testBrowser = gBrowser.getBrowserForTab(testTab);
+  let eventFired = false;
+
+  // Do stuff just after the page loads, so the page script can do its stuff
+  testBrowser.addEventListener("load", function() setTimeout(function() {
+    // The test page loaded, so open an empty tab, select it, then restore
+    // the test tab. This causes the test page's focused element to be removed
+    // from its document.
+    if (!eventFired) {
+      eventFired = true;
+      let emptyTab = gBrowser.addTab();
+      gBrowser.selectedTab = emptyTab;
+      gBrowser.removeCurrentTab();
+      gBrowser.selectedTab = testTab;
+
+      // Make sure focus is given to the window because the element is now gone
+      is(document.commandDispatcher.focusedWindow, window.content,
+         "content window is focused");
+      gBrowser.removeCurrentTab();
+      finish();
+    }
+  }, 0), true);
+
+  // Start the test by loading the test page
+  testBrowser.contentWindow.location = testPage;
+}
new file mode 100644
--- /dev/null
+++ b/suite/browser/test/browser/browser_bug462289.js
@@ -0,0 +1,53 @@
+var tab1, tab2;
+
+function test() {
+  waitForExplicitFinish();
+
+  tab1 = gBrowser.addTab();
+  tab2 = gBrowser.addTab();
+  setTimeout(step1, 0);
+}
+
+function step1() {
+  EventUtils.synthesizeMouse(tab1, 2, 2, {});
+  setTimeout(step2, 0);
+}
+
+function step2()
+{
+  isnot(document.activeElement, tab1, "mouse on tab not activeElement");
+
+  EventUtils.synthesizeMouse(tab1, 2, 2, {});
+  setTimeout(step3, 0);
+}
+
+function step3()
+{
+  isnot(document.activeElement, tab1, "mouse on tab again activeElement");
+
+  document.getElementById("urlbar").inputField.focus();
+  EventUtils.synthesizeKey("VK_TAB", { });
+
+  is(document.activeElement, tab1, "tab key to tab activeElement");
+
+  EventUtils.synthesizeMouse(tab1, 2, 2, {});
+  setTimeout(step4, 0);
+}
+
+function step4()
+{
+  is(document.activeElement, tab1, "mouse on tab while focused still activeElement");
+
+  EventUtils.synthesizeMouse(tab2, 2, 2, {});
+  setTimeout(step5, 0);
+}
+
+function step5()
+{
+  is(document.activeElement, tab2, "mouse on another tab while focused still activeElement");
+
+  gBrowser.removeTab(tab1);
+  gBrowser.removeTab(tab2);
+
+  finish();
+}
new file mode 100644
--- /dev/null
+++ b/suite/browser/test/browser/browser_ctrlTab.js
@@ -0,0 +1,194 @@
+function test() {
+  waitForExplicitFinish();
+
+  gBrowser.addTab();
+  gBrowser.addTab();
+  gBrowser.addTab();
+
+  assertTabs(4);
+
+  ctrlTabTest([2]      , 1, 0);
+  ctrlTabTest([2, 3, 1], 2, 2);
+  ctrlTabTest([]       , 4, 2);
+
+  {
+    let selectedIndex = gBrowser.tabContainer.selectedIndex;
+    pressCtrlTab();
+    pressCtrlTab(true);
+    releaseCtrl();
+    is(gBrowser.tabContainer.selectedIndex, selectedIndex,
+       "Ctrl+Tab -> Ctrl+Shift+Tab keeps the selected tab");
+  }
+
+  { // test for bug 445369
+    let tabs = gBrowser.mTabs.length;
+    pressCtrlTab();
+    EventUtils.synthesizeKey("w", { ctrlKey: true });
+    is(gBrowser.mTabs.length, tabs - 1, "Ctrl+Tab -> Ctrl+W removes one tab");
+    releaseCtrl();
+  }
+  assertTabs(3);
+
+  ctrlTabTest([2, 1, 0], 7, 1);
+
+  { // test for bug 445369
+    selectTabs([1, 2, 0]);
+
+    let selectedTab = gBrowser.selectedTab;
+    let tabToRemove = gBrowser.mTabs[1];
+
+    pressCtrlTab();
+    pressCtrlTab();
+    EventUtils.synthesizeKey("w", { ctrlKey: true });
+    ok(!tabToRemove.parentNode,
+       "Ctrl+Tab*2 -> Ctrl+W removes the second most recently selected tab");
+
+    pressCtrlTab(true);
+    pressCtrlTab(true);
+    releaseCtrl();
+    ok(gBrowser.selectedTab == selectedTab,
+       "Ctrl+Tab*2 -> Ctrl+W -> Ctrl+Shift+Tab*2 keeps the selected tab");
+  }
+  assertTabs(2);
+
+  ctrlTabTest([1], 1, 0);
+
+  gBrowser.removeTab(gBrowser.tabContainer.lastChild);
+
+  assertTabs(1);
+
+  { // test for bug 445768
+    let focusedWindow = document.commandDispatcher.focusedWindow;
+    let eventConsumed = true;
+    let detectKeyEvent = function (event) {
+      eventConsumed = event.getPreventDefault();
+    };
+    document.addEventListener("keypress", detectKeyEvent, false);
+    pressCtrlTab();
+    document.removeEventListener("keypress", detectKeyEvent, false);
+    ok(eventConsumed, "Ctrl+Tab consumed by the tabbed browser if one tab is open");
+    is(focusedWindow.location, document.commandDispatcher.focusedWindow.location,
+       "Ctrl+Tab doesn't change focus if one tab is open");
+  }
+
+  gBrowser.addTab();
+  gBrowser.addTab();
+  gBrowser.addTab();
+
+  assertTabs(4);
+  selectTabs([0, 1, 2, 3]);
+  pressCtrlTab();
+  ctrlTab.panel.addEventListener("popupshown", stickyTests, false);
+
+  function stickyTests() {
+    ctrlTab.panel.removeEventListener("popupshown", stickyTests, false);
+
+    EventUtils.synthesizeKey("f", { ctrlKey: true });
+    is(document.activeElement, ctrlTab.searchField.inputField,
+       "Ctrl+Tab -> Ctrl+F focuses the panel's search field");
+
+    releaseCtrl();
+    ok(isOpen(),
+       "panel is sticky after focusing the search field and releasing the Ctrl key");
+
+    EventUtils.synthesizeKey("f", {});
+    EventUtils.synthesizeKey("o", {});
+    EventUtils.synthesizeKey("o", {});
+    is(ctrlTab.searchField.value, "foo",
+       "text entered into search field");
+
+    EventUtils.synthesizeKey("VK_RETURN", {});
+    ok(isOpen(),
+       "Enter key kicks pending search off; the panel stays open as there's no match");
+    is(ctrlTab.searchField.value, "foo",
+       "search field value persists after Enter pressed");
+
+    EventUtils.synthesizeKey("VK_ESCAPE", {});
+    is(ctrlTab.searchField.value, "",
+       "ESC key clears the search field");
+    ok(isOpen(),
+       "Clearing the search field with ESC keeps the panel open");
+
+    // blur the search field
+    EventUtils.synthesizeKey("VK_TAB", {});
+    isnot(document.activeElement, ctrlTab.searchField.inputField,
+          "Tab key blurs the panel's search field");
+
+    // advance selection and close panel
+    EventUtils.synthesizeKey("VK_TAB", {});
+    EventUtils.synthesizeKey("VK_TAB", {});
+    EventUtils.synthesizeKey("VK_RETURN", {});
+    ok(!isOpen(),
+       "Enter key closes the panel");
+    is(gBrowser.tabContainer.selectedIndex, 1,
+       "Tab key advances the selection while the panel is sticky");
+
+    gBrowser.removeCurrentTab();
+    gBrowser.removeCurrentTab();
+    gBrowser.removeCurrentTab();
+    assertTabs(1);
+    finish();
+  }
+
+
+  /* private utility functions */
+
+  function pressCtrlTab(aShiftKey)
+    EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: !!aShiftKey });
+
+  function releaseCtrl()
+    EventUtils.synthesizeKey("VK_CONTROL", { type: "keyup" });
+
+  function isOpen()
+    ctrlTab.panel.state == "showing" || ctrlTab.panel.state == "open";
+
+  function assertTabs(aTabs) {
+    var tabs = gBrowser.mTabs.length;
+    if (tabs != aTabs) {
+      while (gBrowser.mTabs.length > 1)
+        gBrowser.removeCurrentTab();
+      throw "expected " + aTabs + " open tabs, got " + tabs;
+    }
+  }
+
+  function selectTabs(tabs) {
+    tabs.forEach(function (index) {
+      gBrowser.selectedTab = gBrowser.mTabs[index];
+    });
+  }
+
+  function ctrlTabTest(tabsToSelect, tabTimes, expectedIndex) {
+    selectTabs(tabsToSelect);
+
+    var indexStart = gBrowser.tabContainer.selectedIndex;
+    var tabCount = gBrowser.mTabs.length;
+    var normalized = tabTimes % tabCount;
+    var where = normalized == 1 ? "back to the previously selected tab" :
+                normalized + " tabs back in most-recently-selected order";
+
+    for (let i = 0; i < tabTimes; i++) {
+      pressCtrlTab();
+
+      if (tabCount > 2)
+       is(gBrowser.tabContainer.selectedIndex, indexStart,
+         "Selected tab doesn't change while tabbing");
+    }
+
+    if (tabCount > 2) {
+      ok(isOpen(),
+         "With " + tabCount + " tabs open, Ctrl+Tab opens the preview panel");
+
+      releaseCtrl();
+
+      ok(!isOpen(),
+         "Releasing Ctrl closes the preview panel");
+    } else {
+      ok(!isOpen(),
+         "With " + tabCount + " tabs open, Ctrl+Tab doesn't open the preview panel");
+    }
+
+    is(gBrowser.tabContainer.selectedIndex, expectedIndex,
+       "With "+ tabCount +" tabs open and tab " + indexStart
+       + " selected, Ctrl+Tab*" + tabTimes + " goes " + where);
+  }
+}
new file mode 100644
--- /dev/null
+++ b/suite/browser/test/browser/browser_feed_tab.js
@@ -0,0 +1,54 @@
+function test() {
+  waitForExplicitFinish();
+
+  var pageInfo;
+  var gTestPage = gBrowser.addTab();
+  gBrowser.selectedTab = gTestPage;
+  gTestPage.linkedBrowser.addEventListener("load", handleLoad, true);
+  content.location =
+    "http://localhost:8888/browser/suite/browser/test/feed_tab.html";
+  gTestPage.focus();
+  var obs = Components.classes["@mozilla.org/observer-service;1"]
+                      .getService(Components.interfaces.nsIObserverService);
+
+  var observer = {
+    observe: function(win, topic, data) {
+      if (topic != "page-info-dialog-loaded")
+        return;
+
+      obs.removeObserver(observer, "page-info-dialog-loaded");
+      handlePageInfo();
+    }
+  };
+
+  function handleLoad() {
+    gTestPage.linkedBrowser.removeEventListener("load", handleLoad, true);
+    obs.addObserver(observer, "page-info-dialog-loaded", false);
+    pageInfo = BrowserPageInfo();
+  }
+
+  function handlePageInfo() {
+    function $(aId) { return pageInfo.document.getElementById(aId) };
+    var feedTab = $("feedPanel");
+    var feedListbox = $("feedListbox");
+
+    ok(feedListbox, "Feed list is null (feeds tab is broken)");
+
+    var feedRowsNum = feedListbox.getRowCount();
+
+    ok(feedRowsNum == 3, "Number of feeds listed: " +
+                         feedRowsNum + ", should be 3");
+
+
+    for (var i = 0; i < feedRowsNum; i++) {
+      let feedItem = feedListbox.getItemAtIndex(i);
+      ok(feedItem.getAttribute("name") == (i+1), 
+         "Name given: " + feedItem.getAttribute("name") + ", should be " + (i+1));
+    }
+
+    pageInfo.close();
+    gTestPage.focus();
+    gBrowser.removeCurrentTab();
+    finish();
+  }
+}
new file mode 100644
--- /dev/null
+++ b/suite/browser/test/browser/browser_page_style_menu.js
@@ -0,0 +1,64 @@
+function test() {
+  waitForExplicitFinish();
+
+  var tab = gBrowser.addTab();
+  gBrowser.selectedTab = tab;
+  tab.linkedBrowser.addEventListener("load", checkPageStyleMenu, true);
+  content.location =
+    "chrome://mochikit/content/browser/suite/browser/test/page_style_sample.html";
+}
+
+function checkPageStyleMenu() {
+  var menupopup = document.getElementById("menu_UseStyleSheet")
+                          .getElementsByTagName("menupopup")[0];
+  stylesheetFillPopup(menupopup);
+
+  var items = [];
+  var current = menupopup.getElementsByTagName("menuitem")[1];
+  while (current.nextSibling) {
+    current = current.nextSibling;
+    items.push(current);
+  }
+
+  var validLinks = 0;
+  Array.forEach(content.document.getElementsByTagName("link"), function (link) {
+    var title = link.getAttribute("title");
+    var rel = link.getAttribute("rel");
+    var media = link.getAttribute("media");
+    var idstring = "link " + (title ? title : "without title and") +
+                   " with rel=\"" + rel + "\"" +
+                   (media ? " and media=\"" + media + "\"" : "");
+
+    var item = items.filter(function (item) item.getAttribute("label") == title);
+    var found = item.length == 1;
+    var checked = found && (item[0].getAttribute("checked") == "true");
+
+    switch (link.getAttribute("data-state")) {
+      case "0":
+        ok(!found, idstring + " does not show up in page style menu");
+        break;
+      case "0-todo":
+        validLinks++;
+        todo(!found, idstring + " should not show up in page style menu");
+        ok(!checked, idstring + " is not selected");
+        break;
+      case "1":
+        validLinks++;
+        ok(found, idstring + " shows up in page style menu");
+        ok(!checked, idstring + " is not selected");
+        break;
+      case "2":
+        validLinks++;
+        ok(found, idstring + " shows up in page style menu");
+        ok(checked, idstring + " is selected");
+        break;
+      default:
+        throw "data-state attribute is missing or has invalid value";
+    }
+  });
+
+  is(validLinks, items.length, "all valid links found");
+
+  gBrowser.removeCurrentTab();
+  finish();
+}
new file mode 100644
--- /dev/null
+++ b/suite/browser/test/browser/browser_pluginnotification.js
@@ -0,0 +1,198 @@
+const gTestRoot = "chrome://mochikit/content/browser/suite/browser/test/";
+
+var gTestBrowser = null;
+var gNextTest = null;
+
+function get_test_plugin() {
+  var ph = Components.classes["@mozilla.org/plugin/host;1"]
+                     .getService(Components.interfaces.nsIPluginHost);
+  var tags = ph.getPluginTags({});
+  
+  // Find the test plugin
+  for (var i = 0; i < tags.length; i++) {
+    if (tags[i].name == "Test Plug-in")
+      return tags[i];
+  }
+}
+
+// This listens for the next opened window and checks it is of the right url.
+// opencallback is called when the new window is fully loaded
+// closecallback is called when the window is closed
+function WindowOpenListener(url, opencallback, closecallback) {
+  this.url = url;
+  this.opencallback = opencallback;
+  this.closecallback = closecallback;
+
+  var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+                     .getService(Components.interfaces.nsIWindowMediator);
+  wm.addListener(this);
+}
+
+WindowOpenListener.prototype = {
+  url: null,
+  opencallback: null,
+  closecallback: null,
+  window: null,
+  domwindow: null,
+
+  handleEvent: function(event) {
+    todo_is(this.domwindow.document.location.href, this.url, "Should have opened the correct window");
+
+    this.domwindow.removeEventListener("load", this, false);
+    // Allow any other load handlers to execute
+    var self = this;
+    executeSoon(function() { self.opencallback(self.domwindow); } );
+  },
+
+  onWindowTitleChange: function(window, title) {
+  },
+
+  onOpenWindow: function(window) {
+    if (this.window)
+      return;
+
+    this.window = window;
+    this.domwindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                           .getInterface(Components.interfaces.nsIDOMWindowInternal);
+    this.domwindow.addEventListener("load", this, false);
+  },
+
+  onCloseWindow: function(window) {
+    if (this.window != window)
+      return;
+
+    var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+                       .getService(Components.interfaces.nsIWindowMediator);
+    wm.removeListener(this);
+    this.opencallback = null;
+    this.window = null;
+    this.domwindow = null;
+
+    // Let the window close complete
+    executeSoon(this.closecallback);
+    this.closecallback = null;
+  }
+};
+
+function test() {
+  waitForExplicitFinish();
+
+  var newTab = gBrowser.addTab();
+  gBrowser.selectedTab = newTab;
+  gTestBrowser = gBrowser.selectedBrowser;
+  gTestBrowser.addEventListener("load", pageLoad, true);
+  prepareTest(test1, gTestRoot + "plugin_unknown.html");
+}
+
+function finishTest() {
+  gTestBrowser.removeEventListener("load", pageLoad, true);
+  gBrowser.removeCurrentTab();
+  window.focus();
+  finish();
+}
+
+function pageLoad() {
+  // The plugin events are async dispatched and can come after the load event
+  // This just allows the events to fire before we then go on to test the states
+  executeSoon(gNextTest);
+}
+
+function prepareTest(nextTest, url) {
+  gNextTest = nextTest;
+  gTestBrowser.contentWindow.location = url;
+}
+
+// Tests a page with an unknown plugin in it.
+function test1() {
+  var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
+  ok(notificationBox.getNotificationWithValue("missing-plugins"), "Test 1, Should have displayed the missing plugin notification");
+  ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 1, Should not have displayed the blocked plugin notification");
+  ok(notificationBox.missingPlugins.__count__, "Test 1, Should be a missing plugin list");
+  ok("application/x-unknown" in notificationBox.missingPlugins, "Test 1, Should know about application/x-unknown");
+  ok(!("application/x-test" in notificationBox.missingPlugins), "Test 1, Should not know about application/x-test");
+
+  var plugin = get_test_plugin();
+  ok(plugin, "Should have a test plugin");
+  plugin.disabled = false;
+  plugin.blocklisted = false;
+  prepareTest(test2, gTestRoot + "plugin_test.html");
+}
+
+// Tests a page with a working plugin in it.
+function test2() {
+  var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
+  ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 2, Should not have displayed the missing plugin notification");
+  ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 2, Should not have displayed the blocked plugin notification");
+  ok(!notificationBox.missingPlugins.__count__, "Test 2, Should not be a missing plugin list");
+
+  var plugin = get_test_plugin();
+  ok(plugin, "Should have a test plugin");
+  plugin.disabled = true;
+  prepareTest(test3, gTestRoot + "plugin_test.html");
+}
+
+// Tests a page with a disabled plugin in it.
+function test3() {
+  var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
+  ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 3, Should not have displayed the missing plugin notification");
+  ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 3, Should not have displayed the blocked plugin notification");
+  ok(!notificationBox.missingPlugins.__count__, "Test 3, Should not be a missing plugin list");
+
+  new WindowOpenListener("chrome://mozapps/content/extensions/extensions.xul", test4, prepareTest5);
+
+  EventUtils.synthesizeMouse(gTestBrowser.contentDocument.getElementById("test"),
+                             0, 0, {}, gTestBrowser.contentWindow);
+  // this test doesn't work, we don't open EM atm, put up an alert to trigger rest of test
+  alert("SeaMonkey workaround!");
+}
+
+function test4(win) {
+  todo_is(win.gView, "plugins", "Should have displayed the plugins pane");
+  win.close();
+}
+
+function prepareTest5() {
+  var plugin = get_test_plugin();
+  plugin.disabled = false;
+  plugin.blocklisted = true;
+  prepareTest(test5, gTestRoot + "plugin_test.html");
+}
+
+// Tests a page with a blocked plugin in it.
+function test5() {
+  var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
+  ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 5, Should not have displayed the missing plugin notification");
+  ok(notificationBox.getNotificationWithValue("blocked-plugins"), "Test 5, Should have displayed the blocked plugin notification");
+  ok(notificationBox.missingPlugins.__count__, "Test 5, Should be a missing plugin list");
+  ok("application/x-test" in notificationBox.missingPlugins, "Test 5, Should know about application/x-test");
+  ok(!("application/x-unknown" in notificationBox.missingPlugins), "Test 5, Should not know about application/x-unknown");
+
+  prepareTest(test6, gTestRoot + "plugin_both.html");
+}
+
+// Tests a page with a blocked and unknown plugin in it.
+function test6() {
+  var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
+  ok(notificationBox.getNotificationWithValue("missing-plugins"), "Test 6, Should have displayed the missing plugin notification");
+  ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 6, Should not have displayed the blocked plugin notification");
+  ok(notificationBox.missingPlugins.__count__, "Test 6, Should be a missing plugin list");
+  ok("application/x-unknown" in notificationBox.missingPlugins, "Test 6, Should know about application/x-unknown");
+  ok("application/x-test" in notificationBox.missingPlugins, "Test 6, Should know about application/x-test");
+
+  prepareTest(test7, gTestRoot + "plugin_both2.html");
+}
+
+// Tests a page with a blocked and unknown plugin in it (alternate order to above).
+function test7() {
+  var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
+  ok(notificationBox.getNotificationWithValue("missing-plugins"), "Test 7, Should have displayed the missing plugin notification");
+  ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 7, Should not have displayed the blocked plugin notification");
+  ok(notificationBox.missingPlugins.__count__, "Test 7, Should be a missing plugin list");
+  ok("application/x-unknown" in notificationBox.missingPlugins, "Test 7, Should know about application/x-unknown");
+  ok("application/x-test" in notificationBox.missingPlugins, "Test 7, Should know about application/x-test");
+
+  var plugin = get_test_plugin();
+  plugin.disabled = false;
+  plugin.blocklisted = false;
+  finishTest();
+}
new file mode 100644
--- /dev/null
+++ b/suite/browser/test/browser/browser_scope.js
@@ -0,0 +1,4 @@
+function test() {
+  ok(!!gBrowser, "gBrowser exists");
+  is(gBrowser, getBrowser(), "both ways of getting tabbrowser work");
+}
new file mode 100644
--- /dev/null
+++ b/suite/browser/test/browser/feed_tab.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=458579
+-->
+  <head>
+    <title>Test for page info feeds tab</title>
+
+    <!-- Straight up standard -->
+    <link rel="alternate" type="application/atom+xml" title="1" href="/1.atom" />
+    <link rel="alternate" type="application/rss+xml" title="2" href="/2.rss" />
+    <link rel="feed" title="3" href="/3.xml" />
+
+  </head>
+  <body>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/suite/browser/test/browser/page_style_sample.html
@@ -0,0 +1,31 @@
+<html>
+  <head>
+    <title>Test for page style menu</title>
+    <!-- data-state values:
+      0:      should not appear in the page style menu
+      0-todo: should not appear in the page style menu, but does
+      1:      should appear in the page style menu
+      2:      should appear in the page style menu as the selected stylesheet -->
+    <link data-state="1" href="404.css" title="1" rel="alternate stylesheet">
+    <link data-state="0"                title="2" rel="alternate stylesheet">
+    <link data-state="0" href="404.css"           rel="alternate stylesheet">
+    <link data-state="0" href="404.css" title=""  rel="alternate stylesheet">
+    <link data-state="1" href="404.css" title="3" rel="stylesheet alternate">
+    <link data-state="1" href="404.css" title="4" rel=" alternate stylesheet ">
+    <link data-state="1" href="404.css" title="5" rel="alternate stylesheet">
+    <link data-state="2" href="404.css" title="6" rel="stylesheet">
+    <link data-state="1" href="404.css" title="7" rel="foo stylesheet">
+    <link data-state="0" href="404.css" title="8" rel="alternate">
+    <link data-state="1" href="404.css" title="9" rel="alternate STYLEsheet">
+    <link data-state="1" href="404.css" title="10" rel="alternate stylesheet" media="">
+    <link data-state="1" href="404.css" title="11" rel="alternate stylesheet" media="all">
+    <link data-state="1" href="404.css" title="12" rel="alternate stylesheet" media="ALL ">
+    <link data-state="1" href="404.css" title="13" rel="alternate stylesheet" media="screen">
+    <link data-state="1" href="404.css" title="14" rel="alternate stylesheet" media=" Screen">
+    <link data-state="1" href="404.css" title="15" rel="alternate stylesheet" media="screen foo">
+    <link data-state="1" href="404.css" title="16" rel="alternate stylesheet" media="all  screen">
+    <link data-state="0-todo" href="404.css" title="17" rel="alternate stylesheet" media="allscreen">
+    <link data-state="0-todo" href="404.css" title="18" rel="alternate stylesheet" media="_all">
+  </head>
+  <body></body>
+</html>
new file mode 100644
--- /dev/null
+++ b/suite/browser/test/browser/plugin_both.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+<embed id="unknown" style="width: 100px; height: 100px" type="application/x-unknown">
+<embed id="test" style="width: 100px; height: 100px" type="application/x-test">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/suite/browser/test/browser/plugin_both2.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+<embed id="test" style="width: 100px; height: 100px" type="application/x-test">
+<embed id="unknown" style="width: 100px; height: 100px" type="application/x-unknown">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/suite/browser/test/browser/plugin_test.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+<embed id="test" style="width: 100px; height: 100px" type="application/x-test">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/suite/browser/test/browser/plugin_unknown.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+<embed id="unknown" style="width: 100px; height: 100px" type="application/x-unknown">
+</body>
+</html>