print_view_manager.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/printing/print_view_manager.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "app/l10n_util.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/scoped_ptr.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/printing/print_job.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/printing/print_job_manager.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/printing/printer_query.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/render_view_host.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/navigation_entry.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_contents.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/notification_service.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/render_messages.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "printing/native_metafile.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "printing/printed_document.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeDelta;
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace printing {
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochPrintViewManager::PrintViewManager(TabContents& owner)
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : waiting_to_print_(false),
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      printing_succeeded_(false),
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      inside_inner_message_loop_(false),
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      owner_(owner) {
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochPrintViewManager::~PrintViewManager() {
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DisconnectFromCurrentPrintJob();
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PrintViewManager::Stop() {
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Cancel the current job, wait for the worker to finish.
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TerminatePrintJob(true);
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool PrintViewManager::OnRenderViewGone(RenderViewHost* render_view_host) {
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!print_job_.get())
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (render_view_host != owner_.render_view_host())
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<PrintedDocument> document(print_job_->document());
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (document) {
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If IsComplete() returns false, the document isn't completely rendered.
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Since our renderer is gone, there's nothing to do, cancel it. Otherwise,
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // the print job may finish without problem.
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TerminatePrintJob(!document->IsComplete());
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::wstring PrintViewManager::RenderSourceName() {
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::wstring name(UTF16ToWideHack(owner_.GetTitle()));
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (name.empty())
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    name = l10n_util::GetString(IDS_DEFAULT_PRINT_DOCUMENT_TITLE);
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return name;
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGURL PrintViewManager::RenderSourceUrl() {
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NavigationEntry* entry = owner_.controller().GetActiveEntry();
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (entry)
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return entry->virtual_url();
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return GURL();
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PrintViewManager::DidGetPrintedPagesCount(int cookie, int number_pages) {
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GT(cookie, 0);
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!OpportunisticallyCreatePrintJob(cookie))
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PrintedDocument* document = print_job_->document();
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!document || cookie != document->cookie()) {
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Out of sync. It may happens since we are completely asynchronous. Old
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // spurious message can happen if one of the processes is overloaded.
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Time to inform our print job. Make sure it is for the right document.
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!document->page_count()) {
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    document->set_page_count(number_pages);
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PrintViewManager::DidPrintPage(
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const ViewHostMsg_DidPrintPage_Params& params) {
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!OpportunisticallyCreatePrintJob(params.document_cookie))
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PrintedDocument* document = print_job_->document();
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!document || params.document_cookie != document->cookie()) {
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Out of sync. It may happen since we are completely asynchronous. Old
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // spurious messages can be received if one of the processes is overloaded.
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // http://msdn2.microsoft.com/en-us/library/ms535522.aspx
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Windows 2000/XP: When a page in a spooled file exceeds approximately 350
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // MB, it can fail to print and not send an error message.
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (params.data_size && params.data_size >= 350*1024*1024) {
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "size:" << params.data_size;
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TerminatePrintJob(true);
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    owner_.Stop();
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::SharedMemory shared_buf(params.metafile_data_handle, true);
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!shared_buf.Map(params.data_size)) {
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "couldn't map";
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    owner_.Stop();
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_POSIX) && !defined(OS_MACOSX)
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NOTIMPLEMENTED() << " this printing code doesn't quite work yet.";
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<NativeMetafile> metafile(new NativeMetafile());
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!metafile->CreateFromData(shared_buf.memory(), params.data_size)) {
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Invalid metafile header";
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    owner_.Stop();
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Update the rendered document. It will send notifications to the listener.
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  document->SetPage(params.page_number,
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    metafile.release(),
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    params.actual_shrink,
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    params.page_size,
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    params.content_area,
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    params.has_visible_overlays);
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ShouldQuitFromInnerMessageLoop();
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PrintViewManager::Observe(NotificationType type,
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               const NotificationSource& source,
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               const NotificationDetails& details) {
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (type.value) {
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case NotificationType::PRINT_JOB_EVENT: {
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      OnNotifyPrintJobEvent(*Details<JobEventDetails>(details).ptr());
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default: {
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PrintViewManager::OnNotifyPrintJobEvent(
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const JobEventDetails& event_details) {
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (event_details.type()) {
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case JobEventDetails::FAILED: {
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      TerminatePrintJob(true);
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case JobEventDetails::USER_INIT_DONE:
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case JobEventDetails::DEFAULT_INIT_DONE:
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case JobEventDetails::USER_INIT_CANCELED: {
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case JobEventDetails::ALL_PAGES_REQUESTED: {
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ShouldQuitFromInnerMessageLoop();
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case JobEventDetails::NEW_DOC:
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case JobEventDetails::NEW_PAGE:
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case JobEventDetails::PAGE_DONE: {
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Don't care about the actual printing process.
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case JobEventDetails::DOC_DONE: {
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      waiting_to_print_ = false;
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case JobEventDetails::JOB_DONE: {
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Printing is done, we don't need it anymore.
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // print_job_->is_job_pending() may still be true, depending on the order
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // of object registration.
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      printing_succeeded_ = true;
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ReleasePrintJob();
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default: {
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool PrintViewManager::RenderAllMissingPagesNow() {
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!print_job_.get() || !print_job_->is_job_pending()) {
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_EQ(waiting_to_print_, false);
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We can't print if there is no renderer.
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!owner_.render_view_host() ||
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !owner_.render_view_host()->IsRenderViewLive()) {
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    waiting_to_print_ = false;
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Is the document already complete?
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (print_job_->document() && print_job_->document()->IsComplete()) {
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    waiting_to_print_ = false;
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    printing_succeeded_ = true;
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TabContents is either dying or a second consecutive request to print
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // happened before the first had time to finish. We need to render all the
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // pages in an hurry if a print_job_ is still pending. No need to wait for it
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to actually spool the pages, only to have the renderer generate them. Run
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // a message loop until we get our signal that the print job is satisfied.
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // PrintJob will send a ALL_PAGES_REQUESTED after having received all the
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // pages it needs. MessageLoop::current()->Quit() will be called as soon as
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // print_job_->document()->IsComplete() is true on either ALL_PAGES_REQUESTED
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // or in DidPrintPage(). The check is done in
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ShouldQuitFromInnerMessageLoop().
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // BLOCKS until all the pages are received. (Need to enable recursive task)
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!RunInnerMessageLoop()) {
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This function is always called from DisconnectFromCurrentPrintJob() so we
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // know that the job will be stopped/canceled in any case.
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PrintViewManager::ShouldQuitFromInnerMessageLoop() {
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Look at the reason.
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(print_job_->document());
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (print_job_->document() &&
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      print_job_->document()->IsComplete() &&
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      inside_inner_message_loop_) {
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We are in a message loop created by RenderAllMissingPagesNow. Quit from
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // it.
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MessageLoop::current()->Quit();
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    inside_inner_message_loop_ = false;
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    waiting_to_print_ = false;
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool PrintViewManager::CreateNewPrintJob(PrintJobWorkerOwner* job) {
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!inside_inner_message_loop_);
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (waiting_to_print_) {
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We can't help; we are waiting for a print job initialization. The user is
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // button bashing. The only thing we could do is to batch up the requests.
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Disconnect the current print_job_.
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DisconnectFromCurrentPrintJob();
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We can't print if there is no renderer.
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!owner_.render_view_host() ||
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !owner_.render_view_host()->IsRenderViewLive()) {
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Ask the renderer to generate the print preview, create the print preview
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // view and switch to it, initialize the printer and show the print dialog.
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!print_job_.get());
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(job);
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!job)
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  print_job_ = new PrintJob();
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  print_job_->Initialize(job, this);
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  registrar_.Add(this, NotificationType::PRINT_JOB_EVENT,
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 Source<PrintJob>(print_job_.get()));
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  printing_succeeded_ = false;
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PrintViewManager::DisconnectFromCurrentPrintJob() {
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make sure all the necessary rendered page are done. Don't bother with the
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // return value.
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool result = RenderAllMissingPagesNow();
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that assertion.
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (print_job_.get() &&
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      print_job_->document() &&
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !print_job_->document()->IsComplete()) {
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(!result);
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // That failed.
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TerminatePrintJob(true);
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // DO NOT wait for the job to finish.
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ReleasePrintJob();
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PrintViewManager::PrintingDone(bool success) {
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (print_job_.get()) {
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    owner_.PrintingDone(print_job_->cookie(), success);
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PrintViewManager::TerminatePrintJob(bool cancel) {
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!print_job_.get())
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cancel) {
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We don't need the metafile data anymore because the printing is canceled.
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    print_job_->Cancel();
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    waiting_to_print_ = false;
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    inside_inner_message_loop_ = false;
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(!inside_inner_message_loop_);
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(!print_job_->document() || print_job_->document()->IsComplete() ||
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch           !waiting_to_print_);
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TabContents is either dying or navigating elsewhere. We need to render
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // all the pages in an hurry if a print job is still pending. This does the
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // trick since it runs a blocking message loop:
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    print_job_->Stop();
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ReleasePrintJob();
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PrintViewManager::ReleasePrintJob() {
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(waiting_to_print_, false);
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!print_job_.get())
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PrintingDone(printing_succeeded_);
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  registrar_.Remove(this, NotificationType::PRINT_JOB_EVENT,
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    Source<PrintJob>(print_job_.get()));
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  print_job_->DisconnectSource();
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Don't close the worker thread.
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  print_job_ = NULL;
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PrintViewManager::PrintNowInternal() {
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(waiting_to_print_);
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Settings are already loaded. Go ahead. This will set
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // print_job_->is_job_pending() to true.
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  print_job_->StartPrinting();
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(print_job_->document());
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(print_job_->document()->IsComplete());
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool PrintViewManager::RunInnerMessageLoop() {
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This value may actually be too low:
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // - If we're looping because of printer settings initializaton, the premise
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // here is that some poor users have their print server away on a VPN over
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // dialup. In this situation, the simple fact of opening the printer can be
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // dead slow. On the other side, we don't want to die infinitely for a real
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // network error. Give the printer 60 seconds to comply.
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // - If we're looping because of renderer page generation, the renderer could
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // be cpu bound, the page overly complex/large or the system just
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // memory-bound.
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const int kPrinterSettingsTimeout = 60000;
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::OneShotTimer<MessageLoop> quit_timer;
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  quit_timer.Start(TimeDelta::FromMilliseconds(kPrinterSettingsTimeout),
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   MessageLoop::current(), &MessageLoop::Quit);
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  inside_inner_message_loop_ = true;
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Need to enable recursive task.
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool old_state = MessageLoop::current()->NestableTasksAllowed();
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->SetNestableTasksAllowed(true);
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->Run();
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Restore task state.
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->SetNestableTasksAllowed(old_state);
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool success = true;
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (inside_inner_message_loop_) {
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Ok we timed out. That's sad.
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    inside_inner_message_loop_ = false;
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    success = false;
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return success;
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool PrintViewManager::OpportunisticallyCreatePrintJob(int cookie) {
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (print_job_.get())
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!cookie) {
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Out of sync. It may happens since we are completely asynchronous. Old
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // spurious message can happen if one of the processes is overloaded.
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The job was initiated by a script. Time to get the corresponding worker
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // thread.
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<PrinterQuery> queued_query;
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_browser_process->print_job_manager()->PopPrinterQuery(cookie,
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                          &queued_query);
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(queued_query.get());
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!queued_query.get())
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!CreateNewPrintJob(queued_query.get())) {
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Don't kill anything.
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Settings are already loaded. Go ahead. This will set
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // print_job_->is_job_pending() to true.
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  print_job_->StartPrinting();
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace printing
424