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