diff options
-rw-r--r-- | chrome/common/utility_messages_internal.h | 8 | ||||
-rw-r--r-- | chrome/service/cloud_print/print_system_win.cc | 7 | ||||
-rw-r--r-- | chrome/service/service_child_process_host.cc | 5 | ||||
-rw-r--r-- | chrome/service/service_child_process_host.h | 2 | ||||
-rw-r--r-- | chrome/service/service_utility_process_host.cc | 56 | ||||
-rw-r--r-- | chrome/service/service_utility_process_host.h | 17 | ||||
-rw-r--r-- | chrome/utility/utility_thread.cc | 10 | ||||
-rw-r--r-- | chrome/utility/utility_thread.h | 2 |
8 files changed, 85 insertions, 22 deletions
diff --git a/chrome/common/utility_messages_internal.h b/chrome/common/utility_messages_internal.h index 15bd8d6..18ba3c5 100644 --- a/chrome/common/utility_messages_internal.h +++ b/chrome/common/utility_messages_internal.h @@ -47,8 +47,9 @@ IPC_BEGIN_MESSAGES(Utility) std::vector<unsigned char>) // encoded image contents // Tell the utility process to render the given PDF into a metafile. - IPC_MESSAGE_CONTROL4(UtilityMsg_RenderPDFPagesToMetafile, + IPC_MESSAGE_CONTROL5(UtilityMsg_RenderPDFPagesToMetafile, base::PlatformFile, // PDF file + FilePath, // Location for output metafile gfx::Rect, // Render Area int, // DPI std::vector<printing::PageRange>) @@ -115,9 +116,8 @@ IPC_BEGIN_MESSAGES(UtilityHost) IPC_MESSAGE_CONTROL0(UtilityHostMsg_DecodeImage_Failed) // Reply when the utility process has succeeded in rendering the PDF. - IPC_MESSAGE_CONTROL2(UtilityHostMsg_RenderPDFPagesToMetafile_Succeeded, - printing::NativeMetafile, // Output metafile - int) // Highest rendered page number + IPC_MESSAGE_CONTROL1(UtilityHostMsg_RenderPDFPagesToMetafile_Succeeded, + int) // Highest rendered page number // Reply when an error occured rendering the PDF. IPC_MESSAGE_CONTROL0(UtilityHostMsg_RenderPDFPagesToMetafile_Failed) diff --git a/chrome/service/cloud_print/print_system_win.cc b/chrome/service/cloud_print/print_system_win.cc index 9b71581..fe0d19f 100644 --- a/chrome/service/cloud_print/print_system_win.cc +++ b/chrome/service/cloud_print/print_system_win.cc @@ -503,7 +503,12 @@ class PrintSystemWin : public PrintSystem { utility_host.release(); } } - static const int kPageCountPerBatch = 10; + // Some Cairo-generated PDFs from Chrome OS result in huge metafiles. + // So the PageCountPerBatch is set to 1 for now. + // TODO(sanjeevr): Figure out a smarter way to determine the pages per + // batch. Filed a bug to track this at + // http://code.google.com/p/chromium/issues/detail?id=57350. + static const int kPageCountPerBatch = 1; int last_page_printed_; PlatformJobId job_id_; PrintSystem::JobSpooler::Delegate* delegate_; diff --git a/chrome/service/service_child_process_host.cc b/chrome/service/service_child_process_host.cc index c7cbea2e..00dfacc 100644 --- a/chrome/service/service_child_process_host.cc +++ b/chrome/service/service_child_process_host.cc @@ -22,13 +22,14 @@ ServiceChildProcessHost::~ServiceChildProcessHost() { base::KillProcess(handle(), ResultCodes::NORMAL_EXIT, false); } -bool ServiceChildProcessHost::Launch(CommandLine* cmd_line) { +bool ServiceChildProcessHost::Launch(CommandLine* cmd_line, + const FilePath& exposed_dir) { #if !defined(OS_WIN) // TODO(sanjeevr): Implement for non-Windows OSes. NOTIMPLEMENTED(); return false; #else // !defined(OS_WIN) - set_handle(sandbox::StartProcessWithAccess(cmd_line, FilePath())); + set_handle(sandbox::StartProcessWithAccess(cmd_line, exposed_dir)); return (handle() != base::kNullProcessHandle); #endif // !defined(OS_WIN) } diff --git a/chrome/service/service_child_process_host.h b/chrome/service/service_child_process_host.h index 2743229..fe8b5df 100644 --- a/chrome/service/service_child_process_host.h +++ b/chrome/service/service_child_process_host.h @@ -23,7 +23,7 @@ class ServiceChildProcessHost : public ChildProcessHost, explicit ServiceChildProcessHost(ProcessType type); // Derived classes call this to launch the child process synchronously. // TODO(sanjeevr): Determine whether we need to make the launch asynchronous. - bool Launch(CommandLine* cmd_line); + bool Launch(CommandLine* cmd_line, const FilePath& exposed_dir); }; #endif // CHROME_SERVICE_SERVICE_CHILD_PROCESS_HOST_H_ diff --git a/chrome/service/service_utility_process_host.cc b/chrome/service/service_utility_process_host.cc index 21daaf6..6b2bdbbb 100644 --- a/chrome/service/service_utility_process_host.cc +++ b/chrome/service/service_utility_process_host.cc @@ -9,6 +9,7 @@ #include "base/file_util.h" #include "base/message_loop.h" #include "base/message_loop_proxy.h" +#include "base/scoped_temp_dir.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/utility_messages.h" #include "gfx/rect.h" @@ -38,7 +39,15 @@ bool ServiceUtilityProcessHost::StartRenderPDFPagesToMetafile( NOTIMPLEMENTED(); return false; #else // !defined(OS_WIN) - if (!StartProcess()) + scratch_metafile_dir_.reset(new ScopedTempDir); + if (!scratch_metafile_dir_->CreateUniqueTempDir()) + return false; + if (!file_util::CreateTemporaryFileInDir(scratch_metafile_dir_->path(), + &metafile_path_)) { + return false; + } + + if (!StartProcess(scratch_metafile_dir_->path())) return false; ScopedHandle pdf_file( @@ -60,13 +69,14 @@ bool ServiceUtilityProcessHost::StartRenderPDFPagesToMetafile( waiting_for_reply_ = true; return SendOnChannel( new UtilityMsg_RenderPDFPagesToMetafile(pdf_file_in_utility_process, + metafile_path_, render_area, render_dpi, page_ranges)); #endif // !defined(OS_WIN) } -bool ServiceUtilityProcessHost::StartProcess() { +bool ServiceUtilityProcessHost::StartProcess(const FilePath& exposed_dir) { // Name must be set or metrics_service will crash in any test which // launches a UtilityProcessHost. set_name(L"utility process"); @@ -85,7 +95,7 @@ bool ServiceUtilityProcessHost::StartProcess() { cmd_line.AppendSwitchASCII(switches::kProcessChannelID, channel_id()); cmd_line.AppendSwitch(switches::kLang); - return Launch(&cmd_line); + return Launch(&cmd_line, exposed_dir); } FilePath ServiceUtilityProcessHost::GetUtilityProcessCmd() { @@ -110,6 +120,8 @@ void ServiceUtilityProcessHost::OnMessageReceived(const IPC::Message& message) { #if defined(OS_WIN) // This hack is Windows-specific. IPC_MESSAGE_HANDLER(UtilityHostMsg_PreCacheFont, OnPreCacheFont) #endif + IPC_MESSAGE_HANDLER(UtilityHostMsg_RenderPDFPagesToMetafile_Succeeded, + OnRenderPDFPagesToMetafileSucceeded) IPC_MESSAGE_UNHANDLED(msg_is_ok__ = MessageForClient(message)) IPC_END_MESSAGE_MAP_EX() } @@ -130,16 +142,46 @@ void ServiceUtilityProcessHost::OnPreCacheFont(LOGFONT font) { } #endif // OS_WIN +void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafileSucceeded( + int highest_rendered_page_number) { + DCHECK(waiting_for_reply_); + // If the metafile was successfully created, we need to take our hands off the + // scratch metafile directory. The client will delete it when it is done with + // metafile. + scratch_metafile_dir_->Take(); + client_message_loop_proxy_->PostTask( + FROM_HERE, + NewRunnableMethod(client_.get(), + &Client::MetafileAvailable, + metafile_path_, + highest_rendered_page_number)); + waiting_for_reply_ = false; +} void ServiceUtilityProcessHost::Client::OnMessageReceived( const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(ServiceUtilityProcessHost, message) -#if defined(OS_WIN) - IPC_MESSAGE_HANDLER(UtilityHostMsg_RenderPDFPagesToMetafile_Succeeded, - Client::OnRenderPDFPagesToMetafileSucceeded) -#endif // OS_WIN IPC_MESSAGE_HANDLER(UtilityHostMsg_RenderPDFPagesToMetafile_Failed, Client::OnRenderPDFPagesToMetafileFailed) IPC_END_MESSAGE_MAP_EX() } +void ServiceUtilityProcessHost::Client::MetafileAvailable( + const FilePath& metafile_path, + int highest_rendered_page_number) { + // The metafile was created in a temp folder which needs to get deleted after + // we have processed it. + ScopedTempDir scratch_metafile_dir; + scratch_metafile_dir.Set(metafile_path.DirName()); +#if defined(OS_WIN) + printing::NativeMetafile metafile; + if (!metafile.CreateFromFile(metafile_path)) { + OnRenderPDFPagesToMetafileFailed(); + } else { + OnRenderPDFPagesToMetafileSucceeded(metafile, highest_rendered_page_number); + // Close it so that ScopedTempDir can delete the folder. + metafile.CloseEmf(); + } +#endif // defined(OS_WIN) +} + diff --git a/chrome/service/service_utility_process_host.h b/chrome/service/service_utility_process_host.h index c069426..477e945 100644 --- a/chrome/service/service_utility_process_host.h +++ b/chrome/service/service_utility_process_host.h @@ -15,6 +15,7 @@ #include <vector> #include "base/basictypes.h" +#include "base/file_path.h" #include "base/ref_counted.h" #include "base/task.h" #include "ipc/ipc_channel.h" @@ -22,7 +23,7 @@ #include "printing/native_metafile.h" class CommandLine; -class FilePath; +class ScopedTempDir; namespace base { class MessageLoopProxy; @@ -67,6 +68,9 @@ class ServiceUtilityProcessHost : public ServiceChildProcessHost { friend class ServiceUtilityProcessHost; void OnMessageReceived(const IPC::Message& message); + // Invoked when a metafile file is ready. + void MetafileAvailable(const FilePath& metafile_path, + int highest_rendered_page_number); DISALLOW_COPY_AND_ASSIGN(Client); }; @@ -100,21 +104,28 @@ class ServiceUtilityProcessHost : public ServiceChildProcessHost { private: // Starts a process. Returns true iff it succeeded. - bool StartProcess(); + bool StartProcess(const FilePath& exposed_dir); // IPC messages: void OnMessageReceived(const IPC::Message& message); + // Called when at least one page in the specified PDF has been rendered + // successfully into metafile_path_; + void OnRenderPDFPagesToMetafileSucceeded(int highest_rendered_page_number); + // Any other messages to be handled by the client. bool MessageForClient(const IPC::Message& message); #if defined(OS_WIN) // This hack is Windows-specific. void OnPreCacheFont(LOGFONT font); #endif // defined(OS_WIN) - // A pointer to our client interface, who will be informed of progress. scoped_refptr<Client> client_; scoped_refptr<base::MessageLoopProxy> client_message_loop_proxy_; bool waiting_for_reply_; + // The path to the temp file where the metafile will be written to. + FilePath metafile_path_; + // The temporary folder created for the metafile. + scoped_ptr<ScopedTempDir> scratch_metafile_dir_; DISALLOW_COPY_AND_ASSIGN(ServiceUtilityProcessHost); }; diff --git a/chrome/utility/utility_thread.cc b/chrome/utility/utility_thread.cc index ac8de68..4392557 100644 --- a/chrome/utility/utility_thread.cc +++ b/chrome/utility/utility_thread.cc @@ -119,6 +119,7 @@ void UtilityThread::OnDecodeImage( void UtilityThread::OnRenderPDFPagesToMetafile( base::PlatformFile pdf_file, + const FilePath& metafile_path, const gfx::Rect& render_area, int render_dpi, const std::vector<printing::PageRange>& page_ranges) { @@ -126,11 +127,11 @@ void UtilityThread::OnRenderPDFPagesToMetafile( #if defined(OS_WIN) printing::NativeMetafile metafile; int highest_rendered_page_number = 0; - succeeded = RenderPDFToWinMetafile(pdf_file, render_area, render_dpi, - page_ranges, &metafile, + succeeded = RenderPDFToWinMetafile(pdf_file, metafile_path, render_area, + render_dpi, page_ranges, &metafile, &highest_rendered_page_number); if (succeeded) { - Send(new UtilityHostMsg_RenderPDFPagesToMetafile_Succeeded(metafile, + Send(new UtilityHostMsg_RenderPDFPagesToMetafile_Succeeded( highest_rendered_page_number)); } #endif // defined(OS_WIN) @@ -189,6 +190,7 @@ DWORD WINAPI UtilityProcess_GetFontDataPatch( bool UtilityThread::RenderPDFToWinMetafile( base::PlatformFile pdf_file, + const FilePath& metafile_path, const gfx::Rect& render_area, int render_dpi, const std::vector<printing::PageRange>& page_ranges, @@ -242,7 +244,7 @@ bool UtilityThread::RenderPDFToWinMetafile( if (!get_info_proc(&buffer.front(), buffer.size(), &total_page_count, NULL)) return false; - metafile->CreateDc(NULL, NULL); + metafile->CreateFileBackedDc(NULL, NULL, metafile_path); // Since we created the metafile using the screen DPI (but we actually want // the PDF DLL to print using the passed in render_dpi, we apply the following // transformation. diff --git a/chrome/utility/utility_thread.h b/chrome/utility/utility_thread.h index a92c08b..36419aa 100644 --- a/chrome/utility/utility_thread.h +++ b/chrome/utility/utility_thread.h @@ -53,6 +53,7 @@ class UtilityThread : public ChildThread { // IPC to render a PDF into a platform metafile. void OnRenderPDFPagesToMetafile( base::PlatformFile pdf_file, + const FilePath& metafile_path, const gfx::Rect& render_area, int render_dpi, const std::vector<printing::PageRange>& page_ranges); @@ -62,6 +63,7 @@ class UtilityThread : public ChildThread { // |highest_rendered_page_number| is set to -1 on failure to render any page. bool RenderPDFToWinMetafile( base::PlatformFile pdf_file, + const FilePath& metafile_path, const gfx::Rect& render_area, int render_dpi, const std::vector<printing::PageRange>& page_ranges, |