blob: 75caa7701fc678e88c1619c2e7dbe4b23456d5b4 [file]
// Copyright 2025 The Chromium Authors
// 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_FUNCTIONS_H_
#define CHROME_BROWSER_EXTENSIONS_API_DEVELOPER_PRIVATE_DEVELOPER_PRIVATE_FUNCTIONS_H_
#include <memory>
#include <optional>
#include "base/memory/scoped_refptr.h"
#include "chrome/browser/extensions/api/developer_private/developer_private_api.h"
#include "chrome/browser/extensions/api/developer_private/extension_info_generator.h"
#include "chrome/browser/extensions/pack_extension_job.h"
#include "chrome/common/extensions/api/developer_private.h"
#include "chrome/common/extensions/webstore_install_result.h"
#include "extensions/browser/extension_creator.h"
#include "extensions/browser/extension_function.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/browser/load_error_reporter.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/extension.h"
#include "ui/base/clipboard/file_info.h"
#include "ui/shell_dialogs/select_file_dialog.h"
#include "ui/shell_dialogs/selected_file_info.h"
#if !BUILDFLAG(IS_ANDROID)
#include "base/files/file.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "chrome/browser/extensions/api/developer_private/developer_private_event_router.h"
#include "chrome/browser/extensions/extension_uninstall_dialog.h"
#include "components/prefs/pref_change_registrar.h"
#include "extensions/browser/api/file_system/file_system_api.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/process_manager.h"
#include "extensions/common/extension_id.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/browser/file_system/file_system_operation.h"
#endif // !BUILDFLAG(IS_ANDROID)
static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE));
namespace extensions::api {
class DeveloperPrivateAPIFunction : public ExtensionFunction {
protected:
// These constants here are only temporarily during Android desktop
// development and we can move these constants to an anonymous namespace once
// we finish it.
static constexpr char kNoSuchExtensionError[] =
"No such extension found for call to '*'.";
static constexpr char kRequiresUserGestureError[] =
"This action requires a user gesture.";
static constexpr char kCouldNotShowSelectFileDialogError[] =
"Could not show a file chooser.";
static constexpr char kFileSelectionCanceled[] =
"File selection was canceled.";
static constexpr char kNoSuchRendererError[] = "No such renderer.";
static constexpr char kInvalidPathError[] = "Invalid path.";
static constexpr char kManifestKeyIsRequiredError[] =
"The 'manifestKey' argument is required for manifest files.";
static constexpr char kCouldNotFindWebContentsError[] =
"Could not find a valid web contents.";
static constexpr char kNoOptionsPageForExtensionError[] =
"Extension does not have an options page.";
static constexpr char kCannotRepairHealthyExtension[] =
"Cannot repair a healthy extension.";
static constexpr char kCannotRepairPolicyExtension[] =
"Cannot repair a policy-installed extension.";
static constexpr char kCannotChangeHostPermissions[] =
"Cannot change host permissions for the given extension.";
static constexpr char kCannotSetPinnedWithoutAction[] =
"Cannot set pinned action state for an extension with no action.";
static constexpr char kInvalidHost[] = "Invalid host.";
static constexpr char kInvalidLazyBackgroundPageParameter[] =
"isServiceWorker can not be set for lazy background page based "
"extensions.";
static constexpr char kInvalidRenderProcessId[] =
"render_process_id can be set to -1 for only lazy background page based "
"or "
"service-worker based extensions.";
static constexpr char kFailToUninstallEnterpriseOrComponentExtensions[] =
"Cannot uninstall the enterprise or component extensions in your list.";
static constexpr char kFailToUninstallNoneExistentExtensions[] =
"Cannot uninstall non-existent extensions in your list.";
static constexpr char kUserCancelledError[] = "User cancelled uninstall";
static constexpr char kNoExtensionError[] =
"Extension with ID '*' doesn't exist.";
static constexpr char kExtensionNotAffectedByMV2Deprecation[] =
"Extension with ID '*' is not affected by the MV2 deprecation.";
static constexpr char kCannotRepairNonWebstoreExtension[] =
"Cannot repair an extension that is not installed from the Chrome Web "
"Store.";
static constexpr char kCannotDismissExtensionOnUnsupportedStage[] =
"Cannot dismiss the MV2 deprecation notice for extension with ID '*' on "
"the unsupported stage.";
static constexpr char kUserNotSignedIn[] = "User is not signed in.";
static constexpr char kCannotUploadExtensionToAccount[] =
"Extension with ID '*' cannot be uploaded to the user's account.";
static constexpr char kManifestFile[] = "manifest.json";
// Following helpers are temporarily here during migration for desktop
// android. We should move them back to anonymous namespace after the
// migration.
using GetManifestErrorCallback =
base::OnceCallback<void(const base::FilePath& file_path,
const std::u16string& error,
size_t line_number,
const std::string& manifest)>;
// Takes in an `error` string and tries to parse it as a manifest error (with
// line number), asynchronously calling `callback` with the results.
void GetManifestError(const std::u16string& error,
const base::FilePath& extension_path,
GetManifestErrorCallback callback);
// Creates a developer::LoadError from the provided data.
developer_private::LoadError CreateLoadError(
const base::FilePath& file_path,
const std::u16string& error,
size_t line_number,
const std::string& manifest,
const DeveloperPrivateAPI::UnpackedRetryId& retry_guid);
~DeveloperPrivateAPIFunction() override;
// Returns the extension with the given `id` from the registry, including
// all possible extensions (enabled, disabled, terminated, etc).
const Extension* GetExtensionById(const ExtensionId& id);
// Returns the extension with the given `id` from the registry, only checking
// enabled extensions.
const Extension* GetEnabledExtensionById(const ExtensionId& id);
// Called when there is no extension that exists for a specified ID in a
// function. Logs the function name and returns an error.
ResponseValue LogNoSuchExtensionFoundAndReturn();
};
class DeveloperPrivateAutoUpdateFunction : public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.autoUpdate",
DEVELOPERPRIVATE_AUTOUPDATE)
protected:
~DeveloperPrivateAutoUpdateFunction() override;
ResponseAction Run() override;
private:
void OnComplete();
};
class DeveloperPrivateGetExtensionsInfoFunction
: public DeveloperPrivateAPIFunction {
public:
DeveloperPrivateGetExtensionsInfoFunction();
DeveloperPrivateGetExtensionsInfoFunction(
const DeveloperPrivateGetExtensionsInfoFunction&) = delete;
DeveloperPrivateGetExtensionsInfoFunction& operator=(
const DeveloperPrivateGetExtensionsInfoFunction&) = delete;
DECLARE_EXTENSION_FUNCTION("developerPrivate.getExtensionsInfo",
DEVELOPERPRIVATE_GETEXTENSIONSINFO)
private:
~DeveloperPrivateGetExtensionsInfoFunction() override;
ResponseAction Run() override;
void OnInfosGenerated(
std::vector<api::developer_private::ExtensionInfo> infos);
std::unique_ptr<ExtensionInfoGenerator> info_generator_;
};
class DeveloperPrivateGetExtensionInfoFunction
: public DeveloperPrivateAPIFunction {
public:
DeveloperPrivateGetExtensionInfoFunction();
DeveloperPrivateGetExtensionInfoFunction(
const DeveloperPrivateGetExtensionInfoFunction&) = delete;
DeveloperPrivateGetExtensionInfoFunction& operator=(
const DeveloperPrivateGetExtensionInfoFunction&) = delete;
DECLARE_EXTENSION_FUNCTION("developerPrivate.getExtensionInfo",
DEVELOPERPRIVATE_GETEXTENSIONINFO)
private:
~DeveloperPrivateGetExtensionInfoFunction() override;
ResponseAction Run() override;
void OnInfosGenerated(
std::vector<api::developer_private::ExtensionInfo> infos);
std::unique_ptr<ExtensionInfoGenerator> info_generator_;
};
class DeveloperPrivateGetExtensionSizeFunction
: public DeveloperPrivateAPIFunction {
public:
DeveloperPrivateGetExtensionSizeFunction();
DeveloperPrivateGetExtensionSizeFunction(
const DeveloperPrivateGetExtensionSizeFunction&) = delete;
DeveloperPrivateGetExtensionSizeFunction& operator=(
const DeveloperPrivateGetExtensionSizeFunction&) = delete;
DECLARE_EXTENSION_FUNCTION("developerPrivate.getExtensionSize",
DEVELOPERPRIVATE_GETEXTENSIONSIZE)
private:
~DeveloperPrivateGetExtensionSizeFunction() override;
ResponseAction Run() override;
void OnSizeCalculated(const std::u16string& size);
};
class DeveloperPrivateGetProfileConfigurationFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.getProfileConfiguration",
DEVELOPERPRIVATE_GETPROFILECONFIGURATION)
private:
~DeveloperPrivateGetProfileConfigurationFunction() override;
ResponseAction Run() override;
};
class DeveloperPrivateUpdateProfileConfigurationFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.updateProfileConfiguration",
DEVELOPERPRIVATE_UPDATEPROFILECONFIGURATION)
private:
~DeveloperPrivateUpdateProfileConfigurationFunction() 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 ExtensionRegistryObserver,
public LoadErrorReporter::Observer {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.reload", DEVELOPERPRIVATE_RELOAD)
DeveloperPrivateReloadFunction();
DeveloperPrivateReloadFunction(const DeveloperPrivateReloadFunction&) =
delete;
DeveloperPrivateReloadFunction& operator=(
const DeveloperPrivateReloadFunction&) = delete;
// ExtensionRegistryObserver:
void OnExtensionLoaded(content::BrowserContext* browser_context,
const Extension* extension) override;
void OnShutdown(ExtensionRegistry* registry) override;
// LoadErrorReporter::Observer:
void OnLoadFailure(content::BrowserContext* browser_context,
const base::FilePath& file_path,
const std::u16string& error) override;
protected:
~DeveloperPrivateReloadFunction() override;
// ExtensionFunction:
ResponseAction Run() override;
private:
// Callback once we parse a manifest error from a failed reload.
void OnGotManifestError(const base::FilePath& file_path,
const std::u16string& error,
size_t line_number,
const std::string& manifest);
// Clears the scoped observers.
void ClearObservers();
// The file path of the extension that's reloading.
base::FilePath reloading_extension_path_;
base::ScopedObservation<ExtensionRegistry, ExtensionRegistryObserver>
registry_observation_{this};
base::ScopedObservation<LoadErrorReporter, LoadErrorReporter::Observer>
error_reporter_observation_{this};
};
class DeveloperPrivateLoadUnpackedFunction
: public DeveloperPrivateAPIFunction,
public ui::SelectFileDialog::Listener {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.loadUnpacked",
DEVELOPERPRIVATE_LOADUNPACKED)
DeveloperPrivateLoadUnpackedFunction();
// ui::SelectFileDialog::Listener:
void FileSelected(const ui::SelectedFileInfo& file, int index) override;
void FileSelectionCanceled() override;
// For testing:
void set_accept_dialog_for_testing(bool accept) {
accept_dialog_for_testing_ = accept;
}
void set_selected_file_for_testing(const ui::SelectedFileInfo& file) {
selected_file_for_testing_ = file;
}
protected:
~DeveloperPrivateLoadUnpackedFunction() override;
// DeveloperPrivateAPIFunction:
ResponseAction Run() override;
private:
// Shows the file picker dialog.
void ShowSelectFileDialog();
// Starts loading the given `file_path`.
void StartFileLoad(const base::FilePath file_path);
// Called when `file_path` load is completed
void OnLoadComplete(const Extension* extension,
const base::FilePath& file_path,
const std::u16string& error);
// Called when `file_path` load encounters a manifest parsing `error`.
void OnGotManifestError(const base::FilePath& file_path,
const std::u16string& error,
size_t line_number,
const std::string& manifest);
// Returns `response_value` when the function should finish asynchronously.
void Finish(ResponseValue response_value);
// Whether or not we should fail quietly in the event of a load error.
bool fail_quietly_ = false;
// Whether we populate a developer_private::LoadError on load failure, as
// opposed to simply passing the message in lastError.
bool populate_error_ = false;
// The identifier for the selected path when retrying an unpacked load.
DeveloperPrivateAPI::UnpackedRetryId retry_guid_;
// The dialog with the select file picker.
scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
// For testing:
// Whether to accept or reject the select file dialog without showing it.
std::optional<bool> accept_dialog_for_testing_;
// File to load when accepting the select file dialog without showing it.
std::optional<ui::SelectedFileInfo> selected_file_for_testing_;
};
class DeveloperPrivateInstallDroppedFileFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.installDroppedFile",
DEVELOPERPRIVATE_INSTALLDROPPEDFILE)
DeveloperPrivateInstallDroppedFileFunction();
DeveloperPrivateInstallDroppedFileFunction(
const DeveloperPrivateInstallDroppedFileFunction&) = delete;
DeveloperPrivateInstallDroppedFileFunction& operator=(
const DeveloperPrivateInstallDroppedFileFunction&) = delete;
private:
~DeveloperPrivateInstallDroppedFileFunction() override;
// ExtensionFunction:
ResponseAction Run() override;
};
class DeveloperPrivateNotifyDragInstallInProgressFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.notifyDragInstallInProgress",
DEVELOPERPRIVATE_NOTIFYDRAGINSTALLINPROGRESS)
DeveloperPrivateNotifyDragInstallInProgressFunction();
DeveloperPrivateNotifyDragInstallInProgressFunction(
const DeveloperPrivateNotifyDragInstallInProgressFunction&) = delete;
DeveloperPrivateNotifyDragInstallInProgressFunction& operator=(
const DeveloperPrivateNotifyDragInstallInProgressFunction&) = delete;
ResponseAction Run() override;
static void SetDropFileForTesting(ui::FileInfo* file_info);
private:
~DeveloperPrivateNotifyDragInstallInProgressFunction() override;
};
class DeveloperPrivateDeleteExtensionErrorsFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.deleteExtensionErrors",
DEVELOPERPRIVATE_DELETEEXTENSIONERRORS)
protected:
~DeveloperPrivateDeleteExtensionErrorsFunction() override;
ResponseAction Run() override;
};
class DeveloperPrivateShowOptionsFunction : public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.showOptions",
DEVELOPERPRIVATE_SHOWOPTIONS)
protected:
~DeveloperPrivateShowOptionsFunction() override;
ResponseAction Run() override;
};
class DeveloperPrivateShowPathFunction : public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.showPath",
DEVELOPERPRIVATE_SHOWPATH)
protected:
~DeveloperPrivateShowPathFunction() override;
ResponseAction Run() override;
};
class DeveloperPrivateSetShortcutHandlingSuspendedFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.setShortcutHandlingSuspended",
DEVELOPERPRIVATE_SETSHORTCUTHANDLINGSUSPENDED)
protected:
~DeveloperPrivateSetShortcutHandlingSuspendedFunction() override;
ResponseAction Run() override;
};
class DeveloperPrivateUpdateExtensionCommandFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.updateExtensionCommand",
DEVELOPERPRIVATE_UPDATEEXTENSIONCOMMAND)
protected:
~DeveloperPrivateUpdateExtensionCommandFunction() override;
ResponseAction Run() override;
};
class DeveloperPrivateAddHostPermissionFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.addHostPermission",
DEVELOPERPRIVATE_ADDHOSTPERMISSION)
DeveloperPrivateAddHostPermissionFunction();
DeveloperPrivateAddHostPermissionFunction(
const DeveloperPrivateAddHostPermissionFunction&) = delete;
DeveloperPrivateAddHostPermissionFunction& operator=(
const DeveloperPrivateAddHostPermissionFunction&) = delete;
private:
~DeveloperPrivateAddHostPermissionFunction() override;
ResponseAction Run() override;
void OnRuntimePermissionsGranted();
};
class DeveloperPrivateRemoveHostPermissionFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.removeHostPermission",
DEVELOPERPRIVATE_REMOVEHOSTPERMISSION)
DeveloperPrivateRemoveHostPermissionFunction();
DeveloperPrivateRemoveHostPermissionFunction(
const DeveloperPrivateRemoveHostPermissionFunction&) = delete;
DeveloperPrivateRemoveHostPermissionFunction& operator=(
const DeveloperPrivateRemoveHostPermissionFunction&) = delete;
private:
~DeveloperPrivateRemoveHostPermissionFunction() override;
ResponseAction Run() override;
void OnRuntimePermissionsRevoked();
};
class DeveloperPrivateGetUserSiteSettingsFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.getUserSiteSettings",
DEVELOPERPRIVATE_GETUSERSITESETTINGS)
DeveloperPrivateGetUserSiteSettingsFunction();
DeveloperPrivateGetUserSiteSettingsFunction(
const DeveloperPrivateGetUserSiteSettingsFunction&) = delete;
DeveloperPrivateGetUserSiteSettingsFunction& operator=(
const DeveloperPrivateGetUserSiteSettingsFunction&) = delete;
private:
~DeveloperPrivateGetUserSiteSettingsFunction() override;
ResponseAction Run() override;
};
class DeveloperPrivateAddUserSpecifiedSitesFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.addUserSpecifiedSites",
DEVELOPERPRIVATE_ADDUSERSPECIFIEDSITES)
DeveloperPrivateAddUserSpecifiedSitesFunction();
DeveloperPrivateAddUserSpecifiedSitesFunction(
const DeveloperPrivateAddUserSpecifiedSitesFunction&) = delete;
DeveloperPrivateAddUserSpecifiedSitesFunction& operator=(
const DeveloperPrivateAddUserSpecifiedSitesFunction&) = delete;
private:
~DeveloperPrivateAddUserSpecifiedSitesFunction() override;
ResponseAction Run() override;
};
class DeveloperPrivateRemoveUserSpecifiedSitesFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.removeUserSpecifiedSites",
DEVELOPERPRIVATE_REMOVEUSERSPECIFIEDSITES)
DeveloperPrivateRemoveUserSpecifiedSitesFunction();
DeveloperPrivateRemoveUserSpecifiedSitesFunction(
const DeveloperPrivateRemoveUserSpecifiedSitesFunction&) = delete;
DeveloperPrivateRemoveUserSpecifiedSitesFunction& operator=(
const DeveloperPrivateRemoveUserSpecifiedSitesFunction&) = delete;
private:
~DeveloperPrivateRemoveUserSpecifiedSitesFunction() override;
ResponseAction Run() override;
};
class DeveloperPrivateGetUserAndExtensionSitesByEtldFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.getUserAndExtensionSitesByEtld",
DEVELOPERPRIVATE_GETUSERANDEXTENSIONSITESBYETLD)
DeveloperPrivateGetUserAndExtensionSitesByEtldFunction();
DeveloperPrivateGetUserAndExtensionSitesByEtldFunction(
const DeveloperPrivateGetUserAndExtensionSitesByEtldFunction&) = delete;
DeveloperPrivateGetUserAndExtensionSitesByEtldFunction& operator=(
const DeveloperPrivateGetUserAndExtensionSitesByEtldFunction&) = delete;
private:
~DeveloperPrivateGetUserAndExtensionSitesByEtldFunction() override;
ResponseAction Run() override;
};
class DeveloperPrivateGetMatchingExtensionsForSiteFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.getMatchingExtensionsForSite",
DEVELOPERPRIVATE_GETMATCHINGEXTENSIONSFORSITE)
DeveloperPrivateGetMatchingExtensionsForSiteFunction();
DeveloperPrivateGetMatchingExtensionsForSiteFunction(
const DeveloperPrivateGetMatchingExtensionsForSiteFunction&) = delete;
DeveloperPrivateGetMatchingExtensionsForSiteFunction& operator=(
const DeveloperPrivateGetMatchingExtensionsForSiteFunction&) = delete;
private:
~DeveloperPrivateGetMatchingExtensionsForSiteFunction() override;
ResponseAction Run() override;
};
class DeveloperPrivateUpdateSiteAccessFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.updateSiteAccess",
DEVELOPERPRIVATE_UPDATESITEACCESS)
DeveloperPrivateUpdateSiteAccessFunction();
DeveloperPrivateUpdateSiteAccessFunction(
const DeveloperPrivateUpdateSiteAccessFunction&) = delete;
DeveloperPrivateUpdateSiteAccessFunction& operator=(
const DeveloperPrivateUpdateSiteAccessFunction&) = delete;
private:
~DeveloperPrivateUpdateSiteAccessFunction() override;
ResponseAction Run() override;
void OnSiteSettingsUpdated();
};
class DeveloperPrivateRemoveMultipleExtensionsFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.removeMultipleExtensions",
DEVELOPERPRIVATE_REMOVEMULTIPLEEXTENSIONS)
DeveloperPrivateRemoveMultipleExtensionsFunction();
DeveloperPrivateRemoveMultipleExtensionsFunction(
const DeveloperPrivateRemoveMultipleExtensionsFunction&) = delete;
DeveloperPrivateRemoveMultipleExtensionsFunction& operator=(
const DeveloperPrivateRemoveMultipleExtensionsFunction&) = delete;
void accept_bubble_for_testing(bool accept_bubble) {
accept_bubble_for_testing_ = accept_bubble;
}
private:
~DeveloperPrivateRemoveMultipleExtensionsFunction() override;
// ExtensionFunction:
ResponseAction Run() override;
// A callback function to run when the user accepts the action dialog.
void OnDialogAccepted();
// A callback function to run when the user cancels the action dialog.
void OnDialogCancelled();
// The IDs of the extensions to be uninstalled.
std::vector<ExtensionId> extension_ids_;
raw_ptr<Profile> profile_;
// If true, immediately accept the blocked action dialog by running the
// callback.
std::optional<bool> accept_bubble_for_testing_;
};
class DeveloperPrivateDismissSafetyHubExtensionsMenuNotificationFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION(
"developerPrivate.dismissSafetyHubExtensionsMenuNotification",
DEVELOPERPRIVATE_DISMISSSAFETYHUBEXTENSIONSMENUNOTIFICATION)
DeveloperPrivateDismissSafetyHubExtensionsMenuNotificationFunction();
DeveloperPrivateDismissSafetyHubExtensionsMenuNotificationFunction(
const DeveloperPrivateDismissSafetyHubExtensionsMenuNotificationFunction&) =
delete;
DeveloperPrivateDismissSafetyHubExtensionsMenuNotificationFunction& operator=(
const DeveloperPrivateDismissSafetyHubExtensionsMenuNotificationFunction&) =
delete;
ResponseAction Run() override;
private:
~DeveloperPrivateDismissSafetyHubExtensionsMenuNotificationFunction()
override;
};
class DeveloperPrivatePackDirectoryFunction
: public DeveloperPrivateAPIFunction,
public PackExtensionJob::Client {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.packDirectory",
DEVELOPERPRIVATE_PACKDIRECTORY)
DeveloperPrivatePackDirectoryFunction();
// PackExtensionJob::Client implementation.
void OnPackSuccess(const base::FilePath& crx_file,
const base::FilePath& key_file) override;
void OnPackFailure(const std::u16string& error,
ExtensionCreator::ErrorType error_type) override;
protected:
~DeveloperPrivatePackDirectoryFunction() override;
ResponseAction Run() override;
private:
std::unique_ptr<PackExtensionJob> pack_job_;
std::string item_path_str_;
std::string key_path_str_;
};
class DeveloperPrivateChoosePathFunction
: public DeveloperPrivateAPIFunction,
public ui::SelectFileDialog::Listener {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.choosePath",
DEVELOPERPRIVATE_CHOOSEPATH)
DeveloperPrivateChoosePathFunction();
// ui::SelectFileDialog::Listener:
void FileSelected(const ui::SelectedFileInfo& file, int index) override;
void FileSelectionCanceled() override;
// For testing:
void set_accept_dialog_for_testing(bool accept) {
accept_dialog_for_testing_ = accept;
}
void set_selected_file_for_testing(const ui::SelectedFileInfo& file) {
selected_file_for_testing_ = file;
}
protected:
~DeveloperPrivateChoosePathFunction() override;
ResponseAction Run() override;
private:
// The dialog with the select file picker.
scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
// For testing:
// Whether to accept or reject the select file dialog without showing it.
std::optional<bool> accept_dialog_for_testing_;
// File to load when accepting the select file dialog without showing it.
std::optional<ui::SelectedFileInfo> selected_file_for_testing_;
};
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);
std::optional<api::developer_private::RequestFileSource::Params> params_;
};
class DeveloperPrivateOpenDevToolsFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.openDevTools",
DEVELOPERPRIVATE_OPENDEVTOOLS)
DeveloperPrivateOpenDevToolsFunction();
protected:
~DeveloperPrivateOpenDevToolsFunction() override;
ResponseAction Run() override;
};
class DeveloperPrivateRepairExtensionFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.repairExtension",
DEVELOPERPRIVATE_REPAIREXTENSION)
protected:
~DeveloperPrivateRepairExtensionFunction() override;
ResponseAction Run() override;
void OnReinstallComplete(bool success,
const std::string& error,
webstore_install::Result result);
};
class DeveloperPrivateUploadExtensionToAccountFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.uploadExtensionToAccount",
DEVELOPERPRIVATE_UPLOADEXTENSIONTOACCOUNT)
DeveloperPrivateUploadExtensionToAccountFunction();
DeveloperPrivateUploadExtensionToAccountFunction(
const DeveloperPrivateUploadExtensionToAccountFunction&) = delete;
DeveloperPrivateUploadExtensionToAccountFunction& operator=(
const DeveloperPrivateUploadExtensionToAccountFunction&) = delete;
void accept_bubble_for_testing(bool accept_bubble) {
accept_bubble_for_testing_ = accept_bubble;
}
private:
~DeveloperPrivateUploadExtensionToAccountFunction() override;
ResponseAction Run() override;
// Verify that the extension to be uploaded exists and that there's a signed
// in user. Returns the extension if successful, otherwise returns an error.
base::expected<const Extension*, std::string> VerifyExtensionAndSigninState();
// A callback function to run when the user accepts the action dialog.
void OnDialogAccepted();
// A callback function to run when the user cancels the action dialog.
void OnDialogCancelled();
// The ID of the extension to be uploaded.
ExtensionId extension_id_;
raw_ptr<Profile> profile_;
// If true, immediately accepts the keep dialog by running the callback.
std::optional<bool> accept_bubble_for_testing_;
};
#if BUILDFLAG(IS_ANDROID)
// We don't have to port it to desktop android because it's an old API for
// chromeos, that is kept just in case there's an app still using it.
DECLARE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateLoadDirectoryFunction,
"developerPrivate.loadDirectory",
DEVELOPERPRIVATE_LOADUNPACKEDCROS);
// We don't have to port it to desktop android because MV2 is not supported
// on Android.
DECLARE_UNIMPLEMENTED_EXTENSION_FUNCTION(
DeveloperPrivateDismissMv2DeprecationNoticeForExtensionFunction,
"developerPrivate.dismissMv2DeprecationNoticeForExtension",
DEVELOPERPRIVATE_DISMISSMV2DEPRECATIONNOTICEFOREXTENSION);
class DeveloperPrivateShowSiteSettingsFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.showSiteSettings",
DEVELOPERPRIVATE_SHOWSITESETTINGS)
protected:
~DeveloperPrivateShowSiteSettingsFunction() override {}
ResponseAction Run() override;
};
#else // BUILDFLAG(IS_ANDROID)
class DeveloperPrivateLoadDirectoryFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.loadDirectory",
DEVELOPERPRIVATE_LOADUNPACKEDCROS)
DeveloperPrivateLoadDirectoryFunction();
protected:
~DeveloperPrivateLoadDirectoryFunction() override;
// ExtensionFunction:
ResponseAction Run() override;
ResponseAction 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,
::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,
scoped_refptr<::storage::ShareableFileReference> file_ref);
void CopyFile(const base::FilePath& src_path,
const base::FilePath& dest_path);
void Load();
scoped_refptr<::storage::FileSystemContext> 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_;
// Error string if `success_` is false.
std::string error_;
};
class DeveloperPrivateDismissMv2DeprecationNoticeForExtensionFunction
: public DeveloperPrivateAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION(
"developerPrivate.dismissMv2DeprecationNoticeForExtension",
DEVELOPERPRIVATE_DISMISSMV2DEPRECATIONNOTICEFOREXTENSION)
DeveloperPrivateDismissMv2DeprecationNoticeForExtensionFunction();
DeveloperPrivateDismissMv2DeprecationNoticeForExtensionFunction(
const DeveloperPrivateDismissMv2DeprecationNoticeForExtensionFunction&) =
delete;
DeveloperPrivateDismissMv2DeprecationNoticeForExtensionFunction& operator=(
const DeveloperPrivateDismissMv2DeprecationNoticeForExtensionFunction&) =
delete;
void accept_bubble_for_testing(bool accept_bubble) {
accept_bubble_for_testing_ = accept_bubble;
}
private:
~DeveloperPrivateDismissMv2DeprecationNoticeForExtensionFunction() override;
// ExtensionFunction:
ResponseAction Run() override;
void DismissExtensionNotice();
// Callback to run when the user accepts the keep dialog.
void OnDialogAccepted();
// Callback to run when the user cancels the keep dialog.
void OnDialogCancelled();
// The ID of the extension to be dismissed.
ExtensionId extension_id_;
// If true, immediately accepts the keep dialog by running the callback.
std::optional<bool> accept_bubble_for_testing_;
};
#endif // BUILDFLAG(IS_ANDROID)
} // namespace extensions::api
#endif // CHROME_BROWSER_EXTENSIONS_API_DEVELOPER_PRIVATE_DEVELOPER_PRIVATE_FUNCTIONS_H_