1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <vector> 6 7#include "base/command_line.h" 8#include "base/file_path.h" 9#include "base/file_util.h" 10#include "base/path_service.h" 11#include "chrome/browser/extensions/extension_service.h" 12#include "chrome/browser/extensions/user_script_master.h" 13#include "chrome/browser/profiles/profile.h" 14#include "chrome/browser/ui/browser.h" 15#include "chrome/common/chrome_paths.h" 16#include "chrome/common/chrome_switches.h" 17#include "chrome/test/in_process_browser_test.h" 18#include "chrome/test/ui_test_utils.h" 19#include "content/browser/tab_contents/tab_contents.h" 20#include "content/common/notification_details.h" 21#include "content/common/notification_type.h" 22#include "net/base/net_util.h" 23 24// This file contains high-level startup tests for the extensions system. We've 25// had many silly bugs where command line flags did not get propagated correctly 26// into the services, so we didn't start correctly. 27 28class ExtensionStartupTestBase : public InProcessBrowserTest { 29 public: 30 ExtensionStartupTestBase() : enable_extensions_(false) { 31 num_expected_extensions_ = 3; 32 } 33 34 protected: 35 // InProcessBrowserTest 36 virtual void SetUpCommandLine(CommandLine* command_line) { 37 EnableDOMAutomation(); 38 39 FilePath profile_dir; 40 PathService::Get(chrome::DIR_USER_DATA, &profile_dir); 41 profile_dir = profile_dir.AppendASCII("Default"); 42 file_util::CreateDirectory(profile_dir); 43 44 preferences_file_ = profile_dir.AppendASCII("Preferences"); 45 user_scripts_dir_ = profile_dir.AppendASCII("User Scripts"); 46 extensions_dir_ = profile_dir.AppendASCII("Extensions"); 47 48 if (enable_extensions_) { 49 if (load_extension_.empty()) { 50 FilePath src_dir; 51 PathService::Get(chrome::DIR_TEST_DATA, &src_dir); 52 src_dir = src_dir.AppendASCII("extensions").AppendASCII("good"); 53 54 file_util::CopyFile(src_dir.AppendASCII("Preferences"), 55 preferences_file_); 56 file_util::CopyDirectory(src_dir.AppendASCII("Extensions"), 57 profile_dir, true); // recursive 58 } 59 } else { 60 command_line->AppendSwitch(switches::kDisableExtensions); 61 } 62 63 if (!load_extension_.empty()) { 64 command_line->AppendSwitchPath(switches::kLoadExtension, load_extension_); 65 command_line->AppendSwitch(switches::kDisableExtensionsFileAccessCheck); 66 } 67 } 68 69 virtual void TearDown() { 70 EXPECT_TRUE(file_util::Delete(preferences_file_, false)); 71 72 // TODO(phajdan.jr): Check return values of the functions below, carefully. 73 file_util::Delete(user_scripts_dir_, true); 74 file_util::Delete(extensions_dir_, true); 75 76 InProcessBrowserTest::TearDown(); 77 } 78 79 void WaitForServicesToStart(int num_expected_extensions, 80 bool expect_extensions_enabled) { 81 ExtensionService* service = browser()->profile()->GetExtensionService(); 82 83 // Count the number of non-component extensions. 84 int found_extensions = 0; 85 for (size_t i = 0; i < service->extensions()->size(); i++) 86 if (service->extensions()->at(i)->location() != Extension::COMPONENT) 87 found_extensions++; 88 89 ASSERT_EQ(static_cast<uint32>(num_expected_extensions), 90 static_cast<uint32>(found_extensions)); 91 ASSERT_EQ(expect_extensions_enabled, service->extensions_enabled()); 92 93 UserScriptMaster* master = browser()->profile()->GetUserScriptMaster(); 94 if (!master->ScriptsReady()) { 95 ui_test_utils::WaitForNotification( 96 NotificationType::USER_SCRIPTS_UPDATED); 97 } 98 ASSERT_TRUE(master->ScriptsReady()); 99 } 100 101 void TestInjection(bool expect_css, bool expect_script) { 102 // Load a page affected by the content script and test to see the effect. 103 FilePath test_file; 104 PathService::Get(chrome::DIR_TEST_DATA, &test_file); 105 test_file = test_file.AppendASCII("extensions") 106 .AppendASCII("test_file.html"); 107 108 ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(test_file)); 109 110 bool result = false; 111 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 112 browser()->GetSelectedTabContents()->render_view_host(), L"", 113 L"window.domAutomationController.send(" 114 L"document.defaultView.getComputedStyle(document.body, null)." 115 L"getPropertyValue('background-color') == 'rgb(245, 245, 220)')", 116 &result)); 117 EXPECT_EQ(expect_css, result); 118 119 result = false; 120 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 121 browser()->GetSelectedTabContents()->render_view_host(), L"", 122 L"window.domAutomationController.send(document.title == 'Modified')", 123 &result)); 124 EXPECT_EQ(expect_script, result); 125 } 126 127 FilePath preferences_file_; 128 FilePath extensions_dir_; 129 FilePath user_scripts_dir_; 130 bool enable_extensions_; 131 FilePath load_extension_; 132 133 int num_expected_extensions_; 134}; 135 136 137// ExtensionsStartupTest 138// Ensures that we can startup the browser with --enable-extensions and some 139// extensions installed and see them run and do basic things. 140 141class ExtensionsStartupTest : public ExtensionStartupTestBase { 142 public: 143 ExtensionsStartupTest() { 144 enable_extensions_ = true; 145 } 146}; 147 148IN_PROC_BROWSER_TEST_F(ExtensionsStartupTest, Test) { 149 WaitForServicesToStart(num_expected_extensions_, true); 150 TestInjection(true, true); 151} 152 153// Sometimes times out on Mac. http://crbug.com/48151 154#if defined(OS_MACOSX) 155#define MAYBE_NoFileAccess DISABLED_NoFileAccess 156#else 157#define MAYBE_NoFileAccess NoFileAccess 158#endif 159// Tests that disallowing file access on an extension prevents it from injecting 160// script into a page with a file URL. 161IN_PROC_BROWSER_TEST_F(ExtensionsStartupTest, MAYBE_NoFileAccess) { 162 WaitForServicesToStart(num_expected_extensions_, true); 163 164 ExtensionService* service = browser()->profile()->GetExtensionService(); 165 for (size_t i = 0; i < service->extensions()->size(); ++i) { 166 if (service->extensions()->at(i)->location() == Extension::COMPONENT) 167 continue; 168 if (service->AllowFileAccess(service->extensions()->at(i))) { 169 service->SetAllowFileAccess(service->extensions()->at(i), false); 170 ui_test_utils::WaitForNotification( 171 NotificationType::USER_SCRIPTS_UPDATED); 172 } 173 } 174 175 TestInjection(false, false); 176} 177 178// ExtensionsLoadTest 179// Ensures that we can startup the browser with --load-extension and see them 180// run. 181 182class ExtensionsLoadTest : public ExtensionStartupTestBase { 183 public: 184 ExtensionsLoadTest() { 185 enable_extensions_ = true; 186 PathService::Get(chrome::DIR_TEST_DATA, &load_extension_); 187 load_extension_ = load_extension_ 188 .AppendASCII("extensions") 189 .AppendASCII("good") 190 .AppendASCII("Extensions") 191 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj") 192 .AppendASCII("1.0.0.0"); 193 } 194}; 195 196IN_PROC_BROWSER_TEST_F(ExtensionsLoadTest, Test) { 197 WaitForServicesToStart(1, true); 198 TestInjection(true, true); 199} 200