diff options
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r-- | chrome/browser/extensions/extension_host.cc | 73 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_host.h | 8 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_process_manager.cc | 14 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_process_manager.h | 6 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_view.cc | 76 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_view.h | 11 |
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_; |