Make Print API work on Windows.

This commit is contained in:
Haojian Wu 2015-04-30 11:31:17 +08:00
Родитель ca5ee0fc81
Коммит ff87592722
15 изменённых файлов: 1294 добавлений и 0 удалений

Просмотреть файл

@ -14,6 +14,7 @@
#include "base/debug/stack_trace.h"
#include "base/environment.h"
#include "base/logging.h"
#include "chrome/utility/chrome_content_utility_client.h"
#include "content/public/common/content_switches.h"
#include "ui/base/resource/resource_bundle.h"
@ -94,6 +95,13 @@ content::ContentRendererClient*
return renderer_client_.get();
}
content::ContentUtilityClient* AtomMainDelegate::CreateContentUtilityClient() {
#if defined(OS_WIN)
utility_client_.reset(new AtomContentUtilityClient);
return utility_client_.get();
#endif
}
scoped_ptr<brightray::ContentClient> AtomMainDelegate::CreateContentClient() {
return scoped_ptr<brightray::ContentClient>(new AtomContentClient).Pass();
}

Просмотреть файл

@ -21,6 +21,7 @@ class AtomMainDelegate : public brightray::MainDelegate {
void PreSandboxStartup() override;
content::ContentBrowserClient* CreateContentBrowserClient() override;
content::ContentRendererClient* CreateContentRendererClient() override;
content::ContentUtilityClient* CreateContentUtilityClient() override;
// brightray::MainDelegate:
scoped_ptr<brightray::ContentClient> CreateContentClient() override;
@ -35,6 +36,7 @@ class AtomMainDelegate : public brightray::MainDelegate {
brightray::ContentClient content_client_;
scoped_ptr<content::ContentBrowserClient> browser_client_;
scoped_ptr<content::ContentRendererClient> renderer_client_;
scoped_ptr<content::ContentUtilityClient> utility_client_;
DISALLOW_COPY_AND_ASSIGN(AtomMainDelegate);
};

Просмотреть файл

@ -0,0 +1,76 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/utility/atom_content_utility_client.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "chrome/common/chrome_utility_messages.h"
#include "chrome/utility/utility_message_handler.h"
#include "content/public/common/content_switches.h"
#include "content/public/utility/utility_thread.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_message_macros.h"
#if defined(OS_WIN)
#include "chrome/utility/printing_handler.h"
#endif
namespace {
bool Send(IPC::Message* message) {
return content::UtilityThread::Get()->Send(message);
}
void ReleaseProcessIfNeeded() {
content::UtilityThread::Get()->ReleaseProcessIfNeeded();
}
} // namespace
namespace atom {
int64_t AtomContentUtilityClient::max_ipc_message_size_ =
IPC::Channel::kMaximumMessageSize;
AtomContentUtilityClient::AtomContentUtilityClient()
: filter_messages_(false) {
handlers_.push_back(new PrintingHandler());
}
AtomContentUtilityClient::~AtomContentUtilityClient() {
}
void AtomContentUtilityClient::UtilityThreadStarted() {
}
bool AtomContentUtilityClient::OnMessageReceived(
const IPC::Message& message) {
if (filter_messages_ && !ContainsKey(message_id_whitelist_, message.type()))
return false;
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(AtomContentUtilityClient, message)
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_StartupPing, OnStartupPing)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
for (Handlers::iterator it = handlers_.begin();
!handled && it != handlers_.end(); ++it) {
handled = (*it)->OnMessageReceived(message);
}
return handled;
}
void AtomContentUtilityClient::OnStartupPing() {
Send(new ChromeUtilityHostMsg_ProcessStarted);
// Don't release the process, we assume further messages are on the way.
}
} // namespace atom

Просмотреть файл

@ -0,0 +1,57 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_UTILITY_ATOM_CONTENT_UTILITY_CLIENT_H_
#define ATOM_UTILITY_ATOM_CONTENT_UTILITY_CLIENT_H_
#include <set>
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/memory/scoped_vector.h"
#include "content/public/utility/content_utility_client.h"
#include "ipc/ipc_platform_file.h"
namespace base {
class FilePath;
struct FileDescriptor;
}
class UtilityMessageHandler;
namespace atom {
class AtomContentUtilityClient : public content::ContentUtilityClient {
public:
AtomContentUtilityClient();
~AtomContentUtilityClient() override;
void UtilityThreadStarted() override;
bool OnMessageReceived(const IPC::Message& message) override;
static void set_max_ipc_message_size_for_test(int64_t max_message_size) {
max_ipc_message_size_ = max_message_size;
}
private:
void OnStartupPing();
typedef ScopedVector<UtilityMessageHandler> Handlers;
Handlers handlers_;
// Flag to enable whitelisting.
bool filter_messages_;
// A list of message_ids to filter.
std::set<int> message_id_whitelist_;
// Maximum IPC msg size (default to kMaximumMessageSize; override for testing)
static int64_t max_ipc_message_size_;
DISALLOW_COPY_AND_ASSIGN(AtomContentUtilityClient);
};
} // namespace atom
#endif // ATOM_UTILITY_ATOM_CONTENT_UTILITY_CLIENT_H_

Просмотреть файл

@ -0,0 +1,495 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/printing/pdf_to_emf_converter.h"
#include <queue>
#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/print_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/utility_process_host.h"
#include "content/public/browser/utility_process_host_client.h"
#include "printing/emf_win.h"
#include "printing/pdf_render_settings.h"
namespace printing {
namespace {
using content::BrowserThread;
class PdfToEmfConverterImpl;
// Allows to delete temporary directory after all temporary files created inside
// are closed. Windows cannot delete directory with opened files. Directory is
// used to store PDF and metafiles. PDF should be gone by the time utility
// process exits. Metafiles should be gone when all LazyEmf destroyed.
class RefCountedTempDir
: public base::RefCountedThreadSafe<RefCountedTempDir,
BrowserThread::DeleteOnFileThread> {
public:
RefCountedTempDir() { ignore_result(temp_dir_.CreateUniqueTempDir()); }
bool IsValid() const { return temp_dir_.IsValid(); }
const base::FilePath& GetPath() const { return temp_dir_.path(); }
private:
friend struct BrowserThread::DeleteOnThread<BrowserThread::FILE>;
friend class base::DeleteHelper<RefCountedTempDir>;
~RefCountedTempDir() {}
base::ScopedTempDir temp_dir_;
DISALLOW_COPY_AND_ASSIGN(RefCountedTempDir);
};
typedef scoped_ptr<base::File, BrowserThread::DeleteOnFileThread>
ScopedTempFile;
// Wrapper for Emf to keep only file handle in memory, and load actual data only
// on playback. Emf::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 utility process.
class LazyEmf : public MetafilePlayer {
public:
LazyEmf(const scoped_refptr<RefCountedTempDir>& temp_dir, ScopedTempFile file)
: temp_dir_(temp_dir), file_(file.Pass()) {}
virtual ~LazyEmf() { Close(); }
virtual bool SafePlayback(HDC hdc) const override;
virtual bool SaveTo(base::File* file) const override;
private:
void Close() const;
bool LoadEmf(Emf* emf) const;
mutable scoped_refptr<RefCountedTempDir> temp_dir_;
mutable ScopedTempFile 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 pdf file on the FILE thread.
// 3. Start utility process and start conversion on the IO thread.
// 4. Utility process returns page count.
// 5. For each page:
// 1. Clients requests page with file handle to a temp file.
// 2. Utility converts the page, save it to the file and reply.
//
// All these steps work sequentially, so no data should be accessed
// simultaneously by several threads.
class PdfToEmfUtilityProcessHostClient
: public content::UtilityProcessHostClient {
public:
PdfToEmfUtilityProcessHostClient(
base::WeakPtr<PdfToEmfConverterImpl> converter,
const PdfRenderSettings& settings);
void Start(const scoped_refptr<base::RefCountedMemory>& data,
const PdfToEmfConverter::StartCallback& start_callback);
void GetPage(int page_number,
const PdfToEmfConverter::GetPageCallback& get_page_callback);
void Stop();
// UtilityProcessHostClient implementation.
virtual void OnProcessCrashed(int exit_code) override;
virtual void OnProcessLaunchFailed() override;
virtual bool OnMessageReceived(const IPC::Message& message) override;
private:
class GetPageCallbackData {
MOVE_ONLY_TYPE_FOR_CPP_03(GetPageCallbackData, RValue);
public:
GetPageCallbackData(int page_number,
PdfToEmfConverter::GetPageCallback callback)
: page_number_(page_number), callback_(callback) {}
// Move constructor for STL.
GetPageCallbackData(RValue other) { this->operator=(other); }
// Move assignment for STL.
GetPageCallbackData& operator=(RValue rhs) {
page_number_ = rhs.object->page_number_;
callback_ = rhs.object->callback_;
emf_ = rhs.object->emf_.Pass();
return *this;
}
int page_number() const { return page_number_; }
const PdfToEmfConverter::GetPageCallback& callback() const {
return callback_;
}
ScopedTempFile emf() { return emf_.Pass(); }
void set_emf(ScopedTempFile emf) { emf_ = emf.Pass(); }
private:
int page_number_;
PdfToEmfConverter::GetPageCallback callback_;
ScopedTempFile emf_;
};
virtual ~PdfToEmfUtilityProcessHostClient();
bool Send(IPC::Message* msg);
// Message handlers.
void OnProcessStarted();
void OnPageCount(int page_count);
void OnPageDone(bool success, float scale_factor);
void OnFailed();
void OnTempPdfReady(ScopedTempFile pdf);
void OnTempEmfReady(GetPageCallbackData* callback_data, ScopedTempFile emf);
scoped_refptr<RefCountedTempDir> temp_dir_;
// Used to suppress callbacks after PdfToEmfConverterImpl is deleted.
base::WeakPtr<PdfToEmfConverterImpl> converter_;
PdfRenderSettings settings_;
scoped_refptr<base::RefCountedMemory> data_;
// Document loaded callback.
PdfToEmfConverter::StartCallback start_callback_;
// Process host for IPC.
base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
// Queue of callbacks for GetPage() requests. Utility process should reply
// with PageDone in the same order as requests were received.
// Use containers that keeps element pointers valid after push() and pop().
typedef std::queue<GetPageCallbackData> GetPageCallbacks;
GetPageCallbacks get_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 PdfRenderSettings& conversion_settings,
const StartCallback& start_callback) override;
virtual void GetPage(int page_number,
const GetPageCallback& get_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);
};
ScopedTempFile CreateTempFile(scoped_refptr<RefCountedTempDir>* temp_dir) {
if (!temp_dir->get())
*temp_dir = new RefCountedTempDir();
ScopedTempFile file;
if (!(*temp_dir)->IsValid())
return file.Pass();
base::FilePath path;
if (!base::CreateTemporaryFileInDir((*temp_dir)->GetPath(), &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();
}
ScopedTempFile CreateTempPdfFile(
const scoped_refptr<base::RefCountedMemory>& data,
scoped_refptr<RefCountedTempDir>* temp_dir) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
ScopedTempFile pdf_file = CreateTempFile(temp_dir);
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();
temp_dir_ = NULL;
}
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.data(), data.size()) != size)
return false;
return emf->InitFromData(data.data(), data.size());
}
PdfToEmfUtilityProcessHostClient::PdfToEmfUtilityProcessHostClient(
base::WeakPtr<PdfToEmfConverterImpl> converter,
const PdfRenderSettings& settings)
: converter_(converter), settings_(settings) {
}
PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() {
}
void PdfToEmfUtilityProcessHostClient::Start(
const scoped_refptr<base::RefCountedMemory>& data,
const PdfToEmfConverter::StartCallback& start_callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&PdfToEmfUtilityProcessHostClient::Start,
this,
data,
start_callback));
return;
}
data_ = data;
// Store callback before any OnFailed() call to make it called on failure.
start_callback_ = start_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();
// Should reply with OnProcessStarted().
Send(new ChromeUtilityMsg_StartupPing);
}
void PdfToEmfUtilityProcessHostClient::OnProcessStarted() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!utility_process_host_)
return OnFailed();
scoped_refptr<base::RefCountedMemory> data = data_;
data_ = NULL;
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::FILE,
FROM_HERE,
base::Bind(&CreateTempPdfFile, data, &temp_dir_),
base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this));
}
void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(ScopedTempFile pdf) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!utility_process_host_)
return OnFailed();
base::ProcessHandle process = utility_process_host_->GetData().handle;
// Should reply with OnPageCount().
Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles(
IPC::GetFileHandleForProcess(pdf->GetPlatformFile(), process, false),
settings_));
}
void PdfToEmfUtilityProcessHostClient::OnPageCount(int page_count) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (start_callback_.is_null())
return OnFailed();
BrowserThread::PostTask(BrowserThread::UI,
FROM_HERE,
base::Bind(&PdfToEmfConverterImpl::RunCallback,
converter_,
base::Bind(start_callback_, page_count)));
start_callback_.Reset();
}
void PdfToEmfUtilityProcessHostClient::GetPage(
int page_number,
const PdfToEmfConverter::GetPageCallback& get_page_callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&PdfToEmfUtilityProcessHostClient::GetPage,
this,
page_number,
get_page_callback));
return;
}
// Store callback before any OnFailed() call to make it called on failure.
get_page_callbacks_.push(GetPageCallbackData(page_number, get_page_callback));
if (!utility_process_host_)
return OnFailed();
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::FILE,
FROM_HERE,
base::Bind(&CreateTempFile, &temp_dir_),
base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempEmfReady,
this,
&get_page_callbacks_.back()));
}
void PdfToEmfUtilityProcessHostClient::OnTempEmfReady(
GetPageCallbackData* callback_data,
ScopedTempFile emf) {
DCHECK_CURRENTLY_ON(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);
callback_data->set_emf(emf.Pass());
// Should reply with OnPageDone().
Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage(
callback_data->page_number(), transit));
}
void PdfToEmfUtilityProcessHostClient::OnPageDone(bool success,
float scale_factor) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (get_page_callbacks_.empty())
return OnFailed();
scoped_ptr<MetafilePlayer> emf;
GetPageCallbackData& data = get_page_callbacks_.front();
if (success)
emf.reset(new LazyEmf(temp_dir_, data.emf().Pass()));
BrowserThread::PostTask(BrowserThread::UI,
FROM_HERE,
base::Bind(&PdfToEmfConverterImpl::RunCallback,
converter_,
base::Bind(data.callback(),
data.page_number(),
scale_factor,
base::Passed(&emf))));
get_page_callbacks_.pop();
}
void PdfToEmfUtilityProcessHostClient::Stop() {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&PdfToEmfUtilityProcessHostClient::Stop, this));
return;
}
Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop());
}
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_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::OnFailed() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!start_callback_.is_null())
OnPageCount(0);
while (!get_page_callbacks_.empty())
OnPageDone(false, 0.0f);
utility_process_host_.reset();
}
PdfToEmfConverterImpl::PdfToEmfConverterImpl() : weak_ptr_factory_(this) {
}
PdfToEmfConverterImpl::~PdfToEmfConverterImpl() {
if (utility_client_.get())
utility_client_->Stop();
}
void PdfToEmfConverterImpl::Start(
const scoped_refptr<base::RefCountedMemory>& data,
const PdfRenderSettings& conversion_settings,
const StartCallback& start_callback) {
DCHECK(!utility_client_.get());
utility_client_ = new PdfToEmfUtilityProcessHostClient(
weak_ptr_factory_.GetWeakPtr(), conversion_settings);
utility_client_->Start(data, start_callback);
}
void PdfToEmfConverterImpl::GetPage(int page_number,
const GetPageCallback& get_page_callback) {
utility_client_->GetPage(page_number, get_page_callback);
}
void PdfToEmfConverterImpl::RunCallback(const base::Closure& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
callback.Run();
}
} // namespace
PdfToEmfConverter::~PdfToEmfConverter() {
}
// static
scoped_ptr<PdfToEmfConverter> PdfToEmfConverter::CreateDefault() {
return scoped_ptr<PdfToEmfConverter>(new PdfToEmfConverterImpl());
}
} // namespace printing

Просмотреть файл

@ -0,0 +1,48 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PRINTING_PDF_TO_EMF_CONVERTER_H_
#define CHROME_BROWSER_PRINTING_PDF_TO_EMF_CONVERTER_H_
#include "base/callback.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_ptr.h"
namespace base {
class FilePath;
}
namespace printing {
class MetafilePlayer;
class PdfRenderSettings;
class PdfToEmfConverter {
public:
typedef base::Callback<void(int page_count)> StartCallback;
typedef base::Callback<void(int page_number,
float scale_factor,
scoped_ptr<MetafilePlayer> emf)> GetPageCallback;
virtual ~PdfToEmfConverter();
static scoped_ptr<PdfToEmfConverter> CreateDefault();
// Starts conversion of PDF provided as |data|. Calls |start_callback|
// with positive |page_count|. |page_count| is 0 if initialization failed.
virtual void Start(const scoped_refptr<base::RefCountedMemory>& data,
const PdfRenderSettings& conversion_settings,
const StartCallback& start_callback) = 0;
// Requests conversion of the page. |page_number| is 0-base page number in
// PDF provided in Start() call.
// Calls |get_page_callback| after conversion. |emf| of callback in not NULL
// if conversion succeeded.
virtual void GetPage(int page_number,
const GetPageCallback& get_page_callback) = 0;
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PDF_TO_EMF_CONVERTER_H_

Просмотреть файл

@ -17,6 +17,12 @@
#include "printing/printed_document.h"
#include "printing/printed_page.h"
#if defined(OS_WIN)
#include "chrome/browser/printing/pdf_to_emf_converter.h"
#include "printing/pdf_render_settings.h"
#endif
using base::TimeDelta;
namespace {
@ -272,6 +278,103 @@ void PrintJob::OnNotifyPrintJobEvent(const JobEventDetails& event_details) {
}
}
#if defined(OS_WIN)
class PrintJob::PdfToEmfState {
public:
PdfToEmfState(const gfx::Size& page_size, const gfx::Rect& content_area)
: page_count_(0),
current_page_(0),
pages_in_progress_(0),
page_size_(page_size),
content_area_(content_area),
converter_(PdfToEmfConverter::CreateDefault()) {}
void Start(const scoped_refptr<base::RefCountedMemory>& data,
const PdfRenderSettings& conversion_settings,
const PdfToEmfConverter::StartCallback& start_callback) {
converter_->Start(data, conversion_settings, start_callback);
}
void GetMorePages(
const PdfToEmfConverter::GetPageCallback& get_page_callback) {
const int kMaxNumberOfTempFilesPerDocument = 3;
while (pages_in_progress_ < kMaxNumberOfTempFilesPerDocument &&
current_page_ < page_count_) {
++pages_in_progress_;
converter_->GetPage(current_page_++, get_page_callback);
}
}
void OnPageProcessed(
const PdfToEmfConverter::GetPageCallback& get_page_callback) {
--pages_in_progress_;
GetMorePages(get_page_callback);
// Release converter if we don't need this any more.
if (!pages_in_progress_ && current_page_ >= page_count_)
converter_.reset();
}
void set_page_count(int page_count) { page_count_ = page_count; }
gfx::Size page_size() const { return page_size_; }
gfx::Rect content_area() const { return content_area_; }
private:
int page_count_;
int current_page_;
int pages_in_progress_;
gfx::Size page_size_;
gfx::Rect content_area_;
scoped_ptr<PdfToEmfConverter> converter_;
};
void PrintJob::StartPdfToEmfConversion(
const scoped_refptr<base::RefCountedMemory>& bytes,
const gfx::Size& page_size,
const gfx::Rect& content_area) {
DCHECK(!ptd_to_emf_state_.get());
ptd_to_emf_state_.reset(new PdfToEmfState(page_size, content_area));
const int kPrinterDpi = settings().dpi();
ptd_to_emf_state_->Start(
bytes,
printing::PdfRenderSettings(content_area, kPrinterDpi, true),
base::Bind(&PrintJob::OnPdfToEmfStarted, this));
}
void PrintJob::OnPdfToEmfStarted(int page_count) {
if (page_count <= 0) {
ptd_to_emf_state_.reset();
Cancel();
return;
}
ptd_to_emf_state_->set_page_count(page_count);
ptd_to_emf_state_->GetMorePages(
base::Bind(&PrintJob::OnPdfToEmfPageConverted, this));
}
void PrintJob::OnPdfToEmfPageConverted(int page_number,
float scale_factor,
scoped_ptr<MetafilePlayer> emf) {
DCHECK(ptd_to_emf_state_);
if (!document_.get() || !emf) {
ptd_to_emf_state_.reset();
Cancel();
return;
}
// Update the rendered document. It will send notifications to the listener.
document_->SetPage(page_number,
emf.Pass(),
scale_factor,
ptd_to_emf_state_->page_size(),
ptd_to_emf_state_->content_area());
ptd_to_emf_state_->GetMorePages(
base::Bind(&PrintJob::OnPdfToEmfPageConverted, this));
}
#endif // OS_WIN
void PrintJob::OnDocumentDone() {
// Be sure to live long enough. The instance could be destroyed by the
// JOB_DONE broadcast.

Просмотреть файл

@ -90,6 +90,19 @@ class PrintJob : public PrintJobWorkerOwner,
// Access the current printed document. Warning: may be NULL.
PrintedDocument* document() const;
#if defined(OS_WIN)
void StartPdfToEmfConversion(
const scoped_refptr<base::RefCountedMemory>& bytes,
const gfx::Size& page_size,
const gfx::Rect& content_area);
void OnPdfToEmfStarted(int page_count);
void OnPdfToEmfPageConverted(int page_number,
float scale_factor,
scoped_ptr<MetafilePlayer> emf);
#endif // OS_WIN
protected:
virtual ~PrintJob();
@ -137,6 +150,11 @@ class PrintJob : public PrintJobWorkerOwner,
// the notified calls Cancel() again.
bool is_canceling_;
#if defined(OS_WIN)
class PdfToEmfState;
scoped_ptr<PdfToEmfState> ptd_to_emf_state_;
#endif // OS_WIN
// Used at shutdown so that we can quit a nested message loop.
base::WeakPtrFactory<PrintJob> quit_factory_;

Просмотреть файл

@ -156,6 +156,8 @@ void PrintViewManagerBase::OnDidPrintPage(
params.data_size);
document->DebugDumpData(bytes.get(), FILE_PATH_LITERAL(".pdf"));
print_job_->StartPdfToEmfConversion(
bytes, params.page_size, params.content_area);
}
#endif // !OS_WIN
}

Просмотреть файл

@ -0,0 +1,217 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Multiply-included message file, so no include guard.
#if defined(OS_WIN)
#include <Windows.h>
#endif // defined(OS_WIN)
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/strings/string16.h"
#include "base/tuple.h"
#include "base/values.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_platform_file.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
// Singly-included section for typedefs.
#ifndef CHROME_COMMON_CHROME_UTILITY_MESSAGES_H_
#define CHROME_COMMON_CHROME_UTILITY_MESSAGES_H_
#if defined(OS_WIN)
// A vector of filters, each being a Tuple containing a display string (i.e.
// "Text Files") and a filter pattern (i.e. "*.txt").
typedef std::vector<Tuple<base::string16, base::string16>>
GetOpenFileNameFilter;
#endif // OS_WIN
#endif // CHROME_COMMON_CHROME_UTILITY_MESSAGES_H_
#define IPC_MESSAGE_START ChromeUtilityMsgStart
//#if defined(FULL_SAFE_BROWSING)
//IPC_STRUCT_TRAITS_BEGIN(safe_browsing::zip_analyzer::Results)
//IPC_STRUCT_TRAITS_MEMBER(success)
//IPC_STRUCT_TRAITS_MEMBER(has_executable)
//IPC_STRUCT_TRAITS_MEMBER(has_archive)
//IPC_STRUCT_TRAITS_END()
//#endif
#if defined(OS_WIN)
IPC_STRUCT_BEGIN(ChromeUtilityMsg_GetSaveFileName_Params)
IPC_STRUCT_MEMBER(HWND, owner)
IPC_STRUCT_MEMBER(DWORD, flags)
IPC_STRUCT_MEMBER(GetOpenFileNameFilter, filters)
IPC_STRUCT_MEMBER(int, one_based_filter_index)
IPC_STRUCT_MEMBER(base::FilePath, suggested_filename)
IPC_STRUCT_MEMBER(base::FilePath, initial_directory)
IPC_STRUCT_MEMBER(base::string16, default_extension)
IPC_STRUCT_END()
#endif // OS_WIN
//------------------------------------------------------------------------------
// Utility process messages:
// These are messages from the browser to the utility process.
// Tell the utility process to parse a JSON string into a Value object.
IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_ParseJSON,
std::string /* JSON to parse */)
// Tell the utility process to decode the given image data.
IPC_MESSAGE_CONTROL2(ChromeUtilityMsg_DecodeImage,
std::vector<unsigned char> /* encoded image contents */,
bool /* shrink image if needed for IPC msg limit */)
// Tell the utility process to decode the given JPEG image data with a robust
// libjpeg codec.
IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_RobustJPEGDecodeImage,
std::vector<unsigned char>) // encoded image contents
// Tell the utility process to patch the given |input_file| using |patch_file|
// and place the output in |output_file|. The patch should use the bsdiff
// algorithm (Courgette's version).
IPC_MESSAGE_CONTROL3(ChromeUtilityMsg_PatchFileBsdiff,
base::FilePath /* input_file */,
base::FilePath /* patch_file */,
base::FilePath /* output_file */)
// Tell the utility process to patch the given |input_file| using |patch_file|
// and place the output in |output_file|. The patch should use the Courgette
// algorithm.
IPC_MESSAGE_CONTROL3(ChromeUtilityMsg_PatchFileCourgette,
base::FilePath /* input_file */,
base::FilePath /* patch_file */,
base::FilePath /* output_file */)
#if defined(OS_CHROMEOS)
// Tell the utility process to create a zip file on the given list of files.
IPC_MESSAGE_CONTROL3(ChromeUtilityMsg_CreateZipFile,
base::FilePath /* src_dir */,
std::vector<base::FilePath> /* src_relative_paths */,
base::FileDescriptor /* dest_fd */)
#endif // defined(OS_CHROMEOS)
// Requests the utility process to respond with a
// ChromeUtilityHostMsg_ProcessStarted message once it has started. This may
// be used if the host process needs a handle to the running utility process.
IPC_MESSAGE_CONTROL0(ChromeUtilityMsg_StartupPing)
#if defined(FULL_SAFE_BROWSING)
// Tells the utility process to analyze a zip file for malicious download
// protection.
IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection,
IPC::PlatformFileForTransit /* zip_file */)
#endif
#if defined(OS_WIN)
// Invokes ui::base::win::OpenFileViaShell from the utility process.
IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_OpenFileViaShell,
base::FilePath /* full_path */)
// Invokes ui::base::win::OpenFolderViaShell from the utility process.
IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_OpenFolderViaShell,
base::FilePath /* full_path */)
// Instructs the utility process to invoke GetOpenFileName. |owner| is the
// parent of the modal dialog, |flags| are OFN_* flags. |filter| constrains the
// user's file choices. |initial_directory| and |filename| select the directory
// to be displayed and the file to be initially selected.
//
// Either ChromeUtilityHostMsg_GetOpenFileName_Failed or
// ChromeUtilityHostMsg_GetOpenFileName_Result will be returned when the
// operation completes whether due to error or user action.
IPC_MESSAGE_CONTROL5(ChromeUtilityMsg_GetOpenFileName,
HWND /* owner */,
DWORD /* flags */,
GetOpenFileNameFilter /* filter */,
base::FilePath /* initial_directory */,
base::FilePath /* filename */)
IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_GetSaveFileName,
ChromeUtilityMsg_GetSaveFileName_Params /* params */)
#endif // defined(OS_WIN)
//#if defined(OS_ANDROID)
//// Instructs the utility process to detect support for seccomp-bpf,
//// and the result is reported through
//// ChromeUtilityHostMsg_DetectSeccompSupport_Result.
//IPC_MESSAGE_CONTROL0(ChromeUtilityMsg_DetectSeccompSupport)
//#endif
//------------------------------------------------------------------------------
// Utility process host messages:
// These are messages from the utility process to the browser.
// Reply when the utility process successfully parsed a JSON string.
//
// WARNING: The result can be of any Value subclass type, but we can't easily
// pass indeterminate value types by const object reference with our IPC macros,
// so we put the result Value into a ListValue. Handlers should examine the
// first (and only) element of the ListValue for the actual result.
IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_ParseJSON_Succeeded,
base::ListValue)
// Reply when the utility process failed in parsing a JSON string.
IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_ParseJSON_Failed,
std::string /* error message, if any*/)
// Reply when the utility process has failed while unpacking and parsing a
// web resource. |error_message| is a user-readable explanation of what
// went wrong.
IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_UnpackWebResource_Failed,
std::string /* error_message, if any */)
// Reply when the utility process has succeeded in decoding the image.
IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_DecodeImage_Succeeded,
SkBitmap) // decoded image
// Reply when an error occurred decoding the image.
IPC_MESSAGE_CONTROL0(ChromeUtilityHostMsg_DecodeImage_Failed)
// Reply when a file has been patched.
IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_PatchFile_Finished, int /* result */)
//#if defined(OS_CHROMEOS)
//// Reply when the utility process has succeeded in creating the zip file.
//IPC_MESSAGE_CONTROL0(ChromeUtilityHostMsg_CreateZipFile_Succeeded)
//// Reply when an error occured in creating the zip file.
//IPC_MESSAGE_CONTROL0(ChromeUtilityHostMsg_CreateZipFile_Failed)
//#endif // defined(OS_CHROMEOS)
// Reply when the utility process has started.
IPC_MESSAGE_CONTROL0(ChromeUtilityHostMsg_ProcessStarted)
//#if defined(FULL_SAFE_BROWSING)
//// Reply when a zip file has been analyzed for malicious download protection.
//IPC_MESSAGE_CONTROL1(
//ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished,
//safe_browsing::zip_analyzer::Results)
//#endif
#if defined(OS_WIN)
IPC_MESSAGE_CONTROL0(ChromeUtilityHostMsg_GetOpenFileName_Failed)
IPC_MESSAGE_CONTROL2(ChromeUtilityHostMsg_GetOpenFileName_Result,
base::FilePath /* directory */,
std::vector<base::FilePath> /* filenames */)
IPC_MESSAGE_CONTROL0(ChromeUtilityHostMsg_GetSaveFileName_Failed)
IPC_MESSAGE_CONTROL2(ChromeUtilityHostMsg_GetSaveFileName_Result,
base::FilePath /* path */,
int /* one_based_filter_index */)
IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_BuildDirectWriteFontCache,
base::FilePath /* cache file path */)
#endif // defined(OS_WIN)
//#if defined(OS_ANDROID)
//// Reply to ChromeUtilityMsg_DetectSeccompSupport to report the level
//// of kernel support for seccomp-bpf.
//IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_DetectSeccompSupport_ResultPrctl,
//bool [> seccomp prctl supported <])
//IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_DetectSeccompSupport_ResultSyscall,
//bool [> seccomp syscall supported <])
//#endif

Просмотреть файл

@ -17,6 +17,13 @@
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/geometry/rect.h"
#if defined(OS_WIN)
#include "ipc/ipc_platform_file.h"
#include "printing/backend/print_backend.h"
#include "printing/page_range.h"
#include "printing/pdf_render_settings.h"
#endif
#ifndef CHROME_COMMON_PRINT_MESSAGES_H_
#define CHROME_COMMON_PRINT_MESSAGES_H_
@ -239,3 +246,31 @@ IPC_MESSAGE_ROUTED0(PrintHostMsg_ShowInvalidPrinterSettingsError)
// Tell the browser printing failed.
IPC_MESSAGE_ROUTED1(PrintHostMsg_PrintingFailed,
int /* document cookie */)
#if defined(OS_WIN)
// Tell the utility process to start rendering the given PDF into a metafile.
// Utility process would be alive until
// ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop message.
IPC_MESSAGE_CONTROL2(ChromeUtilityMsg_RenderPDFPagesToMetafiles,
IPC::PlatformFileForTransit, /* input_file */
printing::PdfRenderSettings /* settings */)
// Requests conversion of the next page.
IPC_MESSAGE_CONTROL2(ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage,
int /* page_number */,
IPC::PlatformFileForTransit /* output_file */)
// Requests utility process to stop conversion and exit.
IPC_MESSAGE_CONTROL0(ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop)
// Reply when the utility process loaded PDF. |page_count| is 0, if loading
// failed.
IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount,
int /* page_count */)
// Reply when the utility process rendered the PDF page.
IPC_MESSAGE_CONTROL2(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone,
bool /* success */,
float /* scale_factor */)
#endif

Просмотреть файл

@ -0,0 +1,144 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/utility/printing_handler.h"
#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#include "base/path_service.h"
#include "base/scoped_native_library.h"
#include "chrome/common/print_messages.h"
#include "content/public/utility/utility_thread.h"
#include "pdf/pdf.h"
#include "printing/page_range.h"
#include "printing/pdf_render_settings.h"
#if defined(OS_WIN)
#include "printing/emf_win.h"
#include "ui/gfx/gdi_util.h"
#endif
namespace {
bool Send(IPC::Message* message) {
return content::UtilityThread::Get()->Send(message);
}
void ReleaseProcessIfNeeded() {
content::UtilityThread::Get()->ReleaseProcessIfNeeded();
}
} // namespace
PrintingHandler::PrintingHandler() {}
PrintingHandler::~PrintingHandler() {}
bool PrintingHandler::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintingHandler, message)
#if defined(OS_WIN)
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles,
OnRenderPDFPagesToMetafile)
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage,
OnRenderPDFPagesToMetafileGetPage)
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop,
OnRenderPDFPagesToMetafileStop)
#endif // OS_WIN
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
#if defined(OS_WIN)
void PrintingHandler::OnRenderPDFPagesToMetafile(
IPC::PlatformFileForTransit pdf_transit,
const printing::PdfRenderSettings& settings) {
pdf_rendering_settings_ = settings;
base::File pdf_file = IPC::PlatformFileForTransitToFile(pdf_transit);
int page_count = LoadPDF(pdf_file.Pass());
//int page_count = 1;
Send(
new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount(page_count));
}
void PrintingHandler::OnRenderPDFPagesToMetafileGetPage(
int page_number,
IPC::PlatformFileForTransit output_file) {
base::File emf_file = IPC::PlatformFileForTransitToFile(output_file);
float scale_factor = 1.0f;
bool success =
RenderPdfPageToMetafile(page_number, emf_file.Pass(), &scale_factor);
Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone(
success, scale_factor));
}
void PrintingHandler::OnRenderPDFPagesToMetafileStop() {
ReleaseProcessIfNeeded();
}
int PrintingHandler::LoadPDF(base::File pdf_file) {
int64 length64 = pdf_file.GetLength();
if (length64 <= 0 || length64 > std::numeric_limits<int>::max())
return 0;
int length = static_cast<int>(length64);
pdf_data_.resize(length);
if (length != pdf_file.Read(0, pdf_data_.data(), pdf_data_.size()))
return 0;
int total_page_count = 0;
if (!chrome_pdf::GetPDFDocInfo(
&pdf_data_.front(), pdf_data_.size(), &total_page_count, NULL)) {
return 0;
}
return total_page_count;
}
bool PrintingHandler::RenderPdfPageToMetafile(int page_number,
base::File output_file,
float* scale_factor) {
printing::Emf metafile;
metafile.Init();
// We need to scale down DC to fit an entire page into DC available area.
// Current metafile is based on screen DC and have current screen size.
// Writing outside of those boundaries will result in the cut-off output.
// On metafiles (this is the case here), scaling down will still record
// original coordinates and we'll be able to print in full resolution.
// Before playback we'll need to counter the scaling up that will happen
// in the service (print_system_win.cc).
*scale_factor =
gfx::CalculatePageScale(metafile.context(),
pdf_rendering_settings_.area().right(),
pdf_rendering_settings_.area().bottom());
gfx::ScaleDC(metafile.context(), *scale_factor);
// The underlying metafile is of type Emf and ignores the arguments passed
// to StartPage.
metafile.StartPage(gfx::Size(), gfx::Rect(), 1);
if (!chrome_pdf::RenderPDFPageToDC(
&pdf_data_.front(),
pdf_data_.size(),
page_number,
metafile.context(),
pdf_rendering_settings_.dpi(),
pdf_rendering_settings_.area().x(),
pdf_rendering_settings_.area().y(),
pdf_rendering_settings_.area().width(),
pdf_rendering_settings_.area().height(),
true,
false,
true,
true,
pdf_rendering_settings_.autorotate())) {
return false;
}
metafile.FinishPage();
metafile.FinishDocument();
return metafile.SaveTo(&output_file);
}
#endif // OS_WIN

Просмотреть файл

@ -0,0 +1,59 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_UTILITY_PRINTING_HANDLER_H_
#define CHROME_UTILITY_PRINTING_HANDLER_H_
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "chrome/utility/utility_message_handler.h"
#include "ipc/ipc_platform_file.h"
#include "printing/pdf_render_settings.h"
#if !defined(ENABLE_PRINT_PREVIEW) && !defined(OS_WIN)
#error "Windows or full printing must be enabled"
#endif
namespace printing {
class PdfRenderSettings;
struct PwgRasterSettings;
struct PageRange;
}
// Dispatches IPCs for printing.
class PrintingHandler : public UtilityMessageHandler {
public:
PrintingHandler();
~PrintingHandler() override;
// IPC::Listener:
bool OnMessageReceived(const IPC::Message& message) override;
private:
// IPC message handlers.
#if defined(OS_WIN)
void OnRenderPDFPagesToMetafile(IPC::PlatformFileForTransit pdf_transit,
const printing::PdfRenderSettings& settings);
void OnRenderPDFPagesToMetafileGetPage(
int page_number,
IPC::PlatformFileForTransit output_file);
void OnRenderPDFPagesToMetafileStop();
#endif // OS_WIN
#if defined(OS_WIN)
int LoadPDF(base::File pdf_file);
bool RenderPdfPageToMetafile(int page_number,
base::File output_file,
float* scale_factor);
#endif // OS_WIN
#if defined(OS_WIN)
std::vector<char> pdf_data_;
printing::PdfRenderSettings pdf_rendering_settings_;
#endif
DISALLOW_COPY_AND_ASSIGN(PrintingHandler);
};
#endif // CHROME_UTILITY_PRINTING_HANDLER_H_

Просмотреть файл

@ -0,0 +1,22 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_UTILITY_UTILITY_MESSAGE_HANDLER_H_
#define CHROME_UTILITY_UTILITY_MESSAGE_HANDLER_H_
namespace IPC {
class Message;
}
class UtilityMessageHandler {
public:
virtual ~UtilityMessageHandler() {}
// Called when a message is received. Returns true iff the message was
// handled.
virtual bool OnMessageReceived(const IPC::Message& message) = 0;
};
#endif // CHROME_UTILITY_UTILITY_MESSAGE_HANDLER_H_

Просмотреть файл

@ -280,6 +280,8 @@
'atom/renderer/atom_renderer_client.h',
'atom/renderer/guest_view_container.cc',
'atom/renderer/guest_view_container.h',
'atom/utility/atom_content_utility_client.cc',
'atom/utility/atom_content_utility_client.h',
'chromium_src/chrome/browser/browser_process.cc',
'chromium_src/chrome/browser/browser_process.h',
'chromium_src/chrome/browser/chrome_notification_types.h',
@ -291,6 +293,8 @@
'chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.h',
'chromium_src/chrome/browser/extensions/global_shortcut_listener_win.cc',
'chromium_src/chrome/browser/extensions/global_shortcut_listener_win.h',
'chromium_src/chrome/browser/printing/pdf_to_emf_converter.cc',
'chromium_src/chrome/browser/printing/pdf_to_emf_converter.h',
'chromium_src/chrome/browser/printing/print_job.cc',
'chromium_src/chrome/browser/printing/print_job.h',
'chromium_src/chrome/browser/printing/print_job_manager.cc',
@ -324,6 +328,7 @@
'chromium_src/chrome/browser/ui/views/color_chooser_aura.h',
'chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc',
'chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h',
'chromium_src/chrome/common/chrome_utility_messages.h',
'chromium_src/chrome/common/print_messages.cc',
'chromium_src/chrome/common/print_messages.h',
'chromium_src/chrome/common/tts_messages.h',
@ -338,6 +343,9 @@
'chromium_src/chrome/renderer/spellchecker/spellcheck_worditerator.h',
'chromium_src/chrome/renderer/tts_dispatcher.cc',
'chromium_src/chrome/renderer/tts_dispatcher.h',
'chromium_src/chrome/utility/printing_handler.cc',
'chromium_src/chrome/utility/printing_handler.h',
'chromium_src/chrome/utility/utility_message_handler.h',
'chromium_src/library_loaders/libspeechd_loader.cc',
'chromium_src/library_loaders/libspeechd.h',
'<@(native_mate_files)',