Linux: Add new CefPrintHandler and CefPrintSettings classes to support printing and a GTK implementation in cefclient (issue #1258).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1762 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt
2014-07-10 15:41:30 +00:00
parent 6f63f5d4f8
commit 8313963a27
47 changed files with 3803 additions and 3 deletions

View File

@@ -41,6 +41,10 @@
#include "ui/base/ime/input_method_initializer.h"
#endif
#if defined(OS_LINUX)
#include "libcef/browser/printing/print_dialog_linux.h"
#endif
CefBrowserMainParts::CefBrowserMainParts(
const content::MainFunctionParams& parameters)
: BrowserMainParts(),
@@ -85,6 +89,11 @@ void CefBrowserMainParts::PostMainMessageLoopStart() {
// CEF's internal handling of "chrome://tracing".
content::WebUIControllerFactory::UnregisterFactoryForTesting(
content::ContentWebUIControllerFactory::GetInstance());
#if defined(OS_LINUX)
printing::PrintingContextLinux::SetCreatePrintDialogFunction(
&CefPrintDialogLinux::CreatePrintDialog);
#endif
}
int CefBrowserMainParts::PreCreateThreads() {

View File

@@ -0,0 +1,165 @@
// Copyright (c) 2014 The Chromium Embedded Framework 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 "libcef/browser/print_settings_impl.h"
#include "base/logging.h"
CefPrintSettingsImpl::CefPrintSettingsImpl(printing::PrintSettings* value,
bool will_delete,
bool read_only)
: CefValueBase<CefPrintSettings, printing::PrintSettings>(
value, NULL, will_delete ? kOwnerWillDelete : kOwnerNoDelete,
read_only, NULL) {
}
bool CefPrintSettingsImpl::IsValid() {
return !detached();
}
bool CefPrintSettingsImpl::IsReadOnly() {
return read_only();
}
CefRefPtr<CefPrintSettings> CefPrintSettingsImpl::Copy() {
CEF_VALUE_VERIFY_RETURN(false, NULL);
printing::PrintSettings* new_settings = new printing::PrintSettings;
*new_settings = const_value();
return new CefPrintSettingsImpl(new_settings, true, false);
}
void CefPrintSettingsImpl::SetOrientation(bool landscape) {
CEF_VALUE_VERIFY_RETURN_VOID(true);
mutable_value()->SetOrientation(landscape);
}
bool CefPrintSettingsImpl::IsLandscape() {
CEF_VALUE_VERIFY_RETURN(false, false);
return const_value().landscape();
}
void CefPrintSettingsImpl::SetPrinterPrintableArea(
const CefSize& physical_size_device_units,
const CefRect& printable_area_device_units,
bool landscape_needs_flip) {
CEF_VALUE_VERIFY_RETURN_VOID(true);
gfx::Size size(physical_size_device_units.width,
physical_size_device_units.height);
gfx::Rect rect(printable_area_device_units.x,
printable_area_device_units.y,
printable_area_device_units.width,
printable_area_device_units.height);
mutable_value()->SetPrinterPrintableArea(size, rect, landscape_needs_flip);
}
void CefPrintSettingsImpl::SetDeviceName(const CefString& name) {
CEF_VALUE_VERIFY_RETURN_VOID(true);
mutable_value()->set_device_name(name.ToString16());
}
CefString CefPrintSettingsImpl::GetDeviceName() {
CEF_VALUE_VERIFY_RETURN(false, CefString());
return const_value().device_name();
}
void CefPrintSettingsImpl::SetDPI(int dpi) {
CEF_VALUE_VERIFY_RETURN_VOID(true);
mutable_value()->set_dpi(dpi);
}
int CefPrintSettingsImpl::GetDPI() {
CEF_VALUE_VERIFY_RETURN(false, 0);
return const_value().dpi();
}
void CefPrintSettingsImpl::SetPageRanges(const PageRangeList& ranges) {
CEF_VALUE_VERIFY_RETURN_VOID(true);
printing::PageRanges page_ranges;
PageRangeList::const_iterator it = ranges.begin();
for(; it != ranges.end(); ++it) {
const CefPageRange& cef_range = *it;
printing::PageRange range;
range.from = cef_range.from;
range.to = cef_range.to;
page_ranges.push_back(range);
}
mutable_value()->set_ranges(page_ranges);
}
size_t CefPrintSettingsImpl::GetPageRangesCount() {
CEF_VALUE_VERIFY_RETURN(false, 0);
return const_value().ranges().size();
}
void CefPrintSettingsImpl::GetPageRanges(PageRangeList& ranges) {
CEF_VALUE_VERIFY_RETURN_VOID(false);
if (!ranges.empty())
ranges.clear();
const printing::PageRanges& page_ranges = const_value().ranges();
printing::PageRanges::const_iterator it = page_ranges.begin();
for (; it != page_ranges.end(); ++it) {
const printing::PageRange& range = *it;
ranges.push_back(CefPageRange(range.from, range.to));
}
}
void CefPrintSettingsImpl::SetSelectionOnly(bool selection_only) {
CEF_VALUE_VERIFY_RETURN_VOID(true);
mutable_value()->set_selection_only(selection_only);
}
bool CefPrintSettingsImpl::IsSelectionOnly() {
CEF_VALUE_VERIFY_RETURN(false, false);
return const_value().selection_only();
}
void CefPrintSettingsImpl::SetCollate(bool collate) {
CEF_VALUE_VERIFY_RETURN_VOID(true);
mutable_value()->set_collate(collate);
}
bool CefPrintSettingsImpl::WillCollate() {
CEF_VALUE_VERIFY_RETURN(false, false);
return const_value().collate();
}
void CefPrintSettingsImpl::SetColorModel(ColorModel model) {
CEF_VALUE_VERIFY_RETURN_VOID(true);
mutable_value()->set_color(static_cast<printing::ColorModel>(model));
}
CefPrintSettings::ColorModel CefPrintSettingsImpl::GetColorModel() {
CEF_VALUE_VERIFY_RETURN(false, COLOR_MODEL_UNKNOWN);
return static_cast<ColorModel>(const_value().color());
}
void CefPrintSettingsImpl::SetCopies(int copies) {
CEF_VALUE_VERIFY_RETURN_VOID(true);
mutable_value()->set_copies(copies);
}
int CefPrintSettingsImpl::GetCopies() {
CEF_VALUE_VERIFY_RETURN(false, false);
return const_value().copies();
}
void CefPrintSettingsImpl::SetDuplexMode(DuplexMode mode) {
CEF_VALUE_VERIFY_RETURN_VOID(true);
mutable_value()->set_duplex_mode(static_cast<printing::DuplexMode>(mode));
}
CefPrintSettings::DuplexMode CefPrintSettingsImpl::GetDuplexMode() {
CEF_VALUE_VERIFY_RETURN(false, DUPLEX_MODE_UNKNOWN);
return static_cast<DuplexMode>(const_value().duplex_mode());
}
// CefPrintSettings implementation.
// static
CefRefPtr<CefPrintSettings> CefPrintSettings::Create() {
return new CefPrintSettingsImpl(
new printing::PrintSettings(), true, false);
}

View File

@@ -0,0 +1,56 @@
// Copyright (c) 2014 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_PRINT_SETTINGS_IMPL_H_
#define CEF_LIBCEF_BROWSER_PRINT_SETTINGS_IMPL_H_
#pragma once
#include "include/cef_print_settings.h"
#include "libcef/common/value_base.h"
#include "printing/print_settings.h"
// CefPrintSettings implementation
class CefPrintSettingsImpl
: public CefValueBase<CefPrintSettings, printing::PrintSettings> {
public:
CefPrintSettingsImpl(printing::PrintSettings* value,
bool will_delete,
bool read_only);
// CefPrintSettings methods.
virtual bool IsValid() OVERRIDE;
virtual bool IsReadOnly() OVERRIDE;
virtual CefRefPtr<CefPrintSettings> Copy() OVERRIDE;
virtual void SetOrientation(bool landscape) OVERRIDE;
virtual bool IsLandscape() OVERRIDE;
virtual void SetPrinterPrintableArea(
const CefSize& physical_size_device_units,
const CefRect& printable_area_device_units,
bool landscape_needs_flip) OVERRIDE;
virtual void SetDeviceName(const CefString& name) OVERRIDE;
virtual CefString GetDeviceName() OVERRIDE;
virtual void SetDPI(int dpi) OVERRIDE;
virtual int GetDPI() OVERRIDE;
virtual void SetPageRanges(const PageRangeList& ranges) OVERRIDE;
virtual size_t GetPageRangesCount() OVERRIDE;
virtual void GetPageRanges(PageRangeList& ranges) OVERRIDE;
virtual void SetSelectionOnly(bool selection_only) OVERRIDE;
virtual bool IsSelectionOnly() OVERRIDE;
virtual void SetCollate(bool collate) OVERRIDE;
virtual bool WillCollate() OVERRIDE;
virtual void SetColorModel(ColorModel model) OVERRIDE;
virtual ColorModel GetColorModel() OVERRIDE;
virtual void SetCopies(int copies) OVERRIDE;
virtual int GetCopies() OVERRIDE;
virtual void SetDuplexMode(DuplexMode mode) OVERRIDE;
virtual DuplexMode GetDuplexMode() OVERRIDE;
// Must hold the controller lock while using this value.
const printing::PrintSettings& print_settings() { return const_value(); }
DISALLOW_COPY_AND_ASSIGN(CefPrintSettingsImpl);
};
#endif // CEF_LIBCEF_BROWSER_PRINT_SETTINGS_IMPL_H_

View File

@@ -0,0 +1,275 @@
// Copyright (c) 2014 The Chromium Embedded Framework Authors.
// Portions 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.
#include "libcef/browser/printing/print_dialog_linux.h"
#include <string>
#include <vector>
#include "libcef/browser/print_settings_impl.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/content_client.h"
#include "base/bind.h"
#include "base/file_util.h"
#include "base/files/file_util_proxy.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "printing/metafile.h"
#include "printing/print_job_constants.h"
#include "printing/print_settings.h"
using content::BrowserThread;
using printing::PageRanges;
using printing::PrintSettings;
class CefPrintDialogCallbackImpl : public CefPrintDialogCallback {
public:
explicit CefPrintDialogCallbackImpl(CefRefPtr<CefPrintDialogLinux> dialog)
: dialog_(dialog) {
}
virtual void Continue(CefRefPtr<CefPrintSettings> settings) OVERRIDE {
if (CEF_CURRENTLY_ON_UIT()) {
if (dialog_) {
dialog_->OnPrintContinue(settings);
dialog_ = NULL;
}
} else {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefPrintDialogCallbackImpl::Continue, this, settings));
}
}
virtual void Cancel() OVERRIDE {
if (CEF_CURRENTLY_ON_UIT()) {
if (dialog_) {
dialog_->OnPrintCancel();
dialog_ = NULL;
}
} else {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefPrintDialogCallbackImpl::Cancel, this));
}
}
void Disconnect() {
dialog_ = NULL;
}
private:
CefRefPtr<CefPrintDialogLinux> dialog_;
IMPLEMENT_REFCOUNTING(CefPrintDialogCallbackImpl);
DISALLOW_COPY_AND_ASSIGN(CefPrintDialogCallbackImpl);
};
class CefPrintJobCallbackImpl : public CefPrintJobCallback {
public:
explicit CefPrintJobCallbackImpl(CefRefPtr<CefPrintDialogLinux> dialog)
: dialog_(dialog) {
}
virtual void Continue() OVERRIDE {
if (CEF_CURRENTLY_ON_UIT()) {
if (dialog_) {
dialog_->OnJobCompleted();
dialog_ = NULL;
}
} else {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefPrintJobCallbackImpl::Continue, this));
}
}
void Disconnect() {
dialog_ = NULL;
}
private:
CefRefPtr<CefPrintDialogLinux> dialog_;
IMPLEMENT_REFCOUNTING(CefPrintJobCallbackImpl);
DISALLOW_COPY_AND_ASSIGN(CefPrintJobCallbackImpl);
};
// static
printing::PrintDialogGtkInterface* CefPrintDialogLinux::CreatePrintDialog(
PrintingContextLinux* context) {
CEF_REQUIRE_UIT();
return new CefPrintDialogLinux(context);
}
CefPrintDialogLinux::CefPrintDialogLinux(PrintingContextLinux* context)
: context_(context) {
}
CefPrintDialogLinux::~CefPrintDialogLinux() {
CEF_REQUIRE_UIT();
ReleaseHandler();
}
void CefPrintDialogLinux::UseDefaultSettings() {
PrintSettings settings;
UpdateSettings(&settings, true);
}
bool CefPrintDialogLinux::UpdateSettings(printing::PrintSettings* settings) {
return UpdateSettings(settings, false);
}
void CefPrintDialogLinux::ShowDialog(
gfx::NativeView parent_view,
bool has_selection,
const PrintingContextLinux::PrintSettingsCallback& callback) {
CEF_REQUIRE_UIT();
SetHandler();
if (!handler_) {
callback.Run(PrintingContextLinux::CANCEL);
return;
}
callback_ = callback;
CefRefPtr<CefPrintDialogCallbackImpl> callback_impl(
new CefPrintDialogCallbackImpl(this));
if (!handler_->OnPrintDialog(has_selection, callback_impl.get())) {
callback_impl->Disconnect();
OnPrintCancel();
}
}
void CefPrintDialogLinux::PrintDocument(const printing::Metafile* metafile,
const base::string16& document_name) {
// This runs on the print worker thread, does not block the UI thread.
DCHECK(!CEF_CURRENTLY_ON_UIT());
// The document printing tasks can outlive the PrintingContext that created
// this dialog.
AddRef();
bool error = false;
if (!base::CreateTemporaryFile(&path_to_pdf_)) {
LOG(ERROR) << "Creating temporary file failed";
error = true;
}
if (!error && !metafile->SaveTo(path_to_pdf_)) {
LOG(ERROR) << "Saving metafile failed";
base::DeleteFile(path_to_pdf_, false);
error = true;
}
if (error) {
// Matches AddRef() above.
Release();
} else {
// No errors, continue printing.
CEF_POST_TASK(
CEF_UIT,
base::Bind(&CefPrintDialogLinux::SendDocumentToPrinter, this,
document_name));
}
}
void CefPrintDialogLinux::AddRefToDialog() {
AddRef();
}
void CefPrintDialogLinux::ReleaseDialog() {
Release();
}
void CefPrintDialogLinux::SetHandler() {
if (handler_)
return;
CefRefPtr<CefApp> app = CefContentClient::Get()->application();
if (app.get()) {
CefRefPtr<CefBrowserProcessHandler> browser_handler =
app->GetBrowserProcessHandler();
if (browser_handler)
handler_ = browser_handler->GetPrintHandler();
}
}
void CefPrintDialogLinux::ReleaseHandler() {
if (handler_) {
handler_->OnPrintReset();
handler_ = NULL;
}
}
bool CefPrintDialogLinux::UpdateSettings(printing::PrintSettings* settings,
bool get_defaults) {
CEF_REQUIRE_UIT();
SetHandler();
if (!handler_)
return false;
CefRefPtr<CefPrintSettingsImpl> settings_impl(
new CefPrintSettingsImpl(settings, false, false));
handler_->OnPrintSettings(settings_impl.get(), get_defaults);
settings_impl->Detach(NULL);
context_->InitWithSettings(*settings);
return true;
}
void CefPrintDialogLinux::SendDocumentToPrinter(
const base::string16& document_name) {
CEF_REQUIRE_UIT();
if (!handler_) {
OnJobCompleted();
return;
}
CefRefPtr<CefPrintJobCallbackImpl> callback_impl(
new CefPrintJobCallbackImpl(this));
if (!handler_->OnPrintJob(document_name, path_to_pdf_.value(),
callback_impl.get())) {
callback_impl->Disconnect();
OnJobCompleted();
}
}
void CefPrintDialogLinux::OnPrintContinue(
CefRefPtr<CefPrintSettings> settings) {
{
CefPrintSettingsImpl* impl =
static_cast<CefPrintSettingsImpl*>(settings.get());
CefValueController::AutoLock lock_scope(impl->controller());
context_->InitWithSettings(impl->print_settings());
}
callback_.Run(PrintingContextLinux::OK);
callback_.Reset();
}
void CefPrintDialogLinux::OnPrintCancel() {
callback_.Run(PrintingContextLinux::CANCEL);
callback_.Reset();
}
void CefPrintDialogLinux::OnJobCompleted() {
base::FileUtilProxy::DeleteFile(
content::BrowserThread::GetMessageLoopProxyForThread(
BrowserThread::FILE).get(),
path_to_pdf_,
false,
base::FileUtilProxy::StatusCallback());
// Printing finished. Matches AddRef() in PrintDocument();
Release();
}

View File

@@ -0,0 +1,85 @@
// Copyright (c) 2014 The Chromium Embedded Framework Authors.
// Portions 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.
#ifndef LIBCEF_BROWSER_PRINTING_PRINT_DIALOG_LINUX_H_
#define LIBCEF_BROWSER_PRINTING_PRINT_DIALOG_LINUX_H_
#include "include/cef_print_handler.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner_helpers.h"
#include "content/public/browser/browser_thread.h"
#include "printing/print_dialog_gtk_interface.h"
#include "printing/printing_context_linux.h"
namespace printing {
class Metafile;
class PrintSettings;
}
using printing::PrintingContextLinux;
// Needs to be freed on the UI thread to clean up its member variables.
class CefPrintDialogLinux
: public printing::PrintDialogGtkInterface,
public base::RefCountedThreadSafe<
CefPrintDialogLinux, content::BrowserThread::DeleteOnUIThread> {
public:
// Creates and returns a print dialog.
static printing::PrintDialogGtkInterface* CreatePrintDialog(
PrintingContextLinux* context);
// printing::CefPrintDialogLinuxInterface implementation.
virtual void UseDefaultSettings() OVERRIDE;
virtual bool UpdateSettings(printing::PrintSettings* settings) OVERRIDE;
virtual void ShowDialog(
gfx::NativeView parent_view,
bool has_selection,
const PrintingContextLinux::PrintSettingsCallback& callback) OVERRIDE;
virtual void PrintDocument(const printing::Metafile* metafile,
const base::string16& document_name) OVERRIDE;
virtual void AddRefToDialog() OVERRIDE;
virtual void ReleaseDialog() OVERRIDE;
private:
friend struct content::BrowserThread::DeleteOnThread<
content::BrowserThread::UI>;
friend class base::DeleteHelper<CefPrintDialogLinux>;
friend class CefPrintDialogCallbackImpl;
friend class CefPrintJobCallbackImpl;
explicit CefPrintDialogLinux(PrintingContextLinux* context);
virtual ~CefPrintDialogLinux();
void SetHandler();
void ReleaseHandler();
bool UpdateSettings(printing::PrintSettings* settings,
bool get_defaults);
// Prints document named |document_name|.
void SendDocumentToPrinter(const base::string16& document_name);
// Handles print dialog response.
void OnPrintContinue(CefRefPtr<CefPrintSettings> settings);
void OnPrintCancel();
// Handles print job response.
void OnJobCompleted();
CefRefPtr<CefPrintHandler> handler_;
// Printing dialog callback.
PrintingContextLinux::PrintSettingsCallback callback_;
PrintingContextLinux* context_;
base::FilePath path_to_pdf_;
DISALLOW_COPY_AND_ASSIGN(CefPrintDialogLinux);
};
#endif // LIBCEF_BROWSER_PRINTING_PRINT_DIALOG_LINUX_H_