[email protected] | 8643e6d | 2012-01-18 20:26:10 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 79b1896 | 2012-03-06 06:16:15 | [diff] [blame] | 5 | #include "chrome/browser/ui/sad_tab_helper.h" |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 6 | |
[email protected] | c47317e | 2012-06-20 22:35:31 | [diff] [blame] | 7 | #include "base/logging.h" |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 8 | #include "chrome/browser/browser_shutdown.h" |
[email protected] | a506c5f | 2012-07-10 13:09:06 | [diff] [blame] | 9 | #include "chrome/browser/ui/sad_tab_types.h" |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 10 | #include "content/public/browser/notification_source.h" |
| 11 | #include "content/public/browser/notification_types.h" |
[email protected] | 83ff91c | 2012-01-05 20:54:13 | [diff] [blame] | 12 | #include "content/public/browser/web_contents.h" |
[email protected] | 8643e6d | 2012-01-18 20:26:10 | [diff] [blame] | 13 | #include "content/public/browser/web_contents_view.h" |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 14 | |
| 15 | #if defined(OS_MACOSX) |
| 16 | #include "chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h" |
| 17 | #elif defined(TOOLKIT_VIEWS) |
| 18 | #include "chrome/browser/ui/views/sad_tab_view.h" |
[email protected] | 79b1896 | 2012-03-06 06:16:15 | [diff] [blame] | 19 | #include "ui/views/widget/widget.h" |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 20 | #elif defined(TOOLKIT_GTK) |
[email protected] | 2fdcef1 | 2012-03-05 22:12:24 | [diff] [blame] | 21 | #include <gtk/gtk.h> |
| 22 | |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 23 | #include "chrome/browser/ui/gtk/sad_tab_gtk.h" |
| 24 | #endif |
| 25 | |
[email protected] | ad4c6ff | 2012-09-28 17:10:05 | [diff] [blame] | 26 | DEFINE_WEB_CONTENTS_USER_DATA_KEY(SadTabHelper) |
[email protected] | e81f50d | 2012-09-19 18:42:38 | [diff] [blame] | 27 | |
[email protected] | a506c5f | 2012-07-10 13:09:06 | [diff] [blame] | 28 | SadTabHelper::SadTabHelper(content::WebContents* web_contents) |
[email protected] | 83ff91c | 2012-01-05 20:54:13 | [diff] [blame] | 29 | : content::WebContentsObserver(web_contents) { |
[email protected] | ef9572e | 2012-01-04 22:14:12 | [diff] [blame] | 30 | registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED, |
[email protected] | a506c5f | 2012-07-10 13:09:06 | [diff] [blame] | 31 | content::Source<content::WebContents>(web_contents)); |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 32 | } |
| 33 | |
[email protected] | 79b1896 | 2012-03-06 06:16:15 | [diff] [blame] | 34 | SadTabHelper::~SadTabHelper() { |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 35 | } |
| 36 | |
[email protected] | a506c5f | 2012-07-10 13:09:06 | [diff] [blame] | 37 | bool SadTabHelper::HasSadTab() const { |
| 38 | return sad_tab_.get() != NULL; |
| 39 | } |
| 40 | |
[email protected] | 79b1896 | 2012-03-06 06:16:15 | [diff] [blame] | 41 | void SadTabHelper::RenderViewGone(base::TerminationStatus status) { |
[email protected] | 3dfa7f3c | 2012-04-18 18:01:32 | [diff] [blame] | 42 | // Only show the sad tab if we're not in browser shutdown, so that WebContents |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 43 | // objects that are not in a browser (e.g., HTML dialogs) and thus are |
| 44 | // visible do not flash a sad tab page. |
| 45 | if (browser_shutdown::GetShutdownType() != browser_shutdown::NOT_VALID) |
| 46 | return; |
| 47 | |
| 48 | if (HasSadTab()) |
| 49 | return; |
| 50 | |
[email protected] | caf7c8f8 | 2012-10-18 23:53:58 | [diff] [blame] | 51 | if (status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION || |
| 52 | status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED || |
| 53 | status == base::TERMINATION_STATUS_PROCESS_CRASHED) |
| 54 | InstallSadTab(status); |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 55 | } |
| 56 | |
[email protected] | 79b1896 | 2012-03-06 06:16:15 | [diff] [blame] | 57 | void SadTabHelper::Observe(int type, |
| 58 | const content::NotificationSource& source, |
| 59 | const content::NotificationDetails& details) { |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 60 | switch (type) { |
[email protected] | ef9572e | 2012-01-04 22:14:12 | [diff] [blame] | 61 | case content::NOTIFICATION_WEB_CONTENTS_CONNECTED: |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 62 | if (HasSadTab()) { |
[email protected] | 2fdcef1 | 2012-03-05 22:12:24 | [diff] [blame] | 63 | #if defined(OS_MACOSX) |
| 64 | sad_tab_controller_mac::RemoveSadTab(sad_tab_.get()); |
| 65 | #elif defined(TOOLKIT_VIEWS) |
[email protected] | 79b1896 | 2012-03-06 06:16:15 | [diff] [blame] | 66 | sad_tab_->Close(); |
[email protected] | 020add4c | 2012-03-20 15:23:47 | [diff] [blame] | 67 | // See http://crbug.com/117668. When the Widget is being destructed, we |
| 68 | // want calls to sad_tab() to return NULL. |
| 69 | scoped_ptr<views::Widget> local_sad_tab; |
| 70 | local_sad_tab.swap(sad_tab_); |
[email protected] | 2fdcef1 | 2012-03-05 22:12:24 | [diff] [blame] | 71 | #elif defined(TOOLKIT_GTK) |
[email protected] | b137c12 | 2012-11-20 00:12:00 | [diff] [blame^] | 72 | sad_tab_->Close(); |
[email protected] | 2fdcef1 | 2012-03-05 22:12:24 | [diff] [blame] | 73 | #else |
| 74 | #error Unknown platform |
| 75 | #endif |
| 76 | sad_tab_.reset(); |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 77 | } |
| 78 | break; |
| 79 | |
| 80 | default: |
| 81 | NOTREACHED() << "Got a notification we didn't register for."; |
| 82 | } |
| 83 | } |
| 84 | |
[email protected] | 79b1896 | 2012-03-06 06:16:15 | [diff] [blame] | 85 | void SadTabHelper::InstallSadTab(base::TerminationStatus status) { |
[email protected] | a506c5f | 2012-07-10 13:09:06 | [diff] [blame] | 86 | #if defined(TOOLKIT_VIEWS) || defined(TOOLKIT_GTK) |
| 87 | chrome::SadTabKind kind = |
| 88 | (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) ? |
| 89 | chrome::SAD_TAB_KIND_KILLED : chrome::SAD_TAB_KIND_CRASHED; |
| 90 | #endif |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 91 | #if defined(OS_MACOSX) |
| 92 | sad_tab_.reset( |
[email protected] | c85864d | 2011-12-26 21:18:26 | [diff] [blame] | 93 | sad_tab_controller_mac::CreateSadTabController(web_contents())); |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 94 | #elif defined(TOOLKIT_VIEWS) |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 95 | views::Widget::InitParams sad_tab_params( |
| 96 | views::Widget::InitParams::TYPE_CONTROL); |
[email protected] | 6f1e873 | 2011-12-06 06:27:47 | [diff] [blame] | 97 | // It is not possible to create a native_widget_win that has no parent in |
| 98 | // and later re-parent it. |
| 99 | // TODO(avi): This is a cheat. Can this be made cleaner? |
[email protected] | 9ad527c | 2012-03-07 16:39:34 | [diff] [blame] | 100 | sad_tab_params.parent = web_contents()->GetView()->GetNativeView(); |
[email protected] | b4c1725e | 2012-04-11 21:03:40 | [diff] [blame] | 101 | #if defined(OS_WIN) && !defined(USE_AURA) |
| 102 | // Crash data indicates we can get here when the parent is no longer valid. |
| 103 | // Attempting to create a child window with a bogus parent crashes. So, we |
| 104 | // don't show a sad tab in this case in hopes the tab is in the process of |
| 105 | // shutting down. |
| 106 | if (!IsWindow(sad_tab_params.parent)) |
| 107 | return; |
| 108 | #endif |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 109 | sad_tab_params.ownership = |
| 110 | views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 111 | sad_tab_.reset(new views::Widget); |
| 112 | sad_tab_->Init(sad_tab_params); |
[email protected] | 768c547 | 2011-12-26 19:06:17 | [diff] [blame] | 113 | sad_tab_->SetContentsView(new SadTabView(web_contents(), kind)); |
[email protected] | 79b1896 | 2012-03-06 06:16:15 | [diff] [blame] | 114 | |
| 115 | views::Widget::ReparentNativeView( |
| 116 | sad_tab_->GetNativeView(), web_contents()->GetView()->GetNativeView()); |
| 117 | gfx::Rect bounds; |
| 118 | web_contents()->GetView()->GetContainerBounds(&bounds); |
| 119 | sad_tab_->SetBounds(gfx::Rect(bounds.size())); |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 120 | #elif defined(TOOLKIT_GTK) |
[email protected] | a506c5f | 2012-07-10 13:09:06 | [diff] [blame] | 121 | sad_tab_.reset(new SadTabGtk(web_contents(), kind)); |
[email protected] | b137c12 | 2012-11-20 00:12:00 | [diff] [blame^] | 122 | sad_tab_->Show(); |
[email protected] | 9cddb1a2 | 2011-11-15 15:04:27 | [diff] [blame] | 123 | #else |
| 124 | #error Unknown platform |
| 125 | #endif |
| 126 | } |