blob: 3b17eff05aa50940bb6c3e224a41ff7e164f35ce [file] [log] [blame]
[email protected]5cc4c422011-02-19 00:09:221// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]8ff1d422009-07-07 21:31:395#include "printing/printed_document.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]7d2d0d0e2010-03-06 22:16:107#include <algorithm>
initial.commit09911bf2008-07-26 23:55:298#include <set>
[email protected]7d2d0d0e2010-03-06 22:16:109#include <string>
10#include <vector>
initial.commit09911bf2008-07-26 23:55:2911
[email protected]c95198b2014-06-12 16:56:5512#include "base/bind.h"
[email protected]57999812013-02-24 05:40:5213#include "base/files/file_path.h"
thestig22dfc4012014-09-05 08:29:4414#include "base/files/file_util.h"
[email protected]d0767cb542009-10-08 17:38:3015#include "base/i18n/file_util_icu.h"
[email protected]57999812013-02-24 05:40:5216#include "base/i18n/time_formatting.h"
[email protected]c95198b2014-06-12 16:56:5517#include "base/json/json_writer.h"
[email protected]625332e02010-12-14 07:48:4918#include "base/lazy_instance.h"
[email protected]c95198b2014-06-12 16:56:5519#include "base/memory/ref_counted_memory.h"
[email protected]a76295972013-07-18 00:42:3220#include "base/message_loop/message_loop.h"
[email protected]c95198b2014-06-12 16:56:5521#include "base/numerics/safe_conversions.h"
[email protected]896d161f2013-06-11 22:52:2422#include "base/strings/string_util.h"
23#include "base/strings/stringprintf.h"
[email protected]906265872013-06-07 22:40:4524#include "base/strings/utf_string_conversions.h"
[email protected]c95198b2014-06-12 16:56:5525#include "base/time/time.h"
26#include "base/values.h"
[email protected]8ff1d422009-07-07 21:31:3927#include "printing/page_number.h"
[email protected]c95198b2014-06-12 16:56:5528#include "printing/print_settings_conversion.h"
[email protected]8ff1d422009-07-07 21:31:3929#include "printing/printed_page.h"
[email protected]57999812013-02-24 05:40:5230#include "printing/printed_pages_source.h"
[email protected]4ae30d082009-02-20 17:55:5531#include "printing/units.h"
[email protected]c399a8a2008-11-22 19:38:0032#include "skia/ext/platform_device.h"
[email protected]08397d52011-02-05 01:53:3833#include "ui/gfx/font.h"
[email protected]dbb97ba2013-09-09 22:15:2534#include "ui/gfx/text_elider.h"
initial.commit09911bf2008-07-26 23:55:2935
[email protected]c95198b2014-06-12 16:56:5536namespace printing {
37
[email protected]e1504d82009-07-03 15:27:1538namespace {
39
[email protected]c95198b2014-06-12 16:56:5540base::LazyInstance<base::FilePath> g_debug_dump_info =
[email protected]6de0fd1d2011-11-15 13:31:4941 LAZY_INSTANCE_INITIALIZER;
[email protected]e1504d82009-07-03 15:27:1542
[email protected]c95198b2014-06-12 16:56:5543void DebugDumpPageTask(const base::string16& doc_name,
44 const PrintedPage* page) {
45 if (g_debug_dump_info.Get().empty())
46 return;
47
48 base::string16 filename = doc_name;
49 filename +=
50 base::ASCIIToUTF16(base::StringPrintf("_%04d", page->page_number()));
vitalybuka5d1290582014-09-12 09:19:5951 base::FilePath file_path =
[email protected]c95198b2014-06-12 16:56:5552#if defined(OS_WIN)
vitalybuka5d1290582014-09-12 09:19:5953 PrintedDocument::CreateDebugDumpPath(filename, FILE_PATH_LITERAL(".emf"));
[email protected]c95198b2014-06-12 16:56:5554#else // OS_WIN
vitalybuka5d1290582014-09-12 09:19:5955 PrintedDocument::CreateDebugDumpPath(filename, FILE_PATH_LITERAL(".pdf"));
[email protected]c95198b2014-06-12 16:56:5556#endif // OS_WIN
vitalybuka5d1290582014-09-12 09:19:5957 base::File file(file_path,
58 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
59 page->metafile()->SaveTo(&file);
[email protected]c95198b2014-06-12 16:56:5560}
61
62void DebugDumpDataTask(const base::string16& doc_name,
63 const base::FilePath::StringType& extension,
64 const base::RefCountedMemory* data) {
65 base::FilePath path =
66 PrintedDocument::CreateDebugDumpPath(doc_name, extension);
67 if (path.empty())
68 return;
69 base::WriteFile(path,
70 reinterpret_cast<const char*>(data->front()),
71 base::checked_cast<int>(data->size()));
72}
73
74void DebugDumpSettings(const base::string16& doc_name,
75 const PrintSettings& settings,
76 base::TaskRunner* blocking_runner) {
77 base::DictionaryValue job_settings;
78 PrintSettingsToJobSettingsDebug(settings, &job_settings);
79 std::string settings_str;
80 base::JSONWriter::WriteWithOptions(
estade8d046462015-05-16 01:02:3481 job_settings, base::JSONWriter::OPTIONS_PRETTY_PRINT, &settings_str);
[email protected]c95198b2014-06-12 16:56:5582 scoped_refptr<base::RefCountedMemory> data =
83 base::RefCountedString::TakeString(&settings_str);
84 blocking_runner->PostTask(
85 FROM_HERE,
86 base::Bind(
87 &DebugDumpDataTask, doc_name, FILE_PATH_LITERAL(".json"), data));
88}
89
[email protected]e1504d82009-07-03 15:27:1590} // namespace
91
initial.commit09911bf2008-07-26 23:55:2992PrintedDocument::PrintedDocument(const PrintSettings& settings,
93 PrintedPagesSource* source,
[email protected]c95198b2014-06-12 16:56:5594 int cookie,
95 base::TaskRunner* blocking_runner)
96 : mutable_(source), immutable_(settings, source, cookie, blocking_runner) {
initial.commit09911bf2008-07-26 23:55:2997 // Records the expected page count if a range is setup.
[email protected]e5324b52013-10-29 03:16:3798 if (!settings.ranges().empty()) {
initial.commit09911bf2008-07-26 23:55:2999 // If there is a range, set the number of page
[email protected]e5324b52013-10-29 03:16:37100 for (unsigned i = 0; i < settings.ranges().size(); ++i) {
101 const PageRange& range = settings.ranges()[i];
initial.commit09911bf2008-07-26 23:55:29102 mutable_.expected_page_count_ += range.to - range.from + 1;
103 }
104 }
[email protected]c95198b2014-06-12 16:56:55105
106 if (!g_debug_dump_info.Get().empty())
107 DebugDumpSettings(name(), settings, blocking_runner);
initial.commit09911bf2008-07-26 23:55:29108}
109
110PrintedDocument::~PrintedDocument() {
111}
112
[email protected]0e0fca32009-07-06 15:25:50113void PrintedDocument::SetPage(int page_number,
vitalybuka5d1290582014-09-12 09:19:59114 scoped_ptr<MetafilePlayer> metafile,
[email protected]9de1347a2014-06-12 09:49:08115#if defined(OS_WIN)
pkasting46a62912014-10-09 21:30:00116 float shrink,
[email protected]9de1347a2014-06-12 09:49:08117#endif // OS_WIN
[email protected]40c7cfe2010-07-01 07:04:05118 const gfx::Size& paper_size,
[email protected]3cce5382011-09-23 23:21:21119 const gfx::Rect& page_rect) {
initial.commit09911bf2008-07-26 23:55:29120 // Notice the page_number + 1, the reason is that this is the value that will
121 // be shown. Users dislike 0-based counting.
122 scoped_refptr<PrintedPage> page(
vitalybuka5d1290582014-09-12 09:19:59123 new PrintedPage(page_number + 1, metafile.Pass(), paper_size, page_rect));
[email protected]9de1347a2014-06-12 09:49:08124#if defined(OS_WIN)
125 page->set_shrink_factor(shrink);
126#endif // OS_WIN
initial.commit09911bf2008-07-26 23:55:29127 {
[email protected]20305ec2011-01-21 04:55:52128 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:29129 mutable_.pages_[page_number] = page;
[email protected]da4eefd2011-03-03 23:40:27130
131#if defined(OS_POSIX) && !defined(OS_MACOSX)
132 if (page_number < mutable_.first_page)
133 mutable_.first_page = page_number;
134#endif
initial.commit09911bf2008-07-26 23:55:29135 }
[email protected]c95198b2014-06-12 16:56:55136
137 if (!g_debug_dump_info.Get().empty()) {
138 immutable_.blocking_runner_->PostTask(
139 FROM_HERE, base::Bind(&DebugDumpPageTask, name(), page));
140 }
initial.commit09911bf2008-07-26 23:55:29141}
142
[email protected]c95198b2014-06-12 16:56:55143scoped_refptr<PrintedPage> PrintedDocument::GetPage(int page_number) {
144 scoped_refptr<PrintedPage> page;
145 {
146 base::AutoLock lock(lock_);
147 PrintedPages::const_iterator itr = mutable_.pages_.find(page_number);
148 if (itr != mutable_.pages_.end())
149 page = itr->second;
initial.commit09911bf2008-07-26 23:55:29150 }
[email protected]c95198b2014-06-12 16:56:55151 return page;
initial.commit09911bf2008-07-26 23:55:29152}
153
initial.commit09911bf2008-07-26 23:55:29154bool PrintedDocument::IsComplete() const {
[email protected]20305ec2011-01-21 04:55:52155 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:29156 if (!mutable_.page_count_)
157 return false;
158 PageNumber page(immutable_.settings_, mutable_.page_count_);
159 if (page == PageNumber::npos())
160 return false;
[email protected]5cc4c422011-02-19 00:09:22161
initial.commit09911bf2008-07-26 23:55:29162 for (; page != PageNumber::npos(); ++page) {
[email protected]da4eefd2011-03-03 23:40:27163#if defined(OS_WIN) || defined(OS_MACOSX)
164 const bool metafile_must_be_valid = true;
[email protected]5cc4c422011-02-19 00:09:22165#elif defined(OS_POSIX)
[email protected]da4eefd2011-03-03 23:40:27166 const bool metafile_must_be_valid = (page.ToInt() == mutable_.first_page);
[email protected]5cc4c422011-02-19 00:09:22167#endif
initial.commit09911bf2008-07-26 23:55:29168 PrintedPages::const_iterator itr = mutable_.pages_.find(page.ToInt());
[email protected]5cc4c422011-02-19 00:09:22169 if (itr == mutable_.pages_.end() || !itr->second.get())
170 return false;
[email protected]7d7489902011-04-11 21:54:06171 if (metafile_must_be_valid && !itr->second->metafile())
initial.commit09911bf2008-07-26 23:55:29172 return false;
173 }
174 return true;
175}
176
initial.commit09911bf2008-07-26 23:55:29177void PrintedDocument::DisconnectSource() {
[email protected]20305ec2011-01-21 04:55:52178 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:29179 mutable_.source_ = NULL;
180}
181
initial.commit09911bf2008-07-26 23:55:29182void PrintedDocument::set_page_count(int max_page) {
[email protected]20305ec2011-01-21 04:55:52183 base::AutoLock lock(lock_);
[email protected]e1504d82009-07-03 15:27:15184 DCHECK_EQ(0, mutable_.page_count_);
185 mutable_.page_count_ = max_page;
[email protected]e5324b52013-10-29 03:16:37186 if (immutable_.settings_.ranges().empty()) {
[email protected]e1504d82009-07-03 15:27:15187 mutable_.expected_page_count_ = max_page;
188 } else {
189 // If there is a range, don't bother since expected_page_count_ is already
190 // initialized.
191 DCHECK_NE(mutable_.expected_page_count_, 0);
initial.commit09911bf2008-07-26 23:55:29192 }
initial.commit09911bf2008-07-26 23:55:29193}
194
195int PrintedDocument::page_count() const {
[email protected]20305ec2011-01-21 04:55:52196 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:29197 return mutable_.page_count_;
198}
199
200int PrintedDocument::expected_page_count() const {
[email protected]20305ec2011-01-21 04:55:52201 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:29202 return mutable_.expected_page_count_;
203}
204
[email protected]79f63882013-02-10 05:15:45205void PrintedDocument::set_debug_dump_path(
206 const base::FilePath& debug_dump_path) {
[email protected]c95198b2014-06-12 16:56:55207 g_debug_dump_info.Get() = debug_dump_path;
[email protected]e1504d82009-07-03 15:27:15208}
209
[email protected]c95198b2014-06-12 16:56:55210base::FilePath PrintedDocument::CreateDebugDumpPath(
211 const base::string16& document_name,
212 const base::FilePath::StringType& extension) {
213 if (g_debug_dump_info.Get().empty())
214 return base::FilePath();
215 // Create a filename.
216 base::string16 filename;
217 base::Time now(base::Time::Now());
218 filename = base::TimeFormatShortDateAndTime(now);
219 filename += base::ASCIIToUTF16("_");
220 filename += document_name;
221 base::FilePath::StringType system_filename;
222#if defined(OS_WIN)
223 system_filename = filename;
224#else // OS_WIN
225 system_filename = base::UTF16ToUTF8(filename);
226#endif // OS_WIN
[email protected]6bc03de2014-08-07 23:59:15227 base::i18n::ReplaceIllegalCharactersInPath(&system_filename, '_');
[email protected]c95198b2014-06-12 16:56:55228 return g_debug_dump_info.Get().Append(system_filename).AddExtension(
229 extension);
230}
231
232void PrintedDocument::DebugDumpData(
233 const base::RefCountedMemory* data,
234 const base::FilePath::StringType& extension) {
235 if (g_debug_dump_info.Get().empty())
236 return;
237 immutable_.blocking_runner_->PostTask(
238 FROM_HERE, base::Bind(&DebugDumpDataTask, name(), extension, data));
[email protected]e1504d82009-07-03 15:27:15239}
240
initial.commit09911bf2008-07-26 23:55:29241PrintedDocument::Mutable::Mutable(PrintedPagesSource* source)
242 : source_(source),
243 expected_page_count_(0),
[email protected]732b8132012-01-10 23:17:32244 page_count_(0) {
[email protected]da4eefd2011-03-03 23:40:27245#if defined(OS_POSIX) && !defined(OS_MACOSX)
246 first_page = INT_MAX;
247#endif
initial.commit09911bf2008-07-26 23:55:29248}
249
[email protected]20f0487a2010-09-30 20:06:30250PrintedDocument::Mutable::~Mutable() {
251}
252
initial.commit09911bf2008-07-26 23:55:29253PrintedDocument::Immutable::Immutable(const PrintSettings& settings,
254 PrintedPagesSource* source,
[email protected]c95198b2014-06-12 16:56:55255 int cookie,
256 base::TaskRunner* blocking_runner)
initial.commit09911bf2008-07-26 23:55:29257 : settings_(settings),
initial.commit09911bf2008-07-26 23:55:29258 name_(source->RenderSourceName()),
[email protected]c95198b2014-06-12 16:56:55259 cookie_(cookie),
260 blocking_runner_(blocking_runner) {
initial.commit09911bf2008-07-26 23:55:29261}
262
[email protected]20f0487a2010-09-30 20:06:30263PrintedDocument::Immutable::~Immutable() {
264}
265
[email protected]d53002f42014-01-14 16:08:56266#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
[email protected]b25f0032013-08-19 22:26:25267// This function is not used on aura linux/chromeos or android.
[email protected]82b72cb82011-12-06 00:23:44268void PrintedDocument::RenderPrintedPage(const PrintedPage& page,
269 PrintingContext* context) const {
270}
271#endif
272
initial.commit09911bf2008-07-26 23:55:29273} // namespace printing