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

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

Issue 7800036: Print Preview: Hold on to tabs that do window.print(); window.close() until print preview finishes. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 9 years, 3 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/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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698