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

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: Addressed review comments 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() {}
(...skipping 26 matching lines...) Expand all
57 if (preview_tab) { 59 if (preview_tab) {
58 // Show current preview tab. 60 // Show current preview tab.
59 static_cast<RenderViewHostDelegate*>(preview_tab)->Activate(); 61 static_cast<RenderViewHostDelegate*>(preview_tab)->Activate();
60 return preview_tab; 62 return preview_tab;
61 } 63 }
62 return CreatePrintPreviewTab(initiator_tab); 64 return CreatePrintPreviewTab(initiator_tab);
63 } 65 }
64 66
65 TabContents* PrintPreviewTabController::GetPrintPreviewForTab( 67 TabContents* PrintPreviewTabController::GetPrintPreviewForTab(
66 TabContents* tab) const { 68 TabContents* tab) const {
69 // |preview_tab_map_| is keyed by the preview tab, so if find() succeeds, then
70 // |tab| is the preview tab.
67 PrintPreviewTabMap::const_iterator it = preview_tab_map_.find(tab); 71 PrintPreviewTabMap::const_iterator it = preview_tab_map_.find(tab);
68 if (it != preview_tab_map_.end()) 72 if (it != preview_tab_map_.end())
69 return tab; 73 return tab;
70 74
71 for (it = preview_tab_map_.begin(); it != preview_tab_map_.end(); ++it) { 75 for (it = preview_tab_map_.begin(); it != preview_tab_map_.end(); ++it) {
72 // If |tab| is an initiator tab. 76 // If |tab| is an initiator tab.
73 if (tab == it->second) { 77 if (tab == it->second) {
74 // Return the associated preview tab. 78 // Return the associated preview tab.
75 return it->first; 79 return it->first;
76 } 80 }
77 } 81 }
78 return NULL; 82 return NULL;
79 } 83 }
80 84
81 void PrintPreviewTabController::Observe(int type, 85 void PrintPreviewTabController::Observe(int type,
82 const NotificationSource& source, 86 const NotificationSource& source,
83 const NotificationDetails& details) { 87 const NotificationDetails& details) {
84 TabContents* source_tab = NULL;
85 content::LoadCommittedDetails* detail_info = NULL;
86
87 switch (type) { 88 switch (type) {
89 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
90 OnRendererProcessClosed(Source<RenderProcessHost>(source).ptr());
91 break;
92 }
88 case content::NOTIFICATION_TAB_CONTENTS_DESTROYED: { 93 case content::NOTIFICATION_TAB_CONTENTS_DESTROYED: {
89 source_tab = Source<TabContents>(source).ptr(); 94 OnTabContentsDestroyed(Source<TabContents>(source).ptr());
90 break; 95 break;
91 } 96 }
92 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { 97 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: {
93 NavigationController* controller = 98 NavigationController* controller =
94 Source<NavigationController>(source).ptr(); 99 Source<NavigationController>(source).ptr();
95 source_tab = controller->tab_contents(); 100 content::LoadCommittedDetails* load_details =
96 detail_info = Details<content::LoadCommittedDetails>(details).ptr(); 101 Details<content::LoadCommittedDetails>(details).ptr();
102 OnNavEntryCommitted(controller->tab_contents(), load_details);
97 break; 103 break;
98 } 104 }
99 default: { 105 default: {
100 NOTREACHED(); 106 NOTREACHED();
101 break; 107 break;
102 } 108 }
103 } 109 }
110 }
104 111
105 DCHECK(source_tab); 112 void PrintPreviewTabController::OnRendererProcessClosed(
113 RenderProcessHost* rph) {
114 for (PrintPreviewTabMap::iterator iter = preview_tab_map_.begin();
115 iter != preview_tab_map_.end(); ++iter) {
116 if (iter->second != NULL &&
117 iter->second->render_view_host()->process() == rph) {
118 TabContents* preview_tab = GetPrintPreviewForTab(iter->second);
119 PrintPreviewUI* print_preview_ui =
120 static_cast<PrintPreviewUI*>(preview_tab->web_ui());
121 print_preview_ui->OnInitiatorTabCrashed();
122 }
123 }
124 }
106 125
107 TabContents* preview_tab = GetPrintPreviewForTab(source_tab); 126 void PrintPreviewTabController::OnTabContentsDestroyed(TabContents* tab) {
108 bool source_tab_is_preview_tab = (source_tab == preview_tab); 127 TabContents* preview_tab = GetPrintPreviewForTab(tab);
128 if (!preview_tab)
129 return;
109 130
110 if (detail_info) { 131 if (tab == preview_tab) {
111 PageTransition::Type transition_type = 132 // Remove the initiator tab's observers before erasing the mapping.
112 detail_info->entry->transition_type(); 133 TabContents* initiator_tab = GetInitiatorTab(tab);
113 NavigationType::Type nav_type = detail_info->type; 134 if (initiator_tab)
135 RemoveObservers(initiator_tab);
136
137 // Print preview tab contents are destroyed. Notify |PrintPreviewUI| to
138 // abort the initiator tab preview request.
139 if (IsPrintPreviewTab(tab) && tab->web_ui()) {
140 PrintPreviewUI* print_preview_ui =
141 static_cast<PrintPreviewUI*>(tab->web_ui());
142 print_preview_ui->OnTabDestroyed();
143 }
144
145 // Erase the map entry.
146 preview_tab_map_.erase(tab);
147 } else {
148 // Initiator tab is closed. Disable the controls in preview tab.
149 if (preview_tab->web_ui()) {
150 PrintPreviewUI* print_preview_ui =
151 static_cast<PrintPreviewUI*>(preview_tab->web_ui());
152 print_preview_ui->OnInitiatorTabClosed();
153 }
154
155 // |tab| is an initiator tab, update the map entry and remove observers.
156 preview_tab_map_[preview_tab] = NULL;
157 }
158
159 RemoveObservers(tab);
160 }
161
162 void PrintPreviewTabController::OnNavEntryCommitted(
163 TabContents* tab, content::LoadCommittedDetails* details) {
164 TabContents* preview_tab = GetPrintPreviewForTab(tab);
165 bool source_tab_is_preview_tab = (tab == preview_tab);
166 if (details) {
167 PageTransition::Type transition_type = details->entry->transition_type();
168 NavigationType::Type nav_type = details->type;
114 169
115 // Don't update/erase the map entry if the page has not changed. 170 // Don't update/erase the map entry if the page has not changed.
116 if (transition_type == PageTransition::RELOAD || 171 if (transition_type == PageTransition::RELOAD ||
117 nav_type == NavigationType::SAME_PAGE) { 172 nav_type == NavigationType::SAME_PAGE) {
118 return; 173 return;
119 } 174 }
120 175
121 // New |preview_tab| is created. Don't update/erase map entry. 176 // New |preview_tab| is created. Don't update/erase map entry.
122 if (waiting_for_new_preview_page_ && 177 if (waiting_for_new_preview_page_ &&
123 transition_type == PageTransition::LINK && 178 transition_type == PageTransition::LINK &&
124 nav_type == NavigationType::NEW_PAGE && 179 nav_type == NavigationType::NEW_PAGE &&
125 source_tab_is_preview_tab) { 180 source_tab_is_preview_tab) {
126 waiting_for_new_preview_page_ = false; 181 waiting_for_new_preview_page_ = false;
182 // Set the initiator tab url.
183 TabContents* initiator_tab = GetInitiatorTab(tab);
184 if (initiator_tab && preview_tab->web_ui()) {
185 PrintPreviewUI* print_preview_ui =
186 static_cast<PrintPreviewUI*>(preview_tab->web_ui());
187 print_preview_ui->SetInitiatorTabURL(initiator_tab->GetURL().spec());
188 }
127 return; 189 return;
128 } 190 }
129 191
130 // User navigated to a preview tab using forward/back button. 192 // User navigated to a preview tab using forward/back button.
131 if (source_tab_is_preview_tab && 193 if (source_tab_is_preview_tab &&
132 transition_type == PageTransition::FORWARD_BACK && 194 transition_type == PageTransition::FORWARD_BACK &&
133 nav_type == NavigationType::EXISTING_PAGE) { 195 nav_type == NavigationType::EXISTING_PAGE) {
134 return; 196 return;
135 } 197 }
136 } 198 }
137 199
200 RemoveObservers(tab);
138 if (source_tab_is_preview_tab) { 201 if (source_tab_is_preview_tab) {
139 // Remove the initiator tab's observers before erasing the mapping. 202 // Remove the initiator tab's observers before erasing the mapping.
140 TabContents* initiator_tab = GetInitiatorTab(source_tab); 203 TabContents* initiator_tab = GetInitiatorTab(tab);
141 if (initiator_tab) 204 if (initiator_tab)
142 RemoveObservers(initiator_tab); 205 RemoveObservers(initiator_tab);
206 preview_tab_map_.erase(tab);
207 } else {
208 preview_tab_map_[preview_tab] = NULL;
143 209
144 // |source_tab_is_preview_tab| is misleading in the case where the user 210 // Initiator tab is closed. Disable the controls in preview tab.
145 // chooses to re-open the initiator tab after closing it, as |source_tab| 211 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 = 212 PrintPreviewUI* print_preview_ui =
150 static_cast<PrintPreviewUI*>(source_tab->web_ui()); 213 static_cast<PrintPreviewUI*>(preview_tab->web_ui());
151 print_preview_ui->OnNavigation(); 214 print_preview_ui->OnInitiatorTabClosed();
152 } 215 }
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 } 216 }
165 RemoveObservers(source_tab);
166 } 217 }
167 218
168 // static 219 // static
169 bool PrintPreviewTabController::IsPrintPreviewTab(TabContents* tab) { 220 bool PrintPreviewTabController::IsPrintPreviewTab(TabContents* tab) {
170 const GURL& url = tab->GetURL(); 221 const GURL& url = tab->GetURL();
171 return (url.SchemeIs(chrome::kChromeUIScheme) && 222 return (url.SchemeIs(chrome::kChromeUIScheme) &&
172 url.host() == chrome::kChromeUIPrintHost); 223 url.host() == chrome::kChromeUIPrintHost);
173 } 224 }
174 225
175 void PrintPreviewTabController::EraseInitiatorTabInfo( 226 void PrintPreviewTabController::EraseInitiatorTabInfo(
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 AddObservers(preview_tab->tab_contents()); 284 AddObservers(preview_tab->tab_contents());
234 285
235 return preview_tab->tab_contents(); 286 return preview_tab->tab_contents();
236 } 287 }
237 288
238 void PrintPreviewTabController::AddObservers(TabContents* tab) { 289 void PrintPreviewTabController::AddObservers(TabContents* tab) {
239 registrar_.Add(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED, 290 registrar_.Add(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED,
240 Source<TabContents>(tab)); 291 Source<TabContents>(tab));
241 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 292 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
242 Source<NavigationController>(&tab->controller())); 293 Source<NavigationController>(&tab->controller()));
294
295 // Multiple sites may share the same RenderProcessHost, so check if this
296 // notification has already been added.
297 RenderProcessHost* rph = tab->render_view_host()->process();
298 if (!registrar_.IsRegistered(this,
299 content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
300 Source<RenderProcessHost>(rph))) {
301 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
302 Source<RenderProcessHost>(rph));
303 }
243 } 304 }
244 305
245 void PrintPreviewTabController::RemoveObservers(TabContents* tab) { 306 void PrintPreviewTabController::RemoveObservers(TabContents* tab) {
246 registrar_.Remove(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED, 307 registrar_.Remove(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED,
247 Source<TabContents>(tab)); 308 Source<TabContents>(tab));
248 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 309 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
249 Source<NavigationController>(&tab->controller())); 310 Source<NavigationController>(&tab->controller()));
311
312 // Multiple sites may share the same RenderProcessHost, so check if this
313 // notification has already been added.
314 RenderProcessHost* rph = tab->render_view_host()->process();
315 if (registrar_.IsRegistered(this,
316 content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
317 Source<RenderProcessHost>(rph))) {
318 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
319 Source<RenderProcessHost>(rph));
320 }
250 } 321 }
251 322
252 } // namespace printing 323 } // namespace printing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698