• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/printing/background_printing_manager.h"
6 
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"
18 
19 using content::BrowserThread;
20 using content::WebContents;
21 
22 namespace printing {
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() OVERRIDE;
32 
33   BackgroundPrintingManager* manager_;
34 };
35 
Observer(BackgroundPrintingManager * manager,WebContents * web_contents)36 BackgroundPrintingManager::Observer::Observer(
37     BackgroundPrintingManager* manager, WebContents* web_contents)
38     : content::WebContentsObserver(web_contents),
39       manager_(manager) {
40 }
41 
RenderProcessGone(base::TerminationStatus status)42 void BackgroundPrintingManager::Observer::RenderProcessGone(
43     base::TerminationStatus status) {
44   manager_->DeletePreviewContents(web_contents());
45 }
WebContentsDestroyed()46 void BackgroundPrintingManager::Observer::WebContentsDestroyed() {
47   manager_->DeletePreviewContents(web_contents());
48 }
49 
BackgroundPrintingManager()50 BackgroundPrintingManager::BackgroundPrintingManager() {
51   DCHECK_CURRENTLY_ON(BrowserThread::UI);
52 }
53 
~BackgroundPrintingManager()54 BackgroundPrintingManager::~BackgroundPrintingManager() {
55   DCHECK(CalledOnValidThread());
56   // The might be some WebContentses still in |printing_contents_map_| at this
57   // point (e.g. when the last remaining tab closes and there is still a print
58   // preview WebContents trying to print). In such a case it will fail to print,
59   // but we should at least clean up the observers.
60   // TODO(thestig): Handle this case better.
61   STLDeleteValues(&printing_contents_map_);
62 }
63 
OwnPrintPreviewDialog(WebContents * preview_dialog)64 void BackgroundPrintingManager::OwnPrintPreviewDialog(
65     WebContents* preview_dialog) {
66   DCHECK(CalledOnValidThread());
67   DCHECK(PrintPreviewDialogController::IsPrintPreviewDialog(preview_dialog));
68   CHECK(!HasPrintPreviewDialog(preview_dialog));
69 
70   printing_contents_map_[preview_dialog] = new Observer(this, preview_dialog);
71 
72   // Watch for print jobs finishing. Everything else is watched for by the
73   // Observer. TODO(avi, cait): finish the job of removing this last
74   // notification.
75   registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED,
76                  content::Source<WebContents>(preview_dialog));
77 
78   // Activate the initiator.
79   PrintPreviewDialogController* dialog_controller =
80       PrintPreviewDialogController::GetInstance();
81   if (!dialog_controller)
82     return;
83   WebContents* initiator = dialog_controller->GetInitiator(preview_dialog);
84   if (!initiator)
85     return;
86   initiator->GetDelegate()->ActivateContents(initiator);
87 }
88 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)89 void BackgroundPrintingManager::Observe(
90     int type,
91     const content::NotificationSource& source,
92     const content::NotificationDetails& details) {
93   DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_RELEASED, type);
94   DeletePreviewContents(content::Source<WebContents>(source).ptr());
95 }
96 
DeletePreviewContents(WebContents * preview_contents)97 void BackgroundPrintingManager::DeletePreviewContents(
98     WebContents* preview_contents) {
99   WebContentsObserverMap::iterator i =
100       printing_contents_map_.find(preview_contents);
101   if (i == printing_contents_map_.end()) {
102     // Everyone is racing to be the first to delete the |preview_contents|. If
103     // this case is hit, someone else won the race, so there is no need to
104     // continue. <http://crbug.com/100806>
105     return;
106   }
107 
108   // Stop all observation ...
109   registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_RELEASED,
110                     content::Source<WebContents>(preview_contents));
111   Observer* observer = i->second;
112   printing_contents_map_.erase(i);
113   delete observer;
114 
115   // ... and mortally wound the contents. (Deletion immediately is not a good
116   // idea in case this was called from RenderViewGone.)
117   base::MessageLoop::current()->DeleteSoon(FROM_HERE, preview_contents);
118 }
119 
CurrentContentSet()120 std::set<content::WebContents*> BackgroundPrintingManager::CurrentContentSet() {
121   std::set<content::WebContents*> result;
122   for (WebContentsObserverMap::iterator i = printing_contents_map_.begin();
123        i != printing_contents_map_.end(); ++i) {
124     result.insert(i->first);
125   }
126   return result;
127 }
128 
HasPrintPreviewDialog(WebContents * preview_dialog)129 bool BackgroundPrintingManager::HasPrintPreviewDialog(
130     WebContents* preview_dialog) {
131   return ContainsKey(printing_contents_map_, preview_dialog);
132 }
133 
134 }  // namespace printing
135