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