Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(306)

Unified Diff: chrome/browser/printing/pdf_to_emf_converter.cc

Issue 566693002: Use file handles to interact with utility process. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Mon Sep 15 03:22:54 PDT 2014 Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/printing/pdf_to_emf_converter.cc
diff --git a/chrome/browser/printing/pdf_to_emf_converter.cc b/chrome/browser/printing/pdf_to_emf_converter.cc
index f0a8bab029aa923a92c9ca5788a0843d595a18ab..3fbbd268a46923b89b4da5e75313cad9d5bb6079 100644
--- a/chrome/browser/printing/pdf_to_emf_converter.cc
+++ b/chrome/browser/printing/pdf_to_emf_converter.cc
@@ -4,11 +4,8 @@
#include "chrome/browser/printing/pdf_to_emf_converter.h"
-#include "base/bind_helpers.h"
-#include "base/cancelable_callback.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "chrome/common/chrome_utility_messages.h"
#include "chrome/common/chrome_utility_printing_messages.h"
@@ -17,7 +14,6 @@
#include "content/public/browser/utility_process_host.h"
#include "content/public/browser/utility_process_host_client.h"
#include "printing/emf_win.h"
-#include "printing/page_range.h"
#include "printing/pdf_render_settings.h"
namespace printing {
@@ -26,315 +22,377 @@ namespace {
using content::BrowserThread;
-class FileHandlers
- : public base::RefCountedThreadSafe<FileHandlers,
- BrowserThread::DeleteOnFileThread> {
- public:
- FileHandlers() {}
+class PdfToEmfConverterImpl;
- void Init(base::RefCountedMemory* data);
- bool IsValid();
+const int kMaxNumberOfTempFilesPerDocument = 3;
- base::FilePath GetEmfPath() const {
- return temp_dir_.path().AppendASCII("output.emf");
- }
+typedef scoped_ptr<base::File, BrowserThread::DeleteOnFileThread> TempFilePtr;
- base::FilePath GetEmfPagePath(int page_number) const {
- return GetEmfPath().InsertBeforeExtensionASCII(
- base::StringPrintf(".%d", page_number));
- }
-
- base::FilePath GetPdfPath() const {
- return temp_dir_.path().AppendASCII("input.pdf");
- }
-
- IPC::PlatformFileForTransit GetPdfForProcess(base::ProcessHandle process) {
- DCHECK(pdf_file_.IsValid());
- IPC::PlatformFileForTransit transit =
- IPC::TakeFileHandleForProcess(pdf_file_.Pass(), process);
- return transit;
- }
+// Wrapper for Emf to keep only file handle in memory, and load actual data only
+// on playback. |InitFromFile| can play metafile directly from disk, but it
+// can't open file handles. We need file handles to reliably delete temporary
+// files, and to efficiently interact with sandbox process.
+class LazyEmf : public MetafilePlayer {
+ public:
+ explicit LazyEmf(TempFilePtr file) : file_(file.Pass()) {}
+ virtual ~LazyEmf() { Close(); }
- const base::FilePath& GetBasePath() const {
- return temp_dir_.path();
- }
+ virtual bool SafePlayback(HDC hdc) const OVERRIDE;
+ virtual bool SaveTo(base::File* file) const OVERRIDE;
private:
- friend struct BrowserThread::DeleteOnThread<BrowserThread::FILE>;
- friend class base::DeleteHelper<FileHandlers>;
+ void Close() const;
+ bool LoadEmf(Emf* emf) const;
- ~FileHandlers() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); }
-
- base::ScopedTempDir temp_dir_;
- base::File pdf_file_;
-};
-
-void FileHandlers::Init(base::RefCountedMemory* data) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
- if (!temp_dir_.CreateUniqueTempDir()) {
- return;
- }
-
- pdf_file_.Initialize(GetPdfPath(),
- base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
- base::File::FLAG_READ |
- base::File::FLAG_DELETE_ON_CLOSE);
- if (static_cast<int>(data->size()) !=
- pdf_file_.WriteAtCurrentPos(data->front_as<char>(), data->size())) {
- pdf_file_.Close();
- return;
- }
- pdf_file_.Seek(base::File::FROM_BEGIN, 0);
- pdf_file_.Flush();
-}
-
-bool FileHandlers::IsValid() {
- return pdf_file_.IsValid();
-}
-
-// Modification of Emf to keep references to |FileHandlers|.
-// |FileHandlers| must be deleted after the last metafile is closed because
-// Emf holds files locked.
-// Ideally we want to use FLAG_DELETE_ON_CLOSE, but it requires large changes.
-// It's going to be done for crbug.com/408184
-class TempEmf : public Emf {
- public:
- explicit TempEmf(const scoped_refptr<FileHandlers>& files) : files_(files) {}
- virtual ~TempEmf() {}
-
- virtual bool SafePlayback(HDC hdc) const OVERRIDE {
- bool result = Emf::SafePlayback(hdc);
- TempEmf* this_mutable = const_cast<TempEmf*>(this);
- // TODO(vitalybuka): Fix destruction of metafiles. For some reasons
- // instances of Emf are not deleted. crbug.com/411683
- // |files_| must be released as soon as possible to guarantee deletion.
- // It's know that this Emf file is going to be played just once to
- // a printer. So just release files here.
- this_mutable->Close();
- this_mutable->files_ = NULL;
- return result;
- }
-
- private:
- scoped_refptr<FileHandlers> files_;
- DISALLOW_COPY_AND_ASSIGN(TempEmf);
+ mutable TempFilePtr file_; // Mutable because of consts in base class.
+ DISALLOW_COPY_AND_ASSIGN(LazyEmf);
};
// Converts PDF into EMF.
// Class uses 3 threads: UI, IO and FILE.
// Internal workflow is following:
// 1. Create instance on the UI thread. (files_, settings_,)
-// 2. Create file on the FILE thread.
+// 2. Create pdf file on the FILE thread.
// 3. Start utility process and start conversion on the IO thread.
-// 4. Run result callback on the UI thread.
-// 5. Instance is destroyed from any thread that has the last reference.
-// 6. FileHandlers destroyed on the FILE thread.
-// This step posts |FileHandlers| to be destroyed on the FILE thread.
+// 4. For each page:
+// 1. Utility is requesting open file.
+// 2. Utility converts the page and save to the file.
+// 3. Utility sends notification on page conversion result.
+// 4. ProcessHostClient calls a page callback.
+// 5. Utility sends notification if about document completion.
+// 6. ProcessHostClient calls a document callback.
// All these steps work sequentially, so no data should be accessed
// simultaneously by several threads.
class PdfToEmfUtilityProcessHostClient
: public content::UtilityProcessHostClient {
public:
- explicit PdfToEmfUtilityProcessHostClient(
+ PdfToEmfUtilityProcessHostClient(
+ base::WeakPtr<PdfToEmfConverterImpl> converter,
const printing::PdfRenderSettings& settings);
- void Convert(base::RefCountedMemory* data,
- const PdfToEmfConverter::ResultCallback& callback);
+ void Convert(const scoped_refptr<base::RefCountedMemory>& data,
+ const PdfToEmfConverter::PdfLoadedCallback& document_callback);
+
+ void GetPage(int page_number,
+ const PdfToEmfConverter::PageCallback& page_callback);
// UtilityProcessHostClient implementation.
virtual void OnProcessCrashed(int exit_code) OVERRIDE;
+ virtual void OnProcessLaunchFailed() OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool Send(IPC::Message* msg);
+
private:
virtual ~PdfToEmfUtilityProcessHostClient();
// Message handlers.
void OnProcessStarted();
- void OnSucceeded(const std::vector<printing::PageRange>& page_ranges,
- double scale_factor);
- void OnFailed();
+ void OnPageCount(int page_count);
+ void OnPageDone(bool success, double scale_factor);
- void RunCallback(const std::vector<printing::PageRange>& page_ranges,
- double scale_factor);
+ void OnFailed();
+ void OnTempPdfReady(TempFilePtr pdf);
+ void OnTempEmfReady(int page_number,
+ const PdfToEmfConverter::PageCallback& page_callback,
+ TempFilePtr emf);
- void StartProcessOnIOThread();
+ // Used to suppress callbacks after PdfToEmfConverterImpl is deleted.
+ base::WeakPtr<PdfToEmfConverterImpl> converter_;
+ printing::PdfRenderSettings settings_;
+ scoped_refptr<base::RefCountedMemory> data_;
- void RunCallbackOnUIThread(
- const std::vector<printing::PageRange>& page_ranges,
- double scale_factor);
- void OnFilesReadyOnUIThread();
+ // Final document callback.
+ PdfToEmfConverter::PdfLoadedCallback document_callback_;
- scoped_refptr<FileHandlers> files_;
- printing::PdfRenderSettings settings_;
- PdfToEmfConverter::ResultCallback callback_;
+ // Process host for IPC.
base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
+ typedef base::Callback<
+ void(double scale_factor, scoped_ptr<MetafilePlayer> emf)>
+ PageCallbackInternal;
+ std::deque<std::pair<PageCallbackInternal, TempFilePtr> > page_callbacks_;
+
DISALLOW_COPY_AND_ASSIGN(PdfToEmfUtilityProcessHostClient);
};
+class PdfToEmfConverterImpl : public PdfToEmfConverter {
+ public:
+ PdfToEmfConverterImpl();
+
+ virtual ~PdfToEmfConverterImpl();
+
+ virtual void Start(const scoped_refptr<base::RefCountedMemory>& data,
+ const printing::PdfRenderSettings& conversion_settings,
+ const PdfLoadedCallback& document_callback) OVERRIDE;
+
+ virtual void GetPage(int page_number,
+ const PageCallback& page_callback) OVERRIDE;
+
+ // Helps to cancel callbacks if this object is destroyed.
+ void RunCallback(const base::Closure& callback);
+
+ private:
+ scoped_refptr<PdfToEmfUtilityProcessHostClient> utility_client_;
+ base::WeakPtrFactory<PdfToEmfConverterImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PdfToEmfConverterImpl);
+};
+
+TempFilePtr CreateTempFile() {
+ TempFilePtr file;
+ base::FilePath path;
+ if (!base::CreateTemporaryFile(&path))
+ return file.Pass();
+ file.reset(new 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));
+ if (!file->IsValid())
+ file.reset();
+ return file.Pass();
+}
+
+TempFilePtr CreateTempPdfFile(
+ const scoped_refptr<base::RefCountedMemory>& data) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
Lei Zhang 2014/09/15 21:49:53 nit: DCHECK_CURRENTLY_ON()
Vitaly Buka (NO REVIEWS) 2014/09/15 22:33:49 Done.
+
+ TempFilePtr pdf_file = CreateTempFile();
+ if (!pdf_file ||
+ static_cast<int>(data->size()) !=
+ pdf_file->WriteAtCurrentPos(data->front_as<char>(), data->size())) {
+ pdf_file.reset();
+ }
+ pdf_file->Seek(base::File::FROM_BEGIN, 0);
+ return pdf_file.Pass();
+}
+
+bool LazyEmf::SafePlayback(HDC hdc) const {
+ Emf emf;
+ bool result = LoadEmf(&emf) && emf.SafePlayback(hdc);
+ // TODO(vitalybuka): Fix destruction of metafiles. For some reasons
+ // instances of Emf are not deleted. crbug.com/411683
+ // It's known that the Emf going to be played just once to a printer. So just
+ // release file here.
+ Close();
+ return result;
+}
+
+bool LazyEmf::SaveTo(base::File* file) const {
+ Emf emf;
+ return LoadEmf(&emf) && emf.SaveTo(file);
+}
+
+void LazyEmf::Close() const {
+ file_.reset();
+}
+
+bool LazyEmf::LoadEmf(Emf* emf) const {
+ file_->Seek(base::File::FROM_BEGIN, 0);
+ int64 size = file_->GetLength();
+ if (size <= 0)
+ return false;
+ std::vector<char> data(size);
+ if (file_->ReadAtCurrentPos(&data[0], data.size()) != size)
Lei Zhang 2014/09/15 21:49:53 nit: &data[0] -> data.front()
Vitaly Buka (NO REVIEWS) 2014/09/15 22:33:49 std::vector::data()? Done.
+ return false;
+ return emf->InitFromData(&data[0], data.size());
+}
+
PdfToEmfUtilityProcessHostClient::PdfToEmfUtilityProcessHostClient(
+ base::WeakPtr<PdfToEmfConverterImpl> converter,
const printing::PdfRenderSettings& settings)
- : settings_(settings) {}
+ : converter_(converter), settings_(settings) {
+}
PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() {
}
void PdfToEmfUtilityProcessHostClient::Convert(
- base::RefCountedMemory* data,
- const PdfToEmfConverter::ResultCallback& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- callback_ = callback;
- CHECK(!files_.get());
- files_ = new FileHandlers();
- BrowserThread::PostTaskAndReply(
+ const scoped_refptr<base::RefCountedMemory>& data,
+ const PdfToEmfConverter::PdfLoadedCallback& document_callback) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ BrowserThread::PostTask(
Lei Zhang 2014/09/15 21:49:53 Can we just call Convert() on the IO thread from a
Vitaly Buka (NO REVIEWS) 2014/09/15 22:33:49 I realy like this way. We need to Post anyway, but
Lei Zhang 2014/09/16 03:36:53 But don't you only have 1 caller? Just make the ca
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&PdfToEmfUtilityProcessHostClient::Convert,
+ this,
+ data,
+ document_callback));
+ return;
+ }
+ data_ = data;
+ document_callback_ = document_callback;
+
+ // NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load
+ // gdiplus.dll, change how rendering happens, and not be able to correctly
+ // generate when sent to a metafile DC.
+ utility_process_host_ =
+ content::UtilityProcessHost::Create(
+ this, base::MessageLoop::current()->message_loop_proxy())
+ ->AsWeakPtr();
+ if (!utility_process_host_)
+ return OnFailed();
+ Send(new ChromeUtilityMsg_StartupPing);
+}
+
+void PdfToEmfUtilityProcessHostClient::GetPage(
+ int page_number,
+ const PdfToEmfConverter::PageCallback& page_callback) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&PdfToEmfUtilityProcessHostClient::GetPage,
+ this,
+ page_number,
+ page_callback));
+ return;
+ }
+
+ BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::FILE,
FROM_HERE,
- base::Bind(&FileHandlers::Init, files_, make_scoped_refptr(data)),
- base::Bind(&PdfToEmfUtilityProcessHostClient::OnFilesReadyOnUIThread,
- this));
+ base::Bind(&CreateTempFile),
+ base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempEmfReady,
+ this,
+ page_number,
+ page_callback));
}
void PdfToEmfUtilityProcessHostClient::OnProcessCrashed(int exit_code) {
OnFailed();
}
+void PdfToEmfUtilityProcessHostClient::OnProcessLaunchFailed() {
+ OnFailed();
+}
+
bool PdfToEmfUtilityProcessHostClient::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PdfToEmfUtilityProcessHostClient, message)
IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted, OnProcessStarted)
IPC_MESSAGE_HANDLER(
- ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_Succeeded, OnSucceeded)
- IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Failed,
- OnFailed)
+ ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, OnPageCount)
+ IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone,
+ OnPageDone)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
+bool PdfToEmfUtilityProcessHostClient::Send(IPC::Message* msg) {
+ if (utility_process_host_)
+ return utility_process_host_->Send(msg);
+ delete msg;
+ return false;
+}
+
void PdfToEmfUtilityProcessHostClient::OnProcessStarted() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (!utility_process_host_) {
- RunCallbackOnUIThread(std::vector<printing::PageRange>(), 0.0);
- return;
- }
+ if (!utility_process_host_)
+ return OnFailed();
base::ProcessHandle process = utility_process_host_->GetData().handle;
- utility_process_host_->Send(
- new ChromeUtilityMsg_RenderPDFPagesToMetafiles(
- files_->GetPdfForProcess(process),
- files_->GetEmfPath(),
- settings_,
- std::vector<printing::PageRange>()));
- utility_process_host_.reset();
-}
-
-void PdfToEmfUtilityProcessHostClient::OnSucceeded(
- const std::vector<printing::PageRange>& page_ranges,
- double scale_factor) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- RunCallback(page_ranges, scale_factor);
+ scoped_refptr<base::RefCountedMemory> data = data_;
+ data_ = NULL;
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&CreateTempPdfFile, data),
+ base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this));
}
-void PdfToEmfUtilityProcessHostClient::OnFailed() {
+void PdfToEmfUtilityProcessHostClient::OnPageCount(int page_count) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- RunCallback(std::vector<printing::PageRange>(), 0.0);
-}
-
-void PdfToEmfUtilityProcessHostClient::OnFilesReadyOnUIThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (!files_->IsValid()) {
- RunCallbackOnUIThread(std::vector<printing::PageRange>(), 0.0);
- return;
- }
+ if (document_callback_.is_null())
+ return OnFailed();
BrowserThread::PostTask(
- BrowserThread::IO,
+ BrowserThread::UI,
FROM_HERE,
- base::Bind(&PdfToEmfUtilityProcessHostClient::StartProcessOnIOThread,
- this));
+ base::Bind(&PdfToEmfConverterImpl::RunCallback,
+ converter_,
+ base::Bind(document_callback_, page_count)));
+ document_callback_.Reset();
}
-void PdfToEmfUtilityProcessHostClient::StartProcessOnIOThread() {
+void PdfToEmfUtilityProcessHostClient::OnPageDone(bool success,
+ double scale_factor) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- utility_process_host_ =
- content::UtilityProcessHost::Create(
- this,
- base::MessageLoop::current()->message_loop_proxy())->AsWeakPtr();
- // NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load
- // gdiplus.dll, change how rendering happens, and not be able to correctly
- // generate when sent to a metafile DC.
- utility_process_host_->SetExposedDir(files_->GetBasePath());
- utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
+ if (page_callbacks_.empty())
+ return OnFailed();
+ scoped_ptr<LazyEmf> emf;
+ if (success)
+ emf.reset(new LazyEmf(page_callbacks_.front().second.Pass()));
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&PdfToEmfConverterImpl::RunCallback,
+ converter_,
+ base::Bind(page_callbacks_.front().first,
+ scale_factor,
+ base::Passed(&emf))));
+ page_callbacks_.pop_front();
}
-void PdfToEmfUtilityProcessHostClient::RunCallback(
- const std::vector<printing::PageRange>& page_ranges,
- double scale_factor) {
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&PdfToEmfUtilityProcessHostClient::RunCallbackOnUIThread,
- this,
- page_ranges,
- scale_factor));
+void PdfToEmfUtilityProcessHostClient::OnFailed() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!document_callback_.is_null())
+ OnPageCount(0);
+ while (!page_callbacks_.empty())
+ OnPageDone(false, 0.0);
}
-void PdfToEmfUtilityProcessHostClient::RunCallbackOnUIThread(
- const std::vector<printing::PageRange>& page_ranges,
- double scale_factor) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ScopedVector<MetafilePlayer> pages;
- std::vector<printing::PageRange>::const_iterator iter;
- for (iter = page_ranges.begin(); iter != page_ranges.end(); ++iter) {
- for (int page_number = iter->from; page_number <= iter->to; ++page_number) {
- scoped_ptr<TempEmf> metafile(new TempEmf(files_));
- if (!metafile->InitFromFile(files_->GetEmfPagePath(page_number))) {
- NOTREACHED() << "Invalid metafile";
- metafile.reset();
- }
- pages.push_back(metafile.release());
- }
- }
- files_ = NULL;
- if (!callback_.is_null()) {
- callback_.Run(scale_factor, &pages);
- callback_.Reset();
- }
+void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(TempFilePtr pdf) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!utility_process_host_)
+ return OnFailed();
+ base::ProcessHandle process = utility_process_host_->GetData().handle;
+ Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles(
+ IPC::GetFileHandleForProcess(pdf->GetPlatformFile(), process, false),
+ settings_));
}
-class PdfToEmfConverterImpl : public PdfToEmfConverter {
- public:
- PdfToEmfConverterImpl();
-
- virtual ~PdfToEmfConverterImpl();
-
- virtual void Start(base::RefCountedMemory* data,
- const printing::PdfRenderSettings& conversion_settings,
- const ResultCallback& callback) OVERRIDE;
-
- private:
- scoped_refptr<PdfToEmfUtilityProcessHostClient> utility_client_;
- base::CancelableCallback<ResultCallback::RunType> callback_;
-
- DISALLOW_COPY_AND_ASSIGN(PdfToEmfConverterImpl);
-};
+void PdfToEmfUtilityProcessHostClient::OnTempEmfReady(
+ int page_number,
+ const PdfToEmfConverter::PageCallback& page_callback,
+ TempFilePtr emf) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!utility_process_host_)
+ return OnFailed();
+ base::ProcessHandle process = utility_process_host_->GetData().handle;
+ IPC::PlatformFileForTransit transit =
+ IPC::GetFileHandleForProcess(emf->GetPlatformFile(), process, false);
+ page_callbacks_.push_back(
+ std::make_pair(base::Bind(page_callback, page_number), emf.Pass()));
+ Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_GetPage(page_number,
+ transit));
+}
-PdfToEmfConverterImpl::PdfToEmfConverterImpl() {
+PdfToEmfConverterImpl::PdfToEmfConverterImpl() : weak_ptr_factory_(this) {
}
PdfToEmfConverterImpl::~PdfToEmfConverterImpl() {
}
void PdfToEmfConverterImpl::Start(
- base::RefCountedMemory* data,
+ const scoped_refptr<base::RefCountedMemory>& data,
const printing::PdfRenderSettings& conversion_settings,
- const ResultCallback& callback) {
- // Rebind cancelable callback to avoid calling callback if
- // PdfToEmfConverterImpl is destroyed.
- callback_.Reset(callback);
- utility_client_ = new PdfToEmfUtilityProcessHostClient(conversion_settings);
- utility_client_->Convert(data, callback_.callback());
+ const PdfLoadedCallback& document_callback) {
+ DCHECK(!utility_client_);
+ utility_client_ = new PdfToEmfUtilityProcessHostClient(
+ weak_ptr_factory_.GetWeakPtr(), conversion_settings);
+ utility_client_->Convert(data, document_callback);
+}
+
+void PdfToEmfConverterImpl::GetPage(int page_number,
+ const PageCallback& page_callback) {
+ utility_client_->GetPage(page_number, page_callback);
+}
+
+void PdfToEmfConverterImpl::RunCallback(const base::Closure& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ callback.Run();
}
} // namespace

Powered by Google App Engine
This is Rietveld 408576698