Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / service / service_utility_process_host.cc
index b976448..88240fa 100644 (file)
@@ -4,51 +4,62 @@
 
 #include "chrome/service/service_utility_process_host.h"
 
+#include <queue>
+
 #include "base/bind.h"
 #include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/metrics/histogram.h"
 #include "base/process/kill.h"
-#include "base/strings/utf_string_conversions.h"
+#include "base/process/launch.h"
+#include "base/task_runner_util.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_utility_printing_messages.h"
 #include "content/public/common/child_process_host.h"
 #include "content/public/common/result_codes.h"
 #include "content/public/common/sandbox_init.h"
-#include "ipc/ipc_switches.h"
-#include "printing/page_range.h"
-#include "ui/base/ui_base_switches.h"
-#include "ui/gfx/rect.h"
-
-#if defined(OS_WIN)
-#include "base/files/file_path.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/process/launch.h"
-#include "base/win/scoped_handle.h"
-#include "content/public/common/sandbox_init.h"
 #include "content/public/common/sandboxed_process_launcher_delegate.h"
+#include "ipc/ipc_switches.h"
 #include "printing/emf_win.h"
 #include "sandbox/win/src/sandbox_policy_base.h"
+#include "ui/base/ui_base_switches.h"
 
 namespace {
 
+using content::ChildProcessHost;
+
+enum ServiceUtilityProcessHostEvent {
+  SERVICE_UTILITY_STARTED,
+  SERVICE_UTILITY_DISCONNECTED,
+  SERVICE_UTILITY_METAFILE_REQUEST,
+  SERVICE_UTILITY_METAFILE_SUCCEEDED,
+  SERVICE_UTILITY_METAFILE_FAILED,
+  SERVICE_UTILITY_CAPS_REQUEST,
+  SERVICE_UTILITY_CAPS_SUCCEEDED,
+  SERVICE_UTILITY_CAPS_FAILED,
+  SERVICE_UTILITY_SEMANTIC_CAPS_REQUEST,
+  SERVICE_UTILITY_SEMANTIC_CAPS_SUCCEEDED,
+  SERVICE_UTILITY_SEMANTIC_CAPS_FAILED,
+  SERVICE_UTILITY_FAILED_TO_START,
+  SERVICE_UTILITY_EVENT_MAX,
+};
+
+void ReportUmaEvent(ServiceUtilityProcessHostEvent id) {
+  UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
+                            id,
+                            SERVICE_UTILITY_EVENT_MAX);
+}
+
 // NOTE: changes to this class need to be reviewed by the security team.
 class ServiceSandboxedProcessLauncherDelegate
     : public content::SandboxedProcessLauncherDelegate {
  public:
-  explicit ServiceSandboxedProcessLauncherDelegate(
-      const base::FilePath& exposed_dir)
-    : exposed_dir_(exposed_dir) {
-  }
-
-  virtual void PreSandbox(bool* disable_default_policy,
-                          base::FilePath* exposed_dir) OVERRIDE {
-    *exposed_dir = exposed_dir_;
-  }
+  ServiceSandboxedProcessLauncherDelegate() {}
 
   virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
                               bool* success) OVERRIDE {
@@ -58,39 +69,95 @@ class ServiceSandboxedProcessLauncherDelegate
   }
 
  private:
-  base::FilePath exposed_dir_;
+  DISALLOW_COPY_AND_ASSIGN(ServiceSandboxedProcessLauncherDelegate);
 };
 
 }  // namespace
 
-#endif  // OS_WIN
+class ServiceUtilityProcessHost::PdfToEmfState {
+ public:
+  explicit PdfToEmfState(ServiceUtilityProcessHost* host)
+      : host_(host), page_count_(0), current_page_(0), pages_in_progress_(0) {}
+  ~PdfToEmfState() { Stop(); }
+
+  bool Start(base::File pdf_file,
+             const printing::PdfRenderSettings& conversion_settings) {
+    if (!temp_dir_.CreateUniqueTempDir())
+      return false;
+    return host_->Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles(
+        IPC::TakeFileHandleForProcess(pdf_file.Pass(), host_->handle()),
+        conversion_settings));
+  }
 
-using content::ChildProcessHost;
+  void GetMorePages() {
+    const int kMaxNumberOfTempFilesPerDocument = 3;
+    while (pages_in_progress_ < kMaxNumberOfTempFilesPerDocument &&
+           current_page_ < page_count_) {
+      ++pages_in_progress_;
+      emf_files_.push(CreateTempFile());
+      host_->Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage(
+          current_page_++,
+          IPC::GetFileHandleForProcess(
+              emf_files_.back().GetPlatformFile(), host_->handle(), false)));
+    }
+  }
 
-namespace {
-enum ServiceUtilityProcessHostEvent {
-  SERVICE_UTILITY_STARTED,
-  SERVICE_UTILITY_DISCONNECTED,
-  SERVICE_UTILITY_METAFILE_REQUEST,
-  SERVICE_UTILITY_METAFILE_SUCCEEDED,
-  SERVICE_UTILITY_METAFILE_FAILED,
-  SERVICE_UTILITY_CAPS_REQUEST,
-  SERVICE_UTILITY_CAPS_SUCCEEDED,
-  SERVICE_UTILITY_CAPS_FAILED,
-  SERVICE_UTILITY_SEMANTIC_CAPS_REQUEST,
-  SERVICE_UTILITY_SEMANTIC_CAPS_SUCCEEDED,
-  SERVICE_UTILITY_SEMANTIC_CAPS_FAILED,
-  SERVICE_UTILITY_FAILED_TO_START,
-  SERVICE_UTILITY_EVENT_MAX,
+  // Returns true if all pages processed and client should not expect more
+  // results.
+  bool OnPageProcessed() {
+    --pages_in_progress_;
+    GetMorePages();
+    if (pages_in_progress_ || current_page_ < page_count_)
+      return false;
+    Stop();
+    return true;
+  }
+
+  base::File TakeNextFile() {
+    DCHECK(!emf_files_.empty());
+    base::File file;
+    if (!emf_files_.empty())
+      file = emf_files_.front().Pass();
+    emf_files_.pop();
+    return file.Pass();
+  }
+
+  void set_page_count(int page_count) { page_count_ = page_count; }
+  bool has_page_count() { return page_count_ > 0; }
+
+ private:
+  void Stop() {
+    host_->Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop());
+  }
+
+  base::File CreateTempFile() {
+    base::FilePath path;
+    if (!base::CreateTemporaryFileInDir(temp_dir_.path(), &path))
+      return base::File();
+    return base::File(path,
+                      base::File::FLAG_CREATE_ALWAYS |
+                      base::File::FLAG_WRITE |
+                      base::File::FLAG_READ |
+                      base::File::FLAG_DELETE_ON_CLOSE |
+                      base::File::FLAG_TEMPORARY);
+  }
+
+  base::ScopedTempDir temp_dir_;
+  ServiceUtilityProcessHost* host_;
+  std::queue<base::File> emf_files_;
+  int page_count_;
+  int current_page_;
+  int pages_in_progress_;
 };
-}  // namespace
 
 ServiceUtilityProcessHost::ServiceUtilityProcessHost(
-    Client* client, base::MessageLoopProxy* client_message_loop_proxy)
-        : handle_(base::kNullProcessHandle),
-          client_(client),
-          client_message_loop_proxy_(client_message_loop_proxy),
-          waiting_for_reply_(false) {
+    Client* client,
+    base::MessageLoopProxy* client_message_loop_proxy)
+    : handle_(base::kNullProcessHandle),
+      client_(client),
+      client_message_loop_proxy_(client_message_loop_proxy),
+      waiting_for_reply_(false),
+      weak_ptr_factory_(this) {
   child_process_host_.reset(ChildProcessHost::Create(this));
 }
 
@@ -101,72 +168,44 @@ ServiceUtilityProcessHost::~ServiceUtilityProcessHost() {
 
 bool ServiceUtilityProcessHost::StartRenderPDFPagesToMetafile(
     const base::FilePath& pdf_path,
-    const printing::PdfRenderSettings& render_settings,
-    const std::vector<printing::PageRange>& page_ranges) {
-  UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
-                            SERVICE_UTILITY_METAFILE_REQUEST,
-                            SERVICE_UTILITY_EVENT_MAX);
+    const printing::PdfRenderSettings& render_settings) {
+  ReportUmaEvent(SERVICE_UTILITY_METAFILE_REQUEST);
   start_time_ = base::Time::Now();
-#if !defined(OS_WIN)
-  // This is only implemented on Windows (because currently it is only needed
-  // on Windows). Will add implementations on other platforms when needed.
-  NOTIMPLEMENTED();
-  return false;
-#else  // !defined(OS_WIN)
-  scratch_metafile_dir_.reset(new base::ScopedTempDir);
-  if (!scratch_metafile_dir_->CreateUniqueTempDir())
-    return false;
-  metafile_path_ = scratch_metafile_dir_->path().AppendASCII("output.emf");
-  if (!StartProcess(false, scratch_metafile_dir_->path()))
+  base::File pdf_file(pdf_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+  if (!pdf_file.IsValid() || !StartProcess(false))
     return false;
 
-  base::File pdf_file(
-      pdf_path,
-      base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
   DCHECK(!waiting_for_reply_);
   waiting_for_reply_ = true;
-  return child_process_host_->Send(
-      new ChromeUtilityMsg_RenderPDFPagesToMetafiles(
-          IPC::TakeFileHandleForProcess(pdf_file.Pass(), handle()),
-          metafile_path_,
-          render_settings,
-          page_ranges));
-#endif  // !defined(OS_WIN)
+
+  pdf_to_emf_state_.reset(new PdfToEmfState(this));
+  return pdf_to_emf_state_->Start(pdf_file.Pass(), render_settings);
 }
 
 bool ServiceUtilityProcessHost::StartGetPrinterCapsAndDefaults(
     const std::string& printer_name) {
-  UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
-                            SERVICE_UTILITY_CAPS_REQUEST,
-                            SERVICE_UTILITY_EVENT_MAX);
+  ReportUmaEvent(SERVICE_UTILITY_CAPS_REQUEST);
   start_time_ = base::Time::Now();
-  base::FilePath exposed_path;
-  if (!StartProcess(true, exposed_path))
+  if (!StartProcess(true))
     return false;
   DCHECK(!waiting_for_reply_);
   waiting_for_reply_ = true;
-  return child_process_host_->Send(
-      new ChromeUtilityMsg_GetPrinterCapsAndDefaults(printer_name));
+  return Send(new ChromeUtilityMsg_GetPrinterCapsAndDefaults(printer_name));
 }
 
 bool ServiceUtilityProcessHost::StartGetPrinterSemanticCapsAndDefaults(
     const std::string& printer_name) {
-  UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
-                            SERVICE_UTILITY_SEMANTIC_CAPS_REQUEST,
-                            SERVICE_UTILITY_EVENT_MAX);
+  ReportUmaEvent(SERVICE_UTILITY_SEMANTIC_CAPS_REQUEST);
   start_time_ = base::Time::Now();
-  base::FilePath exposed_path;
-  if (!StartProcess(true, exposed_path))
+  if (!StartProcess(true))
     return false;
   DCHECK(!waiting_for_reply_);
   waiting_for_reply_ = true;
-  return child_process_host_->Send(
+  return Send(
       new ChromeUtilityMsg_GetPrinterSemanticCapsAndDefaults(printer_name));
 }
 
-bool ServiceUtilityProcessHost::StartProcess(
-    bool no_sandbox,
-    const base::FilePath& exposed_dir) {
+bool ServiceUtilityProcessHost::StartProcess(bool no_sandbox) {
   std::string channel_id = child_process_host_->CreateChannel();
   if (channel_id.empty())
     return false;
@@ -177,42 +216,37 @@ bool ServiceUtilityProcessHost::StartProcess(
     return false;
   }
 
-  CommandLine cmd_line(exe_path);
+  base::CommandLine cmd_line(exe_path);
   cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kUtilityProcess);
   cmd_line.AppendSwitchASCII(switches::kProcessChannelID, channel_id);
   cmd_line.AppendSwitch(switches::kLang);
 
-  if (Launch(&cmd_line, no_sandbox, exposed_dir)) {
-    UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
-                              SERVICE_UTILITY_STARTED,
-                              SERVICE_UTILITY_EVENT_MAX);
+  if (Launch(&cmd_line, no_sandbox)) {
+    ReportUmaEvent(SERVICE_UTILITY_STARTED);
     return true;
   }
-  UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
-                            SERVICE_UTILITY_FAILED_TO_START,
-                            SERVICE_UTILITY_EVENT_MAX);
+  ReportUmaEvent(SERVICE_UTILITY_FAILED_TO_START);
   return false;
 }
 
-bool ServiceUtilityProcessHost::Launch(CommandLine* cmd_line,
-                                       bool no_sandbox,
-                                       const base::FilePath& exposed_dir) {
-#if !defined(OS_WIN)
-  // TODO(sanjeevr): Implement for non-Windows OSes.
-  NOTIMPLEMENTED();
-  return false;
-#else  // !defined(OS_WIN)
-
+bool ServiceUtilityProcessHost::Launch(base::CommandLine* cmd_line,
+                                       bool no_sandbox) {
   if (no_sandbox) {
     base::ProcessHandle process = base::kNullProcessHandle;
     cmd_line->AppendSwitch(switches::kNoSandbox);
     base::LaunchProcess(*cmd_line, base::LaunchOptions(), &handle_);
   } else {
-    ServiceSandboxedProcessLauncherDelegate delegate(exposed_dir);
+    ServiceSandboxedProcessLauncherDelegate delegate;
     handle_ = content::StartSandboxedProcess(&delegate, cmd_line);
   }
   return (handle_ != base::kNullProcessHandle);
-#endif  // !defined(OS_WIN)
+}
+
+bool ServiceUtilityProcessHost::Send(IPC::Message* msg) {
+  if (child_process_host_)
+    return child_process_host_->Send(msg);
+  delete msg;
+  return false;
 }
 
 base::FilePath ServiceUtilityProcessHost::GetUtilityProcessCmd() {
@@ -230,9 +264,7 @@ void ServiceUtilityProcessHost::OnChildDisconnected() {
     // child died.
     client_message_loop_proxy_->PostTask(
         FROM_HERE, base::Bind(&Client::OnChildDied, client_.get()));
-    UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
-                              SERVICE_UTILITY_DISCONNECTED,
-                              SERVICE_UTILITY_EVENT_MAX);
+    ReportUmaEvent(SERVICE_UTILITY_DISCONNECTED);
     UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityDisconnectTime",
                         base::Time::Now() - start_time_);
   }
@@ -242,13 +274,11 @@ void ServiceUtilityProcessHost::OnChildDisconnected() {
 bool ServiceUtilityProcessHost::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(ServiceUtilityProcessHost, message)
-#if defined(WIN_PDF_METAFILE_FOR_PRINTING)
     IPC_MESSAGE_HANDLER(
-        ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_Succeeded,
-        OnRenderPDFPagesToMetafilesSucceeded)
-    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Failed,
-                        OnRenderPDFPagesToMetafileFailed)
-#endif
+        ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount,
+        OnRenderPDFPagesToMetafilesPageCount)
+    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone,
+                        OnRenderPDFPagesToMetafilesPageDone)
     IPC_MESSAGE_HANDLER(
         ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded,
         OnGetPrinterCapsAndDefaultsSucceeded)
@@ -269,59 +299,65 @@ base::ProcessHandle ServiceUtilityProcessHost::GetHandle() const {
   return handle_;
 }
 
-#if defined(WIN_PDF_METAFILE_FOR_PRINTING)
-void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafilesSucceeded(
-    const std::vector<printing::PageRange>& page_ranges,
+void ServiceUtilityProcessHost::OnMetafileSpooled(bool success) {
+  if (!success || pdf_to_emf_state_->OnPageProcessed())
+    OnPDFToEmfFinished(success);
+}
+
+void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafilesPageCount(
+    int page_count) {
+  DCHECK(waiting_for_reply_);
+  if (!pdf_to_emf_state_ || page_count <= 0 ||
+      pdf_to_emf_state_->has_page_count()) {
+    return OnPDFToEmfFinished(false);
+  }
+  pdf_to_emf_state_->set_page_count(page_count);
+  pdf_to_emf_state_->GetMorePages();
+}
+
+void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafilesPageDone(
+    bool success,
     double scale_factor) {
-  UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
-                            SERVICE_UTILITY_METAFILE_SUCCEEDED,
-                            SERVICE_UTILITY_EVENT_MAX);
-  UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileTime",
-                      base::Time::Now() - start_time_);
   DCHECK(waiting_for_reply_);
-  waiting_for_reply_ = false;
-  // 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();
-
-  // TODO(vitalybuka|scottmg): http://crbug.com/170859: Currently, only one
-  // page is printed at a time. This would need to be refactored to change
-  // this.
-  CHECK_EQ(1u, page_ranges.size());
-  CHECK_EQ(page_ranges[0].from, page_ranges[0].to);
-  int page_number = page_ranges[0].from;
-  client_message_loop_proxy_->PostTask(
+  if (!pdf_to_emf_state_ || !success)
+    return OnPDFToEmfFinished(false);
+  base::File emf_file = pdf_to_emf_state_->TakeNextFile();
+  base::PostTaskAndReplyWithResult(
+      client_message_loop_proxy_,
       FROM_HERE,
       base::Bind(&Client::MetafileAvailable,
                  client_.get(),
-                 metafile_path_.InsertBeforeExtensionASCII(
-                     base::StringPrintf(".%d", page_number)),
-                 page_number,
-                 scale_factor));
+                 scale_factor,
+                 base::Passed(&emf_file)),
+      base::Bind(&ServiceUtilityProcessHost::OnMetafileSpooled,
+                 weak_ptr_factory_.GetWeakPtr()));
 }
 
-void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafileFailed() {
-  DCHECK(waiting_for_reply_);
-  UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
-                            SERVICE_UTILITY_METAFILE_FAILED,
-                            SERVICE_UTILITY_EVENT_MAX);
-  UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileFailTime",
-                      base::Time::Now() - start_time_);
+void ServiceUtilityProcessHost::OnPDFToEmfFinished(bool success) {
+  if (!waiting_for_reply_)
+    return;
   waiting_for_reply_ = false;
+  if (success) {
+    ReportUmaEvent(SERVICE_UTILITY_METAFILE_SUCCEEDED);
+    UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileTime",
+                        base::Time::Now() - start_time_);
+  } else {
+    ReportUmaEvent(SERVICE_UTILITY_METAFILE_FAILED);
+    UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityMetafileFailTime",
+                        base::Time::Now() - start_time_);
+  }
   client_message_loop_proxy_->PostTask(
       FROM_HERE,
-      base::Bind(&Client::OnRenderPDFPagesToMetafileFailed, client_.get()));
+      base::Bind(
+          &Client::OnRenderPDFPagesToMetafileDone, client_.get(), success));
+  pdf_to_emf_state_.reset();
 }
-#endif  // defined(WIN_PDF_METAFILE_FOR_PRINTING)
 
 void ServiceUtilityProcessHost::OnGetPrinterCapsAndDefaultsSucceeded(
     const std::string& printer_name,
     const printing::PrinterCapsAndDefaults& caps_and_defaults) {
   DCHECK(waiting_for_reply_);
-  UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
-                            SERVICE_UTILITY_CAPS_SUCCEEDED,
-                            SERVICE_UTILITY_EVENT_MAX);
+  ReportUmaEvent(SERVICE_UTILITY_CAPS_SUCCEEDED);
   UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityCapsTime",
                       base::Time::Now() - start_time_);
   waiting_for_reply_ = false;
@@ -335,9 +371,7 @@ void ServiceUtilityProcessHost::OnGetPrinterSemanticCapsAndDefaultsSucceeded(
     const std::string& printer_name,
     const printing::PrinterSemanticCapsAndDefaults& caps_and_defaults) {
   DCHECK(waiting_for_reply_);
-  UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
-                            SERVICE_UTILITY_SEMANTIC_CAPS_SUCCEEDED,
-                            SERVICE_UTILITY_EVENT_MAX);
+  ReportUmaEvent(SERVICE_UTILITY_SEMANTIC_CAPS_SUCCEEDED);
   UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilitySemanticCapsTime",
                       base::Time::Now() - start_time_);
   waiting_for_reply_ = false;
@@ -350,9 +384,7 @@ void ServiceUtilityProcessHost::OnGetPrinterSemanticCapsAndDefaultsSucceeded(
 void ServiceUtilityProcessHost::OnGetPrinterCapsAndDefaultsFailed(
     const std::string& printer_name) {
   DCHECK(waiting_for_reply_);
-  UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
-                            SERVICE_UTILITY_CAPS_FAILED,
-                            SERVICE_UTILITY_EVENT_MAX);
+  ReportUmaEvent(SERVICE_UTILITY_CAPS_FAILED);
   UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilityCapsFailTime",
                       base::Time::Now() - start_time_);
   waiting_for_reply_ = false;
@@ -365,9 +397,7 @@ void ServiceUtilityProcessHost::OnGetPrinterCapsAndDefaultsFailed(
 void ServiceUtilityProcessHost::OnGetPrinterSemanticCapsAndDefaultsFailed(
     const std::string& printer_name) {
   DCHECK(waiting_for_reply_);
-  UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceUtilityProcessHostEvent",
-                            SERVICE_UTILITY_SEMANTIC_CAPS_FAILED,
-                            SERVICE_UTILITY_EVENT_MAX);
+  ReportUmaEvent(SERVICE_UTILITY_SEMANTIC_CAPS_FAILED);
   UMA_HISTOGRAM_TIMES("CloudPrint.ServiceUtilitySemanticCapsFailTime",
                       base::Time::Now() - start_time_);
   waiting_for_reply_ = false;
@@ -378,27 +408,24 @@ void ServiceUtilityProcessHost::OnGetPrinterSemanticCapsAndDefaultsFailed(
                  printing::PrinterSemanticCapsAndDefaults()));
 }
 
-void ServiceUtilityProcessHost::Client::MetafileAvailable(
-    const base::FilePath& metafile_path,
-    int highest_rendered_page_number,
-    double scale_factor) {
-  // The metafile was created in a temp folder which needs to get deleted after
-  // we have processed it.
-  base::ScopedTempDir scratch_metafile_dir;
-  if (!scratch_metafile_dir.Set(metafile_path.DirName()))
-    LOG(WARNING) << "Unable to set scratch metafile directory";
-#if defined(OS_WIN)
-  // It's important that metafile is declared after scratch_metafile_dir so
-  // that the metafile destructor closes the file before the base::ScopedTempDir
-  // destructor tries to remove the directory.
-  printing::Emf metafile;
-  if (!metafile.InitFromFile(metafile_path)) {
-    OnRenderPDFPagesToMetafileFailed();
-  } else {
-    OnRenderPDFPagesToMetafileSucceeded(metafile,
-                                        highest_rendered_page_number,
-                                        scale_factor);
+bool ServiceUtilityProcessHost::Client::MetafileAvailable(double scale_factor,
+                                                          base::File file) {
+  file.Seek(base::File::FROM_BEGIN, 0);
+  int64 size = file.GetLength();
+  if (size <= 0) {
+    OnRenderPDFPagesToMetafileDone(false);
+    return false;
+  }
+  std::vector<char> data(size);
+  if (file.ReadAtCurrentPos(data.data(), data.size()) != size) {
+    OnRenderPDFPagesToMetafileDone(false);
+    return false;
   }
-#endif  // defined(OS_WIN)
+  printing::Emf emf;
+  if (!emf.InitFromData(data.data(), data.size())) {
+    OnRenderPDFPagesToMetafileDone(false);
+    return false;
+  }
+  OnRenderPDFPagesToMetafilePageDone(scale_factor, emf);
+  return true;
 }
-