[Extensions] Make chrome://extensions use developerPrivate for unpacked loading
[chromium-blink-merge.git] / chrome / browser / extensions / api / developer_private / developer_private_api.h
blobcf95fc173ef04a1c3ce2345e026edda8ebd2388c
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 CHROME_BROWSER_EXTENSIONS_API_DEVELOPER_PRIVATE_DEVELOPER_PRIVATE_API_H_
6 #define CHROME_BROWSER_EXTENSIONS_API_DEVELOPER_PRIVATE_DEVELOPER_PRIVATE_API_H_
8 #include <set>
10 #include "base/files/file.h"
11 #include "base/scoped_observer.h"
12 #include "chrome/browser/extensions/api/developer_private/entry_picker.h"
13 #include "chrome/browser/extensions/api/file_system/file_system_api.h"
14 #include "chrome/browser/extensions/chrome_extension_function.h"
15 #include "chrome/browser/extensions/error_console/error_console.h"
16 #include "chrome/browser/extensions/extension_install_prompt.h"
17 #include "chrome/browser/extensions/extension_uninstall_dialog.h"
18 #include "chrome/browser/extensions/pack_extension_job.h"
19 #include "content/public/browser/notification_observer.h"
20 #include "content/public/browser/notification_registrar.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "extensions/browser/browser_context_keyed_api_factory.h"
23 #include "extensions/browser/event_router.h"
24 #include "extensions/browser/extension_registry_observer.h"
25 #include "storage/browser/fileapi/file_system_context.h"
26 #include "storage/browser/fileapi/file_system_operation.h"
27 #include "ui/shell_dialogs/select_file_dialog.h"
29 class Profile;
31 namespace extensions {
33 class ExtensionError;
34 class ExtensionRegistry;
35 class ExtensionSystem;
36 class ManagementPolicy;
37 class RequirementsChecker;
39 namespace api {
41 class EntryPicker;
42 class EntryPickerClient;
44 namespace developer_private {
46 struct ItemInfo;
47 struct ItemInspectView;
48 struct ProjectInfo;
50 } // namespace developer_private
52 } // namespace api
54 namespace developer = api::developer_private;
56 typedef std::vector<linked_ptr<developer::ItemInfo> > ItemInfoList;
57 typedef std::vector<linked_ptr<developer::ProjectInfo> > ProjectInfoList;
58 typedef std::vector<linked_ptr<developer::ItemInspectView> >
59 ItemInspectViewList;
61 class DeveloperPrivateEventRouter : public content::NotificationObserver,
62 public ExtensionRegistryObserver,
63 public ErrorConsole::Observer {
64 public:
65 explicit DeveloperPrivateEventRouter(Profile* profile);
66 ~DeveloperPrivateEventRouter() override;
68 // Add or remove an ID to the list of extensions subscribed to events.
69 void AddExtensionId(const std::string& extension_id);
70 void RemoveExtensionId(const std::string& extension_id);
72 private:
73 // content::NotificationObserver implementation.
74 void Observe(int type,
75 const content::NotificationSource& source,
76 const content::NotificationDetails& details) override;
78 // ExtensionRegistryObserver implementation.
79 void OnExtensionLoaded(content::BrowserContext* browser_context,
80 const Extension* extension) override;
81 void OnExtensionUnloaded(content::BrowserContext* browser_context,
82 const Extension* extension,
83 UnloadedExtensionInfo::Reason reason) override;
84 void OnExtensionWillBeInstalled(content::BrowserContext* browser_context,
85 const Extension* extension,
86 bool is_update,
87 bool from_ephemeral,
88 const std::string& old_name) override;
89 void OnExtensionUninstalled(content::BrowserContext* browser_context,
90 const Extension* extension,
91 extensions::UninstallReason reason) override;
93 // ErrorConsole::Observer implementation.
94 void OnErrorAdded(const ExtensionError* error) override;
96 content::NotificationRegistrar registrar_;
98 ScopedObserver<extensions::ExtensionRegistry,
99 extensions::ExtensionRegistryObserver>
100 extension_registry_observer_;
102 Profile* profile_;
104 // The set of IDs of the Extensions that have subscribed to DeveloperPrivate
105 // events. Since the only consumer of the DeveloperPrivate API is currently
106 // the Apps Developer Tool (which replaces the chrome://extensions page), we
107 // don't want to send information about the subscribing extension in an
108 // update. In particular, we want to avoid entering a loop, which could happen
109 // when, e.g., the Apps Developer Tool throws an error.
110 std::set<std::string> extension_ids_;
112 DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateEventRouter);
115 // The profile-keyed service that manages the DeveloperPrivate API.
116 class DeveloperPrivateAPI : public BrowserContextKeyedAPI,
117 public EventRouter::Observer {
118 public:
119 static BrowserContextKeyedAPIFactory<DeveloperPrivateAPI>*
120 GetFactoryInstance();
122 // Convenience method to get the DeveloperPrivateAPI for a profile.
123 static DeveloperPrivateAPI* Get(content::BrowserContext* context);
125 explicit DeveloperPrivateAPI(content::BrowserContext* context);
126 ~DeveloperPrivateAPI() override;
128 void SetLastUnpackedDirectory(const base::FilePath& path);
130 base::FilePath& GetLastUnpackedDirectory() {
131 return last_unpacked_directory_;
134 // KeyedService implementation
135 void Shutdown() override;
137 // EventRouter::Observer implementation.
138 void OnListenerAdded(const EventListenerInfo& details) override;
139 void OnListenerRemoved(const EventListenerInfo& details) override;
141 private:
142 friend class BrowserContextKeyedAPIFactory<DeveloperPrivateAPI>;
144 // BrowserContextKeyedAPI implementation.
145 static const char* service_name() { return "DeveloperPrivateAPI"; }
146 static const bool kServiceRedirectedInIncognito = true;
147 static const bool kServiceIsNULLWhileTesting = true;
149 void RegisterNotifications();
151 Profile* profile_;
153 // Used to start the load |load_extension_dialog_| in the last directory that
154 // was loaded.
155 base::FilePath last_unpacked_directory_;
157 // Created lazily upon OnListenerAdded.
158 scoped_ptr<DeveloperPrivateEventRouter> developer_private_event_router_;
160 DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateAPI);
163 namespace api {
165 class DeveloperPrivateAPIFunction : public UIThreadExtensionFunction {
166 protected:
167 ~DeveloperPrivateAPIFunction() override;
169 // Returns the extension with the given |id| from the registry, including
170 // all possible extensions (enabled, disabled, terminated, etc).
171 const Extension* GetExtensionById(const std::string& id);
174 class DeveloperPrivateAutoUpdateFunction : public ChromeSyncExtensionFunction {
175 public:
176 DECLARE_EXTENSION_FUNCTION("developerPrivate.autoUpdate",
177 DEVELOPERPRIVATE_AUTOUPDATE)
179 protected:
180 ~DeveloperPrivateAutoUpdateFunction() override;
182 // ExtensionFunction:
183 bool RunSync() override;
186 class DeveloperPrivateGetItemsInfoFunction
187 : public ChromeAsyncExtensionFunction {
188 public:
189 DECLARE_EXTENSION_FUNCTION("developerPrivate.getItemsInfo",
190 DEVELOPERPRIVATE_GETITEMSINFO)
192 protected:
193 ~DeveloperPrivateGetItemsInfoFunction() override;
195 // ExtensionFunction:
196 bool RunAsync() override;
198 private:
199 scoped_ptr<developer::ItemInfo> CreateItemInfo(const Extension& item,
200 bool item_is_enabled);
202 void GetIconsOnFileThread(
203 ItemInfoList item_list,
204 std::map<std::string, ExtensionResource> itemIdToIconResourceMap);
206 // Helper that lists the current inspectable html pages for the extension.
207 void GetInspectablePagesForExtensionProcess(
208 const Extension* extension,
209 const std::set<content::RenderViewHost*>& views,
210 ItemInspectViewList* result);
212 ItemInspectViewList GetInspectablePagesForExtension(
213 const Extension* extension,
214 bool extension_is_enabled);
216 void GetAppWindowPagesForExtensionProfile(const Extension* extension,
217 ItemInspectViewList* result);
219 linked_ptr<developer::ItemInspectView> constructInspectView(
220 const GURL& url,
221 int render_process_id,
222 int render_view_id,
223 bool incognito,
224 bool generated_background_page);
227 class DeveloperPrivateInspectFunction : public ChromeSyncExtensionFunction {
228 public:
229 DECLARE_EXTENSION_FUNCTION("developerPrivate.inspect",
230 DEVELOPERPRIVATE_INSPECT)
232 protected:
233 ~DeveloperPrivateInspectFunction() override;
235 // ExtensionFunction:
236 bool RunSync() override;
239 class DeveloperPrivateAllowFileAccessFunction
240 : public DeveloperPrivateAPIFunction {
241 public:
242 DECLARE_EXTENSION_FUNCTION("developerPrivate.allowFileAccess",
243 DEVELOPERPRIVATE_ALLOWFILEACCESS);
245 protected:
246 ~DeveloperPrivateAllowFileAccessFunction() override;
248 // ExtensionFunction:
249 ResponseAction Run() override;
252 class DeveloperPrivateAllowIncognitoFunction
253 : public DeveloperPrivateAPIFunction {
254 public:
255 DECLARE_EXTENSION_FUNCTION("developerPrivate.allowIncognito",
256 DEVELOPERPRIVATE_ALLOWINCOGNITO);
258 protected:
259 ~DeveloperPrivateAllowIncognitoFunction() override;
261 // UIThreadExtensionFunction:
262 ResponseAction Run() override;
265 class DeveloperPrivateReloadFunction : public DeveloperPrivateAPIFunction {
266 public:
267 DECLARE_EXTENSION_FUNCTION("developerPrivate.reload",
268 DEVELOPERPRIVATE_RELOAD);
270 protected:
271 ~DeveloperPrivateReloadFunction() override;
273 // ExtensionFunction:
274 ResponseAction Run() override;
277 class DeveloperPrivateShowPermissionsDialogFunction
278 : public ChromeSyncExtensionFunction,
279 public ExtensionInstallPrompt::Delegate {
280 public:
281 DECLARE_EXTENSION_FUNCTION("developerPrivate.showPermissionsDialog",
282 DEVELOPERPRIVATE_PERMISSIONS);
284 DeveloperPrivateShowPermissionsDialogFunction();
285 protected:
286 ~DeveloperPrivateShowPermissionsDialogFunction() override;
288 // ExtensionFunction:
289 bool RunSync() override;
291 // Overridden from ExtensionInstallPrompt::Delegate
292 void InstallUIProceed() override;
293 void InstallUIAbort(bool user_initiated) override;
295 scoped_ptr<ExtensionInstallPrompt> prompt_;
296 std::string extension_id_;
299 class DeveloperPrivateChooseEntryFunction : public UIThreadExtensionFunction,
300 public EntryPickerClient {
301 protected:
302 ~DeveloperPrivateChooseEntryFunction() override;
303 bool ShowPicker(ui::SelectFileDialog::Type picker_type,
304 const base::string16& select_title,
305 const ui::SelectFileDialog::FileTypeInfo& info,
306 int file_type_index);
310 class DeveloperPrivateLoadUnpackedFunction
311 : public DeveloperPrivateChooseEntryFunction {
312 public:
313 DECLARE_EXTENSION_FUNCTION("developerPrivate.loadUnpacked",
314 DEVELOPERPRIVATE_LOADUNPACKED);
315 DeveloperPrivateLoadUnpackedFunction();
317 protected:
318 ~DeveloperPrivateLoadUnpackedFunction() override;
319 ResponseAction Run() override;
321 // EntryPickerClient:
322 void FileSelected(const base::FilePath& path) override;
323 void FileSelectionCanceled() override;
325 // Callback for the UnpackedLoader.
326 void OnLoadComplete(const Extension* extension,
327 const base::FilePath& file_path,
328 const std::string& error);
330 private:
331 // Whether or not we should fail quietly in the event of a load error.
332 bool fail_quietly_;
335 class DeveloperPrivateChoosePathFunction
336 : public DeveloperPrivateChooseEntryFunction {
337 public:
338 DECLARE_EXTENSION_FUNCTION("developerPrivate.choosePath",
339 DEVELOPERPRIVATE_CHOOSEPATH);
341 protected:
342 ~DeveloperPrivateChoosePathFunction() override;
343 ResponseAction Run() override;
345 // EntryPickerClient:
346 void FileSelected(const base::FilePath& path) override;
347 void FileSelectionCanceled() override;
350 class DeveloperPrivatePackDirectoryFunction
351 : public DeveloperPrivateAPIFunction,
352 public PackExtensionJob::Client {
354 public:
355 DECLARE_EXTENSION_FUNCTION("developerPrivate.packDirectory",
356 DEVELOPERPRIVATE_PACKDIRECTORY);
358 DeveloperPrivatePackDirectoryFunction();
360 // ExtensionPackJob::Client implementation.
361 void OnPackSuccess(const base::FilePath& crx_file,
362 const base::FilePath& key_file) override;
363 void OnPackFailure(const std::string& error,
364 ExtensionCreator::ErrorType error_type) override;
366 protected:
367 ~DeveloperPrivatePackDirectoryFunction() override;
368 ResponseAction Run() override;
370 private:
371 scoped_refptr<PackExtensionJob> pack_job_;
372 std::string item_path_str_;
373 std::string key_path_str_;
376 class DeveloperPrivateIsProfileManagedFunction
377 : public ChromeSyncExtensionFunction {
378 public:
379 DECLARE_EXTENSION_FUNCTION("developerPrivate.isProfileManaged",
380 DEVELOPERPRIVATE_ISPROFILEMANAGED);
382 protected:
383 ~DeveloperPrivateIsProfileManagedFunction() override;
385 // ExtensionFunction:
386 bool RunSync() override;
389 class DeveloperPrivateLoadDirectoryFunction
390 : public ChromeAsyncExtensionFunction {
391 public:
392 DECLARE_EXTENSION_FUNCTION("developerPrivate.loadDirectory",
393 DEVELOPERPRIVATE_LOADUNPACKEDCROS);
395 DeveloperPrivateLoadDirectoryFunction();
397 protected:
398 ~DeveloperPrivateLoadDirectoryFunction() override;
400 // ExtensionFunction:
401 bool RunAsync() override;
403 bool LoadByFileSystemAPI(const storage::FileSystemURL& directory_url);
405 void ClearExistingDirectoryContent(const base::FilePath& project_path);
407 void ReadDirectoryByFileSystemAPI(const base::FilePath& project_path,
408 const base::FilePath& destination_path);
410 void ReadDirectoryByFileSystemAPICb(
411 const base::FilePath& project_path,
412 const base::FilePath& destination_path,
413 base::File::Error result,
414 const storage::FileSystemOperation::FileEntryList& file_list,
415 bool has_more);
417 void SnapshotFileCallback(
418 const base::FilePath& target_path,
419 base::File::Error result,
420 const base::File::Info& file_info,
421 const base::FilePath& platform_path,
422 const scoped_refptr<storage::ShareableFileReference>& file_ref);
424 void CopyFile(const base::FilePath& src_path,
425 const base::FilePath& dest_path);
427 void Load();
429 scoped_refptr<storage::FileSystemContext> context_;
431 // syncfs url representing the root of the folder to be copied.
432 std::string project_base_url_;
434 // physical path on disc of the folder to be copied.
435 base::FilePath project_base_path_;
437 private:
438 int pending_copy_operations_count_;
440 // This is set to false if any of the copyFile operations fail on
441 // call of the API. It is returned as a response of the API call.
442 bool success_;
445 class DeveloperPrivateRequestFileSourceFunction
446 : public ChromeAsyncExtensionFunction {
447 public:
448 DECLARE_EXTENSION_FUNCTION("developerPrivate.requestFileSource",
449 DEVELOPERPRIVATE_REQUESTFILESOURCE);
451 DeveloperPrivateRequestFileSourceFunction();
453 protected:
454 ~DeveloperPrivateRequestFileSourceFunction() override;
456 // ExtensionFunction:
457 bool RunAsync() override;
459 private:
460 void LaunchCallback(const base::DictionaryValue& results);
463 class DeveloperPrivateOpenDevToolsFunction
464 : public ChromeAsyncExtensionFunction {
465 public:
466 DECLARE_EXTENSION_FUNCTION("developerPrivate.openDevTools",
467 DEVELOPERPRIVATE_OPENDEVTOOLS);
469 DeveloperPrivateOpenDevToolsFunction();
471 protected:
472 ~DeveloperPrivateOpenDevToolsFunction() override;
474 // ExtensionFunction:
475 bool RunAsync() override;
478 } // namespace api
480 } // namespace extensions
482 #endif // CHROME_BROWSER_EXTENSIONS_API_DEVELOPER_PRIVATE_DEVELOPER_PRIVATE_API_H_