OLD | NEW |
---|---|
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: { | |
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) { | |
Lei Zhang
2011/08/11 01:30:51
If multiple tabs can share the same RendererProces
kmadhusu
2011/08/15 18:12:49
Yes. We should display the error on both print pre
| |
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) | |
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(); | |
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 // Print preview tab contents are destroyed. Notify |PrintPreviewUI| to | |
148 // abort the initiator tab preview request. | |
149 if (IsPrintPreviewTab(tab) && tab->web_ui()) { | |
150 PrintPreviewUI* print_preview_ui = | |
151 static_cast<PrintPreviewUI*>(tab->web_ui()); | |
152 print_preview_ui->OnNavigation(); | |
153 } | |
154 | |
155 // Erase the map entry. | |
156 preview_tab_map_.erase(tab); | |
157 } else { | |
158 // Initiator tab is closed. Disable the controls in preview tab. | |
159 if (preview_tab->web_ui()) { | |
160 PrintPreviewUI* print_preview_ui = | |
161 static_cast<PrintPreviewUI*>(preview_tab->web_ui()); | |
162 print_preview_ui->OnInitiatorTabClosed(); | |
163 } | |
164 | |
165 // |tab| is an initiator tab, update the map entry and remove observers. | |
166 preview_tab_map_[preview_tab] = NULL; | |
167 } | |
168 | |
169 RemoveObservers(tab); | |
170 } | |
171 | |
172 void PrintPreviewTabController::OnNavEntryCommitted( | |
173 TabContents* tab, content::LoadCommittedDetails* details) { | |
174 TabContents* preview_tab = GetPrintPreviewForTab(tab); | |
175 bool source_tab_is_preview_tab = (tab == preview_tab); | |
176 if (details) { | |
177 PageTransition::Type transition_type = details->entry->transition_type(); | |
178 NavigationType::Type nav_type = details->type; | |
114 | 179 |
115 // Don't update/erase the map entry if the page has not changed. | 180 // Don't update/erase the map entry if the page has not changed. |
116 if (transition_type == PageTransition::RELOAD || | 181 if (transition_type == PageTransition::RELOAD || |
117 nav_type == NavigationType::SAME_PAGE) { | 182 nav_type == NavigationType::SAME_PAGE) { |
118 return; | 183 return; |
119 } | 184 } |
120 | 185 |
121 // New |preview_tab| is created. Don't update/erase map entry. | 186 // New |preview_tab| is created. Don't update/erase map entry. |
122 if (waiting_for_new_preview_page_ && | 187 if (waiting_for_new_preview_page_ && |
123 transition_type == PageTransition::LINK && | 188 transition_type == PageTransition::LINK && |
124 nav_type == NavigationType::NEW_PAGE && | 189 nav_type == NavigationType::NEW_PAGE && |
125 source_tab_is_preview_tab) { | 190 source_tab_is_preview_tab) { |
126 waiting_for_new_preview_page_ = false; | 191 waiting_for_new_preview_page_ = false; |
192 // Set the initiator tab url. | |
193 TabContents* initiator_tab = GetInitiatorTab(tab); | |
194 if (initiator_tab && preview_tab->web_ui()) { | |
195 PrintPreviewUI* print_preview_ui = | |
196 static_cast<PrintPreviewUI*>(preview_tab->web_ui()); | |
197 print_preview_ui->SetInitiatorTabURL(initiator_tab->GetURL().spec()); | |
198 } | |
127 return; | 199 return; |
128 } | 200 } |
129 | 201 |
130 // User navigated to a preview tab using forward/back button. | 202 // User navigated to a preview tab using forward/back button. |
131 if (source_tab_is_preview_tab && | 203 if (source_tab_is_preview_tab && |
132 transition_type == PageTransition::FORWARD_BACK && | 204 transition_type == PageTransition::FORWARD_BACK && |
133 nav_type == NavigationType::EXISTING_PAGE) { | 205 nav_type == NavigationType::EXISTING_PAGE) { |
134 return; | 206 return; |
135 } | 207 } |
136 } | 208 } |
137 | 209 |
210 RemoveObservers(tab); | |
138 if (source_tab_is_preview_tab) { | 211 if (source_tab_is_preview_tab) { |
139 // Remove the initiator tab's observers before erasing the mapping. | 212 // Remove the initiator tab's observers before erasing the mapping. |
140 TabContents* initiator_tab = GetInitiatorTab(source_tab); | 213 TabContents* initiator_tab = GetInitiatorTab(tab); |
141 if (initiator_tab) | 214 if (initiator_tab) |
142 RemoveObservers(initiator_tab); | 215 RemoveObservers(initiator_tab); |
216 preview_tab_map_.erase(tab); | |
217 } else { | |
218 preview_tab_map_[preview_tab] = NULL; | |
143 | 219 |
144 // |source_tab_is_preview_tab| is misleading in the case where the user | 220 // Initiator tab is closed. Disable the controls in preview tab. |
145 // chooses to re-open the initiator tab after closing it, as |source_tab| | 221 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 = | 222 PrintPreviewUI* print_preview_ui = |
150 static_cast<PrintPreviewUI*>(source_tab->web_ui()); | 223 static_cast<PrintPreviewUI*>(preview_tab->web_ui()); |
151 print_preview_ui->OnNavigation(); | 224 print_preview_ui->OnInitiatorTabClosed(); |
152 } | 225 } |
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 } | 226 } |
165 RemoveObservers(source_tab); | |
166 } | 227 } |
167 | 228 |
168 // static | 229 // static |
169 bool PrintPreviewTabController::IsPrintPreviewTab(TabContents* tab) { | 230 bool PrintPreviewTabController::IsPrintPreviewTab(TabContents* tab) { |
170 const GURL& url = tab->GetURL(); | 231 const GURL& url = tab->GetURL(); |
171 return (url.SchemeIs(chrome::kChromeUIScheme) && | 232 return (url.SchemeIs(chrome::kChromeUIScheme) && |
172 url.host() == chrome::kChromeUIPrintHost); | 233 url.host() == chrome::kChromeUIPrintHost); |
173 } | 234 } |
174 | 235 |
175 void PrintPreviewTabController::EraseInitiatorTabInfo( | 236 void PrintPreviewTabController::EraseInitiatorTabInfo( |
176 TabContents* preview_tab) { | 237 TabContents* preview_tab) { |
177 PrintPreviewTabMap::iterator it = preview_tab_map_.find(preview_tab); | 238 PrintPreviewTabMap::iterator it = preview_tab_map_.find(preview_tab); |
178 if (it == preview_tab_map_.end()) | 239 if (it == preview_tab_map_.end()) |
179 return; | 240 return; |
180 | 241 |
181 RemoveObservers(it->second); | 242 RemoveObservers(it->second); |
182 preview_tab_map_[preview_tab] = NULL; | 243 preview_tab_map_[preview_tab] = NULL; |
183 } | 244 } |
184 | 245 |
185 TabContents* PrintPreviewTabController::GetInitiatorTab( | 246 TabContents* PrintPreviewTabController::GetInitiatorTab( |
186 TabContents* preview_tab) { | 247 TabContents* preview_tab) { |
187 PrintPreviewTabMap::iterator it = preview_tab_map_.find(preview_tab); | 248 PrintPreviewTabMap::iterator it = preview_tab_map_.find(preview_tab); |
188 if (it != preview_tab_map_.end()) | 249 if (it != preview_tab_map_.end()) |
189 return preview_tab_map_[preview_tab]; | 250 return preview_tab_map_[preview_tab]; |
251 | |
190 return NULL; | 252 return NULL; |
191 } | 253 } |
192 | 254 |
193 TabContents* PrintPreviewTabController::CreatePrintPreviewTab( | 255 TabContents* PrintPreviewTabController::CreatePrintPreviewTab( |
194 TabContents* initiator_tab) { | 256 TabContents* initiator_tab) { |
195 // TODO: this should be converted to TabContentsWrapper. | 257 // TODO: this should be converted to TabContentsWrapper. |
196 TabContentsWrapper* tab = | 258 TabContentsWrapper* tab = |
197 TabContentsWrapper::GetCurrentWrapperForContents(initiator_tab); | 259 TabContentsWrapper::GetCurrentWrapperForContents(initiator_tab); |
198 DCHECK(tab); | 260 DCHECK(tab); |
199 Browser* current_browser = BrowserList::FindBrowserWithID( | 261 Browser* current_browser = BrowserList::FindBrowserWithID( |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
233 AddObservers(preview_tab->tab_contents()); | 295 AddObservers(preview_tab->tab_contents()); |
234 | 296 |
235 return preview_tab->tab_contents(); | 297 return preview_tab->tab_contents(); |
236 } | 298 } |
237 | 299 |
238 void PrintPreviewTabController::AddObservers(TabContents* tab) { | 300 void PrintPreviewTabController::AddObservers(TabContents* tab) { |
239 registrar_.Add(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED, | 301 registrar_.Add(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED, |
240 Source<TabContents>(tab)); | 302 Source<TabContents>(tab)); |
241 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 303 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
242 Source<NavigationController>(&tab->controller())); | 304 Source<NavigationController>(&tab->controller())); |
305 | |
306 // Multiple sites may share the same RenderProcessHost, so check if this | |
307 // notification has already been added. | |
308 RenderProcessHost* rph = tab->render_view_host()->process(); | |
309 if (!registrar_.IsRegistered(this, | |
310 content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
311 Source<RenderProcessHost>(rph))) { | |
312 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
313 Source<RenderProcessHost>(rph)); | |
314 } | |
243 } | 315 } |
244 | 316 |
245 void PrintPreviewTabController::RemoveObservers(TabContents* tab) { | 317 void PrintPreviewTabController::RemoveObservers(TabContents* tab) { |
246 registrar_.Remove(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED, | 318 registrar_.Remove(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED, |
247 Source<TabContents>(tab)); | 319 Source<TabContents>(tab)); |
248 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 320 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
249 Source<NavigationController>(&tab->controller())); | 321 Source<NavigationController>(&tab->controller())); |
322 | |
323 // Multiple sites may share the same RenderProcessHost, so check if this | |
324 // notification has already been added. | |
325 RenderProcessHost* rph = tab->render_view_host()->process(); | |
326 if (registrar_.IsRegistered(this, | |
327 content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
328 Source<RenderProcessHost>(rph))) { | |
329 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
330 Source<RenderProcessHost>(rph)); | |
331 } | |
250 } | 332 } |
251 | 333 |
252 } // namespace printing | 334 } // namespace printing |
OLD | NEW |