[M120 Migration][MM] Fix EME AD insert issue
[platform/framework/web/chromium-efl.git] / printing / printed_document.cc
1 // Copyright 2011 The Chromium Authors
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 "printing/printed_document.h"
6
7 #include <algorithm>
8 #include <set>
9 #include <string>
10 #include <utility>
11 #include <vector>
12
13 #include "base/files/file_path.h"
14 #include "base/files/file_util.h"
15 #include "base/functional/bind.h"
16 #include "base/i18n/file_util_icu.h"
17 #include "base/i18n/time_formatting.h"
18 #include "base/json/json_writer.h"
19 #include "base/lazy_instance.h"
20 #include "base/memory/ref_counted_memory.h"
21 #include "base/numerics/safe_conversions.h"
22 #include "base/strings/string_util.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/strings/utf_string_conversions.h"
25 #include "base/task/thread_pool.h"
26 #include "base/time/time.h"
27 #include "base/values.h"
28 #include "build/build_config.h"
29 #include "printing/metafile.h"
30 #include "printing/page_number.h"
31 #include "printing/print_settings_conversion.h"
32 #include "printing/printing_context.h"
33 #include "printing/units.h"
34 #include "ui/gfx/font.h"
35 #include "ui/gfx/text_elider.h"
36
37 #if BUILDFLAG(IS_WIN)
38 #include "printing/printed_page_win.h"
39 #endif
40
41 namespace printing {
42
43 namespace {
44
45 base::LazyInstance<base::FilePath>::Leaky g_debug_dump_info =
46     LAZY_INSTANCE_INITIALIZER;
47
48 #if BUILDFLAG(IS_WIN)
49 void DebugDumpPageTask(const std::u16string& doc_name,
50                        const PrintedPage* page) {
51   DCHECK(PrintedDocument::HasDebugDumpPath());
52
53   static constexpr base::FilePath::CharType kExtension[] =
54       FILE_PATH_LITERAL(".emf");
55
56   std::u16string name = doc_name;
57   name += base::ASCIIToUTF16(base::StringPrintf("_%04d", page->page_number()));
58   base::FilePath path = PrintedDocument::CreateDebugDumpPath(name, kExtension);
59   base::File file(path,
60                   base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
61   page->metafile()->SaveTo(&file);
62 }
63 #endif  // BUILDFLAG(IS_WIN)
64
65 void DebugDumpTask(const std::u16string& doc_name,
66                    const MetafilePlayer* metafile) {
67   DCHECK(PrintedDocument::HasDebugDumpPath());
68
69   static constexpr base::FilePath::CharType kExtension[] =
70       FILE_PATH_LITERAL(".pdf");
71
72   std::u16string name = doc_name;
73   base::FilePath path = PrintedDocument::CreateDebugDumpPath(name, kExtension);
74   base::File file(path,
75                   base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
76 #if BUILDFLAG(IS_ANDROID)
77   metafile->SaveToFileDescriptor(file.GetPlatformFile());
78 #else
79   metafile->SaveTo(&file);
80 #endif  // BUILDFLAG(IS_ANDROID)
81 }
82
83 void DebugDumpDataTask(const std::u16string& doc_name,
84                        const base::FilePath::StringType& extension,
85                        const base::RefCountedMemory* data) {
86   base::FilePath path =
87       PrintedDocument::CreateDebugDumpPath(doc_name, extension);
88   if (path.empty())
89     return;
90   base::WriteFile(path, *data);
91 }
92
93 void DebugDumpSettings(const std::u16string& doc_name,
94                        const PrintSettings& settings) {
95   base::Value job_settings(PrintSettingsToJobSettingsDebug(settings));
96   std::string settings_str;
97   base::JSONWriter::WriteWithOptions(
98       job_settings, base::JSONWriter::OPTIONS_PRETTY_PRINT, &settings_str);
99   scoped_refptr<base::RefCountedMemory> data =
100       base::MakeRefCounted<base::RefCountedString>(std::move(settings_str));
101   base::ThreadPool::PostTask(
102       FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
103       base::BindOnce(&DebugDumpDataTask, doc_name, FILE_PATH_LITERAL(".json"),
104                      base::RetainedRef(data)));
105 }
106
107 }  // namespace
108
109 PrintedDocument::PrintedDocument(std::unique_ptr<PrintSettings> settings,
110                                  const std::u16string& name,
111                                  int cookie)
112     : immutable_(std::move(settings), name, cookie) {
113   // If there is a range, set the number of page
114   for (const PageRange& range : immutable_.settings_->ranges())
115     mutable_.expected_page_count_ += range.to - range.from + 1;
116
117   if (HasDebugDumpPath())
118     DebugDumpSettings(name, *immutable_.settings_);
119 }
120
121 PrintedDocument::~PrintedDocument() = default;
122
123 #if BUILDFLAG(IS_WIN)
124 void PrintedDocument::SetConvertingPdf() {
125   base::AutoLock lock(lock_);
126   mutable_.converting_pdf_ = true;
127 }
128
129 void PrintedDocument::SetPage(uint32_t page_number,
130                               std::unique_ptr<MetafilePlayer> metafile,
131                               float shrink,
132                               const gfx::Size& page_size,
133                               const gfx::Rect& page_content_rect) {
134   // Notice the page_number + 1, the reason is that this is the value that will
135   // be shown. Users dislike 0-based counting.
136   auto page = base::MakeRefCounted<PrintedPage>(
137       page_number + 1, std::move(metafile), page_size, page_content_rect);
138   page->set_shrink_factor(shrink);
139   {
140     base::AutoLock lock(lock_);
141     mutable_.pages_[page_number] = page;
142   }
143
144   if (HasDebugDumpPath()) {
145     base::ThreadPool::PostTask(
146         FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
147         base::BindOnce(&DebugDumpPageTask, name(), base::RetainedRef(page)));
148   }
149 }
150
151 scoped_refptr<PrintedPage> PrintedDocument::GetPage(uint32_t page_number) {
152   scoped_refptr<PrintedPage> page;
153   {
154     base::AutoLock lock(lock_);
155     PrintedPages::const_iterator it = mutable_.pages_.find(page_number);
156     if (it != mutable_.pages_.end())
157       page = it->second;
158   }
159   return page;
160 }
161
162 void PrintedDocument::RemovePage(const PrintedPage* page) {
163   base::AutoLock lock(lock_);
164   PrintedPages::const_iterator it =
165       mutable_.pages_.find(page->page_number() - 1);
166   DCHECK_EQ(page, it->second.get());
167   mutable_.pages_.erase(it);
168 }
169 #endif  // BUILDFLAG(IS_WIN)
170
171 void PrintedDocument::SetDocument(std::unique_ptr<MetafilePlayer> metafile) {
172   {
173     base::AutoLock lock(lock_);
174     mutable_.metafile_ = std::move(metafile);
175   }
176
177   if (HasDebugDumpPath()) {
178     base::ThreadPool::PostTask(
179         FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
180         base::BindOnce(&DebugDumpTask, name(), mutable_.metafile_.get()));
181   }
182 }
183
184 const MetafilePlayer* PrintedDocument::GetMetafile() {
185   return mutable_.metafile_.get();
186 }
187
188 mojom::ResultCode PrintedDocument::RenderPrintedDocument(
189     PrintingContext* context) {
190   base::AutoLock lock(lock_);
191   mojom::ResultCode result = context->PrintDocument(
192       *GetMetafile(), *immutable_.settings_, mutable_.expected_page_count_);
193   if (result != mojom::ResultCode::kSuccess)
194     return result;
195
196   // Beware of any asynchronous aborts of the print job that happened during
197   // printing.
198   if (context->PrintingAborted())
199     return mojom::ResultCode::kCanceled;
200
201   return mojom::ResultCode::kSuccess;
202 }
203
204 bool PrintedDocument::IsComplete() const {
205   base::AutoLock lock(lock_);
206   if (!mutable_.page_count_)
207     return false;
208 #if BUILDFLAG(IS_WIN)
209   if (mutable_.converting_pdf_)
210     return true;
211
212   PageNumber page(immutable_.settings_->ranges(), mutable_.page_count_);
213   if (page == PageNumber::npos())
214     return false;
215
216   for (; page != PageNumber::npos(); ++page) {
217     PrintedPages::const_iterator it = mutable_.pages_.find(page.ToUint());
218     if (it == mutable_.pages_.end() || !it->second.get() ||
219         !it->second->metafile()) {
220       return false;
221     }
222   }
223   return true;
224 #else
225   return !!mutable_.metafile_;
226 #endif
227 }
228
229 void PrintedDocument::set_page_count(uint32_t max_page) {
230   base::AutoLock lock(lock_);
231   DCHECK_EQ(0u, mutable_.page_count_);
232   mutable_.page_count_ = max_page;
233   if (immutable_.settings_->ranges().empty()) {
234     mutable_.expected_page_count_ = max_page;
235   } else {
236     // If there is a range, don't bother since expected_page_count_ is already
237     // initialized.
238     DCHECK_NE(mutable_.expected_page_count_, 0u);
239   }
240 }
241
242 uint32_t PrintedDocument::page_count() const {
243   base::AutoLock lock(lock_);
244   return mutable_.page_count_;
245 }
246
247 uint32_t PrintedDocument::expected_page_count() const {
248   base::AutoLock lock(lock_);
249   return mutable_.expected_page_count_;
250 }
251
252 // static
253 void PrintedDocument::SetDebugDumpPath(const base::FilePath& debug_dump_path) {
254   DCHECK(!debug_dump_path.empty());
255   g_debug_dump_info.Get() = debug_dump_path;
256 }
257
258 // static
259 bool PrintedDocument::HasDebugDumpPath() {
260   return g_debug_dump_info.IsCreated();
261 }
262
263 // static
264 base::FilePath PrintedDocument::CreateDebugDumpPath(
265     const std::u16string& document_name,
266     const base::FilePath::StringType& extension) {
267   DCHECK(HasDebugDumpPath());
268
269   // Create a filename.
270   std::u16string filename;
271   base::Time now(base::Time::Now());
272   filename = base::TimeFormatShortDateAndTime(now);
273   filename += u"_";
274   filename += document_name;
275   base::FilePath::StringType system_filename;
276 #if BUILDFLAG(IS_WIN)
277   system_filename = base::UTF16ToWide(filename);
278 #else   // BUILDFLAG(IS_WIN)
279   system_filename = base::UTF16ToUTF8(filename);
280 #endif  // BUILDFLAG(IS_WIN)
281   base::i18n::ReplaceIllegalCharactersInPath(&system_filename, '_');
282   const auto& dump_path = g_debug_dump_info.Get();
283   DCHECK(!dump_path.empty());
284   return dump_path.Append(system_filename).AddExtension(extension);
285 }
286
287 void PrintedDocument::DebugDumpData(
288     const base::RefCountedMemory* data,
289     const base::FilePath::StringType& extension) {
290   DCHECK(HasDebugDumpPath());
291   base::ThreadPool::PostTask(
292       FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
293       base::BindOnce(&DebugDumpDataTask, name(), extension,
294                      base::RetainedRef(data)));
295 }
296
297 PrintedDocument::Mutable::Mutable() = default;
298
299 PrintedDocument::Mutable::~Mutable() = default;
300
301 PrintedDocument::Immutable::Immutable(std::unique_ptr<PrintSettings> settings,
302                                       const std::u16string& name,
303                                       int cookie)
304     : settings_(std::move(settings)), name_(name), cookie_(cookie) {}
305
306 PrintedDocument::Immutable::~Immutable() = default;
307
308 }  // namespace printing