// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_EXTENSIONS_API_DEVELOPER_PRIVATE_DEVELOPER_PRIVATE_API_H_ #define CHROME_BROWSER_EXTENSIONS_API_DEVELOPER_PRIVATE_DEVELOPER_PRIVATE_API_H_ #include #include "base/files/file.h" #include "base/scoped_observer.h" #include "chrome/browser/extensions/api/developer_private/entry_picker.h" #include "chrome/browser/extensions/api/file_system/file_system_api.h" #include "chrome/browser/extensions/chrome_extension_function.h" #include "chrome/browser/extensions/error_console/error_console.h" #include "chrome/browser/extensions/extension_uninstall_dialog.h" #include "chrome/browser/extensions/pack_extension_job.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/render_view_host.h" #include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/event_router.h" #include "extensions/browser/extension_registry_observer.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation.h" #include "ui/shell_dialogs/select_file_dialog.h" class Profile; namespace extensions { class ExtensionError; class ExtensionRegistry; class ExtensionSystem; class ManagementPolicy; class RequirementsChecker; namespace api { class EntryPicker; class EntryPickerClient; namespace developer_private { struct ItemInfo; struct ItemInspectView; struct ProjectInfo; namespace RequestFileSource { struct Params; } } // namespace developer_private } // namespace api namespace developer = api::developer_private; typedef std::vector > ItemInfoList; typedef std::vector > ProjectInfoList; typedef std::vector > ItemInspectViewList; class DeveloperPrivateEventRouter : public content::NotificationObserver, public ExtensionRegistryObserver, public ErrorConsole::Observer { public: explicit DeveloperPrivateEventRouter(Profile* profile); ~DeveloperPrivateEventRouter() override; // Add or remove an ID to the list of extensions subscribed to events. void AddExtensionId(const std::string& extension_id); void RemoveExtensionId(const std::string& extension_id); private: // content::NotificationObserver implementation. void Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) override; // ExtensionRegistryObserver implementation. void OnExtensionLoaded(content::BrowserContext* browser_context, const Extension* extension) override; void OnExtensionUnloaded(content::BrowserContext* browser_context, const Extension* extension, UnloadedExtensionInfo::Reason reason) override; void OnExtensionWillBeInstalled(content::BrowserContext* browser_context, const Extension* extension, bool is_update, bool from_ephemeral, const std::string& old_name) override; void OnExtensionUninstalled(content::BrowserContext* browser_context, const Extension* extension, extensions::UninstallReason reason) override; // ErrorConsole::Observer implementation. void OnErrorAdded(const ExtensionError* error) override; content::NotificationRegistrar registrar_; ScopedObserver extension_registry_observer_; Profile* profile_; // The set of IDs of the Extensions that have subscribed to DeveloperPrivate // events. Since the only consumer of the DeveloperPrivate API is currently // the Apps Developer Tool (which replaces the chrome://extensions page), we // don't want to send information about the subscribing extension in an // update. In particular, we want to avoid entering a loop, which could happen // when, e.g., the Apps Developer Tool throws an error. std::set extension_ids_; DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateEventRouter); }; // The profile-keyed service that manages the DeveloperPrivate API. class DeveloperPrivateAPI : public BrowserContextKeyedAPI, public EventRouter::Observer { public: static BrowserContextKeyedAPIFactory* GetFactoryInstance(); // Convenience method to get the DeveloperPrivateAPI for a profile. static DeveloperPrivateAPI* Get(content::BrowserContext* context); explicit DeveloperPrivateAPI(content::BrowserContext* context); ~DeveloperPrivateAPI() override; void SetLastUnpackedDirectory(const base::FilePath& path); base::FilePath& GetLastUnpackedDirectory() { return last_unpacked_directory_; } // KeyedService implementation void Shutdown() override; // EventRouter::Observer implementation. void OnListenerAdded(const EventListenerInfo& details) override; void OnListenerRemoved(const EventListenerInfo& details) override; private: friend class BrowserContextKeyedAPIFactory; // BrowserContextKeyedAPI implementation. static const char* service_name() { return "DeveloperPrivateAPI"; } static const bool kServiceRedirectedInIncognito = true; static const bool kServiceIsNULLWhileTesting = true; void RegisterNotifications(); Profile* profile_; // Used to start the load |load_extension_dialog_| in the last directory that // was loaded. base::FilePath last_unpacked_directory_; // Created lazily upon OnListenerAdded. scoped_ptr developer_private_event_router_; DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateAPI); }; namespace api { class DeveloperPrivateAPIFunction : public UIThreadExtensionFunction { protected: ~DeveloperPrivateAPIFunction() override; // Returns the extension with the given |id| from the registry, including // all possible extensions (enabled, disabled, terminated, etc). const Extension* GetExtensionById(const std::string& id); }; class DeveloperPrivateAutoUpdateFunction : public ChromeSyncExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.autoUpdate", DEVELOPERPRIVATE_AUTOUPDATE) protected: ~DeveloperPrivateAutoUpdateFunction() override; // ExtensionFunction: bool RunSync() override; }; class DeveloperPrivateGetItemsInfoFunction : public DeveloperPrivateAPIFunction { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.getItemsInfo", DEVELOPERPRIVATE_GETITEMSINFO) DeveloperPrivateGetItemsInfoFunction(); private: ~DeveloperPrivateGetItemsInfoFunction() override; ResponseAction Run() override; void GetIconsOnFileThread( std::map resource_map); void Finish(); ItemInfoList item_list_; }; class DeveloperPrivateGetExtensionsInfoFunction : public DeveloperPrivateAPIFunction { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.getExtensionsInfo", DEVELOPERPRIVATE_GETEXTENSIONSINFO); private: ~DeveloperPrivateGetExtensionsInfoFunction() override; ResponseAction Run() override; }; class DeveloperPrivateGetExtensionInfoFunction : public DeveloperPrivateAPIFunction { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.getExtensionInfo", DEVELOPERPRIVATE_GETEXTENSIONINFO); private: ~DeveloperPrivateGetExtensionInfoFunction() override; ResponseAction Run() override; }; class DeveloperPrivateUpdateExtensionConfigurationFunction : public DeveloperPrivateAPIFunction { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.updateExtensionConfiguration", DEVELOPERPRIVATE_UPDATEEXTENSIONCONFIGURATION); protected: ~DeveloperPrivateUpdateExtensionConfigurationFunction() override; ResponseAction Run() override; }; class DeveloperPrivateReloadFunction : public DeveloperPrivateAPIFunction { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.reload", DEVELOPERPRIVATE_RELOAD); protected: ~DeveloperPrivateReloadFunction() override; // ExtensionFunction: ResponseAction Run() override; }; class DeveloperPrivateShowPermissionsDialogFunction : public DeveloperPrivateAPIFunction { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.showPermissionsDialog", DEVELOPERPRIVATE_PERMISSIONS); DeveloperPrivateShowPermissionsDialogFunction(); protected: // DeveloperPrivateAPIFunction: ~DeveloperPrivateShowPermissionsDialogFunction() override; ResponseAction Run() override; void Finish(); DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateShowPermissionsDialogFunction); }; class DeveloperPrivateChooseEntryFunction : public UIThreadExtensionFunction, public EntryPickerClient { protected: ~DeveloperPrivateChooseEntryFunction() override; bool ShowPicker(ui::SelectFileDialog::Type picker_type, const base::string16& select_title, const ui::SelectFileDialog::FileTypeInfo& info, int file_type_index); }; class DeveloperPrivateLoadUnpackedFunction : public DeveloperPrivateChooseEntryFunction { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.loadUnpacked", DEVELOPERPRIVATE_LOADUNPACKED); DeveloperPrivateLoadUnpackedFunction(); protected: ~DeveloperPrivateLoadUnpackedFunction() override; ResponseAction Run() override; // EntryPickerClient: void FileSelected(const base::FilePath& path) override; void FileSelectionCanceled() override; // Callback for the UnpackedLoader. void OnLoadComplete(const Extension* extension, const base::FilePath& file_path, const std::string& error); private: // Whether or not we should fail quietly in the event of a load error. bool fail_quietly_; }; class DeveloperPrivateChoosePathFunction : public DeveloperPrivateChooseEntryFunction { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.choosePath", DEVELOPERPRIVATE_CHOOSEPATH); protected: ~DeveloperPrivateChoosePathFunction() override; ResponseAction Run() override; // EntryPickerClient: void FileSelected(const base::FilePath& path) override; void FileSelectionCanceled() override; }; class DeveloperPrivatePackDirectoryFunction : public DeveloperPrivateAPIFunction, public PackExtensionJob::Client { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.packDirectory", DEVELOPERPRIVATE_PACKDIRECTORY); DeveloperPrivatePackDirectoryFunction(); // ExtensionPackJob::Client implementation. void OnPackSuccess(const base::FilePath& crx_file, const base::FilePath& key_file) override; void OnPackFailure(const std::string& error, ExtensionCreator::ErrorType error_type) override; protected: ~DeveloperPrivatePackDirectoryFunction() override; ResponseAction Run() override; private: scoped_refptr pack_job_; std::string item_path_str_; std::string key_path_str_; }; class DeveloperPrivateIsProfileManagedFunction : public ChromeSyncExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.isProfileManaged", DEVELOPERPRIVATE_ISPROFILEMANAGED); protected: ~DeveloperPrivateIsProfileManagedFunction() override; // ExtensionFunction: bool RunSync() override; }; class DeveloperPrivateLoadDirectoryFunction : public ChromeAsyncExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.loadDirectory", DEVELOPERPRIVATE_LOADUNPACKEDCROS); DeveloperPrivateLoadDirectoryFunction(); protected: ~DeveloperPrivateLoadDirectoryFunction() override; // ExtensionFunction: bool RunAsync() override; bool LoadByFileSystemAPI(const storage::FileSystemURL& directory_url); void ClearExistingDirectoryContent(const base::FilePath& project_path); void ReadDirectoryByFileSystemAPI(const base::FilePath& project_path, const base::FilePath& destination_path); void ReadDirectoryByFileSystemAPICb( const base::FilePath& project_path, const base::FilePath& destination_path, base::File::Error result, const storage::FileSystemOperation::FileEntryList& file_list, bool has_more); void SnapshotFileCallback( const base::FilePath& target_path, base::File::Error result, const base::File::Info& file_info, const base::FilePath& platform_path, const scoped_refptr& file_ref); void CopyFile(const base::FilePath& src_path, const base::FilePath& dest_path); void Load(); scoped_refptr context_; // syncfs url representing the root of the folder to be copied. std::string project_base_url_; // physical path on disc of the folder to be copied. base::FilePath project_base_path_; private: int pending_copy_operations_count_; // This is set to false if any of the copyFile operations fail on // call of the API. It is returned as a response of the API call. bool success_; }; class DeveloperPrivateRequestFileSourceFunction : public DeveloperPrivateAPIFunction { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.requestFileSource", DEVELOPERPRIVATE_REQUESTFILESOURCE); DeveloperPrivateRequestFileSourceFunction(); protected: ~DeveloperPrivateRequestFileSourceFunction() override; ResponseAction Run() override; private: void Finish(const std::string& file_contents); scoped_ptr params_; }; class DeveloperPrivateOpenDevToolsFunction : public DeveloperPrivateAPIFunction { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.openDevTools", DEVELOPERPRIVATE_OPENDEVTOOLS); DeveloperPrivateOpenDevToolsFunction(); protected: ~DeveloperPrivateOpenDevToolsFunction() override; ResponseAction Run() override; }; class DeveloperPrivateDeleteExtensionErrorsFunction : public DeveloperPrivateAPIFunction { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.deleteExtensionErrors", DEVELOPERPRIVATE_DELETEEXTENSIONERRORS); protected: ~DeveloperPrivateDeleteExtensionErrorsFunction() override; ResponseAction Run() override; }; } // namespace api } // namespace extensions #endif // CHROME_BROWSER_EXTENSIONS_API_DEVELOPER_PRIVATE_DEVELOPER_PRIVATE_API_H_