summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-19 13:56:25 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-19 13:56:25 +0000
commit7c6877dea4bdbc7bd434ea9c96795529e466903c (patch)
treed7ac3fa32188710955166e416c6bd632759fcf10 /chrome/browser/extensions
parent5b3986e89eca4e3045dde25635e270f6ea5d2961 (diff)
downloadchromium_src-7c6877dea4bdbc7bd434ea9c96795529e466903c.zip
chromium_src-7c6877dea4bdbc7bd434ea9c96795529e466903c.tar.gz
chromium_src-7c6877dea4bdbc7bd434ea9c96795529e466903c.tar.bz2
Display an infobar alert when extension process crashes.
Also correctly handle crashes in task manager. The infobar allows user to restart the extension process. TEST=Install buildbot extension, see its content in the shelf. Open task manager, kill extension process. Click "restart" in the infobar that should appear. The extension content in the shelf should re-appear after the crash. http://crbug.com/14111 Review URL: http://codereview.chromium.org/126289 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18809 0039d316-1c4b-4281-b951-d872f2087c98
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_;