summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-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
-rw-r--r--chrome/browser/views/extensions/extension_install_prompt.cc194
-rw-r--r--chrome/browser/views/location_bar_view.cc10
11 files changed, 339 insertions, 39 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,
diff --git a/chrome/browser/views/extensions/extension_install_prompt.cc b/chrome/browser/views/extensions/extension_install_prompt.cc
new file mode 100644
index 0000000..e110464
--- /dev/null
+++ b/chrome/browser/views/extensions/extension_install_prompt.cc
@@ -0,0 +1,194 @@
+// 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.
+
+#include "app/l10n_util.h"
+#include "base/file_util.h"
+#include "base/rand_util.h"
+#include "base/string_util.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/extensions/extension_install_ui.h"
+#include "chrome/common/extensions/extension.h"
+#include "grit/generated_resources.h"
+#include "views/controls/image_view.h"
+#include "views/controls/label.h"
+#include "views/controls/link.h"
+#include "views/standard_layout.h"
+#include "views/view.h"
+#include "views/window/dialog_delegate.h"
+#include "views/window/window.h"
+
+class Profile;
+
+namespace {
+
+const int kRightColumnWidth = 290;
+
+// Implements the extension installation prompt for Windows.
+// TODO(aa): It would be cool to add an "extensions threat level" when we have
+// granular permissions implemented:
+// - red: npapi
+// - orange: access to any domains
+// - yellow: access to browser data
+// - green: nothing
+// We could have a collection of funny descriptions for each color.
+class InstallDialogContent : public views::View, public views::DialogDelegate {
+ public:
+ InstallDialogContent(CrxInstaller* crx_installer, Extension* extension,
+ SkBitmap* icon)
+ : crx_installer_(crx_installer), icon_(NULL) {
+ if (icon) {
+ icon_ = new views::ImageView();
+ icon_->SetImage(*icon);
+ AddChildView(icon_);
+ }
+
+ heading_ = new views::Label(
+ l10n_util::GetStringF(IDS_EXTENSION_PROMPT_HEADING,
+ UTF8ToWide(extension->name())));
+ heading_->SetFont(heading_->GetFont().DeriveFont(1, gfx::Font::BOLD));
+ heading_->SetMultiLine(true);
+ heading_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ AddChildView(heading_);
+
+ // Pick a random warning.
+ std::wstring warnings[] = {
+ l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_1),
+ l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_2),
+ l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_3)
+ };
+ warning_ = new views::Label(
+ warnings[base::RandInt(0, arraysize(warnings) - 1)]);
+ warning_->SetMultiLine(true);
+ warning_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ AddChildView(warning_);
+
+ severe_ = new views::Label(
+ l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_SEVERE));
+ severe_->SetMultiLine(true);
+ severe_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ severe_->SetFont(heading_->GetFont().DeriveFont(0, gfx::Font::BOLD));
+ severe_->SetColor(SK_ColorRED);
+ AddChildView(severe_);
+ }
+
+ private:
+ // DialogDelegate
+ virtual std::wstring GetDialogButtonLabel(
+ MessageBoxFlags::DialogButton button) const {
+ switch (button) {
+ case MessageBoxFlags::DIALOGBUTTON_OK:
+ return l10n_util::GetString(IDS_EXTENSION_PROMPT_INSTALL_BUTTON);
+ case MessageBoxFlags::DIALOGBUTTON_CANCEL:
+ return l10n_util::GetString(IDS_EXTENSION_PROMPT_CANCEL_BUTTON);
+ default:
+ NOTREACHED();
+ return L"";
+ }
+ }
+
+ virtual int GetDefaultDialogButton() const {
+ return MessageBoxFlags::DIALOGBUTTON_CANCEL;
+ }
+
+ virtual bool Accept() {
+ crx_installer_->ContinueInstall();
+ return true;
+ }
+
+ virtual bool Cancel() {
+ crx_installer_->AbortInstall();
+ return true;
+ }
+
+
+ // WindowDelegate
+ virtual bool IsModal() const { return true; }
+ virtual std::wstring GetWindowTitle() const {
+ return l10n_util::GetString(IDS_EXTENSION_PROMPT_TITLE);
+ }
+ virtual views::View* GetContentsView() { return this; }
+
+ // View
+ virtual gfx::Size GetPreferredSize() {
+ int width = kRightColumnWidth + kPanelHorizMargin + kPanelHorizMargin;
+
+ if (icon_) {
+ width += Extension::EXTENSION_ICON_LARGE;
+ width += kPanelHorizMargin;
+ }
+
+ int height = kPanelVertMargin * 2;
+ height += heading_->GetHeightForWidth(kRightColumnWidth);
+ height += kPanelVertMargin;
+ height += warning_->GetHeightForWidth(kRightColumnWidth);
+ height += kPanelVertMargin;
+ height += severe_->GetHeightForWidth(kRightColumnWidth);
+ height += kPanelVertMargin;
+
+ return gfx::Size(width, std::max(height,
+ static_cast<int>(Extension::EXTENSION_ICON_LARGE)));
+ }
+
+ virtual void Layout() {
+ int x = kPanelHorizMargin;
+ int y = kPanelVertMargin;
+
+ if (icon_) {
+ icon_->SetBounds(x, y, Extension::EXTENSION_ICON_LARGE,
+ Extension::EXTENSION_ICON_LARGE);
+ x += Extension::EXTENSION_ICON_LARGE;
+ x += kPanelHorizMargin;
+ }
+
+ heading_->SizeToFit(kRightColumnWidth);
+ heading_->SetX(x);
+ heading_->SetY(y);
+ y += heading_->height();
+
+ y += kPanelVertMargin;
+
+ warning_->SizeToFit(kRightColumnWidth);
+ warning_->SetX(x);
+ warning_->SetY(y);
+ y += warning_->height();
+
+ y += kPanelVertMargin;
+
+ severe_->SizeToFit(kRightColumnWidth);
+ severe_->SetX(x);
+ severe_->SetY(y);
+ y += severe_->height();
+ }
+
+ scoped_refptr<CrxInstaller> crx_installer_;
+ views::ImageView* icon_;
+ views::Label* heading_;
+ views::Label* warning_;
+ views::Label* severe_;
+
+ DISALLOW_COPY_AND_ASSIGN(InstallDialogContent);
+};
+
+} // namespace
+
+void ExtensionInstallUI::ShowExtensionInstallPrompt(Profile* profile,
+ CrxInstaller* crx_installer,
+ Extension* extension,
+ SkBitmap* icon) {
+ Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
+ if (!browser) {
+ crx_installer->AbortInstall();
+ return;
+ }
+
+ BrowserWindow* window = browser->window();
+ if (!window) {
+ crx_installer->AbortInstall();
+ return;
+ }
+
+ views::Window::CreateChromeWindow(window->GetNativeHandle(), gfx::Rect(),
+ new InstallDialogContent(crx_installer, extension, icon))->Show();
+}
diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc
index 674cdb6..bed40dc 100644
--- a/chrome/browser/views/location_bar_view.cc
+++ b/chrome/browser/views/location_bar_view.cc
@@ -1263,18 +1263,22 @@ LocationBarView::PageActionImageView::PageActionImageView(
page_action_(page_action),
current_tab_id_(-1),
tooltip_(page_action_->name()) {
+ Extension* extension = profile->GetExtensionsService()->GetExtensionById(
+ page_action->extension_id());
+ DCHECK(extension);
+
// Load the images this view needs asynchronously on the file thread. We'll
// get a call back into OnImageLoaded if the image loads successfully. If not,
// the ImageView will have no image and will not appear in the Omnibox.
DCHECK(!page_action->icon_paths().empty());
- const std::vector<FilePath>& icon_paths = page_action->icon_paths();
+ const std::vector<std::string>& icon_paths = page_action->icon_paths();
page_action_icons_.resize(icon_paths.size());
int index = 0;
MessageLoop* file_loop = g_browser_process->file_thread()->message_loop();
tracker_ = new ImageLoadingTracker(this, icon_paths.size());
- for (std::vector<FilePath>::const_iterator iter = icon_paths.begin();
+ for (std::vector<std::string>::const_iterator iter = icon_paths.begin();
iter != icon_paths.end(); ++iter) {
- FilePath path = *iter;
+ FilePath path = extension->GetResourcePath(*iter);
file_loop->PostTask(FROM_HERE, new LoadImageTask(tracker_, path, index++));
}
}