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

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

Issue 133013002: Remove render process and WebContents notifications from background printing. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixes Created 6 years, 11 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "base/stl_util.h" 7 #include "base/stl_util.h"
8 #include "chrome/browser/chrome_notification_types.h" 8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/printing/print_job.h" 9 #include "chrome/browser/printing/print_job.h"
10 #include "chrome/browser/printing/print_preview_dialog_controller.h" 10 #include "chrome/browser/printing/print_preview_dialog_controller.h"
11 #include "content/public/browser/browser_thread.h" 11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/notification_details.h" 12 #include "content/public/browser/notification_details.h"
13 #include "content/public/browser/notification_source.h" 13 #include "content/public/browser/notification_source.h"
14 #include "content/public/browser/render_view_host.h" 14 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/web_contents.h" 15 #include "content/public/browser/web_contents.h"
16 #include "content/public/browser/web_contents_delegate.h" 16 #include "content/public/browser/web_contents_delegate.h"
17 #include "content/public/browser/web_contents_observer.h"
17 18
18 using content::BrowserThread; 19 using content::BrowserThread;
19 using content::WebContents; 20 using content::WebContents;
20 21
21 namespace printing { 22 namespace printing {
22 23
24 class BackgroundPrintingManager::Observer
25 : public content::WebContentsObserver {
26 public:
27 Observer(BackgroundPrintingManager* manager, WebContents* web_contents);
28
29 private:
30 virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
31 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
32
33 BackgroundPrintingManager* manager_;
34 };
35
36 BackgroundPrintingManager::Observer::Observer(
37 BackgroundPrintingManager* manager, WebContents* web_contents)
38 : content::WebContentsObserver(web_contents),
39 manager_(manager) {
40 }
41
42 void BackgroundPrintingManager::Observer::RenderProcessGone(
43 base::TerminationStatus status) {
44 manager_->DeletePreviewContents(web_contents());
45 }
46 void BackgroundPrintingManager::Observer::WebContentsDestroyed(
47 WebContents* web_contents) {
48 manager_->DeletePreviewContents(web_contents);
49 }
50
23 BackgroundPrintingManager::BackgroundPrintingManager() { 51 BackgroundPrintingManager::BackgroundPrintingManager() {
24 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
25 } 53 }
26 54
27 BackgroundPrintingManager::~BackgroundPrintingManager() { 55 BackgroundPrintingManager::~BackgroundPrintingManager() {
28 DCHECK(CalledOnValidThread()); 56 DCHECK(CalledOnValidThread());
29 // The might be some WebContentses still in |printing_contents_set_| at this 57 // The might be some WebContentses still in |printing_contents_map_| at this
30 // point. E.g. when the last remaining tab closes and there is still a print 58 // point (e.g. when the last remaining tab closes and there is still a print
31 // preview WebContents trying to print. In which case it will fail to print. 59 // preview WebContents trying to print). In such a case it will fail to print,
60 // but we should at least clean up the observers.
32 // TODO(thestig): Handle this case better. 61 // TODO(thestig): Handle this case better.
62 STLDeleteValues(&printing_contents_map_);
33 } 63 }
34 64
35 void BackgroundPrintingManager::OwnPrintPreviewDialog( 65 void BackgroundPrintingManager::OwnPrintPreviewDialog(
36 WebContents* preview_dialog) { 66 WebContents* preview_dialog) {
37 DCHECK(CalledOnValidThread()); 67 DCHECK(CalledOnValidThread());
38 DCHECK(PrintPreviewDialogController::IsPrintPreviewDialog(preview_dialog)); 68 DCHECK(PrintPreviewDialogController::IsPrintPreviewDialog(preview_dialog));
39 CHECK(!HasPrintPreviewDialog(preview_dialog)); 69 CHECK(!HasPrintPreviewDialog(preview_dialog));
40 70
41 printing_contents_set_.insert(preview_dialog); 71 printing_contents_map_[preview_dialog] = new Observer(this, preview_dialog);
42 72
43 content::Source<WebContents> preview_source(preview_dialog); 73 // Watch for print jobs finishing. Everything else is watched for by the
44 registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED, preview_source); 74 // Observer. TODO(avi, cait): finish the job of removing this last
45 75 // notification.
46 // OwnInitiatorWebContents() may have already added this notification. 76 registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED,
47 if (!registrar_.IsRegistered(this, 77 content::Source<WebContents>(preview_dialog));
48 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, preview_source)) {
49 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
50 preview_source);
51 }
52
53 // If a WebContents that is printing crashes, the user cannot destroy it since
54 // it is hidden. Thus listen for crashes here and delete it.
55 //
56 // Multiple sites may share the same RenderProcessHost, so check if this
57 // notification has already been added.
58 content::Source<content::RenderProcessHost> rph_source(
59 preview_dialog->GetRenderProcessHost());
60 if (!registrar_.IsRegistered(this,
61 content::NOTIFICATION_RENDERER_PROCESS_CLOSED, rph_source)) {
62 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
63 rph_source);
64 }
65 78
66 // Activate the initiator. 79 // Activate the initiator.
67 PrintPreviewDialogController* dialog_controller = 80 PrintPreviewDialogController* dialog_controller =
68 PrintPreviewDialogController::GetInstance(); 81 PrintPreviewDialogController::GetInstance();
69 if (!dialog_controller) 82 if (!dialog_controller)
70 return; 83 return;
71 WebContents* initiator = dialog_controller->GetInitiator(preview_dialog); 84 WebContents* initiator = dialog_controller->GetInitiator(preview_dialog);
72 if (!initiator) 85 if (!initiator)
73 return; 86 return;
74 initiator->GetDelegate()->ActivateContents(initiator); 87 initiator->GetDelegate()->ActivateContents(initiator);
75 } 88 }
76 89
77 void BackgroundPrintingManager::Observe( 90 void BackgroundPrintingManager::Observe(
78 int type, 91 int type,
79 const content::NotificationSource& source, 92 const content::NotificationSource& source,
80 const content::NotificationDetails& details) { 93 const content::NotificationDetails& details) {
81 if (type == content::NOTIFICATION_RENDERER_PROCESS_CLOSED) { 94 DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_RELEASED, type);
82 OnRendererProcessClosed( 95 DeletePreviewContents(content::Source<WebContents>(source).ptr());
83 content::Source<content::RenderProcessHost>(source).ptr());
84 } else if (type == chrome::NOTIFICATION_PRINT_JOB_RELEASED) {
85 OnPrintJobReleased(content::Source<WebContents>(source).ptr());
86 } else {
87 DCHECK_EQ(content::NOTIFICATION_WEB_CONTENTS_DESTROYED, type);
88 OnWebContentsDestroyed(content::Source<WebContents>(source).ptr());
89 }
90 }
91
92 void BackgroundPrintingManager::OnRendererProcessClosed(
93 content::RenderProcessHost* rph) {
94 WebContentsSet printing_contents_pending_deletion_set;
95 WebContentsSet::const_iterator it;
96 for (it = begin(); it != end(); ++it) {
97 WebContents* preview_contents = *it;
98 if (preview_contents->GetRenderProcessHost() == rph) {
99 printing_contents_pending_deletion_set.insert(preview_contents);
100 }
101 }
102 for (it = printing_contents_pending_deletion_set.begin();
103 it != printing_contents_pending_deletion_set.end();
104 ++it) {
105 DeletePreviewContents(*it);
106 }
107 }
108
109 void BackgroundPrintingManager::OnPrintJobReleased(
110 WebContents* preview_contents) {
111 DeletePreviewContents(preview_contents);
112 }
113
114 void BackgroundPrintingManager::OnWebContentsDestroyed(
115 WebContents* preview_contents) {
116 // Always need to remove this notification since the WebContents is gone.
117 content::Source<WebContents> preview_source(preview_contents);
118 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
119 preview_source);
120
121 if (!HasPrintPreviewDialog(preview_contents)) {
122 NOTREACHED();
123 return;
124 }
125
126 // Remove NOTIFICATION_RENDERER_PROCESS_CLOSED if |preview_contents| is the
127 // last WebContents associated with |rph|.
128 bool shared_rph =
129 (HasSharedRenderProcessHost(printing_contents_set_, preview_contents) ||
130 HasSharedRenderProcessHost(printing_contents_pending_deletion_set_,
131 preview_contents));
132 if (!shared_rph) {
133 content::RenderProcessHost* rph = preview_contents->GetRenderProcessHost();
134 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
135 content::Source<content::RenderProcessHost>(rph));
136 }
137
138 // Remove other notifications and remove the WebContents from its
139 // WebContentsSet.
140 if (printing_contents_set_.erase(preview_contents) == 1) {
141 registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED,
142 preview_source);
143 } else {
144 // DeletePreviewContents already deleted the notification.
145 printing_contents_pending_deletion_set_.erase(preview_contents);
146 }
147 } 96 }
148 97
149 void BackgroundPrintingManager::DeletePreviewContents( 98 void BackgroundPrintingManager::DeletePreviewContents(
150 WebContents* preview_contents) { 99 WebContents* preview_contents) {
100 WebContentsObserverMap::iterator i =
101 printing_contents_map_.find(preview_contents);
102 if (i == printing_contents_map_.end()) {
103 // Everyone is racing to be the first to delete the |preview_contents|. If
104 // this case is hit, someone else won the race, so there is no need to
105 // continue. <http://crbug.com/100806>
106 return;
107 }
108
109 // Stop all observation ...
151 registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED, 110 registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED,
152 content::Source<WebContents>(preview_contents)); 111 content::Source<WebContents>(preview_contents));
153 printing_contents_set_.erase(preview_contents); 112 Observer* observer = i->second;
154 printing_contents_pending_deletion_set_.insert(preview_contents); 113 printing_contents_map_.erase(i);
114 delete observer;
115
116 // ... and mortally wound the contents. (Deletion immediately is not a good
117 // idea in case this was called from RenderViewGone.)
155 base::MessageLoop::current()->DeleteSoon(FROM_HERE, preview_contents); 118 base::MessageLoop::current()->DeleteSoon(FROM_HERE, preview_contents);
156 } 119 }
157 120
158 bool BackgroundPrintingManager::HasSharedRenderProcessHost( 121 std::set<content::WebContents*> BackgroundPrintingManager::CurrentContentSet() {
159 const WebContentsSet& set, WebContents* preview_contents) { 122 std::set<content::WebContents*> result;
160 content::RenderProcessHost* rph = preview_contents->GetRenderProcessHost(); 123 for (WebContentsObserverMap::iterator i = printing_contents_map_.begin();
161 for (WebContentsSet::const_iterator it = set.begin(); it != set.end(); ++it) { 124 i != printing_contents_map_.end(); ++i) {
162 WebContents* iter_contents = *it; 125 result.insert(i->first);
163 if (iter_contents == preview_contents)
164 continue;
165 if (iter_contents->GetRenderProcessHost() == rph)
166 return true;
167 } 126 }
168 return false; 127 return result;
169 }
170
171 BackgroundPrintingManager::WebContentsSet::const_iterator
172 BackgroundPrintingManager::begin() {
173 return printing_contents_set_.begin();
174 }
175
176 BackgroundPrintingManager::WebContentsSet::const_iterator
177 BackgroundPrintingManager::end() {
178 return printing_contents_set_.end();
179 } 128 }
180 129
181 bool BackgroundPrintingManager::HasPrintPreviewDialog( 130 bool BackgroundPrintingManager::HasPrintPreviewDialog(
182 WebContents* preview_dialog) { 131 WebContents* preview_dialog) {
183 return (ContainsKey(printing_contents_set_, preview_dialog) || 132 return ContainsKey(printing_contents_map_, preview_dialog);
184 ContainsKey(printing_contents_pending_deletion_set_, preview_dialog));
185 } 133 }
186 134
187 } // namespace printing 135 } // namespace printing
OLDNEW
« no previous file with comments | « chrome/browser/printing/background_printing_manager.h ('k') | chrome/browser/task_manager/tab_contents_resource_provider.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698