Remove linux_chromium_gn_dbg from the chromium CQ.
[chromium-blink-merge.git] / extensions / browser / sandboxed_unpacker.h
blob826d9393ab74b74d8076109ce424cf1b95359c06
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.
5 #ifndef EXTENSIONS_BROWSER_SANDBOXED_UNPACKER_H_
6 #define EXTENSIONS_BROWSER_SANDBOXED_UNPACKER_H_
8 #include <string>
10 #include "base/files/file_path.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/memory/ref_counted_delete_on_message_loop.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/time/time.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/utility_process_host_client.h"
17 #include "extensions/browser/crx_file_info.h"
18 #include "extensions/browser/install/crx_install_error.h"
19 #include "extensions/common/manifest.h"
21 class SkBitmap;
23 namespace base {
24 class DictionaryValue;
25 class SequencedTaskRunner;
28 namespace content {
29 class UtilityProcessHost;
32 namespace crypto {
33 class SecureHash;
36 namespace extensions {
37 class Extension;
39 class SandboxedUnpackerClient
40 : public base::RefCountedDeleteOnMessageLoop<SandboxedUnpackerClient> {
41 public:
42 // Initialize the ref-counted base to always delete on the UI thread. Note
43 // the constructor call must also happen on the UI thread.
44 SandboxedUnpackerClient();
46 // temp_dir - A temporary directory containing the results of the extension
47 // unpacking. The client is responsible for deleting this directory.
49 // extension_root - The path to the extension root inside of temp_dir.
51 // original_manifest - The parsed but unmodified version of the manifest,
52 // with no modifications such as localization, etc.
54 // extension - The extension that was unpacked. The client is responsible
55 // for deleting this memory.
57 // install_icon - The icon we will display in the installation UI, if any.
58 virtual void OnUnpackSuccess(const base::FilePath& temp_dir,
59 const base::FilePath& extension_root,
60 const base::DictionaryValue* original_manifest,
61 const Extension* extension,
62 const SkBitmap& install_icon) = 0;
63 virtual void OnUnpackFailure(const CrxInstallError& error) = 0;
65 protected:
66 friend class base::RefCountedDeleteOnMessageLoop<SandboxedUnpackerClient>;
67 friend class base::DeleteHelper<SandboxedUnpackerClient>;
69 virtual ~SandboxedUnpackerClient() {}
72 // SandboxedUnpacker does work to optionally unpack and then validate/sanitize
73 // an extension, either starting from a crx file or an already unzipped
74 // directory (eg from differential update). This is done in a sandboxed
75 // subprocess to protect the browser process from parsing complex formats like
76 // JPEG or JSON from untrusted sources.
78 // Unpacking an extension using this class makes minor changes to its source,
79 // such as transcoding all images to PNG, parsing all message catalogs
80 // and rewriting the manifest JSON. As such, it should not be used when the
81 // output is not intended to be given back to the author.
84 // Lifetime management:
86 // This class is ref-counted by each call it makes to itself on another thread,
87 // and by UtilityProcessHost.
89 // Additionally, we hold a reference to our own client so that it lives at least
90 // long enough to receive the result of unpacking.
93 // NOTE: This class should only be used on the file thread.
94 class SandboxedUnpacker : public content::UtilityProcessHostClient {
95 public:
96 // Creates a SanboxedUnpacker that will do work to unpack an extension,
97 // passing the |location| and |creation_flags| to Extension::Create. The
98 // |extensions_dir| parameter should specify the directory under which we'll
99 // create a subdirectory to write the unpacked extension contents.
100 SandboxedUnpacker(
101 Manifest::Location location,
102 int creation_flags,
103 const base::FilePath& extensions_dir,
104 const scoped_refptr<base::SequencedTaskRunner>& unpacker_io_task_runner,
105 SandboxedUnpackerClient* client);
107 // Start processing the extension, either from a CRX file or already unzipped
108 // in a directory. The client is called with the results. The directory form
109 // requires the id and base64-encoded public key (for insertion into the
110 // 'key' field of the manifest.json file).
111 void StartWithCrx(const CRXFileInfo& crx_info);
112 void StartWithDirectory(const std::string& extension_id,
113 const std::string& public_key_base64,
114 const base::FilePath& directory);
116 private:
117 class ProcessHostClient;
119 // Enumerate all the ways unpacking can fail. Calls to ReportFailure()
120 // take a failure reason as an argument, and put it in histogram
121 // Extensions.SandboxUnpackFailureReason.
122 enum FailureReason {
123 // SandboxedUnpacker::CreateTempDirectory()
124 COULD_NOT_GET_TEMP_DIRECTORY,
125 COULD_NOT_CREATE_TEMP_DIRECTORY,
127 // SandboxedUnpacker::Start()
128 FAILED_TO_COPY_EXTENSION_FILE_TO_TEMP_DIRECTORY,
129 COULD_NOT_GET_SANDBOX_FRIENDLY_PATH,
131 // SandboxedUnpacker::OnUnpackExtensionSucceeded()
132 COULD_NOT_LOCALIZE_EXTENSION,
133 INVALID_MANIFEST,
135 // SandboxedUnpacker::OnUnpackExtensionFailed()
136 UNPACKER_CLIENT_FAILED,
138 // SandboxedUnpacker::OnProcessCrashed()
139 UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL,
141 // SandboxedUnpacker::ValidateSignature()
142 CRX_FILE_NOT_READABLE,
143 CRX_HEADER_INVALID,
144 CRX_MAGIC_NUMBER_INVALID,
145 CRX_VERSION_NUMBER_INVALID,
146 CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE,
147 CRX_ZERO_KEY_LENGTH,
148 CRX_ZERO_SIGNATURE_LENGTH,
149 CRX_PUBLIC_KEY_INVALID,
150 CRX_SIGNATURE_INVALID,
151 CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED,
152 CRX_SIGNATURE_VERIFICATION_FAILED,
154 // SandboxedUnpacker::RewriteManifestFile()
155 ERROR_SERIALIZING_MANIFEST_JSON,
156 ERROR_SAVING_MANIFEST_JSON,
158 // SandboxedUnpacker::RewriteImageFiles()
159 COULD_NOT_READ_IMAGE_DATA_FROM_DISK,
160 DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST,
161 INVALID_PATH_FOR_BROWSER_IMAGE,
162 ERROR_REMOVING_OLD_IMAGE_FILE,
163 INVALID_PATH_FOR_BITMAP_IMAGE,
164 ERROR_RE_ENCODING_THEME_IMAGE,
165 ERROR_SAVING_THEME_IMAGE,
166 ABORTED_DUE_TO_SHUTDOWN,
168 // SandboxedUnpacker::RewriteCatalogFiles()
169 COULD_NOT_READ_CATALOG_DATA_FROM_DISK,
170 INVALID_CATALOG_DATA,
171 INVALID_PATH_FOR_CATALOG,
172 ERROR_SERIALIZING_CATALOG,
173 ERROR_SAVING_CATALOG,
175 // SandboxedUnpacker::ValidateSignature()
176 CRX_HASH_VERIFICATION_FAILED,
178 UNZIP_FAILED,
179 DIRECTORY_MOVE_FAILED,
180 COULD_NOT_START_UTILITY_PROCESS,
182 NUM_FAILURE_REASONS
185 friend class ProcessHostClient;
186 friend class SandboxedUnpackerTest;
188 ~SandboxedUnpacker() override;
190 // Set |temp_dir_| as a temporary directory to unpack the extension in.
191 // Return true on success.
192 virtual bool CreateTempDirectory();
194 // Helper functions to simplify calls to ReportFailure.
195 base::string16 FailureReasonToString16(FailureReason reason);
196 void FailWithPackageError(FailureReason reason);
198 // Validates the signature of the extension and extract the key to
199 // |public_key_|. Returns true if the signature validates, false otherwise.
200 bool ValidateSignature(const base::FilePath& crx_path,
201 const std::string& expected_hash);
203 void StartUnzipOnIOThread(const base::FilePath& crx_path);
204 void StartUnpackOnIOThread(const base::FilePath& directory_path);
206 // UtilityProcessHostClient
207 bool OnMessageReceived(const IPC::Message& message) override;
208 void OnProcessCrashed(int exit_code) override;
210 // IPC message handlers.
211 void OnUnzipToDirSucceeded(const base::FilePath& directory);
212 void OnUnzipToDirFailed(const std::string& error);
213 void OnUnpackExtensionSucceeded(const base::DictionaryValue& manifest);
214 void OnUnpackExtensionFailed(const base::string16& error_message);
216 void ReportFailure(FailureReason reason, const base::string16& message);
217 void ReportSuccess(const base::DictionaryValue& original_manifest,
218 const SkBitmap& install_icon);
220 // Overwrites original manifest with safe result from utility process.
221 // Returns NULL on error. Caller owns the returned object.
222 base::DictionaryValue* RewriteManifestFile(
223 const base::DictionaryValue& manifest);
225 // Overwrites original files with safe results from utility process.
226 // Reports error and returns false if it fails.
227 bool RewriteImageFiles(SkBitmap* install_icon);
228 bool RewriteCatalogFiles();
230 // Cleans up temp directory artifacts.
231 void Cleanup();
233 // This is a helper class to make it easier to keep track of the lifecycle of
234 // a UtilityProcessHost, including automatic begin and end of batch mode.
235 class UtilityHostWrapper : public base::RefCountedThreadSafe<
236 UtilityHostWrapper,
237 content::BrowserThread::DeleteOnIOThread> {
238 public:
239 UtilityHostWrapper();
241 // Start up the utility process if it is not already started, putting it
242 // into batch mode and giving it access to |exposed_dir|. This should only
243 // be called on the IO thread. Returns false if there was an error starting
244 // the utility process or putting it into batch mode.
245 bool StartIfNeeded(
246 const base::FilePath& exposed_dir,
247 const scoped_refptr<UtilityProcessHostClient>& client,
248 const scoped_refptr<base::SequencedTaskRunner>& client_task_runner);
250 // This should only be called on the IO thread.
251 content::UtilityProcessHost* host() const;
253 private:
254 friend struct content::BrowserThread::DeleteOnThread<
255 content::BrowserThread::IO>;
256 friend class base::DeleteHelper<UtilityHostWrapper>;
257 ~UtilityHostWrapper();
259 // Should only be used on the IO thread.
260 base::WeakPtr<content::UtilityProcessHost> utility_host_;
262 DISALLOW_COPY_AND_ASSIGN(UtilityHostWrapper);
265 // If we unpacked a crx file, we hold on to the path for use in various
266 // histograms.
267 base::FilePath crx_path_for_histograms_;
269 // Our client.
270 scoped_refptr<SandboxedUnpackerClient> client_;
272 // The Extensions directory inside the profile.
273 base::FilePath extensions_dir_;
275 // A temporary directory to use for unpacking.
276 base::ScopedTempDir temp_dir_;
278 // The root directory of the unpacked extension. This is a child of temp_dir_.
279 base::FilePath extension_root_;
281 // Represents the extension we're unpacking.
282 scoped_refptr<Extension> extension_;
284 // Whether we've received a response from the utility process yet.
285 bool got_response_;
287 // The public key that was extracted from the CRX header.
288 std::string public_key_;
290 // The extension's ID. This will be calculated from the public key in the crx
291 // header.
292 std::string extension_id_;
294 // If we unpacked a .crx file, the time at which unpacking started. Used to
295 // compute the time unpacking takes.
296 base::TimeTicks crx_unpack_start_time_;
298 // Location to use for the unpacked extension.
299 Manifest::Location location_;
301 // Creation flags to use for the extension. These flags will be used
302 // when calling Extenion::Create() by the crx installer.
303 int creation_flags_;
305 // Sequenced task runner where file I/O operations will be performed at.
306 scoped_refptr<base::SequencedTaskRunner> unpacker_io_task_runner_;
308 // Used for sending tasks to the utility process.
309 scoped_refptr<UtilityHostWrapper> utility_wrapper_;
311 DISALLOW_COPY_AND_ASSIGN(SandboxedUnpacker);
314 } // namespace extensions
316 #endif // EXTENSIONS_BROWSER_SANDBOXED_UNPACKER_H_