Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Side by Side Diff: chrome/browser/printing/print_preview_tab_controller.cc

Issue 7550063: Print Preview: Handle a crashed initiator tab by showing a message in PP. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/printing/print_preview_tab_controller.h" 5 #include "chrome/browser/printing/print_preview_tab_controller.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "chrome/browser/browser_process.h" 8 #include "chrome/browser/browser_process.h"
9 #include "chrome/browser/profiles/profile.h" 9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/sessions/restore_tab_helper.h" 10 #include "chrome/browser/sessions/restore_tab_helper.h"
11 #include "chrome/browser/tabs/tab_strip_model.h" 11 #include "chrome/browser/tabs/tab_strip_model.h"
12 #include "chrome/browser/ui/browser.h" 12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_list.h" 13 #include "chrome/browser/ui/browser_list.h"
14 #include "chrome/browser/ui/browser_navigator.h" 14 #include "chrome/browser/ui/browser_navigator.h"
15 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 15 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
16 #include "chrome/browser/ui/webui/print_preview_ui.h" 16 #include "chrome/browser/ui/webui/print_preview_ui.h"
17 #include "chrome/common/chrome_switches.h" 17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/common/url_constants.h" 18 #include "chrome/common/url_constants.h"
19 #include "content/browser/renderer_host/render_view_host.h"
19 #include "content/browser/tab_contents/navigation_details.h" 20 #include "content/browser/tab_contents/navigation_details.h"
20 #include "content/browser/tab_contents/tab_contents.h" 21 #include "content/browser/tab_contents/tab_contents.h"
22 #include "content/common/content_notification_types.h"
21 #include "content/common/notification_details.h" 23 #include "content/common/notification_details.h"
22 #include "content/common/notification_source.h" 24 #include "content/common/notification_source.h"
23 25
24 namespace printing { 26 namespace printing {
25 27
26 PrintPreviewTabController::PrintPreviewTabController() 28 PrintPreviewTabController::PrintPreviewTabController()
27 : waiting_for_new_preview_page_(false) { 29 : waiting_for_new_preview_page_(false) {
28 } 30 }
29 31
30 PrintPreviewTabController::~PrintPreviewTabController() {} 32 PrintPreviewTabController::~PrintPreviewTabController() {}
31 33
32 // static 34 // static
33 PrintPreviewTabController* PrintPreviewTabController::GetInstance() { 35 PrintPreviewTabController* PrintPreviewTabController::GetInstance() {
34 if (!g_browser_process) 36 if (!g_browser_process)
35 return NULL; 37 return NULL;
36 return g_browser_process->print_preview_tab_controller(); 38 return g_browser_process->print_preview_tab_controller();
37 } 39 }
38 40
39 // static 41 // static
40 void PrintPreviewTabController::PrintPreview(TabContents* tab) { 42 void PrintPreviewTabController::PrintPreview(TabContents* tab) {
41 if (tab->showing_interstitial_page()) 43 if (tab->showing_interstitial_page())
42 return; 44 return;
43 45
44 printing::PrintPreviewTabController* tab_controller = 46 printing::PrintPreviewTabController* tab_controller =
45 printing::PrintPreviewTabController::GetInstance(); 47 printing::PrintPreviewTabController::GetInstance();
46 if (!tab_controller) 48 if (!tab_controller)
47 return; 49 return;
50
48 tab_controller->GetOrCreatePreviewTab(tab); 51 tab_controller->GetOrCreatePreviewTab(tab);
49 } 52 }
50 53
51 TabContents* PrintPreviewTabController::GetOrCreatePreviewTab( 54 TabContents* PrintPreviewTabController::GetOrCreatePreviewTab(
52 TabContents* initiator_tab) { 55 TabContents* initiator_tab) {
53 DCHECK(initiator_tab); 56 DCHECK(initiator_tab);
54 57
55 // Get the print preview tab for |initiator_tab|. 58 // Get the print preview tab for |initiator_tab|.
56 TabContents* preview_tab = GetPrintPreviewForTab(initiator_tab); 59 TabContents* preview_tab = GetPrintPreviewForTab(initiator_tab);
57 if (preview_tab) { 60 if (preview_tab) {
58 // Show current preview tab. 61 // Show current preview tab.
59 static_cast<RenderViewHostDelegate*>(preview_tab)->Activate(); 62 static_cast<RenderViewHostDelegate*>(preview_tab)->Activate();
60 return preview_tab; 63 return preview_tab;
61 } 64 }
65
62 return CreatePrintPreviewTab(initiator_tab); 66 return CreatePrintPreviewTab(initiator_tab);
63 } 67 }
64 68
65 TabContents* PrintPreviewTabController::GetPrintPreviewForTab( 69 TabContents* PrintPreviewTabController::GetPrintPreviewForTab(
66 TabContents* tab) const { 70 TabContents* tab) const {
71 // |preview_tab_map_| is keyed by the preview tab, so if find() succeeds, then
72 // |tab| is the preview tab.
67 PrintPreviewTabMap::const_iterator it = preview_tab_map_.find(tab); 73 PrintPreviewTabMap::const_iterator it = preview_tab_map_.find(tab);
68 if (it != preview_tab_map_.end()) 74 if (it != preview_tab_map_.end())
69 return tab; 75 return tab;
70 76
71 for (it = preview_tab_map_.begin(); it != preview_tab_map_.end(); ++it) { 77 for (it = preview_tab_map_.begin(); it != preview_tab_map_.end(); ++it) {
72 // If |tab| is an initiator tab. 78 // If |tab| is an initiator tab.
73 if (tab == it->second) { 79 if (tab == it->second) {
74 // Return the associated preview tab. 80 // Return the associated preview tab.
75 return it->first; 81 return it->first;
76 } 82 }
77 } 83 }
84
78 return NULL; 85 return NULL;
79 } 86 }
80 87
81 void PrintPreviewTabController::Observe(int type, 88 void PrintPreviewTabController::Observe(int type,
82 const NotificationSource& source, 89 const NotificationSource& source,
83 const NotificationDetails& details) { 90 const NotificationDetails& details) {
84 TabContents* source_tab = NULL;
85 content::LoadCommittedDetails* detail_info = NULL;
86
87 switch (type) { 91 switch (type) {
92 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
Lei Zhang 2011/08/09 20:51:19 If we just close a tab, do we get this notificatio
kmadhusu 2011/08/10 16:46:59 When a tab is closed, we do not get this notificat
93 OnRendererProcessClosed(Source<RenderProcessHost>(source).ptr());
94 break;
95 }
88 case content::NOTIFICATION_TAB_CONTENTS_DESTROYED: { 96 case content::NOTIFICATION_TAB_CONTENTS_DESTROYED: {
89 source_tab = Source<TabContents>(source).ptr(); 97 OnTabContentsDestroyed(Source<TabContents>(source).ptr());
90 break; 98 break;
91 } 99 }
92 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { 100 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: {
93 NavigationController* controller = 101 NavigationController* controller =
94 Source<NavigationController>(source).ptr(); 102 Source<NavigationController>(source).ptr();
95 source_tab = controller->tab_contents(); 103 content::LoadCommittedDetails* load_details =
96 detail_info = Details<content::LoadCommittedDetails>(details).ptr(); 104 Details<content::LoadCommittedDetails>(details).ptr();
105 OnNavEntryCommitted(controller->tab_contents(), load_details);
97 break; 106 break;
98 } 107 }
99 default: { 108 default: {
100 NOTREACHED(); 109 NOTREACHED();
101 break; 110 break;
102 } 111 }
103 } 112 }
113 }
114
115 void PrintPreviewTabController::OnRendererProcessClosed(
116 RenderProcessHost* rph) {
117 TabContents* initiator_tab = NULL;
118 for (PrintPreviewTabMap::iterator iter = preview_tab_map_.begin();
119 iter != preview_tab_map_.end(); ++iter) {
120 if (iter->second->render_view_host()->process() == rph) {
121 initiator_tab = iter->second;
122 break;
123 }
124 }
104 125
105 DCHECK(source_tab); 126 // The Print Preview renderer crashed.
127 if (!initiator_tab)
Lei Zhang 2011/08/09 20:51:19 In this case, do you need to call RemoveObservers(
kmadhusu 2011/08/10 16:46:59 We should not remove the observers for the preview
128 return;
106 129
107 TabContents* preview_tab = GetPrintPreviewForTab(source_tab); 130 TabContents* preview_tab = GetPrintPreviewForTab(initiator_tab);
108 bool source_tab_is_preview_tab = (source_tab == preview_tab); 131 PrintPreviewUI* print_preview_ui =
132 static_cast<PrintPreviewUI*>(preview_tab->web_ui());
133 print_preview_ui->OnInitiatorTabCrashed();
Lei Zhang 2011/08/09 20:51:19 Do you need to check |preview_tab| or |print_previ
kmadhusu 2011/08/10 16:46:59 They will be valid. If you want I can add a DCHECK
134 }
109 135
110 if (detail_info) { 136 void PrintPreviewTabController::OnTabContentsDestroyed(TabContents* tab) {
111 PageTransition::Type transition_type = 137 TabContents* preview_tab = GetPrintPreviewForTab(tab);
112 detail_info->entry->transition_type(); 138 if (!preview_tab)
113 NavigationType::Type nav_type = detail_info->type; 139 return;
140
141 if (tab == preview_tab) {
142 // Remove the initiator tab's observers before erasing the mapping.
143 TabContents* initiator_tab = GetInitiatorTab(tab);
144 if (initiator_tab)
145 RemoveObservers(initiator_tab);
146
147 // In the case where the user chooses to re-open the initiator tab after
148 // closing it, |tab| has navigated to the URL of the initiator tab at this
149 // point. Verify that |tab| really is a print preview tab.
150 if (IsPrintPreviewTab(tab) && tab->web_ui()) {
Lei Zhang 2011/08/09 20:51:19 If the print preview tab is navigating to its init
kmadhusu 2011/08/10 16:46:59 The comment is misleading. Here, the preview tab i
151 PrintPreviewUI* print_preview_ui =
152 static_cast<PrintPreviewUI*>(tab->web_ui());
153 print_preview_ui->OnNavigation();
154 }
155
156 // Erase the map entry.
157 preview_tab_map_.erase(tab);
158 } else {
159 // Initiator tab is closed. Disable the controls in preview tab.
160 if (preview_tab->web_ui()) {
161 PrintPreviewUI* print_preview_ui =
162 static_cast<PrintPreviewUI*>(preview_tab->web_ui());
163 print_preview_ui->OnInitiatorTabClosed();
164 }
165
166 // |tab| is an initiator tab, update the map entry and remove observers.
167 preview_tab_map_[preview_tab] = NULL;
168 }
169
170 RemoveObservers(tab);
171 }
172
173 void PrintPreviewTabController::OnNavEntryCommitted(
174 TabContents* tab, content::LoadCommittedDetails* details) {
175 TabContents* preview_tab = GetPrintPreviewForTab(tab);
176 bool source_tab_is_preview_tab = (tab == preview_tab);
177 if (details) {
178 PageTransition::Type transition_type = details->entry->transition_type();
179 NavigationType::Type nav_type = details->type;
114 180
115 // Don't update/erase the map entry if the page has not changed. 181 // Don't update/erase the map entry if the page has not changed.
116 if (transition_type == PageTransition::RELOAD || 182 if (transition_type == PageTransition::RELOAD ||
117 nav_type == NavigationType::SAME_PAGE) { 183 nav_type == NavigationType::SAME_PAGE) {
118 return; 184 return;
119 } 185 }
120 186
121 // New |preview_tab| is created. Don't update/erase map entry. 187 // New |preview_tab| is created. Don't update/erase map entry.
122 if (waiting_for_new_preview_page_ && 188 if (waiting_for_new_preview_page_ &&
123 transition_type == PageTransition::LINK && 189 transition_type == PageTransition::LINK &&
124 nav_type == NavigationType::NEW_PAGE && 190 nav_type == NavigationType::NEW_PAGE &&
125 source_tab_is_preview_tab) { 191 source_tab_is_preview_tab) {
126 waiting_for_new_preview_page_ = false; 192 waiting_for_new_preview_page_ = false;
193 // Set the initiator tab url.
194 TabContents* initiator_tab = GetInitiatorTab(tab);
195 if (initiator_tab) {
196 if (preview_tab->web_ui()) {
Lei Zhang 2011/08/09 20:51:19 nit: combine with the if statement above.
kmadhusu 2011/08/10 16:46:59 Done.
197 PrintPreviewUI* print_preview_ui =
198 static_cast<PrintPreviewUI*>(preview_tab->web_ui());
199 print_preview_ui->SetInitiatorTabURL(initiator_tab->GetURL().spec());
200 }
201 }
127 return; 202 return;
128 } 203 }
129 204
130 // User navigated to a preview tab using forward/back button. 205 // User navigated to a preview tab using forward/back button.
131 if (source_tab_is_preview_tab && 206 if (source_tab_is_preview_tab &&
132 transition_type == PageTransition::FORWARD_BACK && 207 transition_type == PageTransition::FORWARD_BACK &&
133 nav_type == NavigationType::EXISTING_PAGE) { 208 nav_type == NavigationType::EXISTING_PAGE) {
134 return; 209 return;
135 } 210 }
136 } 211 }
137 212
213 RemoveObservers(tab);
138 if (source_tab_is_preview_tab) { 214 if (source_tab_is_preview_tab) {
139 // Remove the initiator tab's observers before erasing the mapping. 215 // Remove the initiator tab's observers before erasing the mapping.
140 TabContents* initiator_tab = GetInitiatorTab(source_tab); 216 TabContents* initiator_tab = GetInitiatorTab(tab);
141 if (initiator_tab) 217 if (initiator_tab)
142 RemoveObservers(initiator_tab); 218 RemoveObservers(initiator_tab);
219 preview_tab_map_.erase(tab);
220 } else {
221 preview_tab_map_[preview_tab] = NULL;
143 222
144 // |source_tab_is_preview_tab| is misleading in the case where the user 223 // Initiator tab is closed. Disable the controls in preview tab.
145 // chooses to re-open the initiator tab after closing it, as |source_tab| 224 if (preview_tab->web_ui()) {
146 // has navigated to the URL of the initiator tab at this point. Make sure to
147 // verify that |source_tab| really is a print preview tab.
148 if (IsPrintPreviewTab(source_tab) && source_tab->web_ui()) {
149 PrintPreviewUI* print_preview_ui = 225 PrintPreviewUI* print_preview_ui =
150 static_cast<PrintPreviewUI*>(source_tab->web_ui()); 226 static_cast<PrintPreviewUI*>(preview_tab->web_ui());
151 print_preview_ui->OnNavigation(); 227 print_preview_ui->OnInitiatorTabClosed();
152 } 228 }
153
154 // Erase the map entry.
155 preview_tab_map_.erase(source_tab);
156 } else {
157 // Initiator tab is closed. Disable the controls in preview tab.
158 PrintPreviewUI* print_preview_ui =
159 static_cast<PrintPreviewUI*>(preview_tab->web_ui());
160 print_preview_ui->OnInitiatorTabClosed(source_tab->GetURL().spec());
161
162 // |source_tab| is an initiator tab, update the map entry.
163 preview_tab_map_[preview_tab] = NULL;
164 } 229 }
165 RemoveObservers(source_tab);
166 } 230 }
167 231
168 // static 232 // static
169 bool PrintPreviewTabController::IsPrintPreviewTab(TabContents* tab) { 233 bool PrintPreviewTabController::IsPrintPreviewTab(TabContents* tab) {
170 const GURL& url = tab->GetURL(); 234 const GURL& url = tab->GetURL();
171 return (url.SchemeIs(chrome::kChromeUIScheme) && 235 return (url.SchemeIs(chrome::kChromeUIScheme) &&
172 url.host() == chrome::kChromeUIPrintHost); 236 url.host() == chrome::kChromeUIPrintHost);
173 } 237 }
174 238
175 void PrintPreviewTabController::EraseInitiatorTabInfo( 239 void PrintPreviewTabController::EraseInitiatorTabInfo(
176 TabContents* preview_tab) { 240 TabContents* preview_tab) {
177 PrintPreviewTabMap::iterator it = preview_tab_map_.find(preview_tab); 241 PrintPreviewTabMap::iterator it = preview_tab_map_.find(preview_tab);
178 if (it == preview_tab_map_.end()) 242 if (it == preview_tab_map_.end())
179 return; 243 return;
180 244
181 RemoveObservers(it->second); 245 RemoveObservers(it->second);
182 preview_tab_map_[preview_tab] = NULL; 246 preview_tab_map_[preview_tab] = NULL;
183 } 247 }
184 248
185 TabContents* PrintPreviewTabController::GetInitiatorTab( 249 TabContents* PrintPreviewTabController::GetInitiatorTab(
186 TabContents* preview_tab) { 250 TabContents* preview_tab) {
187 PrintPreviewTabMap::iterator it = preview_tab_map_.find(preview_tab); 251 PrintPreviewTabMap::iterator it = preview_tab_map_.find(preview_tab);
188 if (it != preview_tab_map_.end()) 252 if (it != preview_tab_map_.end())
189 return preview_tab_map_[preview_tab]; 253 return preview_tab_map_[preview_tab];
254
190 return NULL; 255 return NULL;
191 } 256 }
192 257
193 TabContents* PrintPreviewTabController::CreatePrintPreviewTab( 258 TabContents* PrintPreviewTabController::CreatePrintPreviewTab(
194 TabContents* initiator_tab) { 259 TabContents* initiator_tab) {
195 // TODO: this should be converted to TabContentsWrapper. 260 // TODO: this should be converted to TabContentsWrapper.
196 TabContentsWrapper* tab = 261 TabContentsWrapper* tab =
197 TabContentsWrapper::GetCurrentWrapperForContents(initiator_tab); 262 TabContentsWrapper::GetCurrentWrapperForContents(initiator_tab);
198 DCHECK(tab); 263 DCHECK(tab);
199 Browser* current_browser = BrowserList::FindBrowserWithID( 264 Browser* current_browser = BrowserList::FindBrowserWithID(
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 AddObservers(preview_tab->tab_contents()); 298 AddObservers(preview_tab->tab_contents());
234 299
235 return preview_tab->tab_contents(); 300 return preview_tab->tab_contents();
236 } 301 }
237 302
238 void PrintPreviewTabController::AddObservers(TabContents* tab) { 303 void PrintPreviewTabController::AddObservers(TabContents* tab) {
239 registrar_.Add(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED, 304 registrar_.Add(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED,
240 Source<TabContents>(tab)); 305 Source<TabContents>(tab));
241 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 306 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
242 Source<NavigationController>(&tab->controller())); 307 Source<NavigationController>(&tab->controller()));
308
309 // Multiple sites may share the same RenderProcessHost, so check if this
310 // notification has already been added.
311 RenderProcessHost* rph = tab->render_view_host()->process();
312 if (!registrar_.IsRegistered(this,
313 content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
314 Source<RenderProcessHost>(rph))) {
315 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
316 Source<RenderProcessHost>(rph));
317 }
243 } 318 }
244 319
245 void PrintPreviewTabController::RemoveObservers(TabContents* tab) { 320 void PrintPreviewTabController::RemoveObservers(TabContents* tab) {
246 registrar_.Remove(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED, 321 registrar_.Remove(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED,
247 Source<TabContents>(tab)); 322 Source<TabContents>(tab));
248 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 323 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
249 Source<NavigationController>(&tab->controller())); 324 Source<NavigationController>(&tab->controller()));
325
326 // Multiple sites may share the same RenderProcessHost, so check if this
327 // notification has already been added.
328 RenderProcessHost* rph = tab->render_view_host()->process();
329 if (registrar_.IsRegistered(this,
330 content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
331 Source<RenderProcessHost>(rph))) {
332 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
333 Source<RenderProcessHost>(rph));
334 }
250 } 335 }
251 336
252 } // namespace printing 337 } // namespace printing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698