summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpam@chromium.org <pam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-26 19:22:43 +0000
committerpam@chromium.org <pam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-26 19:22:43 +0000
commite258706e9be6555e9d4f3da80b0f1ba71594590b (patch)
tree90c83c9cc62203c846e08e7cf2442149b5945ff2
parent3f90dbc4e700692dbb1b03103f4e4b93c002e56b (diff)
downloadchromium_src-e258706e9be6555e9d4f3da80b0f1ba71594590b.zip
chromium_src-e258706e9be6555e9d4f3da80b0f1ba71594590b.tar.gz
chromium_src-e258706e9be6555e9d4f3da80b0f1ba71594590b.tar.bz2
Add tons of tests for the option page and fix overlay back/forward.
The behavior of the options page and its overlays was almost entirely untested. Add a bunch of browser tests covering general behavior and especially recent regressions (bugs 256997 and 248051). Rename the OptionsUIBrowserTest and the OptionsBrowserTest to match their respective filenames. Options-page back/forward handling was relying on the behavior fixed in r206418, in which parent pages were re-shown even if they were already visible. That re-showing was hiding the topmost overlay as a side effect; now that it's fixed, the overlay needs to be hidden manually (but without updating the tab history). BUG=256997 TEST=browser_tests --gtest_filter=OptionsWebUINavigationTest.* Review URL: https://chromiumcodereview.appspot.com/19601002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@213965 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/resources/options/options_page.js12
-rw-r--r--chrome/browser/ui/webui/options/certificate_manager_browsertest.cc2
-rw-r--r--chrome/browser/ui/webui/options/chromeos/guest_mode_options_ui_browsertest.cc6
-rw-r--r--chrome/browser/ui/webui/options/options_browsertest.cc49
-rw-r--r--chrome/browser/ui/webui/options/options_browsertest.h36
-rw-r--r--chrome/browser/ui/webui/options/options_browsertest.js415
-rw-r--r--chrome/browser/ui/webui/options/options_ui_browsertest.cc10
-rw-r--r--chrome/browser/ui/webui/options/options_ui_browsertest.h4
-rw-r--r--chrome/chrome_tests.gypi1
9 files changed, 522 insertions, 13 deletions
diff --git a/chrome/browser/resources/options/options_page.js b/chrome/browser/resources/options/options_page.js
index 0f4fc9c..0db5148 100644
--- a/chrome/browser/resources/options/options_page.js
+++ b/chrome/browser/resources/options/options_page.js
@@ -565,12 +565,20 @@ cr.define('options', function() {
};
/**
- * Callback for window.onpopstate.
+ * Callback for window.onpopstate to handle back/forward navigations.
* @param {Object} data State data pushed into history.
*/
OptionsPage.setState = function(data) {
if (data && data.pageName) {
- this.willClose();
+ var currentOverlay = this.getVisibleOverlay_();
+ var lowercaseName = data.pageName.toLowerCase();
+ var newPage = this.registeredPages[lowercaseName] ||
+ this.registeredOverlayPages[lowercaseName] ||
+ this.getDefaultPage();
+ if (currentOverlay && !currentOverlay.isAncestorOfPage(newPage)) {
+ currentOverlay.visible = false;
+ if (currentOverlay.didClosePage) currentOverlay.didClosePage();
+ }
this.showPageByName(data.pageName, false);
}
};
diff --git a/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc b/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
index 3fc5148..ba52cd7 100644
--- a/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
+++ b/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
@@ -31,7 +31,7 @@ using testing::AnyNumber;
using testing::Return;
using testing::_;
-class CertificateManagerBrowserTest : public options::OptionsBrowserTest {
+class CertificateManagerBrowserTest : public options::OptionsUIBrowserTest {
public:
CertificateManagerBrowserTest() {}
virtual ~CertificateManagerBrowserTest() {}
diff --git a/chrome/browser/ui/webui/options/chromeos/guest_mode_options_ui_browsertest.cc b/chrome/browser/ui/webui/options/chromeos/guest_mode_options_ui_browsertest.cc
index 5256c8d..fe5d060 100644
--- a/chrome/browser/ui/webui/options/chromeos/guest_mode_options_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/options/chromeos/guest_mode_options_ui_browsertest.cc
@@ -9,11 +9,11 @@
namespace {
-// Same as OptionsBrowserTest but launches with Guest mode command line
+// Same as OptionsUIBrowserTest but launches with Guest mode command line
// switches.
-class GuestModeOptionsBrowserTest : public options::OptionsBrowserTest {
+class GuestModeOptionsBrowserTest : public options::OptionsUIBrowserTest {
public:
- GuestModeOptionsBrowserTest() : OptionsBrowserTest() {}
+ GuestModeOptionsBrowserTest() : OptionsUIBrowserTest() {}
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
command_line->AppendSwitch(chromeos::switches::kGuestSession);
diff --git a/chrome/browser/ui/webui/options/options_browsertest.cc b/chrome/browser/ui/webui/options/options_browsertest.cc
new file mode 100644
index 0000000..7cb42fd3
--- /dev/null
+++ b/chrome/browser/ui/webui/options/options_browsertest.cc
@@ -0,0 +1,49 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/options/options_browsertest.h"
+
+#include "base/bind.h"
+#include "base/values.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "url/gurl.h"
+
+using content::NavigationController;
+using content::NavigationEntry;
+using content::WebUIMessageHandler;
+
+OptionsBrowserTest::OptionsBrowserTest() {
+}
+
+OptionsBrowserTest::~OptionsBrowserTest() {
+}
+
+void OptionsBrowserTest::RegisterMessages() {
+ web_ui()->RegisterMessageCallback(
+ "optionsTestReportHistory", base::Bind(&OptionsBrowserTest::ReportHistory,
+ base::Unretained(this)));
+}
+
+// Includes the current entry.
+void OptionsBrowserTest::ReportHistory(const base::ListValue* list_value) {
+ const NavigationController& controller =
+ browser()->tab_strip_model()->GetActiveWebContents()->GetController();
+ base::ListValue history;
+ const int current = controller.GetCurrentEntryIndex();
+ for (int i = 0; i <= current; ++i) {
+ GURL url = controller.GetEntryAtIndex(i)->GetVirtualURL();
+ history.Append(new base::StringValue(url.spec()));
+ }
+ web_ui()->CallJavascriptFunction(
+ "OptionsWebUINavigationTest.verifyHistoryCallback", history);
+}
+
+content::WebUIMessageHandler* OptionsBrowserTest::GetMockMessageHandler() {
+ return this;
+}
diff --git a/chrome/browser/ui/webui/options/options_browsertest.h b/chrome/browser/ui/webui/options/options_browsertest.h
new file mode 100644
index 0000000..7499ca8
--- /dev/null
+++ b/chrome/browser/ui/webui/options/options_browsertest.h
@@ -0,0 +1,36 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS_OPTIONS_BROWSERTEST_H_
+#define CHROME_BROWSER_UI_WEBUI_OPTIONS_OPTIONS_BROWSERTEST_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/test/base/web_ui_browsertest.h"
+#include "content/public/browser/web_ui_message_handler.h"
+
+// This is a helper class used by options_browsertest.js to feed the navigation
+// history back to the test.
+class OptionsBrowserTest : public WebUIBrowserTest,
+ public content::WebUIMessageHandler {
+ public:
+ OptionsBrowserTest();
+ virtual ~OptionsBrowserTest();
+
+ private:
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ // WebUIBrowserTest implementation.
+ virtual content::WebUIMessageHandler* GetMockMessageHandler() OVERRIDE;
+
+ // A callback for the 'optionsTestReportHistory' message, this sends the
+ // URLs in the "back" tab history, including the current entry, back to the
+ // WebUI via a callback.
+ void ReportHistory(const base::ListValue* list_value);
+
+ DISALLOW_COPY_AND_ASSIGN(OptionsBrowserTest);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS_OPTIONS_BROWSERTEST_H_
diff --git a/chrome/browser/ui/webui/options/options_browsertest.js b/chrome/browser/ui/webui/options/options_browsertest.js
index 8a5f1cd..5fa7932 100644
--- a/chrome/browser/ui/webui/options/options_browsertest.js
+++ b/chrome/browser/ui/webui/options/options_browsertest.js
@@ -2,6 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+GEN('#include "chrome/browser/ui/webui/options/options_browsertest.h"');
+
+/**
+ * Wait for the global window.onpopstate callback to be called (after a tab
+ * history navigation), then execute |afterFunction|.
+ */
+function waitForPopstate(afterFunction) {
+ var originalCallback = window.onpopstate;
+
+ // Install a wrapper that temporarily replaces the original function.
+ window.onpopstate = function() {
+ window.onpopstate = originalCallback;
+ originalCallback.apply(this, arguments);
+ afterFunction();
+ };
+}
+
/**
* TestFixture for OptionsPage WebUI testing.
* @extends {testing.Test}
@@ -214,3 +231,401 @@ TEST_F('OptionsWebUITest', 'EnableAndDisableDoNotTrack', function() {
dntCheckbox.click();
});
+
+/**
+ * TestFixture for OptionsPage WebUI testing including tab history.
+ * @extends {testing.Test}
+ * @constructor
+ */
+function OptionsWebUINavigationTest() {}
+
+OptionsWebUINavigationTest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ /** @override */
+ browsePreload: 'chrome://settings-frame',
+
+ /** @override */
+ typedefCppFixture: 'OptionsBrowserTest',
+
+ /** @override */
+ isAsync: true,
+
+ /**
+ * Asserts that two non-nested arrays are equal. The arrays must contain only
+ * plain data types, no nested arrays or other objects.
+ * @param {Array} expected An array of expected values.
+ * @param {Array} result An array of actual values.
+ * @param {boolean} doSort If true, the arrays will be sorted before being
+ * compared.
+ * @param {string} description A brief description for the array of actual
+ * values, to use in an error message if the arrays differ.
+ * @private
+ */
+ compareArrays_: function(expected, result, doSort, description) {
+ var errorMessage = '\n' + description + ': ' + result +
+ '\nExpected: ' + expected;
+ assertEquals(expected.length, result.length, errorMessage);
+
+ var expectedSorted = expected.slice();
+ var resultSorted = result.slice();
+ if (doSort) {
+ expectedSorted.sort();
+ resultSorted.sort();
+ }
+
+ for (var i = 0; i < expectedSorted.length; ++i) {
+ assertEquals(expectedSorted[i], resultSorted[i], errorMessage);
+ }
+ },
+
+ /**
+ * Verifies that the correct pages are currently open/visible.
+ * @param {!Array.<string>} expectedPages An array of page names expected to
+ * be open, with the topmost listed last.
+ * @param {string=} expectedUrl The URL path, including hash, expected to be
+ * open. If undefined, the topmost (last) page name in |expectedPages|
+ * will be used. In either case, 'chrome://settings-frame/' will be
+ * prepended.
+ * @private
+ */
+ verifyOpenPages_: function(expectedPages, expectedUrl) {
+ // Check the topmost page.
+ assertEquals(null, OptionsPage.getVisibleBubble());
+ var currentPage = OptionsPage.getTopmostVisiblePage();
+
+ var lastExpected = expectedPages[expectedPages.length - 1];
+ assertEquals(lastExpected, currentPage.name);
+ // We'd like to check the title too, but we have to load the settings-frame
+ // instead of the outer settings page in order to have access to
+ // OptionsPage, and setting the title from within the settings-frame fails
+ // because of cross-origin access restrictions.
+ // TODO(pamg): Add a test fixture that loads chrome://settings and uses
+ // UI elements to access sub-pages, so we can test the titles and
+ // search-page URLs.
+ var fullExpectedUrl = 'chrome://settings-frame/' +
+ (expectedUrl ? expectedUrl : lastExpected);
+ assertEquals(fullExpectedUrl, window.location.href);
+
+ // Collect open pages.
+ var allPageNames = Object.keys(OptionsPage.registeredPages).concat(
+ Object.keys(OptionsPage.registeredOverlayPages));
+ var openPages = [];
+ for (var i = 0; i < allPageNames.length; ++i) {
+ var name = allPageNames[i];
+ var page = OptionsPage.registeredPages[name] ||
+ OptionsPage.registeredOverlayPages[name];
+ if (page.visible)
+ openPages.push(page.name);
+ }
+
+ this.compareArrays_(expectedPages, openPages, true, 'Open pages');
+ },
+
+ /*
+ * Verifies that the correct URLs are listed in the history. Asynchronous.
+ * @param {!Array.<string>} expectedHistory An array of URL paths expected to
+ * be in the tab navigation history, sorted by visit time, including the
+ * current page as the last entry. The base URL (chrome://settings-frame/)
+ * will be prepended to each. An initial 'about:blank' history entry is
+ * assumed and should not be included in this list.
+ * @param {Function=} callback A function to be called after the history has
+ * been verified successfully. May be undefined.
+ * @private
+ */
+ verifyHistory_: function(expectedHistory, callback) {
+ var self = this;
+ OptionsWebUINavigationTest.verifyHistoryCallback = function(results) {
+ // The history always starts with a blank page.
+ assertEquals('about:blank', results.shift());
+ var fullExpectedHistory = [];
+ for (var i = 0; i < expectedHistory.length; ++i) {
+ fullExpectedHistory.push(
+ 'chrome://settings-frame/' + expectedHistory[i]);
+ }
+ self.compareArrays_(fullExpectedHistory, results, false, 'History');
+ callback();
+ };
+
+ // The C++ fixture will call verifyHistoryCallback with the results.
+ chrome.send('optionsTestReportHistory');
+ },
+
+ /**
+ * Overrides the page callbacks for the given OptionsPage overlay to verify
+ * that they are not called.
+ * @param {Object} overlay The singleton instance of the overlay.
+ * @private
+ */
+ prohibitChangesToOverlay_: function(overlay) {
+ overlay.initializePage =
+ overlay.didShowPage =
+ overlay.didClosePage = function() {
+ assertTrue(false,
+ 'Overlay was affected when changes were prohibited.');
+ };
+ },
+};
+
+/*
+ * Set by verifyHistory_ to incorporate a followup callback, then called by the
+ * C++ fixture with the navigation history to be verified.
+ * @type {Function}
+ */
+OptionsWebUINavigationTest.verifyHistoryCallback = null;
+
+// Show the search page with no query string, to fall back to the settings page.
+TEST_F('OptionsWebUINavigationTest', 'ShowSearchPageNoQuery', function() {
+ OptionsPage.showPageByName('search');
+ this.verifyOpenPages_(['settings']);
+ this.verifyHistory_(['settings'], testDone);
+});
+
+// Show a page without updating history.
+TEST_F('OptionsWebUINavigationTest', 'ShowPageNoHistory', function() {
+ this.verifyOpenPages_(['settings']);
+ // There are only two main pages, 'settings' and 'search'. It's not possible
+ // to show the search page using OptionsPage.showPageByName, because it
+ // reverts to the settings page if it has no search text set. So we show the
+ // search page by performing a search, then test showPageByName.
+ $('search-field').onsearch({currentTarget: {value: 'query'}});
+
+ // The settings page is also still "open" (i.e., visible), in order to show
+ // the search results. Furthermore, the URL hasn't been updated in the parent
+ // page, because we've loaded the chrome-settings frame instead of the whole
+ // settings page, so the cross-origin call to set the URL fails.
+ this.verifyOpenPages_(['settings', 'search'], 'settings#query');
+ var self = this;
+ this.verifyHistory_(['settings', 'settings#query'], function() {
+ OptionsPage.showPageByName('settings', false);
+ self.verifyOpenPages_(['settings'], 'settings#query');
+ self.verifyHistory_(['settings', 'settings#query'], testDone);
+ });
+});
+
+TEST_F('OptionsWebUINavigationTest', 'ShowPageWithHistory', function() {
+ // See comments for ShowPageNoHistory.
+ $('search-field').onsearch({currentTarget: {value: 'query'}});
+ var self = this;
+ this.verifyHistory_(['settings', 'settings#query'], function() {
+ OptionsPage.showPageByName('settings', true);
+ self.verifyOpenPages_(['settings'], 'settings#query');
+ self.verifyHistory_(['settings', 'settings#query', 'settings#query'],
+ testDone);
+ });
+});
+
+TEST_F('OptionsWebUINavigationTest', 'ShowPageReplaceHistory', function() {
+ // See comments for ShowPageNoHistory.
+ $('search-field').onsearch({currentTarget: {value: 'query'}});
+ var self = this;
+ this.verifyHistory_(['settings', 'settings#query'], function() {
+ OptionsPage.showPageByName('settings', true, {'replaceState': true});
+ self.verifyOpenPages_(['settings'], 'settings#query');
+ self.verifyHistory_(['settings', 'settings#query'], testDone);
+ });
+});
+
+// This should be identical to ShowPageWithHisory.
+TEST_F('OptionsWebUINavigationTest', 'NavigateToPage', function() {
+ // See comments for ShowPageNoHistory.
+ $('search-field').onsearch({currentTarget: {value: 'query'}});
+ var self = this;
+ this.verifyHistory_(['settings', 'settings#query'], function() {
+ OptionsPage.navigateToPage('settings');
+ self.verifyOpenPages_(['settings'], 'settings#query');
+ self.verifyHistory_(['settings', 'settings#query', 'settings#query'],
+ testDone);
+ });
+});
+
+// Settings overlays are much more straightforward than settings pages, opening
+// normally with none of the latter's quirks in the expected history or URL.
+TEST_F('OptionsWebUINavigationTest', 'ShowOverlayNoHistory', function() {
+ // Open a layer-1 overlay, not updating history.
+ OptionsPage.showPageByName('languages', false);
+ this.verifyOpenPages_(['settings', 'languages'], 'settings');
+
+ var self = this;
+ this.verifyHistory_(['settings'], function() {
+ // Open a layer-2 overlay for which the layer-1 is a parent, not updating
+ // history.
+ OptionsPage.showPageByName('addLanguage', false);
+ self.verifyOpenPages_(['settings', 'languages', 'addLanguage'],
+ 'settings');
+ self.verifyHistory_(['settings'], testDone);
+ });
+});
+
+TEST_F('OptionsWebUINavigationTest', 'ShowOverlayWithHistory', function() {
+ // Open a layer-1 overlay, updating history.
+ OptionsPage.showPageByName('languages', true);
+ this.verifyOpenPages_(['settings', 'languages']);
+
+ var self = this;
+ this.verifyHistory_(['settings', 'languages'], function() {
+ // Open a layer-2 overlay, updating history.
+ OptionsPage.showPageByName('addLanguage', true);
+ self.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
+ self.verifyHistory_(['settings', 'languages', 'addLanguage'], testDone);
+ });
+});
+
+TEST_F('OptionsWebUINavigationTest', 'ShowOverlayReplaceHistory', function() {
+ // Open a layer-1 overlay, updating history.
+ OptionsPage.showPageByName('languages', true);
+ var self = this;
+ this.verifyHistory_(['settings', 'languages'], function() {
+ // Open a layer-2 overlay, replacing history.
+ OptionsPage.showPageByName('addLanguage', true, {'replaceState': true});
+ self.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
+ self.verifyHistory_(['settings', 'addLanguage'], testDone);
+ });
+});
+
+// Directly show an overlay further above this page, i.e. one for which the
+// current page is an ancestor but not a parent.
+TEST_F('OptionsWebUINavigationTest', 'ShowOverlayFurtherAbove', function() {
+ // Open a layer-2 overlay directly.
+ OptionsPage.showPageByName('addLanguage', true);
+ this.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
+ var self = this;
+ this.verifyHistory_(['settings', 'addLanguage'], testDone);
+});
+
+// Directly show a layer-2 overlay for which the layer-1 overlay is not a
+// parent.
+TEST_F('OptionsWebUINavigationTest', 'ShowUnrelatedOverlay', function() {
+ // Open a layer-1 overlay.
+ OptionsPage.showPageByName('languages', true);
+ this.verifyOpenPages_(['settings', 'languages']);
+
+ var self = this;
+ this.verifyHistory_(['settings', 'languages'], function() {
+ // Open an unrelated layer-2 overlay.
+ OptionsPage.showPageByName('cookies', true);
+ self.verifyOpenPages_(['settings', 'content', 'cookies']);
+ self.verifyHistory_(['settings', 'languages', 'cookies'], testDone);
+ });
+});
+
+// Close an overlay.
+TEST_F('OptionsWebUINavigationTest', 'CloseOverlay', function() {
+ // Open a layer-1 overlay, then a layer-2 overlay on top of it.
+ OptionsPage.showPageByName('languages', true);
+ this.verifyOpenPages_(['settings', 'languages']);
+ OptionsPage.showPageByName('addLanguage', true);
+ this.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
+
+ var self = this;
+ this.verifyHistory_(['settings', 'languages', 'addLanguage'], function() {
+ // Close the layer-2 overlay.
+ OptionsPage.closeOverlay();
+ self.verifyOpenPages_(['settings', 'languages']);
+ self.verifyHistory_(
+ ['settings', 'languages', 'addLanguage', 'languages'],
+ function() {
+ // Close the layer-1 overlay.
+ OptionsPage.closeOverlay();
+ self.verifyOpenPages_(['settings']);
+ self.verifyHistory_(
+ ['settings', 'languages', 'addLanguage', 'languages', 'settings'],
+ testDone);
+ });
+ });
+});
+
+// Make sure an overlay isn't closed (even temporarily) when another overlay is
+// opened on top.
+TEST_F('OptionsWebUINavigationTest', 'OverlayAboveNoReset', function() {
+ // Open a layer-1 overlay.
+ OptionsPage.showPageByName('languages', true);
+ this.verifyOpenPages_(['settings', 'languages']);
+
+ // Open a layer-2 overlay on top. This should not close 'languages'.
+ this.prohibitChangesToOverlay_(options.LanguageOptions.getInstance());
+ OptionsPage.showPageByName('addLanguage', true);
+ this.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
+ testDone();
+});
+
+TEST_F('OptionsWebUINavigationTest', 'OverlayTabNavigation', function() {
+ // Open a layer-1 overlay, then a layer-2 overlay on top of it.
+ OptionsPage.showPageByName('languages', true);
+ OptionsPage.showPageByName('addLanguage', true);
+ var self = this;
+
+ // Go back twice, then forward twice.
+ self.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
+ self.verifyHistory_(['settings', 'languages', 'addLanguage'], function() {
+ window.history.back();
+ waitForPopstate(function() {
+ self.verifyOpenPages_(['settings', 'languages']);
+ self.verifyHistory_(['settings', 'languages'], function() {
+ window.history.back();
+ waitForPopstate(function() {
+ self.verifyOpenPages_(['settings']);
+ self.verifyHistory_(['settings'], function() {
+ window.history.forward();
+ waitForPopstate(function() {
+ self.verifyOpenPages_(['settings', 'languages']);
+ self.verifyHistory_(['settings', 'languages'], function() {
+ window.history.forward();
+ waitForPopstate(function() {
+ self.verifyOpenPages_(
+ ['settings', 'languages', 'addLanguage']);
+ self.verifyHistory_(
+ ['settings', 'languages', 'addLanguage'], testDone);
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+});
+
+// Going "back" to an overlay that's a child of the current overlay shouldn't
+// close the current one.
+TEST_F('OptionsWebUINavigationTest', 'OverlayBackToChild', function() {
+ // Open a layer-1 overlay, then a layer-2 overlay on top of it.
+ OptionsPage.showPageByName('languages', true);
+ OptionsPage.showPageByName('addLanguage', true);
+ var self = this;
+
+ self.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
+ self.verifyHistory_(['settings', 'languages', 'addLanguage'], function() {
+ // Close the top overlay, then go back to it.
+ OptionsPage.closeOverlay();
+ self.verifyOpenPages_(['settings', 'languages']);
+ self.verifyHistory_(
+ ['settings', 'languages', 'addLanguage', 'languages'],
+ function() {
+ // Going back to the 'addLanguage' page should not close 'languages'.
+ self.prohibitChangesToOverlay_(options.LanguageOptions.getInstance());
+ window.history.back();
+ waitForPopstate(function() {
+ self.verifyOpenPages_(['settings', 'languages', 'addLanguage']);
+ self.verifyHistory_(['settings', 'languages', 'addLanguage'],
+ testDone);
+ });
+ });
+ });
+});
+
+// Going back to an unrelated overlay should close the overlay and its parent.
+TEST_F('OptionsWebUINavigationTest', 'OverlayBackToUnrelated', function() {
+ // Open a layer-1 overlay, then an unrelated layer-2 overlay.
+ OptionsPage.showPageByName('languages', true);
+ OptionsPage.showPageByName('cookies', true);
+ var self = this;
+ self.verifyOpenPages_(['settings', 'content', 'cookies']);
+ self.verifyHistory_(['settings', 'languages', 'cookies'], function() {
+ window.history.back();
+ waitForPopstate(function() {
+ self.verifyOpenPages_(['settings', 'languages']);
+ testDone();
+ });
+ });
+});
diff --git a/chrome/browser/ui/webui/options/options_ui_browsertest.cc b/chrome/browser/ui/webui/options/options_ui_browsertest.cc
index ce607b3..e23ec21 100644
--- a/chrome/browser/ui/webui/options/options_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/options/options_ui_browsertest.cc
@@ -17,15 +17,15 @@
namespace options {
-OptionsBrowserTest::OptionsBrowserTest() {
+OptionsUIBrowserTest::OptionsUIBrowserTest() {
}
-void OptionsBrowserTest::NavigateToSettings() {
+void OptionsUIBrowserTest::NavigateToSettings() {
const GURL& url = GURL(chrome::kChromeUISettingsURL);
ui_test_utils::NavigateToURL(browser(), url);
}
-void OptionsBrowserTest::VerifyNavbar() {
+void OptionsUIBrowserTest::VerifyNavbar() {
bool navbar_exist = false;
EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
browser()->tab_strip_model()->GetActiveWebContents(),
@@ -35,7 +35,7 @@ void OptionsBrowserTest::VerifyNavbar() {
EXPECT_EQ(true, navbar_exist);
}
-void OptionsBrowserTest::VerifyTitle() {
+void OptionsUIBrowserTest::VerifyTitle() {
string16 title =
browser()->tab_strip_model()->GetActiveWebContents()->GetTitle();
string16 expected_title = l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE);
@@ -43,7 +43,7 @@ void OptionsBrowserTest::VerifyTitle() {
}
// Flaky, see http://crbug.com/119671.
-IN_PROC_BROWSER_TEST_F(OptionsBrowserTest, DISABLED_LoadOptionsByURL) {
+IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, DISABLED_LoadOptionsByURL) {
NavigateToSettings();
VerifyTitle();
VerifyNavbar();
diff --git a/chrome/browser/ui/webui/options/options_ui_browsertest.h b/chrome/browser/ui/webui/options/options_ui_browsertest.h
index 2d5a822..aed9a6b 100644
--- a/chrome/browser/ui/webui/options/options_ui_browsertest.h
+++ b/chrome/browser/ui/webui/options/options_ui_browsertest.h
@@ -10,9 +10,9 @@
namespace options {
-class OptionsBrowserTest : public InProcessBrowserTest {
+class OptionsUIBrowserTest : public InProcessBrowserTest {
public:
- OptionsBrowserTest();
+ OptionsUIBrowserTest();
// Navigate to the settings tab and block until complete.
void NavigateToSettings();
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 37a7077..dad04a8 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1639,6 +1639,7 @@
'browser/ui/webui/options/font_settings_browsertest.js',
'browser/ui/webui/options/language_options_browsertest.js',
'browser/ui/webui/options/language_options_dictionary_download_browsertest.js',
+ 'browser/ui/webui/options/options_browsertest.cc',
'browser/ui/webui/options/options_browsertest.js',
'browser/ui/webui/options/options_ui_browsertest.cc',
'browser/ui/webui/options/options_ui_browsertest.h',