blob: 70373ff9a7b98a5ee0b343bf7cd6e11c0cec6381 [file] [log] [blame]
// Copyright (c) 2009 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_EXTENSIONS_SERVICE_H_
#define CHROME_BROWSER_EXTENSIONS_EXTENSIONS_SERVICE_H_
#include <set>
#include <string>
#include <vector>
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/message_loop.h"
#include "base/ref_counted.h"
#include "base/task.h"
#include "base/values.h"
#include "chrome/common/chrome_switches.h"
class Browser;
class Extension;
class ExtensionsServiceBackend;
class GURL;
class PrefService;
class Profile;
class ResourceDispatcherHost;
class SkBitmap;
class SiteInstance;
class UserScriptMaster;
typedef std::vector<Extension*> ExtensionList;
// Manages installed and running Chromium extensions.
class ExtensionsService
: public base::RefCountedThreadSafe<ExtensionsService> {
public:
ExtensionsService(Profile* profile,
MessageLoop* frontend_loop,
MessageLoop* backend_loop,
const std::string& registry_path);
~ExtensionsService();
// Gets the list of currently installed extensions.
const ExtensionList* extensions() const {
return &extensions_;
}
// Initialize and start all installed extensions.
bool Init();
// Install the extension file at |extension_path|. Will install as an
// update if an older version is already installed.
// For fresh installs, this method also causes the extension to be
// immediately loaded.
void InstallExtension(const FilePath& extension_path);
// Uninstalls the specified extension. Callers should only call this method
// with extensions that exist and are "internal".
void UninstallExtension(const std::string& extension_id);
// Load the extension from the directory |extension_path|.
void LoadExtension(const FilePath& extension_path);
// Lookup an extension by |id|.
Extension* GetExtensionByID(std::string id);
// The name of the file that the current active version number is stored in.
static const char* kCurrentVersionFileName;
void set_extensions_enabled(bool enabled) { extensions_enabled_ = enabled; }
void set_show_extensions_disabled_notification(bool enabled) {
show_extensions_disabled_notification_ = enabled;
}
bool extensions_enabled() { return extensions_enabled_; }
bool show_extensions_disabled_notification() {
return show_extensions_disabled_notification_;
}
private:
// For OnExtensionLoaded, OnExtensionInstalled, and
// OnExtensionVersionReinstalled.
friend class ExtensionsServiceBackend;
// Called by the backend when extensions have been loaded.
void OnExtensionsLoaded(ExtensionList* extensions);
// Called by the backend when an extensoin hsa been installed.
void OnExtensionInstalled(Extension* extension, bool is_update);
// Called by the backend when an extension has been reinstalled.
void OnExtensionVersionReinstalled(const std::string& id);
// The name of the directory inside the profile where extensions are
// installed to.
static const char* kInstallDirectoryName;
// Preferences for the owning profile.
PrefService* prefs_;
// The message loop to use with the backend.
MessageLoop* backend_loop_;
// The current list of installed extensions.
ExtensionList extensions_;
// The full path to the directory where extensions are installed.
FilePath install_directory_;
// Whether or not extensions are enabled.
bool extensions_enabled_;
// Whether to notify users when they attempt to install an extension without
// the flag being enabled.
bool show_extensions_disabled_notification_;
// The backend that will do IO on behalf of this instance.
scoped_refptr<ExtensionsServiceBackend> backend_;
DISALLOW_COPY_AND_ASSIGN(ExtensionsService);
};
// Implements IO for the ExtensionsService.
// TODO(aa): This can probably move into the .cc file.
class ExtensionsServiceBackend
: public base::RefCountedThreadSafe<ExtensionsServiceBackend> {
public:
// |rdh| can be NULL in the case of test environment.
// |registry_path| can be NULL *except* in the case of the test environment,
// where it is specified to a temp location.
ExtensionsServiceBackend(const FilePath& install_directory,
ResourceDispatcherHost* rdh,
MessageLoop* frontend_loop,
const std::string& registry_path);
// Loads extensions from the install directory. The extensions are assumed to
// be unpacked in directories that are direct children of the specified path.
// Errors are reported through ExtensionErrorReporter. On completion,
// OnExtensionsLoaded() is called with any successfully loaded extensions.
void LoadExtensionsFromInstallDirectory(
scoped_refptr<ExtensionsService> frontend);
// Loads a single extension from |path| where |path| is the top directory of
// a specific extension where its manifest file lives.
// Errors are reported through ExtensionErrorReporter. On completion,
// OnExtensionsLoadedFromDirectory() is called with any successfully loaded
// extensions.
// TODO(erikkay): It might be useful to be able to load a packed extension
// (presumably into memory) without installing it.
void LoadSingleExtension(const FilePath &path,
scoped_refptr<ExtensionsService> frontend);
// Install the extension file at |extension_path|. Errors are reported through
// ExtensionErrorReporter. OnExtensionInstalled is called in the frontend on
// success.
void InstallExtension(const FilePath& extension_path,
scoped_refptr<ExtensionsService> frontend);
// Check externally updated extensions for updates and install if necessary.
// Errors are reported through ExtensionErrorReporter. Succcess is not
// reported.
void CheckForExternalUpdates(std::set<std::string> ids_to_ignore,
scoped_refptr<ExtensionsService> frontend);
// Deletes all versions of the extension from the filesystem. Note that only
// extensions whose location() == INTERNAL can be uninstalled. Attempting to
// uninstall other extensions will silently fail.
void UninstallExtension(const std::string& extension_id);
private:
class UnpackerClient;
friend class UnpackerClient;
// Load a single extension from |extension_path|, the top directory of
// a specific extension where its manifest file lives.
Extension* LoadExtension(const FilePath& extension_path, bool require_id);
// Load a single extension from |extension_path|, the top directory of
// a versioned extension where its Current Version file lives.
Extension* LoadExtensionCurrentVersion(const FilePath& extension_path);
// Install a crx file at |extension_path|. If |expected_id| is not empty, it's
// verified against the extension's manifest before installation. If
// |from_external| is true, this extension install is from an external source,
// ie the Windows registry, and will be marked as such. If the extension is
// already installed, install the new version only if its version number is
// greater than the current installed version.
void InstallOrUpdateExtension(const FilePath& extension_path,
const std::string& expected_id,
bool from_external);
// Finish installing an extension after it has been unpacked to
// |temp_extension_dir| by our utility process. If |expected_id| is not
// empty, it's verified against the extension's manifest before installation.
// |manifest| and |images| are parsed information from the extension that
// we want to write to disk in the browser process.
void OnExtensionUnpacked(
const FilePath& extension_path,
const FilePath& temp_extension_dir,
const std::string expected_id,
bool from_external,
const DictionaryValue& manifest,
const std::vector< Tuple2<SkBitmap, FilePath> >& images);
// Notify the frontend that there was an error loading an extension.
void ReportExtensionLoadError(const FilePath& extension_path,
const std::string& error);
// Notify the frontend that extensions were loaded.
void ReportExtensionsLoaded(ExtensionList* extensions);
// Notify the frontend that there was an error installing an extension.
void ReportExtensionInstallError(const FilePath& extension_path,
const std::string& error);
// Notify the frontend that the extension had already been installed.
void ReportExtensionVersionReinstalled(const std::string& id);
// Read the manifest from the front of the extension file.
// Caller takes ownership of return value.
DictionaryValue* ReadManifest(const FilePath& extension_path);
// Reads the Current Version file from |dir| into |version_string|.
bool ReadCurrentVersion(const FilePath& dir, std::string* version_string);
// Check that the version to be installed is greater than the current
// installed extension.
bool CheckCurrentVersion(const std::string& version,
const std::string& current_version,
const FilePath& dest_dir);
// Install the extension dir by moving it from |source| to |dest| safely.
bool InstallDirSafely(const FilePath& source,
const FilePath& dest);
// Update the CurrentVersion file in |dest_dir| to |version|.
bool SetCurrentVersion(const FilePath& dest_dir,
std::string version);
// For the extension in |version_path| with |id|, check to see if it's an
// externally managed extension. If so return true if it should be
// uninstalled.
bool CheckExternalUninstall(const FilePath& version_path,
const std::string& id);
// Should an extension of |id| and |version| be installed?
// Returns true if no extension of type |id| is installed or if |version|
// is greater than the current installed version.
bool ShouldInstall(const std::string& id, const std::string& version);
// The name of a temporary directory to install an extension into for
// validation before finalizing install.
static const char* kTempExtensionName;
// This is a naked pointer which is set by each entry point.
// The entry point is responsible for ensuring lifetime.
ExtensionsService* frontend_;
// The top-level extensions directory being installed to.
FilePath install_directory_;
// We only need a pointer to this to pass along to other interfaces.
ResourceDispatcherHost* resource_dispatcher_host_;
// Whether errors result in noisy alerts.
bool alert_on_error_;
// The message loop to use to call the frontend.
MessageLoop* frontend_loop_;
// The path to look for externally registered extensions in. This is a
// registry key on windows, but it could be a similar string for the
// appropriate system on other platforms in the future.
std::string registry_path_;
DISALLOW_COPY_AND_ASSIGN(ExtensionsServiceBackend);
};
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSIONS_SERVICE_H_