Chromium Code Reviews| 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/background_printing_manager.h" | 5 #include "chrome/browser/printing/background_printing_manager.h" |
| 6 | 6 |
| 7 #include "chrome/browser/printing/print_job.h" | 7 #include "chrome/browser/printing/print_job.h" |
| 8 #include "chrome/browser/printing/print_preview_tab_controller.h" | 8 #include "chrome/browser/printing/print_preview_tab_controller.h" |
| 9 #include "chrome/browser/sessions/restore_tab_helper.h" | 9 #include "chrome/browser/sessions/restore_tab_helper.h" |
| 10 #include "chrome/browser/tabs/tab_strip_model.h" | 10 #include "chrome/browser/tabs/tab_strip_model.h" |
| 11 #include "chrome/browser/ui/browser_list.h" | 11 #include "chrome/browser/ui/browser_list.h" |
| 12 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 12 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 13 #include "chrome/common/chrome_notification_types.h" | 13 #include "chrome/common/chrome_notification_types.h" |
| 14 #include "content/browser/browser_thread.h" | 14 #include "content/browser/browser_thread.h" |
| 15 #include "content/browser/renderer_host/render_view_host.h" | |
| 15 #include "content/common/notification_details.h" | 16 #include "content/common/notification_details.h" |
| 16 #include "content/common/notification_source.h" | 17 #include "content/common/notification_source.h" |
| 17 | 18 |
| 18 namespace printing { | 19 namespace printing { |
| 19 | 20 |
| 20 BackgroundPrintingManager::BackgroundPrintingManager() { | 21 BackgroundPrintingManager::BackgroundPrintingManager() { |
| 21 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 22 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 22 } | 23 } |
| 23 | 24 |
| 24 BackgroundPrintingManager::~BackgroundPrintingManager() { | 25 BackgroundPrintingManager::~BackgroundPrintingManager() { |
| 25 DCHECK(CalledOnValidThread()); | 26 DCHECK(CalledOnValidThread()); |
| 26 // The might be some TabContentsWrappers still in |printing_tabs_| at | 27 // The might be some TabContentsWrappers still in |printing_tabs_| at |
| 27 // this point. E.g. when the last remaining tab is a print preview tab and | 28 // this point. E.g. when the last remaining tab is a print preview tab and |
| 28 // tries to print. In which case it will fail to print. | 29 // tries to print. In which case it will fail to print. |
| 29 // TODO(thestig) handle this case better. | 30 // TODO(thestig) handle this case better. |
| 30 } | 31 } |
| 31 | 32 |
| 32 void BackgroundPrintingManager::OwnPrintPreviewTab( | 33 void BackgroundPrintingManager::OwnPrintPreviewTab( |
| 33 TabContentsWrapper* preview_tab) { | 34 TabContentsWrapper* preview_tab) { |
| 34 DCHECK(CalledOnValidThread()); | 35 DCHECK(CalledOnValidThread()); |
| 35 DCHECK(PrintPreviewTabController::IsPrintPreviewTab(preview_tab)); | 36 DCHECK(PrintPreviewTabController::IsPrintPreviewTab(preview_tab)); |
| 36 CHECK(printing_tabs_.find(preview_tab) == printing_tabs_.end()); | 37 CHECK(printing_tabs_.find(preview_tab) == printing_tabs_.end()); |
| 37 | 38 |
| 38 printing_tabs_.insert(preview_tab); | 39 printing_tabs_.insert(preview_tab); |
| 39 | 40 |
| 40 registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED, | 41 registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED, |
| 41 Source<TabContentsWrapper>(preview_tab)); | 42 Source<TabContentsWrapper>(preview_tab)); |
| 42 registrar_.Add(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED, | |
| 43 Source<TabContents>(preview_tab->tab_contents())); | |
| 44 | 43 |
| 45 // Detach |preview_tab| from its tab strip. | 44 // OwnInitiatorTabContents() may have already added this notification. |
| 46 Browser* browser = BrowserList::FindBrowserWithID( | 45 TabContents* preview_contents = preview_tab->tab_contents(); |
| 47 preview_tab->restore_tab_helper()->window_id().id()); | 46 if (!registrar_.IsRegistered(this, |
| 48 DCHECK(browser); | 47 content::NOTIFICATION_TAB_CONTENTS_DESTROYED, |
| 48 Source<TabContents>(preview_contents))) { | |
| 49 registrar_.Add(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED, | |
| 50 Source<TabContents>(preview_contents)); | |
| 51 } | |
| 49 | 52 |
| 50 TabStripModel* tabstrip = browser->tabstrip_model(); | 53 // If a tab that is printing crashes, the user cannot destroy it since it is |
| 51 tabstrip->DetachTabContentsAt(tabstrip->GetIndexOfTabContents(preview_tab)); | 54 // not in any tab strip. Thus listen for crashes here and delete the tab. |
| 55 // | |
| 56 // Multiple sites may share the same RenderProcessHost, so check if this | |
| 57 // notification has already been added. | |
| 58 RenderProcessHost* rph = preview_tab->render_view_host()->process(); | |
| 59 if (!registrar_.IsRegistered(this, | |
| 60 content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
| 61 Source<RenderProcessHost>(rph))) { | |
| 62 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
| 63 Source<RenderProcessHost>(rph)); | |
| 64 } | |
| 65 | |
| 66 RemoveFromTabStrip(preview_tab); | |
| 52 | 67 |
| 53 // Activate the initiator tab. | 68 // Activate the initiator tab. |
| 54 PrintPreviewTabController* tab_controller = | 69 PrintPreviewTabController* tab_controller = |
| 55 PrintPreviewTabController::GetInstance(); | 70 PrintPreviewTabController::GetInstance(); |
| 56 if (!tab_controller) | 71 if (!tab_controller) |
| 57 return; | 72 return; |
| 58 TabContentsWrapper* initiator_tab = | 73 TabContentsWrapper* initiator_tab = |
| 59 tab_controller->GetInitiatorTab(preview_tab); | 74 tab_controller->GetInitiatorTab(preview_tab); |
| 60 if (!initiator_tab) | 75 if (!initiator_tab) |
| 61 return; | 76 return; |
| 62 static_cast<RenderViewHostDelegate*>( | 77 static_cast<RenderViewHostDelegate*>( |
| 63 initiator_tab->tab_contents())->Activate(); | 78 initiator_tab->tab_contents())->Activate(); |
| 64 } | 79 } |
| 65 | 80 |
| 81 bool BackgroundPrintingManager::OwnInitiatorTab( | |
| 82 TabContentsWrapper* initiator_tab) { | |
| 83 DCHECK(CalledOnValidThread()); | |
| 84 DCHECK(!PrintPreviewTabController::IsPrintPreviewTab(initiator_tab)); | |
| 85 CHECK(initiator_tabs_.find(initiator_tab) == initiator_tabs_.end()); | |
| 86 | |
| 87 PrintPreviewTabController* tab_controller = | |
| 88 PrintPreviewTabController::GetInstance(); | |
| 89 if (!tab_controller) | |
| 90 return false; | |
| 91 TabContentsWrapper* preview_tab = | |
| 92 tab_controller->GetPrintPreviewForTab(initiator_tab); | |
| 93 if (!preview_tab) | |
| 94 return false; | |
| 95 | |
| 96 initiator_tabs_.insert(initiator_tab); | |
| 97 map_[preview_tab] = initiator_tab; | |
| 98 | |
| 99 // OwnPrintPreviewTab() may have already added this notification. | |
| 100 TabContents* preview_contents = preview_tab->tab_contents(); | |
| 101 if (!registrar_.IsRegistered(this, | |
| 102 content::NOTIFICATION_TAB_CONTENTS_DESTROYED, | |
| 103 Source<TabContents>(preview_contents))) { | |
| 104 registrar_.Add(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED, | |
| 105 Source<TabContents>(preview_contents)); | |
| 106 } | |
| 107 | |
| 108 RemoveFromTabStrip(initiator_tab); | |
| 109 return true; | |
| 110 } | |
| 111 | |
| 66 void BackgroundPrintingManager::Observe(int type, | 112 void BackgroundPrintingManager::Observe(int type, |
| 67 const NotificationSource& source, | 113 const NotificationSource& source, |
| 68 const NotificationDetails& details) { | 114 const NotificationDetails& details) { |
| 69 switch (type) { | 115 switch (type) { |
| 116 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { | |
| 117 OnRendererProcessClosed(Source<RenderProcessHost>(source).ptr()); | |
| 118 break; | |
| 119 } | |
| 70 case chrome::NOTIFICATION_PRINT_JOB_RELEASED: { | 120 case chrome::NOTIFICATION_PRINT_JOB_RELEASED: { |
| 71 TabContentsWrapper* tab = Source<TabContentsWrapper>(source).ptr(); | 121 OnPrintJobReleased(Source<TabContentsWrapper>(source).ptr()); |
| 72 registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED, | |
| 73 Source<TabContentsWrapper>(tab)); | |
| 74 | |
| 75 // This might be happening in the middle of a RenderViewGone() loop. | |
| 76 // Deleting |contents| later so the RenderViewGone() loop can finish. | |
| 77 MessageLoop::current()->DeleteSoon(FROM_HERE, tab); | |
| 78 break; | 122 break; |
| 79 } | 123 } |
| 80 case content::NOTIFICATION_TAB_CONTENTS_DESTROYED: { | 124 case content::NOTIFICATION_TAB_CONTENTS_DESTROYED: { |
| 81 TabContentsWrapper* tab = | 125 OnTabContentsDestroyed( |
| 82 TabContentsWrapper::GetCurrentWrapperForContents( | 126 TabContentsWrapper::GetCurrentWrapperForContents( |
| 83 Source<TabContents>(source).ptr()); | 127 Source<TabContents>(source).ptr())); |
| 84 if (registrar_.IsRegistered(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED, | |
| 85 Source<TabContentsWrapper>(tab))) { | |
| 86 registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED, | |
| 87 Source<TabContentsWrapper>(tab)); | |
| 88 } | |
| 89 registrar_.Remove(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED, | |
| 90 Source<TabContents>(tab->tab_contents())); | |
| 91 printing_tabs_.erase(tab); | |
| 92 break; | 128 break; |
| 93 } | 129 } |
| 94 default: { | 130 default: { |
| 95 NOTREACHED(); | 131 NOTREACHED(); |
| 96 break; | 132 break; |
| 97 } | 133 } |
| 98 } | 134 } |
| 99 } | 135 } |
| 100 | 136 |
| 137 void BackgroundPrintingManager::OnRendererProcessClosed( | |
| 138 RenderProcessHost* rph) { | |
| 139 TabContentsWrapperSet::const_iterator it; | |
| 140 for (it = begin(); it != end(); ++it) { | |
| 141 TabContentsWrapper* tab = *it; | |
| 142 if (tab->render_view_host()->process() == rph) | |
| 143 MessageLoop::current()->DeleteSoon(FROM_HERE, tab); | |
|
kmadhusu
2011/09/07 23:21:10
When exactly multiple preview tabs share the same
Lei Zhang
2011/09/07 23:41:16
This happens quite often. For example, open two ta
| |
| 144 } | |
| 145 } | |
| 146 | |
| 147 void BackgroundPrintingManager::OnPrintJobReleased( | |
| 148 TabContentsWrapper* preview_tab) { | |
| 149 registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED, | |
| 150 Source<TabContentsWrapper>(preview_tab)); | |
| 151 | |
| 152 // This might be happening in the middle of a RenderViewGone() loop. | |
| 153 // Deleting |contents| later so the RenderViewGone() loop can finish. | |
| 154 MessageLoop::current()->DeleteSoon(FROM_HERE, preview_tab); | |
| 155 } | |
| 156 | |
| 157 void BackgroundPrintingManager::OnTabContentsDestroyed( | |
| 158 TabContentsWrapper* preview_tab) { | |
| 159 bool is_owned_printing_tab = | |
| 160 (printing_tabs_.find(preview_tab) != printing_tabs_.end()); | |
|
kmadhusu
2011/09/07 23:21:10
= HasPrintPreviewTab(preview_tab);
Lei Zhang
2011/09/07 23:41:16
Done.
| |
| 161 bool is_preview_tab_for_owned_initator_tab = | |
| 162 (map_.find(preview_tab) != map_.end()); | |
| 163 DCHECK(is_owned_printing_tab || is_preview_tab_for_owned_initator_tab); | |
| 164 | |
| 165 // Always need to remove this notification since the tab is gone. | |
| 166 registrar_.Remove(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED, | |
| 167 Source<TabContents>(preview_tab->tab_contents())); | |
| 168 | |
| 169 // Delete the associated initiator tab if one exists. | |
| 170 if (is_preview_tab_for_owned_initator_tab) { | |
| 171 TabContentsWrapper* initiator_tab = map_[preview_tab]; | |
| 172 initiator_tabs_.erase(initiator_tab); | |
| 173 MessageLoop::current()->DeleteSoon(FROM_HERE, initiator_tab); | |
| 174 } | |
| 175 | |
| 176 // If |preview_tab| is not owned, then we are done. | |
| 177 if (!is_owned_printing_tab) | |
| 178 return; | |
| 179 | |
| 180 // Remove NOTIFICATION_RENDERER_PROCESS_CLOSED if |tab| is the last | |
| 181 // TabContents associated with |rph|. | |
| 182 bool shared_rph = false; | |
| 183 RenderProcessHost* rph = preview_tab->render_view_host()->process(); | |
| 184 TabContentsWrapperSet::const_iterator it; | |
| 185 for (it = begin(); it != end(); ++it) { | |
| 186 TabContentsWrapper* iter_tab = *it; | |
| 187 if (iter_tab == preview_tab) | |
| 188 continue; | |
| 189 if (iter_tab->render_view_host()->process() == rph) { | |
| 190 shared_rph = true; | |
| 191 break; | |
| 192 } | |
| 193 } | |
| 194 if (!shared_rph) { | |
| 195 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
| 196 Source<RenderProcessHost>(rph)); | |
| 197 } | |
| 198 | |
| 199 // Remove other notifications and remove the tab from |printing_tabs_|. | |
| 200 if (registrar_.IsRegistered(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED, | |
| 201 Source<TabContentsWrapper>(preview_tab))) { | |
| 202 registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED, | |
| 203 Source<TabContentsWrapper>(preview_tab)); | |
| 204 } | |
| 205 printing_tabs_.erase(preview_tab); | |
| 206 } | |
| 207 | |
| 208 void BackgroundPrintingManager::RemoveFromTabStrip(TabContentsWrapper* tab) { | |
| 209 Browser* browser = BrowserList::FindBrowserWithID( | |
| 210 tab->restore_tab_helper()->window_id().id()); | |
| 211 DCHECK(browser); | |
| 212 | |
| 213 TabStripModel* tabstrip = browser->tabstrip_model(); | |
| 214 int index = tabstrip->GetIndexOfTabContents(tab); | |
| 215 if (index == TabStripModel::kNoTab) | |
| 216 return; | |
| 217 tabstrip->DetachTabContentsAt(index); | |
| 218 } | |
| 219 | |
| 101 BackgroundPrintingManager::TabContentsWrapperSet::const_iterator | 220 BackgroundPrintingManager::TabContentsWrapperSet::const_iterator |
| 102 BackgroundPrintingManager::begin() { | 221 BackgroundPrintingManager::begin() { |
| 103 return printing_tabs_.begin(); | 222 return printing_tabs_.begin(); |
| 104 } | 223 } |
| 105 | 224 |
| 106 BackgroundPrintingManager::TabContentsWrapperSet::const_iterator | 225 BackgroundPrintingManager::TabContentsWrapperSet::const_iterator |
| 107 BackgroundPrintingManager::end() { | 226 BackgroundPrintingManager::end() { |
| 108 return printing_tabs_.end(); | 227 return printing_tabs_.end(); |
| 109 } | 228 } |
| 110 | 229 |
| 111 bool BackgroundPrintingManager::HasPrintPreviewTab( | 230 bool BackgroundPrintingManager::HasPrintPreviewTab( |
| 112 TabContentsWrapper* preview_tab) { | 231 TabContentsWrapper* preview_tab) { |
| 113 return printing_tabs_.find(preview_tab) != printing_tabs_.end(); | 232 return printing_tabs_.find(preview_tab) != printing_tabs_.end(); |
| 114 } | 233 } |
| 115 | 234 |
| 116 } // namespace printing | 235 } // namespace printing |
| OLD | NEW |