summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r--chrome/browser/extensions/crx_installer.cc71
-rw-r--r--chrome/browser/extensions/crx_installer.h31
-rw-r--r--chrome/browser/extensions/extension_file_util.cc9
-rw-r--r--chrome/browser/extensions/extension_install_ui.cc35
-rw-r--r--chrome/browser/extensions/extension_install_ui.h12
-rw-r--r--chrome/browser/extensions/extension_prefs.cc2
-rw-r--r--chrome/browser/extensions/sandboxed_extension_unpacker.cc7
-rw-r--r--chrome/browser/extensions/theme_preview_infobar_delegate.cc4
-rw-r--r--chrome/browser/extensions/theme_preview_infobar_delegate.h3
9 files changed, 138 insertions, 36 deletions
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index 60fe23e..5fede2e 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -13,6 +13,8 @@
#include "chrome/browser/extensions/extension_file_util.h"
#include "chrome/common/extensions/extension_error_reporter.h"
#include "grit/chromium_strings.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "webkit/glue/image_decoder.h"
namespace {
// Helper function to delete files. This is used to avoid ugly casts which
@@ -116,6 +118,7 @@ void CrxInstaller::OnUnpackSuccess(const FilePath& temp_dir,
}
if (client_.get()) {
+ DecodeInstallIcon();
ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
&CrxInstaller::ConfirmInstall));
} else {
@@ -123,16 +126,60 @@ void CrxInstaller::OnUnpackSuccess(const FilePath& temp_dir,
}
}
-void CrxInstaller::ConfirmInstall() {
- if (!client_->ConfirmInstall(extension_.get())) {
- // We're done. Since we don't post any more tasks to ourselves, our ref
- // count should go to zero and we die. The destructor will clean up the temp
- // dir.
+void CrxInstaller::DecodeInstallIcon() {
+ std::map<int, std::string>::const_iterator iter =
+ extension_->icons().find(128);
+ if (iter == extension_->icons().end())
+ return;
+
+ FilePath path = extension_->GetResourcePath(iter->second);
+ std::string file_contents;
+ if (!file_util::ReadFileToString(path, &file_contents)) {
+ LOG(ERROR) << "Could not read icon file: "
+ << WideToUTF8(path.ToWStringHack());
+ return;
+ }
+
+ // Decode the image using WebKit's image decoder.
+ const unsigned char* data =
+ reinterpret_cast<const unsigned char*>(file_contents.data());
+ webkit_glue::ImageDecoder decoder;
+ scoped_ptr<SkBitmap> decoded(new SkBitmap());
+ *decoded = decoder.Decode(data, file_contents.length());
+ if(decoded->empty()) {
+ LOG(ERROR) << "Could not decode icon file: "
+ << WideToUTF8(path.ToWStringHack());
return;
}
+ if (decoded->width() != 128 || decoded->height() != 128) {
+ LOG(ERROR) << "Icon file has unexpected size: "
+ << IntToString(decoded->width()) << "x"
+ << IntToString(decoded->height());
+ return;
+ }
+
+ install_icon_.reset(decoded.release());
+}
+
+void CrxInstaller::ConfirmInstall() {
+ AddRef(); // balanced in ContinueInstall() and AbortInstall().
+
+ client_->ConfirmInstall(this, extension_.get(), install_icon_.get());
+}
+
+void CrxInstaller::ContinueInstall() {
file_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
&CrxInstaller::CompleteInstall));
+
+ Release(); // balanced in ConfirmInstall().
+}
+
+void CrxInstaller::AbortInstall() {
+ Release(); // balanced in ConfirmInstall().
+
+ // We're done. Since we don't post any more tasks to ourself, our ref count
+ // should go to zero and we die. The destructor will clean up the temp dir.
}
void CrxInstaller::CompleteInstall() {
@@ -156,15 +203,23 @@ void CrxInstaller::CompleteInstall() {
return;
}
- extension_->set_path(version_dir);
- extension_->set_location(install_source_);
-
if (install_type == Extension::REINSTALL) {
// We use this as a signal to switch themes.
ReportOverinstallFromFileThread();
return;
}
+ // This is lame, but we must reload the extension because absolute paths
+ // inside the content scripts are established inside InitFromValue() and we
+ // just moved the extension.
+ // TODO(aa): All paths to resources inside extensions should be created
+ // lazily and based on the Extension's root path at that moment.
+ std::string error;
+ extension_.reset(extension_file_util::LoadExtension(version_dir, true,
+ &error));
+ DCHECK(error.empty());
+ extension_->set_location(install_source_);
+
ReportSuccessFromFileThread();
}
diff --git a/chrome/browser/extensions/crx_installer.h b/chrome/browser/extensions/crx_installer.h
index 5c373d9..0ea8398 100644
--- a/chrome/browser/extensions/crx_installer.h
+++ b/chrome/browser/extensions/crx_installer.h
@@ -14,6 +14,9 @@
#include "chrome/browser/extensions/sandboxed_extension_unpacker.h"
#include "chrome/common/extensions/extension.h"
+class CrxInstaller;
+class SkBitmap;
+
// Classes that want to know about install completion, or that want to have an
// opportunity to reject the unpacked extension before installation, should
// implement this interface.
@@ -22,8 +25,17 @@ class CrxInstallerClient
public:
virtual ~CrxInstallerClient() {}
- // Return true to indicate that installation should proceed, false otherwise.
- virtual bool ConfirmInstall(Extension* extension) = 0;
+ // This is called by the installer to verify whether the installation should
+ // proceed. Clients can use this time to put up UI, or to do any checks they
+ // need to on the unpacked extension.
+ //
+ // Clients *MUST* eventually call either ContinueInstall() or AbortInstall()
+ // on |installer|.
+ //
+ // Clients should not AddRef() |installer|.
+ virtual void ConfirmInstall(CrxInstaller* installer,
+ Extension* extension,
+ SkBitmap* icon) = 0;
// Installation was successful.
virtual void OnInstallSuccess(Extension* extension) = 0;
@@ -79,6 +91,14 @@ class CrxInstaller : public SandboxedExtensionUnpackerClient {
ExtensionsService* frontend,
CrxInstallerClient* client);
+ // Clients should call this method after ConfirmInstall() if they want the
+ // installation to continue.
+ void ContinueInstall();
+
+ // Clients should call this method after ConfirmInstall() if they want the
+ // installation to stop.
+ void AbortInstall();
+
private:
CrxInstaller(const FilePath& crx_path,
const FilePath& install_directory,
@@ -96,6 +116,10 @@ class CrxInstaller : public SandboxedExtensionUnpackerClient {
const FilePath& extension_dir,
Extension* extension);
+ // Read the icon from the extension if present and decode it into
+ // install_icon_.
+ void DecodeInstallIcon();
+
// Runs on the UI thread. Confirms with the user (via CrxInstallerClient) that
// it is OK to install this extension.
void ConfirmInstall();
@@ -145,6 +169,9 @@ class CrxInstaller : public SandboxedExtensionUnpackerClient {
// ExtensionsService on success, or delete it on failure.
scoped_ptr<Extension> extension_;
+ // The icon we will display in the installation UI, if any.
+ scoped_ptr<SkBitmap> install_icon_;
+
// The temp directory extension resources were unpacked to. We own this and
// must delete it when we are done with it.
FilePath temp_dir_;
diff --git a/chrome/browser/extensions/extension_file_util.cc b/chrome/browser/extensions/extension_file_util.cc
index b46404c..9020b1b 100644
--- a/chrome/browser/extensions/extension_file_util.cc
+++ b/chrome/browser/extensions/extension_file_util.cc
@@ -254,13 +254,12 @@ Extension* LoadExtension(const FilePath& extension_path, bool require_key,
for (PageActionMap::const_iterator i(page_actions.begin());
i != page_actions.end(); ++i) {
PageAction* page_action = i->second;
- const std::vector<FilePath>& icon_paths = page_action->icon_paths();
- for (std::vector<FilePath>::const_iterator iter = icon_paths.begin();
+ const std::vector<std::string>& icon_paths = page_action->icon_paths();
+ for (std::vector<std::string>::const_iterator iter = icon_paths.begin();
iter != icon_paths.end(); ++iter) {
- FilePath path = *iter;
- if (!file_util::PathExists(path)) {
+ if (!file_util::PathExists(extension->GetResourcePath(*iter))) {
*error = StringPrintf("Could not load icon '%s' for page action.",
- WideToUTF8(path.ToWStringHack()).c_str());
+ iter->c_str());
return NULL;
}
}
diff --git a/chrome/browser/extensions/extension_install_ui.cc b/chrome/browser/extensions/extension_install_ui.cc
index 4416701..135aac7 100644
--- a/chrome/browser/extensions/extension_install_ui.cc
+++ b/chrome/browser/extensions/extension_install_ui.cc
@@ -4,12 +4,17 @@
#include "chrome/browser/extensions/extension_install_ui.h"
+#include <map>
+
#include "app/l10n_util.h"
-#include "grit/chromium_strings.h"
+#include "base/file_util.h"
#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/theme_preview_infobar_delegate.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/extensions/extension.h"
+#include "grit/chromium_strings.h"
#if defined(OS_WIN)
#include "app/win_util.h"
@@ -23,24 +28,24 @@ ExtensionInstallUI::ExtensionInstallUI(Profile* profile)
: profile_(profile), ui_loop_(MessageLoop::current()) {
}
-bool ExtensionInstallUI::ConfirmInstall(Extension* extension) {
+void ExtensionInstallUI::ConfirmInstall(CrxInstaller* installer,
+ Extension* extension,
+ SkBitmap* install_icon) {
DCHECK(ui_loop_ == MessageLoop::current());
// We special-case themes to not show any confirm UI. Instead they are
// immediately installed, and then we show an infobar (see OnInstallSuccess)
// to allow the user to revert if they don't like it.
- if (extension->IsTheme())
- return true;
+ if (extension->IsTheme()) {
+ installer->ContinueInstall();
+ return;
+ }
#if defined(OS_WIN)
- if (win_util::MessageBox(GetForegroundWindow(),
- L"Are you sure you want to install this extension?\n\n"
- L"You should only install extensions from sources you trust.",
- l10n_util::GetString(IDS_PRODUCT_NAME).c_str(),
- MB_OKCANCEL) != IDOK) {
- return false;
- }
+ ShowExtensionInstallPrompt(profile_, installer, extension, install_icon);
+
#elif defined(OS_MACOSX)
+ // TODO(port): Implement nicer UI.
// Using CoreFoundation to do this dialog is unimaginably lame but will do
// until the UI is redone.
scoped_cftyperef<CFStringRef> product_name(
@@ -53,13 +58,15 @@ bool ExtensionInstallUI::ConfirmInstall(Extension* extension) {
"This is a temporary message and it will be removed when "
"extensions UI is finalized."),
NULL, CFSTR("Cancel"), NULL, &response)) {
- return false;
+ installer->AbortInstall();
+ } else {
+ installer->ContinueInstall();
}
#else
+ // TODO(port): Implement some UI.
NOTREACHED();
+ installer->ContinueInstall();
#endif // OS_*
-
- return true;
}
void ExtensionInstallUI::OnInstallSuccess(Extension* extension) {
diff --git a/chrome/browser/extensions/extension_install_ui.h b/chrome/browser/extensions/extension_install_ui.h
index 1fc0379..9cdc5ac 100644
--- a/chrome/browser/extensions/extension_install_ui.h
+++ b/chrome/browser/extensions/extension_install_ui.h
@@ -16,16 +16,20 @@ class Profile;
class SandboxedExtensionUnpacker;
// Displays all the UI around extension installation.
-//
-// TODO(aa): This will become a view and move to browser/views/extensions in the
-// future.
class ExtensionInstallUI : public CrxInstallerClient {
public:
+ // NOTE: The implementation of this is platform-specific.
+ static void ShowExtensionInstallPrompt(Profile* profile,
+ CrxInstaller* installer,
+ Extension* extension,
+ SkBitmap* install_icon);
+
ExtensionInstallUI(Profile* profile);
private:
// CrxInstallerClient
- virtual bool ConfirmInstall(Extension* extension);
+ virtual void ConfirmInstall(CrxInstaller* installer, Extension* extension,
+ SkBitmap* icon);
virtual void OnInstallSuccess(Extension* extension);
virtual void OnInstallFailure(const std::string& error);
virtual void OnOverinstallAttempted(Extension* extension);
diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc
index 08a99a4..7b4d061 100644
--- a/chrome/browser/extensions/extension_prefs.cc
+++ b/chrome/browser/extensions/extension_prefs.cc
@@ -213,7 +213,7 @@ void ExtensionPrefs::OnExtensionInstalled(Extension* extension) {
FilePath::StringType path = MakePathRelative(install_directory_,
extension->path(), NULL);
UpdateExtensionPref(id, kPrefPath, Value::CreateStringValue(path));
- prefs_->ScheduleSavePersistentPrefs();
+ prefs_->SavePersistentPrefs();
}
void ExtensionPrefs::OnExtensionUninstalled(const Extension* extension,
diff --git a/chrome/browser/extensions/sandboxed_extension_unpacker.cc b/chrome/browser/extensions/sandboxed_extension_unpacker.cc
index 46a8382..c736f39 100644
--- a/chrome/browser/extensions/sandboxed_extension_unpacker.cc
+++ b/chrome/browser/extensions/sandboxed_extension_unpacker.cc
@@ -119,6 +119,13 @@ void SandboxedExtensionUnpacker::OnUnpackExtensionSucceeded(
// originals are gone for good.
extension_.reset(new Extension);
std::string manifest_error;
+
+ // Update the path to refer to the temporary location. We do this because
+ // clients may want to use resources inside the extension before it is
+ // installed and they need the correct path. For example, the install UI shows
+ // one of the icons from the extension.
+ extension_->set_path(extension_root_);
+
if (!extension_->InitFromValue(*final_manifest, true, // require id
&manifest_error)) {
ReportFailure(std::string("Manifest is invalid: ") +
diff --git a/chrome/browser/extensions/theme_preview_infobar_delegate.cc b/chrome/browser/extensions/theme_preview_infobar_delegate.cc
index d22ebda..a1a179f 100644
--- a/chrome/browser/extensions/theme_preview_infobar_delegate.cc
+++ b/chrome/browser/extensions/theme_preview_infobar_delegate.cc
@@ -21,7 +21,7 @@ void ThemePreviewInfobarDelegate::InfoBarClosed() {
}
std::wstring ThemePreviewInfobarDelegate::GetMessageText() const {
- return l10n_util::GetStringF(IDS_THEME_PREVIEW_INFOBAR_LABEL,
+ return l10n_util::GetStringF(IDS_THEME_INSTALL_INFOBAR_LABEL,
UTF8ToWide(name_));
}
@@ -44,7 +44,7 @@ std::wstring ThemePreviewInfobarDelegate::GetButtonLabel(
ConfirmInfoBarDelegate::InfoBarButton button) const {
switch (button) {
case BUTTON_CANCEL:
- return l10n_util::GetString(IDS_THEME_PREVIEW_INFOBAR_UNDO_BUTTON);
+ return l10n_util::GetString(IDS_THEME_INSTALL_INFOBAR_UNDO_BUTTON);
default:
return L"";
}
diff --git a/chrome/browser/extensions/theme_preview_infobar_delegate.h b/chrome/browser/extensions/theme_preview_infobar_delegate.h
index 54a8507..dcc34b6 100644
--- a/chrome/browser/extensions/theme_preview_infobar_delegate.h
+++ b/chrome/browser/extensions/theme_preview_infobar_delegate.h
@@ -14,6 +14,9 @@ class TabContents;
// When a user installs a theme, we display it immediately, but provide an
// infobar allowing them to cancel.
+//
+// TODO(aa): Rename this to ThemeInstalledInfoBarDelegate, since it isn't
+// used for previewing anymore.
class ThemePreviewInfobarDelegate : public ConfirmInfoBarDelegate {
public:
ThemePreviewInfobarDelegate(TabContents* tab_contents,