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_UNPACKED_INSTALLER_H_
6 #define CHROME_BROWSER_EXTENSIONS_UNPACKED_INSTALLER_H_
7 
8 #include <memory>
9 #include <string>
10 #include <utility>
11 #include <vector>
12 
13 #include "base/bind.h"
14 #include "base/files/file_path.h"
15 #include "base/macros.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/optional.h"
19 #include "extensions/browser/api/declarative_net_request/ruleset_install_pref.h"
20 #include "extensions/browser/preload_check.h"
21 #include "extensions/common/manifest.h"
22 
23 class Profile;
24 
25 namespace extensions {
26 
27 class Extension;
28 class ExtensionService;
29 class PreloadCheckGroup;
30 
31 // Installs and loads an unpacked extension. Because internal state needs to be
32 // held about the instalation process, only one call to Load*() should be made
33 // per UnpackedInstaller.
34 // TODO(erikkay): It might be useful to be able to load a packed extension
35 // (presumably into memory) without installing it.
36 class UnpackedInstaller
37     : public base::RefCountedThreadSafe<UnpackedInstaller> {
38  public:
39   using CompletionCallback = base::OnceCallback<void(const Extension* extension,
40                                                      const base::FilePath&,
41                                                      const std::string&)>;
42 
43   static scoped_refptr<UnpackedInstaller> Create(
44       ExtensionService* extension_service);
45 
46   // Loads the extension from the directory |extension_path|, which is
47   // the top directory of a specific extension where its manifest file lives.
48   // Errors are reported through LoadErrorReporter. On success,
49   // ExtensionService::AddExtension() is called.
50   void Load(const base::FilePath& extension_path);
51 
52   // Loads the extension from the directory |extension_path|;
53   // for use with command line switch --load-extension=path or
54   // --load-and-launch-app=path.
55   // This is equivalent to Load, except that it reads the extension from
56   // |extension_path| synchronously.
57   // The return value indicates whether the installation has begun successfully.
58   // The id of the extension being loaded is returned in |extension_id|.
59   // |only_allow_apps| is used to avoid side-loading of non-app extensions.
60   bool LoadFromCommandLine(const base::FilePath& extension_path,
61                            std::string* extension_id,
62                            bool only_allow_apps);
63 
64   // Allows overriding of whether modern manifest versions are required;
65   // intended for testing.
require_modern_manifest_version()66   bool require_modern_manifest_version() const {
67     return require_modern_manifest_version_;
68   }
set_require_modern_manifest_version(bool val)69   void set_require_modern_manifest_version(bool val) {
70     require_modern_manifest_version_ = val;
71   }
72 
set_be_noisy_on_failure(bool be_noisy_on_failure)73   void set_be_noisy_on_failure(bool be_noisy_on_failure) {
74     be_noisy_on_failure_ = be_noisy_on_failure;
75   }
76 
set_completion_callback(CompletionCallback callback)77   void set_completion_callback(CompletionCallback callback) {
78     callback_ = std::move(callback);
79   }
80 
81  private:
82   friend class base::RefCountedThreadSafe<UnpackedInstaller>;
83 
84   explicit UnpackedInstaller(ExtensionService* extension_service);
85   virtual ~UnpackedInstaller();
86 
87   // Must be called from the UI thread. Begin management policy and requirements
88   // checks.
89   void StartInstallChecks();
90 
91   // Callback from PreloadCheckGroup.
92   void OnInstallChecksComplete(const PreloadCheck::Errors& errors);
93 
94   // Verifies if loading unpacked extensions is allowed.
95   bool IsLoadingUnpackedAllowed() const;
96 
97   // We change the input extension path to an absolute path, on the file thread.
98   // Then we need to check the file access preference, which needs
99   // to happen back on the UI thread, so it posts CheckExtensionFileAccess on
100   // the UI thread. In turn, once that gets the pref, it goes back to the
101   // file thread with LoadWithFileAccess.
102   // TODO(yoz): It would be nice to remove this ping-pong, but we need to know
103   // what file access flags to pass to file_util::LoadExtension.
104   void GetAbsolutePath();
105   void CheckExtensionFileAccess();
106   void LoadWithFileAccess(int flags);
107 
108   // Notify the frontend that an attempt to retry will not be necessary.
109   void UnregisterLoadRetryListener();
110 
111   // Notify the frontend that there was an error loading an extension.
112   void ReportExtensionLoadError(const std::string& error);
113 
114   // Passes the extension onto extension service.
115   void InstallExtension();
116 
117   // Helper to get the Extension::CreateFlags for the installing extension.
118   int GetFlags();
119 
120   // Helper to load an extension. Should be called on a sequence where file IO
121   // is allowed. Loads the extension, validates extension locales and persists
122   // the ruleset for the Declarative Net Request API, if needed. In case of an
123   // error, returns false and populates |error|.
124   bool LoadExtension(Manifest::Location location,
125                      int flags,
126                      std::string* error);
127 
128   // Reads the Declarative Net Request JSON rulesets for the extension, if it
129   // provided any, and persists the indexed rulesets. Returns false and
130   // populates |error| in case of an error. Should be called on a sequence where
131   // file IO is allowed.
132   bool IndexAndPersistRulesIfNeeded(std::string* error);
133 
extension()134   const Extension* extension() { return extension_.get(); }
135 
136   // The service we will report results back to.
137   base::WeakPtr<ExtensionService> service_weak_;
138 
139   // The Profile the extension is being installed in.
140   Profile* profile_;
141 
142   // The pathname of the directory to load from, which is an absolute path
143   // after GetAbsolutePath has been called.
144   base::FilePath extension_path_;
145 
146   // The extension being installed.
147   scoped_refptr<Extension> extension_;
148 
149   // Whether to require the extension installed to have a modern manifest
150   // version.
151   bool require_modern_manifest_version_;
152 
153   // Whether or not to be noisy (show a dialog) on failure. Defaults to true.
154   bool be_noisy_on_failure_;
155 
156   // Checks to run before the extension can be installed.
157   std::unique_ptr<PreloadCheck> policy_check_;
158   std::unique_ptr<PreloadCheck> requirements_check_;
159 
160   // Runs the above checks.
161   std::unique_ptr<PreloadCheckGroup> check_group_;
162 
163   // Install prefs needed for the Declarative Net Request API.
164   declarative_net_request::RulesetInstallPrefs ruleset_install_prefs_;
165 
166   CompletionCallback callback_;
167 
168   DISALLOW_COPY_AND_ASSIGN(UnpackedInstaller);
169 };
170 
171 }  // namespace extensions
172 
173 #endif  // CHROME_BROWSER_EXTENSIONS_UNPACKED_INSTALLER_H_
174