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

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
« no previous file with comments | « chrome/browser/printing/background_printing_manager.h ('k') | chrome/browser/ui/browser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(!HasPrintPreviewTab(preview_tab));
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 bool has_initiator_tab = false;
86 for (TabContentsWrapperMap::iterator it = map_.begin(); it != map_.end();
87 ++it) {
88 if (it->second == initiator_tab) {
89 has_initiator_tab = true;
90 break;
91 }
92 }
93 CHECK(!has_initiator_tab);
94
95 PrintPreviewTabController* tab_controller =
96 PrintPreviewTabController::GetInstance();
97 if (!tab_controller)
98 return false;
99 TabContentsWrapper* preview_tab =
100 tab_controller->GetPrintPreviewForTab(initiator_tab);
101 if (!preview_tab)
102 return false;
103
104 map_[preview_tab] = initiator_tab;
105
106 // OwnPrintPreviewTab() may have already added this notification.
107 TabContents* preview_contents = preview_tab->tab_contents();
108 if (!registrar_.IsRegistered(this,
109 content::NOTIFICATION_TAB_CONTENTS_DESTROYED,
110 Source<TabContents>(preview_contents))) {
111 registrar_.Add(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED,
112 Source<TabContents>(preview_contents));
113 }
114
115 RemoveFromTabStrip(initiator_tab);
116 return true;
117 }
118
66 void BackgroundPrintingManager::Observe(int type, 119 void BackgroundPrintingManager::Observe(int type,
67 const NotificationSource& source, 120 const NotificationSource& source,
68 const NotificationDetails& details) { 121 const NotificationDetails& details) {
69 switch (type) { 122 switch (type) {
123 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
124 OnRendererProcessClosed(Source<RenderProcessHost>(source).ptr());
125 break;
126 }
70 case chrome::NOTIFICATION_PRINT_JOB_RELEASED: { 127 case chrome::NOTIFICATION_PRINT_JOB_RELEASED: {
71 TabContentsWrapper* tab = Source<TabContentsWrapper>(source).ptr(); 128 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; 129 break;
79 } 130 }
80 case content::NOTIFICATION_TAB_CONTENTS_DESTROYED: { 131 case content::NOTIFICATION_TAB_CONTENTS_DESTROYED: {
81 TabContentsWrapper* tab = 132 OnTabContentsDestroyed(
82 TabContentsWrapper::GetCurrentWrapperForContents( 133 TabContentsWrapper::GetCurrentWrapperForContents(
83 Source<TabContents>(source).ptr()); 134 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; 135 break;
93 } 136 }
94 default: { 137 default: {
95 NOTREACHED(); 138 NOTREACHED();
96 break; 139 break;
97 } 140 }
98 } 141 }
99 } 142 }
100 143
144 void BackgroundPrintingManager::OnRendererProcessClosed(
145 RenderProcessHost* rph) {
146 TabContentsWrapperSet::const_iterator it;
147 for (it = begin(); it != end(); ++it) {
148 TabContentsWrapper* tab = *it;
149 if (tab->render_view_host()->process() == rph)
150 MessageLoop::current()->DeleteSoon(FROM_HERE, tab);
151 }
152 }
153
154 void BackgroundPrintingManager::OnPrintJobReleased(
155 TabContentsWrapper* preview_tab) {
156 registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED,
157 Source<TabContentsWrapper>(preview_tab));
158
159 // This might be happening in the middle of a RenderViewGone() loop.
160 // Deleting |contents| later so the RenderViewGone() loop can finish.
161 MessageLoop::current()->DeleteSoon(FROM_HERE, preview_tab);
162 }
163
164 void BackgroundPrintingManager::OnTabContentsDestroyed(
165 TabContentsWrapper* preview_tab) {
166 bool is_owned_printing_tab = HasPrintPreviewTab(preview_tab);
167 bool is_preview_tab_for_owned_initator_tab =
168 (map_.find(preview_tab) != map_.end());
169 DCHECK(is_owned_printing_tab || is_preview_tab_for_owned_initator_tab);
170
171 // Always need to remove this notification since the tab is gone.
172 registrar_.Remove(this, content::NOTIFICATION_TAB_CONTENTS_DESTROYED,
173 Source<TabContents>(preview_tab->tab_contents()));
174
175 // Delete the associated initiator tab if one exists.
176 if (is_preview_tab_for_owned_initator_tab) {
177 TabContentsWrapper* initiator_tab = map_[preview_tab];
178 map_.erase(preview_tab);
179 MessageLoop::current()->DeleteSoon(FROM_HERE, initiator_tab);
180 }
181
182 // If |preview_tab| is not owned, then we are done.
183 if (!is_owned_printing_tab)
184 return;
185
186 // Remove NOTIFICATION_RENDERER_PROCESS_CLOSED if |tab| is the last
187 // TabContents associated with |rph|.
188 bool shared_rph = false;
189 RenderProcessHost* rph = preview_tab->render_view_host()->process();
190 TabContentsWrapperSet::const_iterator it;
191 for (it = begin(); it != end(); ++it) {
192 TabContentsWrapper* iter_tab = *it;
193 if (iter_tab == preview_tab)
194 continue;
195 if (iter_tab->render_view_host()->process() == rph) {
196 shared_rph = true;
197 break;
198 }
199 }
200 if (!shared_rph) {
201 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
202 Source<RenderProcessHost>(rph));
203 }
204
205 // Remove other notifications and remove the tab from |printing_tabs_|.
206 if (registrar_.IsRegistered(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED,
207 Source<TabContentsWrapper>(preview_tab))) {
208 registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED,
209 Source<TabContentsWrapper>(preview_tab));
210 }
211 printing_tabs_.erase(preview_tab);
212 }
213
214 void BackgroundPrintingManager::RemoveFromTabStrip(TabContentsWrapper* tab) {
215 Browser* browser = BrowserList::FindBrowserWithID(
216 tab->restore_tab_helper()->window_id().id());
217 DCHECK(browser);
218
219 TabStripModel* tabstrip = browser->tabstrip_model();
220 int index = tabstrip->GetIndexOfTabContents(tab);
221 if (index == TabStripModel::kNoTab)
222 return;
223 tabstrip->DetachTabContentsAt(index);
224 }
225
101 BackgroundPrintingManager::TabContentsWrapperSet::const_iterator 226 BackgroundPrintingManager::TabContentsWrapperSet::const_iterator
102 BackgroundPrintingManager::begin() { 227 BackgroundPrintingManager::begin() {
103 return printing_tabs_.begin(); 228 return printing_tabs_.begin();
104 } 229 }
105 230
106 BackgroundPrintingManager::TabContentsWrapperSet::const_iterator 231 BackgroundPrintingManager::TabContentsWrapperSet::const_iterator
107 BackgroundPrintingManager::end() { 232 BackgroundPrintingManager::end() {
108 return printing_tabs_.end(); 233 return printing_tabs_.end();
109 } 234 }
110 235
111 bool BackgroundPrintingManager::HasPrintPreviewTab( 236 bool BackgroundPrintingManager::HasPrintPreviewTab(
112 TabContentsWrapper* preview_tab) { 237 TabContentsWrapper* preview_tab) {
113 return printing_tabs_.find(preview_tab) != printing_tabs_.end(); 238 return printing_tabs_.find(preview_tab) != printing_tabs_.end();
114 } 239 }
115 240
116 } // namespace printing 241 } // namespace printing
OLDNEW
« no previous file with comments | « chrome/browser/printing/background_printing_manager.h ('k') | chrome/browser/ui/browser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698