summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r--chrome/browser/extensions/extension_host.cc73
-rw-r--r--chrome/browser/extensions/extension_host.h8
-rw-r--r--chrome/browser/extensions/extension_process_manager.cc14
-rw-r--r--chrome/browser/extensions/extension_process_manager.h6
-rw-r--r--chrome/browser/extensions/extension_view.cc76
-rw-r--r--chrome/browser/extensions/extension_view.h11
6 files changed, 158 insertions, 30 deletions
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index aebf7cf..b993f73 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -4,7 +4,9 @@
#include "chrome/browser/extensions/extension_host.h"
+#include "app/l10n_util.h"
#include "app/resource_bundle.h"
+#include "base/string_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
@@ -16,6 +18,7 @@
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
#include "chrome/browser/tab_contents/site_instance.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
@@ -25,9 +28,55 @@
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
#include "webkit/glue/context_menu.h"
+namespace {
+
+class CrashedExtensionInfobarDelegate : public ConfirmInfoBarDelegate {
+ public:
+ CrashedExtensionInfobarDelegate(TabContents* tab_contents,
+ ExtensionHost* extension_host)
+ : ConfirmInfoBarDelegate(tab_contents),
+ extension_host_(extension_host) {
+ }
+
+ virtual std::wstring GetMessageText() const {
+ return l10n_util::GetStringF(IDS_EXTENSION_CRASHED_INFOBAR_MESSAGE,
+ UTF8ToWide(extension_host_->extension()->name()));
+ }
+
+ virtual SkBitmap* GetIcon() const {
+ // TODO(erikkay): Create extension-specific icon. http://crbug.com/14591
+ return ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_INFOBAR_PLUGIN_CRASHED);
+ }
+
+ virtual int GetButtons() const {
+ return BUTTON_OK;
+ }
+
+ virtual std::wstring GetButtonLabel(
+ ConfirmInfoBarDelegate::InfoBarButton button) const {
+ if (button == BUTTON_OK)
+ return l10n_util::GetString(IDS_EXTENSION_CRASHED_INFOBAR_RESTART_BUTTON);
+ return ConfirmInfoBarDelegate::GetButtonLabel(button);
+ }
+
+ virtual bool Accept() {
+ extension_host_->RecoverCrashedExtension();
+ return true;
+ }
+
+ private:
+ ExtensionHost* extension_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(CrashedExtensionInfobarDelegate);
+};
+
+} // namespace
+
ExtensionHost::ExtensionHost(Extension* extension, SiteInstance* site_instance,
const GURL& url, ExtensionProcessManager* manager)
: extension_(extension),
@@ -65,12 +114,25 @@ SiteInstance* ExtensionHost::site_instance() const {
return render_view_host_->site_instance();
}
+bool ExtensionHost::IsRenderViewLive() const {
+ return render_view_host_->IsRenderViewLive();
+}
+
void ExtensionHost::CreateRenderView(RenderWidgetHostView* host_view) {
render_view_host_->set_view(host_view);
render_view_host_->CreateRenderView();
render_view_host_->NavigateToURL(url_);
}
+void ExtensionHost::RecoverCrashedExtension() {
+ DCHECK(!IsRenderViewLive());
+#if defined(TOOLKIT_VIEWS)
+ view_->RecoverCrashedExtension();
+#endif
+ if (IsRenderViewLive())
+ manager_->OnExtensionProcessRestored(this);
+}
+
void ExtensionHost::UpdatePreferredWidth(int pref_width) {
#if defined(OS_WIN)
if (view_.get())
@@ -78,6 +140,17 @@ void ExtensionHost::UpdatePreferredWidth(int pref_width) {
#endif
}
+void ExtensionHost::RenderViewGone(RenderViewHost* render_view_host) {
+ DCHECK_EQ(render_view_host_, render_view_host);
+ TabContents* current_tab = GetBrowser()->GetSelectedTabContents();
+ DCHECK(current_tab);
+ if (current_tab) {
+ current_tab->AddInfoBar(
+ new CrashedExtensionInfobarDelegate(current_tab, this));
+ }
+ manager_->OnExtensionProcessCrashed(this);
+}
+
WebPreferences ExtensionHost::GetWebkitPrefs() {
PrefService* prefs = render_view_host()->process()->profile()->GetPrefs();
const bool kIsDomUI = true;
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index 4634723..f54f4fc 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -49,13 +49,21 @@ class ExtensionHost : public RenderViewHostDelegate,
SiteInstance* site_instance() const;
bool did_stop_loading() const { return did_stop_loading_; }
+ // Returns true if the render view is initialized and didn't crash.
+ bool IsRenderViewLive() const;
+
// Initializes our RenderViewHost by creating its RenderView and navigating
// to this host's url. Uses host_view for the RenderViewHost's view (can be
// NULL).
void CreateRenderView(RenderWidgetHostView* host_view);
+ // Restarts extension's renderer process. Can be called only if the renderer
+ // process crashed.
+ void RecoverCrashedExtension();
+
// RenderViewHostDelegate
virtual const GURL& GetURL() const { return url_; }
+ virtual void RenderViewGone(RenderViewHost* render_view_host);
virtual WebPreferences GetWebkitPrefs();
virtual void RunJavaScriptMessage(
const std::wstring& message,
diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc
index a4f2df7..774d3a9e 100644
--- a/chrome/browser/extensions/extension_process_manager.cc
+++ b/chrome/browser/extensions/extension_process_manager.cc
@@ -120,6 +120,20 @@ void ExtensionProcessManager::OnExtensionHostDestroyed(ExtensionHost* host) {
Details<ExtensionHost>(host));
}
+void ExtensionProcessManager::OnExtensionProcessCrashed(ExtensionHost* host) {
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_PROCESS_CRASHED,
+ Source<ExtensionProcessManager>(this),
+ Details<ExtensionHost>(host));
+}
+
+void ExtensionProcessManager::OnExtensionProcessRestored(ExtensionHost* host) {
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_PROCESS_RESTORED,
+ Source<ExtensionProcessManager>(this),
+ Details<ExtensionHost>(host));
+}
+
void ExtensionProcessManager::OnExtensionHostCreated(ExtensionHost* host,
bool is_background) {
all_hosts_.insert(host);
diff --git a/chrome/browser/extensions/extension_process_manager.h b/chrome/browser/extensions/extension_process_manager.h
index 9cd861c..a5c6296 100644
--- a/chrome/browser/extensions/extension_process_manager.h
+++ b/chrome/browser/extensions/extension_process_manager.h
@@ -57,6 +57,12 @@ class ExtensionProcessManager : public NotificationObserver {
// from our lists.
void OnExtensionHostDestroyed(ExtensionHost* host);
+ // Called after an extension render process crashes.
+ void OnExtensionProcessCrashed(ExtensionHost* host);
+
+ // Called after an extension process successfully restarts after crash.
+ void OnExtensionProcessRestored(ExtensionHost* host);
+
private:
// Called just after |host| is created so it can be registered in our lists.
void OnExtensionHostCreated(ExtensionHost* host, bool is_background);
diff --git a/chrome/browser/extensions/extension_view.cc b/chrome/browser/extensions/extension_view.cc
index a375c04..7a8be62 100644
--- a/chrome/browser/extensions/extension_view.cc
+++ b/chrome/browser/extensions/extension_view.cc
@@ -19,8 +19,7 @@ ExtensionView::ExtensionView(ExtensionHost* host, Browser* browser)
}
ExtensionView::~ExtensionView() {
- if (native_view())
- Detach();
+ CleanUp();
}
Extension* ExtensionView::extension() const {
@@ -56,6 +55,37 @@ void ExtensionView::DidChangeBounds(const gfx::Rect& previous,
render_view_host()->view()->SetSize(gfx::Size(width(), height()));
}
+void ExtensionView::CreateWidgetHostView() {
+ DCHECK(!initialized_);
+ initialized_ = true;
+ RenderWidgetHostView* view =
+ RenderWidgetHostView::CreateViewForWidget(render_view_host());
+
+ // TODO(mpcomplete): RWHV needs a cross-platform Init function.
+#if defined(OS_WIN)
+ // Create the HWND. Note:
+ // RenderWidgetHostHWND supports windowed plugins, but if we ever also
+ // wanted to support constrained windows with this, we would need an
+ // additional HWND to parent off of because windowed plugin HWNDs cannot
+ // exist in the same z-order as constrained windows.
+ RenderWidgetHostViewWin* view_win =
+ static_cast<RenderWidgetHostViewWin*>(view);
+ HWND hwnd = view_win->Create(GetWidget()->GetNativeView());
+ view_win->ShowWindow(SW_SHOW);
+ Attach(hwnd);
+#else
+ NOTIMPLEMENTED();
+#endif
+
+ host_->CreateRenderView(view);
+ SetVisible(false);
+
+ if (!pending_background_.empty()) {
+ render_view_host()->view()->SetBackground(pending_background_);
+ pending_background_.reset();
+ }
+}
+
void ExtensionView::ShowIfCompletelyLoaded() {
// We wait to show the ExtensionView until it has loaded and our parent has
// given us a background. These can happen in different orders.
@@ -66,6 +96,14 @@ void ExtensionView::ShowIfCompletelyLoaded() {
}
}
+void ExtensionView::CleanUp() {
+ if (!initialized_)
+ return;
+ if (native_view())
+ Detach();
+ initialized_ = false;
+}
+
void ExtensionView::SetBackground(const SkBitmap& background) {
if (initialized_ && render_view_host()->view()) {
render_view_host()->view()->SetBackground(background);
@@ -89,35 +127,13 @@ void ExtensionView::ViewHierarchyChanged(bool is_add,
views::View *parent,
views::View *child) {
NativeViewHost::ViewHierarchyChanged(is_add, parent, child);
- if (is_add && GetWidget() && !initialized_) {
- initialized_ = true;
- RenderWidgetHostView* view =
- RenderWidgetHostView::CreateViewForWidget(render_view_host());
-
- // TODO(mpcomplete): RWHV needs a cross-platform Init function.
-#if defined(OS_WIN)
- // Create the HWND. Note:
- // RenderWidgetHostHWND supports windowed plugins, but if we ever also
- // wanted to support constrained windows with this, we would need an
- // additional HWND to parent off of because windowed plugin HWNDs cannot
- // exist in the same z-order as constrained windows.
- RenderWidgetHostViewWin* view_win =
- static_cast<RenderWidgetHostViewWin*>(view);
- HWND hwnd = view_win->Create(GetWidget()->GetNativeView());
- view_win->ShowWindow(SW_SHOW);
- Attach(hwnd);
-#else
- NOTIMPLEMENTED();
-#endif
-
- host_->CreateRenderView(view);
- SetVisible(false);
+ if (is_add && GetWidget() && !initialized_)
+ CreateWidgetHostView();
+}
- if (!pending_background_.empty()) {
- render_view_host()->view()->SetBackground(pending_background_);
- pending_background_.reset();
- }
- }
+void ExtensionView::RecoverCrashedExtension() {
+ CleanUp();
+ CreateWidgetHostView();
}
void ExtensionView::HandleMouseEvent() {
diff --git a/chrome/browser/extensions/extension_view.h b/chrome/browser/extensions/extension_view.h
index cf2fc40..1904db2 100644
--- a/chrome/browser/extensions/extension_view.h
+++ b/chrome/browser/extensions/extension_view.h
@@ -56,12 +56,23 @@ class ExtensionView : public views::NativeViewHost {
virtual void ViewHierarchyChanged(bool is_add,
views::View *parent, views::View *child);
+ // Call after extension process crash to re-initialize view, so that
+ // extension content can be rendered again.
+ void RecoverCrashedExtension();
+
private:
friend class ExtensionHost;
+ // Initializes the RenderWidgetHostView for this object.
+ void CreateWidgetHostView();
+
// We wait to show the ExtensionView until several things have loaded.
void ShowIfCompletelyLoaded();
+ // Restore object to initial state. Called on shutdown or after a renderer
+ // crash.
+ void CleanUp();
+
// The running extension instance that we're displaying.
// Note that host_ owns view
ExtensionHost* host_;