blob: d045d5e3a99ec20dbc866ce146273ac4c7a30eba [file] [log] [blame]
// Copyright 2017 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 "base/macros.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/search/instant_test_base.h"
#include "chrome/browser/ui/search/instant_test_utils.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/theme_source.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/extension_registry.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
class InstantThemeTest : public ExtensionBrowserTest, public InstantTestBase {
public:
InstantThemeTest() {}
protected:
void SetUpInProcessBrowserTestFixture() override {
ASSERT_TRUE(https_test_server().Start());
GURL base_url = https_test_server().GetURL("/instant_extended.html");
GURL ntp_url = https_test_server().GetURL("/instant_extended_ntp.html");
InstantTestBase::Init(base_url, ntp_url, false);
}
void SetUpOnMainThread() override {
ExtensionBrowserTest::SetUpOnMainThread();
content::URLDataSource::Add(profile(), new ThemeSource(profile()));
}
void InstallThemeAndVerify(const std::string& theme_dir,
const std::string& theme_name) {
bool had_previous_theme =
!!ThemeServiceFactory::GetThemeForProfile(profile());
const base::FilePath theme_path = test_data_dir_.AppendASCII(theme_dir);
// Themes install asynchronously so we must check the number of enabled
// extensions after theme install completes.
size_t num_before = extensions::ExtensionRegistry::Get(profile())
->enabled_extensions()
.size();
content::WindowedNotificationObserver theme_change_observer(
chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
content::Source<ThemeService>(
ThemeServiceFactory::GetForProfile(profile())));
ASSERT_TRUE(InstallExtensionWithUIAutoConfirm(
theme_path, 1, ExtensionBrowserTest::browser()));
theme_change_observer.Wait();
size_t num_after = extensions::ExtensionRegistry::Get(profile())
->enabled_extensions()
.size();
// If a theme was already installed, we're just swapping one for another, so
// no change in extension count.
int expected_change = had_previous_theme ? 0 : 1;
EXPECT_EQ(num_before + expected_change, num_after);
const extensions::Extension* new_theme =
ThemeServiceFactory::GetThemeForProfile(profile());
ASSERT_NE(nullptr, new_theme);
ASSERT_EQ(new_theme->name(), theme_name);
}
// Loads a named image from |image_url| in the given |tab|. |loaded|
// returns whether the image was able to load without error.
// The method returns true if the JavaScript executed cleanly.
bool LoadImage(content::WebContents* tab,
const GURL& image_url,
bool* loaded) {
std::string js_chrome =
"var img = document.createElement('img');"
"img.onerror = function() { domAutomationController.send(false); };"
"img.onload = function() { domAutomationController.send(true); };"
"img.src = '" +
image_url.spec() + "';";
return content::ExecuteScriptAndExtractBool(tab, js_chrome, loaded);
}
private:
DISALLOW_COPY_AND_ASSIGN(InstantThemeTest);
};
IN_PROC_BROWSER_TEST_F(InstantThemeTest, ThemeBackgroundAccess) {
ASSERT_NO_FATAL_FAILURE(InstallThemeAndVerify("theme", "camo theme"));
ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
ui_test_utils::NavigateToURLWithDisposition(
browser(), GURL(chrome::kChromeUINewTabURL),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB |
ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
// The "Instant" New Tab should have access to chrome-search: scheme but not
// chrome: scheme.
const GURL chrome_url("chrome://theme/IDR_THEME_NTP_BACKGROUND");
const GURL search_url("chrome-search://theme/IDR_THEME_NTP_BACKGROUND");
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
bool loaded = false;
ASSERT_TRUE(LoadImage(tab, chrome_url, &loaded));
EXPECT_FALSE(loaded) << chrome_url;
ASSERT_TRUE(LoadImage(tab, search_url, &loaded));
EXPECT_TRUE(loaded) << search_url;
}
// Flaky on all bots. http://crbug.com/335297.
IN_PROC_BROWSER_TEST_F(InstantThemeTest,
DISABLED_NoThemeBackgroundChangeEventOnTabSwitch) {
ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
// Install a theme.
ASSERT_NO_FATAL_FAILURE(InstallThemeAndVerify("theme", "camo theme"));
ASSERT_EQ(1, browser()->tab_strip_model()->count());
// Open new tab.
ui_test_utils::NavigateToURLWithDisposition(
browser(), GURL(chrome::kChromeUINewTabURL),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB |
ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
ASSERT_EQ(2, browser()->tab_strip_model()->count());
// Make sure the tab did not receive an onthemechange event for the
// already-installed theme. (An event *is* sent, but that happens before the
// page can register its handler.)
content::WebContents* active_tab =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
int on_theme_changed_calls = 0;
ASSERT_TRUE(instant_test_utils::GetIntFromJS(
active_tab, "onThemeChangedCalls", &on_theme_changed_calls));
EXPECT_EQ(0, on_theme_changed_calls);
// Activate the previous tab.
browser()->tab_strip_model()->ActivateTabAt(0, false);
ASSERT_EQ(0, browser()->tab_strip_model()->active_index());
// Switch back to new tab.
browser()->tab_strip_model()->ActivateTabAt(1, false);
ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
// Confirm that new tab got no onthemechange event while switching tabs.
active_tab = browser()->tab_strip_model()->GetActiveWebContents();
on_theme_changed_calls = 0;
ASSERT_TRUE(instant_test_utils::GetIntFromJS(
active_tab, "onThemeChangedCalls", &on_theme_changed_calls));
EXPECT_EQ(0, on_theme_changed_calls);
}
// Flaky on all bots. http://crbug.com/335297, http://crbug.com/265971.
IN_PROC_BROWSER_TEST_F(InstantThemeTest,
DISABLED_SendThemeBackgroundChangedEvent) {
ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
// Install a theme.
ASSERT_NO_FATAL_FAILURE(InstallThemeAndVerify("theme", "camo theme"));
ASSERT_EQ(1, browser()->tab_strip_model()->count());
// Open new tab.
ui_test_utils::NavigateToURLWithDisposition(
browser(), GURL(chrome::kChromeUINewTabURL),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB |
ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
ASSERT_EQ(2, browser()->tab_strip_model()->count());
// Make sure the tab did not receive an onthemechange event for the
// already-installed theme. (An event *is* sent, but that happens before the
// page can register its handler.)
content::WebContents* active_tab =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
int on_theme_changed_calls = 0;
ASSERT_TRUE(instant_test_utils::GetIntFromJS(
active_tab, "onThemeChangedCalls", &on_theme_changed_calls));
EXPECT_EQ(0, on_theme_changed_calls);
// Install a different theme.
ASSERT_NO_FATAL_FAILURE(InstallThemeAndVerify("theme2", "snowflake theme"));
// Confirm that the new tab got notified about the theme changed event.
on_theme_changed_calls = 0;
ASSERT_TRUE(instant_test_utils::GetIntFromJS(
active_tab, "onThemeChangedCalls", &on_theme_changed_calls));
EXPECT_EQ(1, on_theme_changed_calls);
}