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
3 // found in the LICENSE file.
5 #include "chrome/browser/printing/background_printing_manager.h"
7 #include "base/stl_util.h"
8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/printing/print_job.h"
10 #include "chrome/browser/printing/print_preview_dialog_controller.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/notification_details.h"
13 #include "content/public/browser/notification_source.h"
14 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/web_contents.h"
16 #include "content/public/browser/web_contents_delegate.h"
17 #include "content/public/browser/web_contents_observer.h"
19 using content::BrowserThread
;
20 using content::WebContents
;
24 class BackgroundPrintingManager::Observer
25 : public content::WebContentsObserver
{
27 Observer(BackgroundPrintingManager
* manager
, WebContents
* web_contents
);
30 virtual void RenderProcessGone(base::TerminationStatus status
) OVERRIDE
;
31 virtual void WebContentsDestroyed(WebContents
* web_contents
) OVERRIDE
;
33 BackgroundPrintingManager
* manager_
;
36 BackgroundPrintingManager::Observer::Observer(
37 BackgroundPrintingManager
* manager
, WebContents
* web_contents
)
38 : content::WebContentsObserver(web_contents
),
42 void BackgroundPrintingManager::Observer::RenderProcessGone(
43 base::TerminationStatus status
) {
44 manager_
->DeletePreviewContents(web_contents());
46 void BackgroundPrintingManager::Observer::WebContentsDestroyed(
47 WebContents
* web_contents
) {
48 manager_
->DeletePreviewContents(web_contents
);
51 BackgroundPrintingManager::BackgroundPrintingManager() {
52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
55 BackgroundPrintingManager::~BackgroundPrintingManager() {
56 DCHECK(CalledOnValidThread());
57 // The might be some WebContentses still in |printing_contents_map_| at this
58 // point (e.g. when the last remaining tab closes and there is still a 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.
61 // TODO(thestig): Handle this case better.
62 STLDeleteValues(&printing_contents_map_
);
65 void BackgroundPrintingManager::OwnPrintPreviewDialog(
66 WebContents
* preview_dialog
) {
67 DCHECK(CalledOnValidThread());
68 DCHECK(PrintPreviewDialogController::IsPrintPreviewDialog(preview_dialog
));
69 CHECK(!HasPrintPreviewDialog(preview_dialog
));
71 printing_contents_map_
[preview_dialog
] = new Observer(this, preview_dialog
);
73 // Watch for print jobs finishing. Everything else is watched for by the
74 // Observer. TODO(avi, cait): finish the job of removing this last
76 registrar_
.Add(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED
,
77 content::Source
<WebContents
>(preview_dialog
));
79 // Activate the initiator.
80 PrintPreviewDialogController
* dialog_controller
=
81 PrintPreviewDialogController::GetInstance();
82 if (!dialog_controller
)
84 WebContents
* initiator
= dialog_controller
->GetInitiator(preview_dialog
);
87 initiator
->GetDelegate()->ActivateContents(initiator
);
90 void BackgroundPrintingManager::Observe(
92 const content::NotificationSource
& source
,
93 const content::NotificationDetails
& details
) {
94 DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_RELEASED
, type
);
95 DeletePreviewContents(content::Source
<WebContents
>(source
).ptr());
98 void BackgroundPrintingManager::DeletePreviewContents(
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>
109 // Stop all observation ...
110 registrar_
.Remove(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED
,
111 content::Source
<WebContents
>(preview_contents
));
112 Observer
* observer
= i
->second
;
113 printing_contents_map_
.erase(i
);
116 // ... and mortally wound the contents. (Deletion immediately is not a good
117 // idea in case this was called from RenderViewGone.)
118 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, preview_contents
);
121 std::set
<content::WebContents
*> BackgroundPrintingManager::CurrentContentSet() {
122 std::set
<content::WebContents
*> result
;
123 for (WebContentsObserverMap::iterator i
= printing_contents_map_
.begin();
124 i
!= printing_contents_map_
.end(); ++i
) {
125 result
.insert(i
->first
);
130 bool BackgroundPrintingManager::HasPrintPreviewDialog(
131 WebContents
* preview_dialog
) {
132 return ContainsKey(printing_contents_map_
, preview_dialog
);
135 } // namespace printing