• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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 #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSERTEST_H_
6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSERTEST_H_
7 
8 #include <string>
9 
10 #include "base/command_line.h"
11 
12 #include "base/files/file_path.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/test/scoped_path_override.h"
15 #include "chrome/browser/extensions/extension_test_notification_observer.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/common/extensions/features/feature_channel.h"
19 #include "chrome/test/base/in_process_browser_test.h"
20 #include "content/public/browser/web_contents.h"
21 #include "extensions/browser/extension_host.h"
22 #include "extensions/browser/extension_system.h"
23 #include "extensions/common/extension.h"
24 #include "extensions/common/feature_switch.h"
25 #include "extensions/common/manifest.h"
26 
27 class ExtensionService;
28 class Profile;
29 
30 namespace extensions {
31 class ExtensionCacheFake;
32 class ExtensionSet;
33 class ProcessManager;
34 }
35 
36 // Base class for extension browser tests. Provides utilities for loading,
37 // unloading, and installing extensions.
38 class ExtensionBrowserTest : virtual public InProcessBrowserTest {
39  protected:
40   // Flags used to configure how the tests are run.
41   enum Flags {
42     kFlagNone = 0,
43 
44     // Allow the extension to run in incognito mode.
45     kFlagEnableIncognito = 1 << 0,
46 
47     // Allow file access for the extension.
48     kFlagEnableFileAccess = 1 << 1,
49 
50     // Don't fail when the loaded manifest has warnings (should only be used
51     // when testing deprecated features).
52     kFlagIgnoreManifestWarnings = 1 << 2,
53 
54     // Allow older manifest versions (typically these can't be loaded - we allow
55     // them for testing).
56     kFlagAllowOldManifestVersions = 1 << 3,
57   };
58 
59   ExtensionBrowserTest();
60   virtual ~ExtensionBrowserTest();
61 
62   // Useful accessors.
extension_service()63   ExtensionService* extension_service() {
64     return extensions::ExtensionSystem::Get(profile())->extension_service();
65   }
66 
last_loaded_extension_id()67   const std::string& last_loaded_extension_id() {
68     return observer_->last_loaded_extension_id();
69   }
70 
71   // Get the profile to use.
72   virtual Profile* profile();
73 
74   static const extensions::Extension* GetExtensionByPath(
75       const extensions::ExtensionSet* extensions, const base::FilePath& path);
76 
77   // InProcessBrowserTest
78   virtual void SetUp() OVERRIDE;
79   virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE;
80   virtual void SetUpOnMainThread() OVERRIDE;
81 
82   const extensions::Extension* LoadExtension(const base::FilePath& path);
83 
84   // Load extension and enable it in incognito mode.
85   const extensions::Extension* LoadExtensionIncognito(
86       const base::FilePath& path);
87 
88   // Load extension from the |path| folder. |flags| is bit mask of values from
89   // |Flags| enum.
90   const extensions::Extension* LoadExtensionWithFlags(
91       const base::FilePath& path, int flags);
92 
93   // Same as above, but sets the installation parameter to the extension
94   // preferences.
95   const extensions::Extension* LoadExtensionWithInstallParam(
96       const base::FilePath& path,
97       int flags,
98       const std::string& install_param);
99 
100   // Loads unpacked extension from |path| with manifest |manifest_relative_path|
101   // and imitates that it is a component extension.
102   // |manifest_relative_path| is relative to |path|.
103   const extensions::Extension* LoadExtensionAsComponentWithManifest(
104       const base::FilePath& path,
105       const base::FilePath::CharType* manifest_relative_path);
106 
107   // Loads unpacked extension from |path| and imitates that it is a component
108   // extension. Equivalent to
109   // LoadExtensionAsComponentWithManifest(path, extensions::kManifestFilename).
110   const extensions::Extension* LoadExtensionAsComponent(
111       const base::FilePath& path);
112 
113   // Pack the extension in |dir_path| into a crx file and return its path.
114   // Return an empty FilePath if there were errors.
115   base::FilePath PackExtension(const base::FilePath& dir_path);
116 
117   // Pack the extension in |dir_path| into a crx file at |crx_path|, using the
118   // key |pem_path|. If |pem_path| does not exist, create a new key at
119   // |pem_out_path|.
120   // Return the path to the crx file, or an empty FilePath if there were errors.
121   base::FilePath PackExtensionWithOptions(const base::FilePath& dir_path,
122                                           const base::FilePath& crx_path,
123                                           const base::FilePath& pem_path,
124                                           const base::FilePath& pem_out_path);
125 
126   // |expected_change| indicates how many extensions should be installed (or
127   // disabled, if negative).
128   // 1 means you expect a new install, 0 means you expect an upgrade, -1 means
129   // you expect a failed upgrade.
InstallExtension(const base::FilePath & path,int expected_change)130   const extensions::Extension* InstallExtension(const base::FilePath& path,
131                                                 int expected_change) {
132     return InstallOrUpdateExtension(
133         std::string(), path, INSTALL_UI_TYPE_NONE, expected_change);
134   }
135 
136   // Same as above, but an install source other than Manifest::INTERNAL can be
137   // specified.
InstallExtension(const base::FilePath & path,int expected_change,extensions::Manifest::Location install_source)138   const extensions::Extension* InstallExtension(
139       const base::FilePath& path,
140       int expected_change,
141       extensions::Manifest::Location install_source) {
142     return InstallOrUpdateExtension(std::string(),
143                                     path,
144                                     INSTALL_UI_TYPE_NONE,
145                                     expected_change,
146                                     install_source);
147   }
148 
149   // Installs extension as if it came from the Chrome Webstore.
150   const extensions::Extension* InstallExtensionFromWebstore(
151       const base::FilePath& path, int expected_change);
152 
153   // Same as above but passes an id to CrxInstaller and does not allow a
154   // privilege increase.
UpdateExtension(const std::string & id,const base::FilePath & path,int expected_change)155   const extensions::Extension* UpdateExtension(const std::string& id,
156                                                const base::FilePath& path,
157                                                int expected_change) {
158     return InstallOrUpdateExtension(id, path, INSTALL_UI_TYPE_NONE,
159                                     expected_change);
160   }
161 
162   // Same as UpdateExtension but waits for the extension to be idle first.
163   const extensions::Extension* UpdateExtensionWaitForIdle(
164       const std::string& id, const base::FilePath& path, int expected_change);
165 
166   // Same as |InstallExtension| but with the normal extension UI showing up
167   // (for e.g. info bar on success).
InstallExtensionWithUI(const base::FilePath & path,int expected_change)168   const extensions::Extension* InstallExtensionWithUI(
169       const base::FilePath& path,
170       int expected_change) {
171     return InstallOrUpdateExtension(
172         std::string(), path, INSTALL_UI_TYPE_NORMAL, expected_change);
173   }
174 
InstallExtensionWithUIAutoConfirm(const base::FilePath & path,int expected_change,Browser * browser)175   const extensions::Extension* InstallExtensionWithUIAutoConfirm(
176       const base::FilePath& path,
177       int expected_change,
178       Browser* browser) {
179     return InstallOrUpdateExtension(std::string(),
180                                     path,
181                                     INSTALL_UI_TYPE_AUTO_CONFIRM,
182                                     expected_change,
183                                     browser,
184                                     extensions::Extension::NO_FLAGS);
185   }
186 
InstallExtensionWithSourceAndFlags(const base::FilePath & path,int expected_change,extensions::Manifest::Location install_source,extensions::Extension::InitFromValueFlags creation_flags)187   const extensions::Extension* InstallExtensionWithSourceAndFlags(
188       const base::FilePath& path,
189       int expected_change,
190       extensions::Manifest::Location install_source,
191       extensions::Extension::InitFromValueFlags creation_flags) {
192     return InstallOrUpdateExtension(std::string(),
193                                     path,
194                                     INSTALL_UI_TYPE_NONE,
195                                     expected_change,
196                                     install_source,
197                                     browser(),
198                                     creation_flags,
199                                     false,
200                                     false);
201   }
202 
InstallEphemeralAppWithSourceAndFlags(const base::FilePath & path,int expected_change,extensions::Manifest::Location install_source,extensions::Extension::InitFromValueFlags creation_flags)203   const extensions::Extension* InstallEphemeralAppWithSourceAndFlags(
204       const base::FilePath& path,
205       int expected_change,
206       extensions::Manifest::Location install_source,
207       extensions::Extension::InitFromValueFlags creation_flags) {
208     return InstallOrUpdateExtension(std::string(),
209                                     path,
210                                     INSTALL_UI_TYPE_NONE,
211                                     expected_change,
212                                     install_source,
213                                     browser(),
214                                     creation_flags,
215                                     false,
216                                     true);
217   }
218 
219   // Begins install process but simulates a user cancel.
StartInstallButCancel(const base::FilePath & path)220   const extensions::Extension* StartInstallButCancel(
221       const base::FilePath& path) {
222     return InstallOrUpdateExtension(
223         std::string(), path, INSTALL_UI_TYPE_CANCEL, 0);
224   }
225 
226   void ReloadExtension(const std::string extension_id);
227 
228   void UnloadExtension(const std::string& extension_id);
229 
230   void UninstallExtension(const std::string& extension_id);
231 
232   void DisableExtension(const std::string& extension_id);
233 
234   void EnableExtension(const std::string& extension_id);
235 
236   // Wait for the number of visible page actions to change to |count|.
WaitForPageActionVisibilityChangeTo(int count)237   bool WaitForPageActionVisibilityChangeTo(int count) {
238     return observer_->WaitForPageActionVisibilityChangeTo(count);
239   }
240 
241   // Waits until an extension is installed and loaded. Returns true if an
242   // install happened before timeout.
WaitForExtensionInstall()243   bool WaitForExtensionInstall() {
244     return observer_->WaitForExtensionInstall();
245   }
246 
247   // Wait for an extension install error to be raised. Returns true if an
248   // error was raised.
WaitForExtensionInstallError()249   bool WaitForExtensionInstallError() {
250     return observer_->WaitForExtensionInstallError();
251   }
252 
253   // Waits until an extension is loaded and all view have loaded.
WaitForExtensionAndViewLoad()254   void WaitForExtensionAndViewLoad() {
255     return observer_->WaitForExtensionAndViewLoad();
256   }
257 
258   // Waits until an extension is loaded.
WaitForExtensionLoad()259   void WaitForExtensionLoad() {
260     return observer_->WaitForExtensionLoad();
261   }
262 
263   // Waits for an extension load error. Returns true if the error really
264   // happened.
WaitForExtensionLoadError()265   bool WaitForExtensionLoadError() {
266     return observer_->WaitForExtensionLoadError();
267   }
268 
269   // Wait for the specified extension to crash. Returns true if it really
270   // crashed.
WaitForExtensionCrash(const std::string & extension_id)271   bool WaitForExtensionCrash(const std::string& extension_id) {
272     return observer_->WaitForExtensionCrash(extension_id);
273   }
274 
275   // Wait for the crx installer to be done. Returns true if it really is done.
WaitForCrxInstallerDone()276   bool WaitForCrxInstallerDone() {
277     return observer_->WaitForCrxInstallerDone();
278   }
279 
280   // Wait for all extension views to load.
WaitForExtensionViewsToLoad()281   bool WaitForExtensionViewsToLoad() {
282     return observer_->WaitForExtensionViewsToLoad();
283   }
284 
285   // Simulates a page calling window.open on an URL and waits for the
286   // navigation.
287   void OpenWindow(content::WebContents* contents,
288                   const GURL& url,
289                   bool newtab_process_should_equal_opener,
290                   content::WebContents** newtab_result);
291 
292   // Simulates a page navigating itself to an URL and waits for the
293   // navigation.
294   void NavigateInRenderer(content::WebContents* contents, const GURL& url);
295 
296   // Looks for an ExtensionHost whose URL has the given path component
297   // (including leading slash).  Also verifies that the expected number of hosts
298   // are loaded.
299   extensions::ExtensionHost* FindHostWithPath(
300       extensions::ProcessManager* manager,
301       const std::string& path,
302       int expected_hosts);
303 
304   // Returns
305   // extensions::browsertest_util::ExecuteScriptInBackgroundPage(profile(),
306   // extension_id, script).
307   std::string ExecuteScriptInBackgroundPage(const std::string& extension_id,
308                                             const std::string& script);
309 
310   // Returns
311   // extensions::browsertest_util::ExecuteScriptInBackgroundPageNoWait(
312   // profile(), extension_id, script).
313   bool ExecuteScriptInBackgroundPageNoWait(const std::string& extension_id,
314                                            const std::string& script);
315 
316   bool loaded_;
317   bool installed_;
318 
319 #if defined(OS_CHROMEOS)
320   // True if the command line should be tweaked as if ChromeOS user is
321   // already logged in.
322   bool set_chromeos_user_;
323 #endif
324 
325   // test_data/extensions.
326   base::FilePath test_data_dir_;
327 
328   scoped_ptr<ExtensionTestNotificationObserver> observer_;
329 
330  private:
331   // Temporary directory for testing.
332   base::ScopedTempDir temp_dir_;
333 
334   // Specifies the type of UI (if any) to show during installation and what
335   // user action to simulate.
336   enum InstallUIType {
337     INSTALL_UI_TYPE_NONE,
338     INSTALL_UI_TYPE_CANCEL,
339     INSTALL_UI_TYPE_NORMAL,
340     INSTALL_UI_TYPE_AUTO_CONFIRM,
341   };
342 
343   const extensions::Extension* InstallOrUpdateExtension(
344       const std::string& id,
345       const base::FilePath& path,
346       InstallUIType ui_type,
347       int expected_change);
348   const extensions::Extension* InstallOrUpdateExtension(
349       const std::string& id,
350       const base::FilePath& path,
351       InstallUIType ui_type,
352       int expected_change,
353       Browser* browser,
354       extensions::Extension::InitFromValueFlags creation_flags);
355   const extensions::Extension* InstallOrUpdateExtension(
356       const std::string& id,
357       const base::FilePath& path,
358       InstallUIType ui_type,
359       int expected_change,
360       extensions::Manifest::Location install_source);
361   const extensions::Extension* InstallOrUpdateExtension(
362       const std::string& id,
363       const base::FilePath& path,
364       InstallUIType ui_type,
365       int expected_change,
366       extensions::Manifest::Location install_source,
367       Browser* browser,
368       extensions::Extension::InitFromValueFlags creation_flags,
369       bool wait_for_idle,
370       bool is_ephemeral);
371 
372   // Make the current channel "dev" for the duration of the test.
373   extensions::ScopedCurrentChannel current_channel_;
374 
375   // Disable external install UI.
376   extensions::FeatureSwitch::ScopedOverride
377       override_prompt_for_external_extensions_;
378 
379 #if defined(OS_WIN)
380   // Use mock shortcut directories to ensure app shortcuts are cleaned up.
381   base::ScopedPathOverride user_desktop_override_;
382   base::ScopedPathOverride common_desktop_override_;
383   base::ScopedPathOverride user_quick_launch_override_;
384   base::ScopedPathOverride start_menu_override_;
385   base::ScopedPathOverride common_start_menu_override_;
386 #endif
387 
388   // The default profile to be used.
389   Profile* profile_;
390 
391   // Cache cache implementation.
392   scoped_ptr<extensions::ExtensionCacheFake> test_extension_cache_;
393 };
394 
395 #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSERTEST_H_
396