Add support for printing via CefBrowserHost::Print() and JavaScript window.print() (issue #505).
git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1479 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
f248b937f9
commit
bc1ea4974a
49
cef.gyp
49
cef.gyp
|
@ -439,6 +439,7 @@
|
|||
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
|
||||
'dependencies': [
|
||||
'<(DEPTH)/build/linux/system.gyp:gtk',
|
||||
'<(DEPTH)/build/linux/system.gyp:gtkprint',
|
||||
],
|
||||
'sources': [
|
||||
'tests/cefclient/resource_util_linux.cpp',
|
||||
|
@ -530,8 +531,9 @@
|
|||
'dependencies':[
|
||||
'<(DEPTH)/base/allocator/allocator.gyp:allocator',
|
||||
'<(DEPTH)/build/linux/system.gyp:gtk',
|
||||
'<(DEPTH)/build/linux/system.gyp:gtkprint',
|
||||
],
|
||||
}],
|
||||
}],
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -557,6 +559,7 @@
|
|||
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
|
||||
'dependencies': [
|
||||
'<(DEPTH)/build/linux/system.gyp:gtk',
|
||||
'<(DEPTH)/build/linux/system.gyp:gtkprint',
|
||||
],
|
||||
}],
|
||||
],
|
||||
|
@ -768,6 +771,7 @@
|
|||
'<(DEPTH)/third_party/WebKit/public/platform',
|
||||
'<(DEPTH)/third_party/WebKit/public/web',
|
||||
# CEF grit resource includes
|
||||
'<(DEPTH)/cef/libcef/resources/grit_stub',
|
||||
'<(grit_out_dir)',
|
||||
'<(SHARED_INTERMEDIATE_DIR)/content/browser/tracing',
|
||||
'<(SHARED_INTERMEDIATE_DIR)/ui/ui_strings',
|
||||
|
@ -831,6 +835,8 @@
|
|||
'libcef/browser/browser_settings.h',
|
||||
'libcef/browser/browser_urlrequest_impl.cc',
|
||||
'libcef/browser/browser_urlrequest_impl.h',
|
||||
'libcef/browser/chrome_browser_process_stub.cc',
|
||||
'libcef/browser/chrome_browser_process_stub.h',
|
||||
'libcef/browser/chrome_scheme_handler.cc',
|
||||
'libcef/browser/chrome_scheme_handler.h',
|
||||
'libcef/browser/content_browser_client.cc',
|
||||
|
@ -868,6 +874,12 @@
|
|||
'libcef/browser/origin_whitelist_impl.cc',
|
||||
'libcef/browser/origin_whitelist_impl.h',
|
||||
'libcef/browser/path_util_impl.cc',
|
||||
'libcef/browser/printing/printing_message_filter.cc',
|
||||
'libcef/browser/printing/printing_message_filter.h',
|
||||
'libcef/browser/printing/print_view_manager.cc',
|
||||
'libcef/browser/printing/print_view_manager.h',
|
||||
'libcef/browser/printing/print_view_manager_base.cc',
|
||||
'libcef/browser/printing/print_view_manager_base.h',
|
||||
'libcef/browser/process_util_impl.cc',
|
||||
'libcef/browser/proxy_stubs.cc',
|
||||
'libcef/browser/render_widget_host_view_osr.cc',
|
||||
|
@ -1004,6 +1016,28 @@
|
|||
# Include sources for the loadtimes V8 extension.
|
||||
'<(DEPTH)/chrome/renderer/loadtimes_extension_bindings.h',
|
||||
'<(DEPTH)/chrome/renderer/loadtimes_extension_bindings.cc',
|
||||
# Include sources for printing.
|
||||
'<(DEPTH)/chrome/browser/printing/print_job.cc',
|
||||
'<(DEPTH)/chrome/browser/printing/print_job.h',
|
||||
'<(DEPTH)/chrome/browser/printing/print_job_manager.cc',
|
||||
'<(DEPTH)/chrome/browser/printing/print_job_manager.h',
|
||||
'<(DEPTH)/chrome/browser/printing/print_job_worker.cc',
|
||||
'<(DEPTH)/chrome/browser/printing/print_job_worker.h',
|
||||
'<(DEPTH)/chrome/browser/printing/print_job_worker_owner.h',
|
||||
'<(DEPTH)/chrome/browser/printing/print_job_worker_owner.h',
|
||||
'<(DEPTH)/chrome/browser/printing/printer_query.cc',
|
||||
'<(DEPTH)/chrome/browser/printing/printer_query.h',
|
||||
'<(DEPTH)/chrome/common/prerender_messages.h',
|
||||
'<(DEPTH)/chrome/common/print_messages.cc',
|
||||
'<(DEPTH)/chrome/common/print_messages.h',
|
||||
'<(DEPTH)/chrome/renderer/prerender/prerender_helper.cc',
|
||||
'<(DEPTH)/chrome/renderer/prerender/prerender_helper.h',
|
||||
'<(DEPTH)/chrome/renderer/printing/print_web_view_helper.cc',
|
||||
'<(DEPTH)/chrome/renderer/printing/print_web_view_helper.h',
|
||||
# Include header for stub creation (BrowserProcess) so print_job_worker can
|
||||
# determine the current locale.
|
||||
'<(DEPTH)/chrome/browser/browser_process.cc',
|
||||
'<(DEPTH)/chrome/browser/browser_process.h',
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
|
@ -1024,6 +1058,8 @@
|
|||
'<(DEPTH)/ui/views/controls/menu/menu_listener.h',
|
||||
'<(DEPTH)/ui/views/controls/menu/native_menu_win.cc',
|
||||
'<(DEPTH)/ui/views/controls/menu/native_menu_win.h',
|
||||
# Include sources for printing.
|
||||
'<(DEPTH)/chrome/renderer/printing/print_web_view_helper_win.cc',
|
||||
],
|
||||
}],
|
||||
[ 'OS=="mac"', {
|
||||
|
@ -1045,9 +1081,14 @@
|
|||
'libcef/browser/text_input_client_osr_mac.h',
|
||||
'libcef/browser/web_contents_view_osr.cc',
|
||||
'libcef/browser/web_contents_view_osr.h',
|
||||
# Include sources for printing.
|
||||
'<(DEPTH)/chrome/renderer/printing/print_web_view_helper_mac.mm',
|
||||
],
|
||||
}],
|
||||
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
|
||||
'dependencies':[
|
||||
'<(DEPTH)/build/linux/system.gyp:gtkprint',
|
||||
],
|
||||
'sources': [
|
||||
'<@(includes_linux)',
|
||||
'libcef/browser/browser_host_impl_gtk.cc',
|
||||
|
@ -1065,6 +1106,10 @@
|
|||
'<(DEPTH)/chrome/browser/ui/gtk/menu_gtk.h',
|
||||
'<(DEPTH)/chrome/browser/ui/views/event_utils.cc',
|
||||
'<(DEPTH)/chrome/browser/ui/views/event_utils.h',
|
||||
#Include sources for printing.
|
||||
'<(DEPTH)/chrome/browser/printing/print_dialog_gtk.cc',
|
||||
'<(DEPTH)/chrome/browser/printing/print_dialog_gtk.h',
|
||||
'<(DEPTH)/chrome/renderer/printing/print_web_view_helper_linux.cc',
|
||||
],
|
||||
}],
|
||||
],
|
||||
|
@ -1334,7 +1379,7 @@
|
|||
# gtk requires gmodule, but it does not list it as a dependency
|
||||
# in some misconfigured systems.
|
||||
# gtkglext is required by the cefclient OSR example.
|
||||
'gtk_packages': 'gmodule-2.0 gtk+-2.0 gthread-2.0 gtkglext-1.0',
|
||||
'gtk_packages': 'gmodule-2.0 gtk+-2.0 gthread-2.0 gtkglext-1.0 gtk+-unix-print-2.0',
|
||||
},
|
||||
'direct_dependent_settings': {
|
||||
'cflags': [
|
||||
|
|
|
@ -319,6 +319,11 @@ typedef struct _cef_browser_host_t {
|
|||
void (CEF_CALLBACK *start_download)(struct _cef_browser_host_t* self,
|
||||
const cef_string_t* url);
|
||||
|
||||
///
|
||||
// Print the current browser contents.
|
||||
///
|
||||
void (CEF_CALLBACK *print)(struct _cef_browser_host_t* self);
|
||||
|
||||
///
|
||||
// Set whether mouse cursor change is disabled.
|
||||
///
|
||||
|
|
|
@ -366,6 +366,12 @@ class CefBrowserHost : public virtual CefBase {
|
|||
/*--cef()--*/
|
||||
virtual void StartDownload(const CefString& url) =0;
|
||||
|
||||
///
|
||||
// Print the current browser contents.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual void Print() =0;
|
||||
|
||||
///
|
||||
// Set whether mouse cursor change is disabled.
|
||||
///
|
||||
|
@ -485,7 +491,6 @@ class CefBrowserHost : public virtual CefBase {
|
|||
///
|
||||
/*--cef()--*/
|
||||
virtual void HandleKeyEventAfterTextInputClient(CefEventHandle keyEvent) =0;
|
||||
|
||||
};
|
||||
|
||||
#endif // CEF_INCLUDE_CEF_BROWSER_H_
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "libcef/browser/devtools_delegate.h"
|
||||
#include "libcef/browser/media_capture_devices_dispatcher.h"
|
||||
#include "libcef/browser/navigate_params.h"
|
||||
#include "libcef/browser/printing/print_view_manager.h"
|
||||
#include "libcef/browser/render_widget_host_view_osr.h"
|
||||
#include "libcef/browser/request_context_impl.h"
|
||||
#include "libcef/browser/scheme_handler.h"
|
||||
|
@ -603,6 +604,18 @@ void CefBrowserHostImpl::StartDownload(const CefString& url) {
|
|||
manager->DownloadUrl(params.Pass());
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::Print() {
|
||||
if (CEF_CURRENTLY_ON_UIT()) {
|
||||
if (!web_contents_)
|
||||
return;
|
||||
printing::PrintViewManager::FromWebContents(
|
||||
web_contents_.get())->PrintNow();
|
||||
} else {
|
||||
CEF_POST_TASK(CEF_UIT,
|
||||
base::Bind(&CefBrowserHostImpl::Print, this));
|
||||
}
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::SetMouseCursorChangeDisabled(bool disabled) {
|
||||
base::AutoLock lock_scope(state_lock_);
|
||||
mouse_cursor_change_disabled_ = disabled;
|
||||
|
@ -2114,6 +2127,8 @@ CefBrowserHostImpl::CefBrowserHostImpl(
|
|||
CefString(), CefString(),
|
||||
CefFrameHostImpl::kInvalidFrameId);
|
||||
|
||||
printing::PrintViewManager::CreateForWebContents(web_contents_.get());
|
||||
|
||||
// Make sure RenderViewCreated is called at least one time.
|
||||
RenderViewCreated(web_contents->GetRenderViewHost());
|
||||
|
||||
|
|
|
@ -124,6 +124,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||
const std::vector<CefString>& accept_types,
|
||||
CefRefPtr<CefRunFileDialogCallback> callback) OVERRIDE;
|
||||
virtual void StartDownload(const CefString& url) OVERRIDE;
|
||||
virtual void Print() OVERRIDE;
|
||||
virtual void SetMouseCursorChangeDisabled(bool disabled) OVERRIDE;
|
||||
virtual bool IsMouseCursorChangeDisabled() OVERRIDE;
|
||||
virtual bool IsWindowRenderingDisabled() OVERRIDE;
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
#include "ui/base/resource/resource_bundle.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
#include "chrome/browser/printing/print_dialog_gtk.h"
|
||||
#endif
|
||||
|
||||
CefBrowserMainParts::CefBrowserMainParts(
|
||||
const content::MainFunctionParams& parameters)
|
||||
: BrowserMainParts(),
|
||||
|
@ -48,6 +52,11 @@ void CefBrowserMainParts::PostMainMessageLoopStart() {
|
|||
// CEF's internal handling of "chrome://tracing".
|
||||
content::WebUIControllerFactory::UnregisterFactoryForTesting(
|
||||
content::ContentWebUIControllerFactory::GetInstance());
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
printing::PrintingContextGtk::SetCreatePrintDialogFunction(
|
||||
&PrintDialogGtk::CreatePrintDialog);
|
||||
#endif
|
||||
}
|
||||
|
||||
int CefBrowserMainParts::PreCreateThreads() {
|
||||
|
|
|
@ -29,6 +29,8 @@ PrefService* CefBrowserPrefStore::CreateService() {
|
|||
CefMediaCaptureDevicesDispatcher::RegisterPrefs(registry);
|
||||
PrefProxyConfigTrackerImpl::RegisterPrefs(registry);
|
||||
|
||||
registry->RegisterBooleanPref(prefs::kPrintingEnabled, true);
|
||||
|
||||
return builder.Create(registry);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
// Copyright (c) 2013 The Chromium Embedded Framework Authors.
|
||||
// Portions (c) 2011 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/chrome_browser_process_stub.h"
|
||||
#include "libcef/browser/context.h"
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "ui/message_center/message_center.h"
|
||||
|
||||
ChromeBrowserProcessStub::ChromeBrowserProcessStub()
|
||||
: locale_("en-US") {
|
||||
}
|
||||
|
||||
ChromeBrowserProcessStub::~ChromeBrowserProcessStub() {
|
||||
g_browser_process = NULL;
|
||||
}
|
||||
|
||||
void ChromeBrowserProcessStub::ResourceDispatcherHostCreated() {
|
||||
NOTIMPLEMENTED();
|
||||
};
|
||||
|
||||
void ChromeBrowserProcessStub::EndSession() {
|
||||
NOTIMPLEMENTED();
|
||||
};
|
||||
|
||||
MetricsService* ChromeBrowserProcessStub::metrics_service() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IOThread* ChromeBrowserProcessStub::io_thread() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WatchDogThread* ChromeBrowserProcessStub::watchdog_thread() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ProfileManager* ChromeBrowserProcessStub::profile_manager() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PrefService* ChromeBrowserProcessStub::local_state() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
net::URLRequestContextGetter*
|
||||
ChromeBrowserProcessStub::system_request_context() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chrome_variations::VariationsService*
|
||||
ChromeBrowserProcessStub::variations_service() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BrowserProcessPlatformPart* ChromeBrowserProcessStub::platform_part() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extensions::EventRouterForwarder*
|
||||
ChromeBrowserProcessStub::extension_event_router_forwarder() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NotificationUIManager* ChromeBrowserProcessStub::notification_ui_manager() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message_center::MessageCenter* ChromeBrowserProcessStub::message_center() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
policy::BrowserPolicyConnector*
|
||||
ChromeBrowserProcessStub::browser_policy_connector() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
policy::PolicyService* ChromeBrowserProcessStub::policy_service() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IconManager* ChromeBrowserProcessStub::icon_manager() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GLStringManager* ChromeBrowserProcessStub::gl_string_manager() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GpuModeManager* ChromeBrowserProcessStub::gpu_mode_manager() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RenderWidgetSnapshotTaker*
|
||||
ChromeBrowserProcessStub::GetRenderWidgetSnapshotTaker() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AutomationProviderList*
|
||||
ChromeBrowserProcessStub::GetAutomationProviderList() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ChromeBrowserProcessStub::CreateDevToolsHttpProtocolHandler(
|
||||
chrome::HostDesktopType host_desktop_type,
|
||||
const std::string& ip,
|
||||
int port,
|
||||
const std::string& frontend_url) {
|
||||
}
|
||||
|
||||
unsigned int ChromeBrowserProcessStub::AddRefModule() {
|
||||
NOTIMPLEMENTED();
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int ChromeBrowserProcessStub::ReleaseModule() {
|
||||
NOTIMPLEMENTED();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ChromeBrowserProcessStub::IsShuttingDown() {
|
||||
NOTIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
printing::PrintJobManager* ChromeBrowserProcessStub::print_job_manager() {
|
||||
return CefContext::Get()->print_job_manager();
|
||||
}
|
||||
|
||||
printing::PrintPreviewDialogController*
|
||||
ChromeBrowserProcessStub::print_preview_dialog_controller() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
printing::BackgroundPrintingManager*
|
||||
ChromeBrowserProcessStub::background_printing_manager() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IntranetRedirectDetector*
|
||||
ChromeBrowserProcessStub::intranet_redirect_detector() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const std::string &ChromeBrowserProcessStub::GetApplicationLocale() {
|
||||
DCHECK(!locale_.empty());
|
||||
return locale_;
|
||||
}
|
||||
|
||||
void ChromeBrowserProcessStub::SetApplicationLocale(const std::string& locale) {
|
||||
locale_ = locale;
|
||||
}
|
||||
|
||||
DownloadStatusUpdater* ChromeBrowserProcessStub::download_status_updater() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DownloadRequestLimiter* ChromeBrowserProcessStub::download_request_limiter() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BackgroundModeManager* ChromeBrowserProcessStub::background_mode_manager() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ChromeBrowserProcessStub::set_background_mode_manager_for_test(
|
||||
scoped_ptr<BackgroundModeManager> manager) {
|
||||
NOTIMPLEMENTED();
|
||||
}
|
||||
|
||||
StatusTray* ChromeBrowserProcessStub::status_tray() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SafeBrowsingService* ChromeBrowserProcessStub::safe_browsing_service() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
safe_browsing::ClientSideDetectionService*
|
||||
ChromeBrowserProcessStub::safe_browsing_detection_service() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
|
||||
void ChromeBrowserProcessStub::StartAutoupdateTimer() {
|
||||
}
|
||||
#endif
|
||||
|
||||
ChromeNetLog* ChromeBrowserProcessStub::net_log() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
prerender::PrerenderTracker* ChromeBrowserProcessStub::prerender_tracker() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ComponentUpdateService* ChromeBrowserProcessStub::component_updater() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CRLSetFetcher* ChromeBrowserProcessStub::crl_set_fetcher() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PnaclComponentInstaller*
|
||||
ChromeBrowserProcessStub::pnacl_component_installer() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BookmarkPromptController*
|
||||
ChromeBrowserProcessStub::bookmark_prompt_controller() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MediaFileSystemRegistry*
|
||||
ChromeBrowserProcessStub::media_file_system_registry() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ChromeBrowserProcessStub::created_local_state() const {
|
||||
NOTIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
StorageMonitor* ChromeBrowserProcessStub::storage_monitor() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(ENABLE_WEBRTC)
|
||||
WebRtcLogUploader* ChromeBrowserProcessStub::webrtc_log_uploader() {
|
||||
NOTIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,103 @@
|
|||
// Copyright (c) 2013 The Chromium Embedded Framework Authors.
|
||||
// Portions (c) 2011 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 CEF_LIBCEF_BROWSER_CHROME_BROWSER_PROCESS_STUB_H_
|
||||
#define CEF_LIBCEF_BROWSER_CHROME_BROWSER_PROCESS_STUB_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
|
||||
// This file provides a stub implementation of chrome::BrowserProcess so that
|
||||
// PrintJobWorker can determine the current locale.
|
||||
|
||||
class BackgroundModeManager {
|
||||
public:
|
||||
BackgroundModeManager();
|
||||
virtual ~BackgroundModeManager();
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(BackgroundModeManager);
|
||||
};
|
||||
|
||||
class ChromeBrowserProcessStub : public BrowserProcess {
|
||||
public:
|
||||
ChromeBrowserProcessStub();
|
||||
virtual ~ChromeBrowserProcessStub();
|
||||
|
||||
// BrowserProcess implementation.
|
||||
virtual void ResourceDispatcherHostCreated() OVERRIDE;
|
||||
virtual void EndSession() OVERRIDE;
|
||||
virtual MetricsService* metrics_service() OVERRIDE;
|
||||
virtual IOThread* io_thread() OVERRIDE;
|
||||
virtual WatchDogThread* watchdog_thread() OVERRIDE;
|
||||
virtual ProfileManager* profile_manager() OVERRIDE;
|
||||
virtual PrefService* local_state() OVERRIDE;
|
||||
virtual net::URLRequestContextGetter* system_request_context() OVERRIDE;
|
||||
virtual chrome_variations::VariationsService* variations_service() OVERRIDE;
|
||||
virtual BrowserProcessPlatformPart* platform_part() OVERRIDE;
|
||||
virtual extensions::EventRouterForwarder*
|
||||
extension_event_router_forwarder() OVERRIDE;
|
||||
virtual NotificationUIManager* notification_ui_manager() OVERRIDE;
|
||||
virtual message_center::MessageCenter* message_center() OVERRIDE;
|
||||
virtual policy::BrowserPolicyConnector* browser_policy_connector() OVERRIDE;
|
||||
virtual policy::PolicyService* policy_service() OVERRIDE;
|
||||
virtual IconManager* icon_manager() OVERRIDE;
|
||||
virtual GLStringManager* gl_string_manager() OVERRIDE;
|
||||
virtual GpuModeManager* gpu_mode_manager() OVERRIDE;
|
||||
virtual RenderWidgetSnapshotTaker* GetRenderWidgetSnapshotTaker() OVERRIDE;
|
||||
virtual AutomationProviderList* GetAutomationProviderList() OVERRIDE;
|
||||
virtual void CreateDevToolsHttpProtocolHandler(
|
||||
chrome::HostDesktopType host_desktop_type,
|
||||
const std::string& ip,
|
||||
int port,
|
||||
const std::string& frontend_url) OVERRIDE;
|
||||
virtual unsigned int AddRefModule() OVERRIDE;
|
||||
virtual unsigned int ReleaseModule() OVERRIDE;
|
||||
virtual bool IsShuttingDown() OVERRIDE;
|
||||
virtual printing::PrintJobManager* print_job_manager() OVERRIDE;
|
||||
virtual printing::PrintPreviewDialogController*
|
||||
print_preview_dialog_controller() OVERRIDE;
|
||||
virtual printing::BackgroundPrintingManager*
|
||||
background_printing_manager() OVERRIDE;
|
||||
virtual IntranetRedirectDetector* intranet_redirect_detector() OVERRIDE;
|
||||
virtual const std::string& GetApplicationLocale() OVERRIDE;
|
||||
virtual void SetApplicationLocale(const std::string& locale) OVERRIDE;
|
||||
virtual DownloadStatusUpdater* download_status_updater() OVERRIDE;
|
||||
virtual DownloadRequestLimiter* download_request_limiter() OVERRIDE;
|
||||
virtual BackgroundModeManager* background_mode_manager() OVERRIDE;
|
||||
virtual void set_background_mode_manager_for_test(
|
||||
scoped_ptr<BackgroundModeManager> manager) OVERRIDE;
|
||||
virtual StatusTray* status_tray() OVERRIDE;
|
||||
virtual SafeBrowsingService* safe_browsing_service() OVERRIDE;
|
||||
virtual safe_browsing::ClientSideDetectionService*
|
||||
safe_browsing_detection_service() OVERRIDE;
|
||||
|
||||
#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
|
||||
virtual void StartAutoupdateTimer() OVERRIDE;
|
||||
#endif
|
||||
|
||||
virtual ChromeNetLog* net_log() OVERRIDE;
|
||||
virtual prerender::PrerenderTracker* prerender_tracker() OVERRIDE;
|
||||
virtual ComponentUpdateService* component_updater() OVERRIDE;
|
||||
virtual CRLSetFetcher* crl_set_fetcher() OVERRIDE;
|
||||
virtual PnaclComponentInstaller* pnacl_component_installer() OVERRIDE;
|
||||
virtual BookmarkPromptController* bookmark_prompt_controller() OVERRIDE;
|
||||
virtual MediaFileSystemRegistry*
|
||||
media_file_system_registry() OVERRIDE;
|
||||
virtual bool created_local_state() const OVERRIDE;
|
||||
virtual StorageMonitor* storage_monitor() OVERRIDE;
|
||||
#if defined(ENABLE_WEBRTC)
|
||||
virtual WebRtcLogUploader* webrtc_log_uploader() OVERRIDE;
|
||||
#endif
|
||||
|
||||
private:
|
||||
std::string locale_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ChromeBrowserProcessStub);
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_CHROME_BROWSER_PROCESS_STUB_H_
|
|
@ -15,6 +15,7 @@
|
|||
#include "libcef/browser/browser_settings.h"
|
||||
#include "libcef/browser/chrome_scheme_handler.h"
|
||||
#include "libcef/browser/media_capture_devices_dispatcher.h"
|
||||
#include "libcef/browser/printing/printing_message_filter.h"
|
||||
#include "libcef/browser/resource_dispatcher_host_delegate.h"
|
||||
#include "libcef/browser/speech_recognition_manager_delegate.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
|
@ -454,6 +455,8 @@ CefContentBrowserClient::OverrideCreateWebContentsView(
|
|||
void CefContentBrowserClient::RenderProcessHostCreated(
|
||||
content::RenderProcessHost* host) {
|
||||
host->GetChannel()->AddFilter(new CefBrowserMessageFilter(host));
|
||||
host->AddFilter(new PrintingMessageFilter(host->GetID()));
|
||||
|
||||
AddBrowserContextReference(
|
||||
static_cast<CefBrowserContext*>(host->GetBrowserContext()));
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "libcef/browser/browser_info.h"
|
||||
#include "libcef/browser/browser_main.h"
|
||||
#include "libcef/browser/browser_message_loop.h"
|
||||
#include "libcef/browser/chrome_browser_process_stub.h"
|
||||
#include "libcef/browser/content_browser_client.h"
|
||||
#include "libcef/browser/scheme_handler.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
|
@ -19,6 +20,7 @@
|
|||
#include "base/command_line.h"
|
||||
#include "base/file_util.h"
|
||||
#include "base/synchronization/waitable_event.h"
|
||||
#include "chrome/browser/printing/print_job_manager.h"
|
||||
#include "content/public/app/content_main.h"
|
||||
#include "content/public/app/content_main_runner.h"
|
||||
#include "content/public/browser/notification_service.h"
|
||||
|
@ -44,13 +46,13 @@ CefContext* g_context = NULL;
|
|||
// CefShutdown() has not been explicitly called.
|
||||
class CefForceShutdown {
|
||||
public:
|
||||
~CefForceShutdown() {
|
||||
if (g_context) {
|
||||
g_context->Shutdown();
|
||||
delete g_context;
|
||||
g_context = NULL;
|
||||
}
|
||||
}
|
||||
~CefForceShutdown() {
|
||||
if (g_context) {
|
||||
g_context->Shutdown();
|
||||
delete g_context;
|
||||
g_context = NULL;
|
||||
}
|
||||
}
|
||||
} g_force_shutdown;
|
||||
|
||||
} // namespace
|
||||
|
@ -102,6 +104,8 @@ bool CefInitialize(const CefMainArgs& args,
|
|||
return false;
|
||||
}
|
||||
|
||||
g_browser_process = new ChromeBrowserProcessStub();
|
||||
|
||||
// Create the new global context object.
|
||||
g_context = new CefContext();
|
||||
|
||||
|
@ -267,9 +271,13 @@ bool CefContext::Initialize(const CefMainArgs& args,
|
|||
|
||||
initialized_ = true;
|
||||
|
||||
// Continue initialization on the UI thread.
|
||||
CEF_POST_TASK(CEF_UIT,
|
||||
base::Bind(&CefContext::OnContextInitialized, base::Unretained(this)));
|
||||
if (CEF_CURRENTLY_ON_UIT()) {
|
||||
OnContextInitialized();
|
||||
} else {
|
||||
// Continue initialization on the UI thread.
|
||||
CEF_POST_TASK(CEF_UIT,
|
||||
base::Bind(&CefContext::OnContextInitialized, base::Unretained(this)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -329,6 +337,9 @@ void CefContext::OnContextInitialized() {
|
|||
registrar_->Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
|
||||
content::NotificationService::AllBrowserContextsAndSources());
|
||||
|
||||
// Must be created after the NotificationService.
|
||||
print_job_manager_.reset(new printing::PrintJobManager());
|
||||
|
||||
// Notify the handler.
|
||||
CefRefPtr<CefApp> app = CefContentClient::Get()->application();
|
||||
if (app.get()) {
|
||||
|
@ -343,6 +354,12 @@ void CefContext::FinishShutdownOnUIThread(
|
|||
base::WaitableEvent* uithread_shutdown_event) {
|
||||
CEF_REQUIRE_UIT();
|
||||
|
||||
// Wait for the pending print jobs to finish. Don't do this later, since
|
||||
// this might cause a nested message loop to run, and we don't want pending
|
||||
// tasks to run once teardown has started.
|
||||
print_job_manager_->Shutdown();
|
||||
print_job_manager_.reset(NULL);
|
||||
|
||||
CefContentBrowserClient::Get()->DestroyAllBrowsers();
|
||||
|
||||
registrar_.reset();
|
||||
|
|
|
@ -27,6 +27,10 @@ namespace content {
|
|||
class ContentMainRunner;
|
||||
}
|
||||
|
||||
namespace printing {
|
||||
class PrintJobManager;
|
||||
}
|
||||
|
||||
class CefBrowserHostImpl;
|
||||
class CefMainDelegate;
|
||||
class CefTraceSubscriber;
|
||||
|
@ -61,6 +65,10 @@ class CefContext : public content::NotificationObserver {
|
|||
|
||||
const CefSettings& settings() const { return settings_; }
|
||||
|
||||
printing::PrintJobManager* print_job_manager() const {
|
||||
return print_job_manager_.get();
|
||||
}
|
||||
|
||||
CefTraceSubscriber* GetTraceSubscriber();
|
||||
|
||||
private:
|
||||
|
@ -95,6 +103,7 @@ class CefContext : public content::NotificationObserver {
|
|||
|
||||
// Only accessed on the UI Thread.
|
||||
scoped_ptr<content::NotificationRegistrar> registrar_;
|
||||
scoped_ptr<printing::PrintJobManager> print_job_manager_;
|
||||
};
|
||||
|
||||
// Helper macro that returns true if the global context is in a valid state.
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
// 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_view_manager.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/lazy_instance.h"
|
||||
#include "base/metrics/histogram.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/browser/printing/print_job_manager.h"
|
||||
#include "chrome/browser/printing/print_preview_dialog_controller.h"
|
||||
#include "chrome/common/print_messages.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "printing/print_destination_interface.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::PrintViewManager);
|
||||
|
||||
namespace printing {
|
||||
|
||||
PrintViewManager::PrintViewManager(content::WebContents* web_contents)
|
||||
: PrintViewManagerBase(web_contents) {
|
||||
}
|
||||
|
||||
PrintViewManager::~PrintViewManager() {
|
||||
}
|
||||
|
||||
bool PrintViewManager::PrintForSystemDialogNow() {
|
||||
return PrintNowInternal(new PrintMsg_PrintForSystemDialog(routing_id()));
|
||||
}
|
||||
|
||||
bool PrintViewManager::PrintToDestination() {
|
||||
// TODO(mad): Remove this once we can send user metrics from the metro driver.
|
||||
// crbug.com/142330
|
||||
UMA_HISTOGRAM_ENUMERATION("Metro.Print", 0, 2);
|
||||
// TODO(mad): Use a passed in destination interface instead.
|
||||
g_browser_process->print_job_manager()->queue()->SetDestination(
|
||||
printing::CreatePrintDestination());
|
||||
return PrintNowInternal(new PrintMsg_PrintPages(routing_id()));
|
||||
}
|
||||
|
||||
void PrintViewManager::RenderProcessGone(base::TerminationStatus status) {
|
||||
PrintViewManagerBase::RenderProcessGone(status);
|
||||
}
|
||||
|
||||
void PrintViewManager::OnDidShowPrintDialog() {
|
||||
}
|
||||
|
||||
bool PrintViewManager::OnMessageReceived(const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(PrintViewManager, message)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_DidShowPrintDialog, OnDidShowPrintDialog)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
|
||||
return handled ? true : PrintViewManagerBase::OnMessageReceived(message);
|
||||
}
|
||||
|
||||
} // namespace printing
|
|
@ -0,0 +1,51 @@
|
|||
// 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 CEF_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_H_
|
||||
#define CEF_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_H_
|
||||
|
||||
#include "libcef/browser/printing/print_view_manager_base.h"
|
||||
#include "content/public/browser/web_contents_user_data.h"
|
||||
|
||||
namespace content {
|
||||
class RenderProcessHost;
|
||||
}
|
||||
|
||||
namespace printing {
|
||||
|
||||
// Manages the print commands for a WebContents.
|
||||
class PrintViewManager : public PrintViewManagerBase,
|
||||
public content::WebContentsUserData<PrintViewManager> {
|
||||
public:
|
||||
virtual ~PrintViewManager();
|
||||
|
||||
// Same as PrintNow(), but for the case where a user prints with the system
|
||||
// dialog from print preview.
|
||||
bool PrintForSystemDialogNow();
|
||||
|
||||
// Same as PrintNow(), but for the case where we want to send the result to
|
||||
// another destination.
|
||||
// TODO(mad) Add an argument so we can pass the destination interface.
|
||||
bool PrintToDestination();
|
||||
|
||||
// content::WebContentsObserver implementation.
|
||||
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
|
||||
|
||||
// content::WebContentsObserver implementation.
|
||||
// Terminates or cancels the print job if one was pending.
|
||||
virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
|
||||
|
||||
private:
|
||||
explicit PrintViewManager(content::WebContents* web_contents);
|
||||
friend class content::WebContentsUserData<PrintViewManager>;
|
||||
|
||||
// IPC Message handlers.
|
||||
void OnDidShowPrintDialog();
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintViewManager);
|
||||
};
|
||||
|
||||
} // namespace printing
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_H_
|
|
@ -0,0 +1,522 @@
|
|||
// 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.
|
||||
|
||||
#include "libcef/browser/printing/print_view_manager_base.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "libcef/browser/content_browser_client.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/prefs/pref_service.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/timer/timer.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/browser/chrome_notification_types.h"
|
||||
#include "chrome/browser/printing/print_job.h"
|
||||
#include "chrome/browser/printing/print_job_manager.h"
|
||||
#include "chrome/browser/printing/printer_query.h"
|
||||
#include "chrome/common/pref_names.h"
|
||||
#include "chrome/common/print_messages.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/notification_details.h"
|
||||
#include "content/public/browser/notification_service.h"
|
||||
#include "content/public/browser/notification_source.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/browser/web_contents_view.h"
|
||||
#include "grit/generated_resources.h"
|
||||
#include "printing/metafile_impl.h"
|
||||
#include "printing/printed_document.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "base/command_line.h"
|
||||
#include "chrome/common/chrome_switches.h"
|
||||
#endif
|
||||
|
||||
using base::TimeDelta;
|
||||
using content::BrowserThread;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Limits memory usage by raster to 64 MiB.
|
||||
const int kMaxRasterSizeInPixels = 16*1024*1024;
|
||||
#endif
|
||||
|
||||
namespace printing {
|
||||
|
||||
PrintViewManagerBase::PrintViewManagerBase(content::WebContents* web_contents)
|
||||
: content::WebContentsObserver(web_contents),
|
||||
number_pages_(0),
|
||||
printing_succeeded_(false),
|
||||
inside_inner_message_loop_(false),
|
||||
cookie_(0),
|
||||
queue_(g_browser_process->print_job_manager()->queue()) {
|
||||
DCHECK(queue_);
|
||||
#if defined(OS_POSIX) && !defined(OS_MACOSX)
|
||||
expecting_first_page_ = true;
|
||||
#endif
|
||||
printing_enabled_.Init(
|
||||
prefs::kPrintingEnabled,
|
||||
CefContentBrowserClient::Get()->pref_service(),
|
||||
base::Bind(&PrintViewManagerBase::UpdateScriptedPrintingBlocked,
|
||||
base::Unretained(this)));
|
||||
}
|
||||
|
||||
PrintViewManagerBase::~PrintViewManagerBase() {
|
||||
ReleasePrinterQuery();
|
||||
DisconnectFromCurrentPrintJob();
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::PrintNow() {
|
||||
return PrintNowInternal(new PrintMsg_PrintPages(routing_id()));
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::UpdateScriptedPrintingBlocked() {
|
||||
Send(new PrintMsg_SetScriptedPrintingBlocked(
|
||||
routing_id(),
|
||||
!printing_enabled_.GetValue()));
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::NavigationStopped() {
|
||||
// Cancel the current job, wait for the worker to finish.
|
||||
TerminatePrintJob(true);
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::RenderProcessGone(base::TerminationStatus status) {
|
||||
ReleasePrinterQuery();
|
||||
|
||||
if (!print_job_.get())
|
||||
return;
|
||||
|
||||
scoped_refptr<PrintedDocument> document(print_job_->document());
|
||||
if (document.get()) {
|
||||
// If IsComplete() returns false, the document isn't completely rendered.
|
||||
// Since our renderer is gone, there's nothing to do, cancel it. Otherwise,
|
||||
// the print job may finish without problem.
|
||||
TerminatePrintJob(!document->IsComplete());
|
||||
}
|
||||
}
|
||||
|
||||
string16 PrintViewManagerBase::RenderSourceName() {
|
||||
string16 name(web_contents()->GetTitle());
|
||||
if (name.empty())
|
||||
name = l10n_util::GetStringUTF16(IDS_DEFAULT_PRINT_DOCUMENT_TITLE);
|
||||
return name;
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::OnDidGetPrintedPagesCount(int cookie,
|
||||
int number_pages) {
|
||||
DCHECK_GT(cookie, 0);
|
||||
DCHECK_GT(number_pages, 0);
|
||||
number_pages_ = number_pages;
|
||||
OpportunisticallyCreatePrintJob(cookie);
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::OnDidGetDocumentCookie(int cookie) {
|
||||
cookie_ = cookie;
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::OnDidPrintPage(
|
||||
const PrintHostMsg_DidPrintPage_Params& params) {
|
||||
if (!OpportunisticallyCreatePrintJob(params.document_cookie))
|
||||
return;
|
||||
|
||||
PrintedDocument* document = print_job_->document();
|
||||
if (!document || params.document_cookie != document->cookie()) {
|
||||
// Out of sync. It may happen since we are completely asynchronous. Old
|
||||
// spurious messages can be received if one of the processes is overloaded.
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(OS_WIN) || defined(OS_MACOSX)
|
||||
const bool metafile_must_be_valid = true;
|
||||
#elif defined(OS_POSIX)
|
||||
const bool metafile_must_be_valid = expecting_first_page_;
|
||||
expecting_first_page_ = false;
|
||||
#endif
|
||||
|
||||
base::SharedMemory shared_buf(params.metafile_data_handle, true);
|
||||
if (metafile_must_be_valid) {
|
||||
if (!shared_buf.Map(params.data_size)) {
|
||||
NOTREACHED() << "couldn't map";
|
||||
web_contents()->Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
scoped_ptr<NativeMetafile> metafile(new NativeMetafile);
|
||||
if (metafile_must_be_valid) {
|
||||
if (!metafile->InitFromData(shared_buf.memory(), params.data_size)) {
|
||||
NOTREACHED() << "Invalid metafile header";
|
||||
web_contents()->Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
bool big_emf = (params.data_size && params.data_size >= kMetafileMaxSize);
|
||||
const CommandLine* cmdline = CommandLine::ForCurrentProcess();
|
||||
int raster_size = std::min(params.page_size.GetArea(),
|
||||
kMaxRasterSizeInPixels);
|
||||
if (big_emf || (cmdline && cmdline->HasSwitch(switches::kPrintRaster))) {
|
||||
scoped_ptr<NativeMetafile> raster_metafile(
|
||||
metafile->RasterizeMetafile(raster_size));
|
||||
if (raster_metafile.get()) {
|
||||
metafile.swap(raster_metafile);
|
||||
} else if (big_emf) {
|
||||
// Don't fall back to emf here.
|
||||
NOTREACHED() << "size:" << params.data_size;
|
||||
TerminatePrintJob(true);
|
||||
web_contents()->Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Update the rendered document. It will send notifications to the listener.
|
||||
document->SetPage(params.page_number,
|
||||
metafile.release(),
|
||||
params.actual_shrink,
|
||||
params.page_size,
|
||||
params.content_area);
|
||||
|
||||
ShouldQuitFromInnerMessageLoop();
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::OnPrintingFailed(int cookie) {
|
||||
if (cookie != cookie_) {
|
||||
NOTREACHED();
|
||||
return;
|
||||
}
|
||||
|
||||
ReleasePrinterQuery();
|
||||
|
||||
content::NotificationService::current()->Notify(
|
||||
chrome::NOTIFICATION_PRINT_JOB_RELEASED,
|
||||
content::Source<content::WebContents>(web_contents()),
|
||||
content::NotificationService::NoDetails());
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::DidStartLoading(
|
||||
content::RenderViewHost* render_view_host) {
|
||||
UpdateScriptedPrintingBlocked();
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::OnMessageReceived(const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBase, message)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPrintedPagesCount,
|
||||
OnDidGetPrintedPagesCount)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetDocumentCookie,
|
||||
OnDidGetDocumentCookie)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintPage, OnDidPrintPage)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_PrintingFailed, OnPrintingFailed)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
return handled;
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::Observe(
|
||||
int type,
|
||||
const content::NotificationSource& source,
|
||||
const content::NotificationDetails& details) {
|
||||
switch (type) {
|
||||
case chrome::NOTIFICATION_PRINT_JOB_EVENT: {
|
||||
OnNotifyPrintJobEvent(*content::Details<JobEventDetails>(details).ptr());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::OnNotifyPrintJobEvent(
|
||||
const JobEventDetails& event_details) {
|
||||
switch (event_details.type()) {
|
||||
case JobEventDetails::FAILED: {
|
||||
TerminatePrintJob(true);
|
||||
|
||||
content::NotificationService::current()->Notify(
|
||||
chrome::NOTIFICATION_PRINT_JOB_RELEASED,
|
||||
content::Source<content::WebContents>(web_contents()),
|
||||
content::NotificationService::NoDetails());
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::USER_INIT_DONE:
|
||||
case JobEventDetails::DEFAULT_INIT_DONE:
|
||||
case JobEventDetails::USER_INIT_CANCELED: {
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::ALL_PAGES_REQUESTED: {
|
||||
ShouldQuitFromInnerMessageLoop();
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::NEW_DOC:
|
||||
case JobEventDetails::NEW_PAGE:
|
||||
case JobEventDetails::PAGE_DONE:
|
||||
case JobEventDetails::DOC_DONE: {
|
||||
// Don't care about the actual printing process.
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::JOB_DONE: {
|
||||
// Printing is done, we don't need it anymore.
|
||||
// print_job_->is_job_pending() may still be true, depending on the order
|
||||
// of object registration.
|
||||
printing_succeeded_ = true;
|
||||
ReleasePrintJob();
|
||||
|
||||
content::NotificationService::current()->Notify(
|
||||
chrome::NOTIFICATION_PRINT_JOB_RELEASED,
|
||||
content::Source<content::WebContents>(web_contents()),
|
||||
content::NotificationService::NoDetails());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::RenderAllMissingPagesNow() {
|
||||
if (!print_job_.get() || !print_job_->is_job_pending())
|
||||
return false;
|
||||
|
||||
// We can't print if there is no renderer.
|
||||
if (!web_contents() ||
|
||||
!web_contents()->GetRenderViewHost() ||
|
||||
!web_contents()->GetRenderViewHost()->IsRenderViewLive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the document already complete?
|
||||
if (print_job_->document() && print_job_->document()->IsComplete()) {
|
||||
printing_succeeded_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// WebContents is either dying or a second consecutive request to print
|
||||
// happened before the first had time to finish. We need to render all the
|
||||
// pages in an hurry if a print_job_ is still pending. No need to wait for it
|
||||
// to actually spool the pages, only to have the renderer generate them. Run
|
||||
// a message loop until we get our signal that the print job is satisfied.
|
||||
// PrintJob will send a ALL_PAGES_REQUESTED after having received all the
|
||||
// pages it needs. MessageLoop::current()->Quit() will be called as soon as
|
||||
// print_job_->document()->IsComplete() is true on either ALL_PAGES_REQUESTED
|
||||
// or in DidPrintPage(). The check is done in
|
||||
// ShouldQuitFromInnerMessageLoop().
|
||||
// BLOCKS until all the pages are received. (Need to enable recursive task)
|
||||
if (!RunInnerMessageLoop()) {
|
||||
// This function is always called from DisconnectFromCurrentPrintJob() so we
|
||||
// know that the job will be stopped/canceled in any case.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::ShouldQuitFromInnerMessageLoop() {
|
||||
// Look at the reason.
|
||||
DCHECK(print_job_->document());
|
||||
if (print_job_->document() &&
|
||||
print_job_->document()->IsComplete() &&
|
||||
inside_inner_message_loop_) {
|
||||
// We are in a message loop created by RenderAllMissingPagesNow. Quit from
|
||||
// it.
|
||||
base::MessageLoop::current()->Quit();
|
||||
inside_inner_message_loop_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::CreateNewPrintJob(PrintJobWorkerOwner* job) {
|
||||
DCHECK(!inside_inner_message_loop_);
|
||||
|
||||
// Disconnect the current print_job_.
|
||||
DisconnectFromCurrentPrintJob();
|
||||
|
||||
// We can't print if there is no renderer.
|
||||
if (!web_contents()->GetRenderViewHost() ||
|
||||
!web_contents()->GetRenderViewHost()->IsRenderViewLive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ask the renderer to generate the print preview, create the print preview
|
||||
// view and switch to it, initialize the printer and show the print dialog.
|
||||
DCHECK(!print_job_.get());
|
||||
DCHECK(job);
|
||||
if (!job)
|
||||
return false;
|
||||
|
||||
print_job_ = new PrintJob();
|
||||
print_job_->Initialize(job, this, number_pages_);
|
||||
registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
|
||||
content::Source<PrintJob>(print_job_.get()));
|
||||
printing_succeeded_ = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::DisconnectFromCurrentPrintJob() {
|
||||
// Make sure all the necessary rendered page are done. Don't bother with the
|
||||
// return value.
|
||||
bool result = RenderAllMissingPagesNow();
|
||||
|
||||
// Verify that assertion.
|
||||
if (print_job_.get() &&
|
||||
print_job_->document() &&
|
||||
!print_job_->document()->IsComplete()) {
|
||||
DCHECK(!result);
|
||||
// That failed.
|
||||
TerminatePrintJob(true);
|
||||
} else {
|
||||
// DO NOT wait for the job to finish.
|
||||
ReleasePrintJob();
|
||||
}
|
||||
#if defined(OS_POSIX) && !defined(OS_MACOSX)
|
||||
expecting_first_page_ = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::PrintingDone(bool success) {
|
||||
if (!print_job_.get())
|
||||
return;
|
||||
Send(new PrintMsg_PrintingDone(routing_id(), success));
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::TerminatePrintJob(bool cancel) {
|
||||
if (!print_job_.get())
|
||||
return;
|
||||
|
||||
if (cancel) {
|
||||
// We don't need the metafile data anymore because the printing is canceled.
|
||||
print_job_->Cancel();
|
||||
inside_inner_message_loop_ = false;
|
||||
} else {
|
||||
DCHECK(!inside_inner_message_loop_);
|
||||
DCHECK(!print_job_->document() || print_job_->document()->IsComplete());
|
||||
|
||||
// WebContents is either dying or navigating elsewhere. We need to render
|
||||
// all the pages in an hurry if a print job is still pending. This does the
|
||||
// trick since it runs a blocking message loop:
|
||||
print_job_->Stop();
|
||||
}
|
||||
ReleasePrintJob();
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::ReleasePrintJob() {
|
||||
if (!print_job_.get())
|
||||
return;
|
||||
|
||||
PrintingDone(printing_succeeded_);
|
||||
|
||||
registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
|
||||
content::Source<PrintJob>(print_job_.get()));
|
||||
print_job_->DisconnectSource();
|
||||
// Don't close the worker thread.
|
||||
print_job_ = NULL;
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::RunInnerMessageLoop() {
|
||||
// This value may actually be too low:
|
||||
//
|
||||
// - If we're looping because of printer settings initialization, the premise
|
||||
// here is that some poor users have their print server away on a VPN over a
|
||||
// slow connection. In this situation, the simple fact of opening the printer
|
||||
// can be dead slow. On the other side, we don't want to die infinitely for a
|
||||
// real network error. Give the printer 60 seconds to comply.
|
||||
//
|
||||
// - If we're looping because of renderer page generation, the renderer could
|
||||
// be CPU bound, the page overly complex/large or the system just
|
||||
// memory-bound.
|
||||
static const int kPrinterSettingsTimeout = 60000;
|
||||
base::OneShotTimer<base::MessageLoop> quit_timer;
|
||||
quit_timer.Start(FROM_HERE,
|
||||
TimeDelta::FromMilliseconds(kPrinterSettingsTimeout),
|
||||
base::MessageLoop::current(), &base::MessageLoop::Quit);
|
||||
|
||||
inside_inner_message_loop_ = true;
|
||||
|
||||
// Need to enable recursive task.
|
||||
{
|
||||
base::MessageLoop::ScopedNestableTaskAllower allow(
|
||||
base::MessageLoop::current());
|
||||
base::MessageLoop::current()->Run();
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
if (inside_inner_message_loop_) {
|
||||
// Ok we timed out. That's sad.
|
||||
inside_inner_message_loop_ = false;
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::OpportunisticallyCreatePrintJob(int cookie) {
|
||||
if (print_job_.get())
|
||||
return true;
|
||||
|
||||
if (!cookie) {
|
||||
// Out of sync. It may happens since we are completely asynchronous. Old
|
||||
// spurious message can happen if one of the processes is overloaded.
|
||||
return false;
|
||||
}
|
||||
|
||||
// The job was initiated by a script. Time to get the corresponding worker
|
||||
// thread.
|
||||
scoped_refptr<PrinterQuery> queued_query = queue_->PopPrinterQuery(cookie);
|
||||
if (!queued_query) {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateNewPrintJob(queued_query)) {
|
||||
// Don't kill anything.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Settings are already loaded. Go ahead. This will set
|
||||
// print_job_->is_job_pending() to true.
|
||||
print_job_->StartPrinting();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::PrintNowInternal(IPC::Message* message) {
|
||||
// Don't print / print preview interstitials.
|
||||
if (web_contents()->ShowingInterstitialPage()) {
|
||||
delete message;
|
||||
return false;
|
||||
}
|
||||
return Send(message);
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::ReleasePrinterQuery() {
|
||||
if (!cookie_)
|
||||
return;
|
||||
|
||||
int cookie = cookie_;
|
||||
cookie_ = 0;
|
||||
queue_->SetDestination(NULL);
|
||||
|
||||
|
||||
printing::PrintJobManager* print_job_manager =
|
||||
g_browser_process->print_job_manager();
|
||||
// May be NULL in tests.
|
||||
if (!print_job_manager)
|
||||
return;
|
||||
|
||||
scoped_refptr<printing::PrinterQuery> printer_query;
|
||||
printer_query = queue_->PopPrinterQuery(cookie);
|
||||
if (!printer_query)
|
||||
return;
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&PrinterQuery::StopWorker, printer_query.get()));
|
||||
}
|
||||
|
||||
} // namespace printing
|
|
@ -0,0 +1,166 @@
|
|||
// 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 CEF_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASE_H_
|
||||
#define CEF_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASE_H_
|
||||
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/prefs/pref_member.h"
|
||||
#include "base/strings/string16.h"
|
||||
#include "content/public/browser/notification_observer.h"
|
||||
#include "content/public/browser/notification_registrar.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "content/public/browser/web_contents_user_data.h"
|
||||
#include "printing/printed_pages_source.h"
|
||||
|
||||
struct PrintHostMsg_DidPrintPage_Params;
|
||||
|
||||
namespace content {
|
||||
class RenderViewHost;
|
||||
}
|
||||
|
||||
namespace printing {
|
||||
|
||||
class JobEventDetails;
|
||||
class PrintJob;
|
||||
class PrintJobWorkerOwner;
|
||||
class PrintQueriesQueue;
|
||||
|
||||
// Base class for managing the print commands for a WebContents.
|
||||
class PrintViewManagerBase : public content::NotificationObserver,
|
||||
public PrintedPagesSource,
|
||||
public content::WebContentsObserver {
|
||||
public:
|
||||
virtual ~PrintViewManagerBase();
|
||||
|
||||
// Prints the current document immediately. Since the rendering is
|
||||
// asynchronous, the actual printing will not be completed on the return of
|
||||
// this function. Returns false if printing is impossible at the moment.
|
||||
virtual bool PrintNow();
|
||||
|
||||
// Whether to block scripted printing for our tab or not.
|
||||
void UpdateScriptedPrintingBlocked();
|
||||
|
||||
// PrintedPagesSource implementation.
|
||||
virtual string16 RenderSourceName() OVERRIDE;
|
||||
|
||||
protected:
|
||||
explicit PrintViewManagerBase(content::WebContents* web_contents);
|
||||
|
||||
// Helper method for Print*Now().
|
||||
bool PrintNowInternal(IPC::Message* message);
|
||||
|
||||
// Terminates or cancels the print job if one was pending.
|
||||
virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
|
||||
|
||||
// content::WebContentsObserver implementation.
|
||||
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
|
||||
|
||||
// IPC Message handlers.
|
||||
virtual void OnPrintingFailed(int cookie);
|
||||
|
||||
private:
|
||||
// content::NotificationObserver implementation.
|
||||
virtual void Observe(int type,
|
||||
const content::NotificationSource& source,
|
||||
const content::NotificationDetails& details) OVERRIDE;
|
||||
|
||||
// content::WebContentsObserver implementation.
|
||||
virtual void DidStartLoading(
|
||||
content::RenderViewHost* render_view_host) OVERRIDE;
|
||||
|
||||
// Cancels the print job.
|
||||
virtual void NavigationStopped() OVERRIDE;
|
||||
|
||||
// IPC Message handlers.
|
||||
void OnDidGetPrintedPagesCount(int cookie, int number_pages);
|
||||
void OnDidGetDocumentCookie(int cookie);
|
||||
void OnDidPrintPage(const PrintHostMsg_DidPrintPage_Params& params);
|
||||
|
||||
// Processes a NOTIFY_PRINT_JOB_EVENT notification.
|
||||
void OnNotifyPrintJobEvent(const JobEventDetails& event_details);
|
||||
|
||||
// Requests the RenderView to render all the missing pages for the print job.
|
||||
// No-op if no print job is pending. Returns true if at least one page has
|
||||
// been requested to the renderer.
|
||||
bool RenderAllMissingPagesNow();
|
||||
|
||||
// Quits the current message loop if these conditions hold true: a document is
|
||||
// loaded and is complete and waiting_for_pages_to_be_rendered_ is true. This
|
||||
// function is called in DidPrintPage() or on ALL_PAGES_REQUESTED
|
||||
// notification. The inner message loop is created was created by
|
||||
// RenderAllMissingPagesNow().
|
||||
void ShouldQuitFromInnerMessageLoop();
|
||||
|
||||
// Creates a new empty print job. It has no settings loaded. If there is
|
||||
// currently a print job, safely disconnect from it. Returns false if it is
|
||||
// impossible to safely disconnect from the current print job or it is
|
||||
// impossible to create a new print job.
|
||||
bool CreateNewPrintJob(PrintJobWorkerOwner* job);
|
||||
|
||||
// Makes sure the current print_job_ has all its data before continuing, and
|
||||
// disconnect from it.
|
||||
void DisconnectFromCurrentPrintJob();
|
||||
|
||||
// Notify that the printing is done.
|
||||
void PrintingDone(bool success);
|
||||
|
||||
// Terminates the print job. No-op if no print job has been created. If
|
||||
// |cancel| is true, cancel it instead of waiting for the job to finish. Will
|
||||
// call ReleasePrintJob().
|
||||
void TerminatePrintJob(bool cancel);
|
||||
|
||||
// Releases print_job_. Correctly deregisters from notifications. No-op if
|
||||
// no print job has been created.
|
||||
void ReleasePrintJob();
|
||||
|
||||
// Runs an inner message loop. It will set inside_inner_message_loop_ to true
|
||||
// while the blocking inner message loop is running. This is useful in cases
|
||||
// where the RenderView is about to be destroyed while a printing job isn't
|
||||
// finished.
|
||||
bool RunInnerMessageLoop();
|
||||
|
||||
// In the case of Scripted Printing, where the renderer is controlling the
|
||||
// control flow, print_job_ is initialized whenever possible. No-op is
|
||||
// print_job_ is initialized.
|
||||
bool OpportunisticallyCreatePrintJob(int cookie);
|
||||
|
||||
// Release the PrinterQuery associated with our |cookie_|.
|
||||
void ReleasePrinterQuery();
|
||||
|
||||
content::NotificationRegistrar registrar_;
|
||||
|
||||
// Manages the low-level talk to the printer.
|
||||
scoped_refptr<PrintJob> print_job_;
|
||||
|
||||
// Number of pages to print in the print job.
|
||||
int number_pages_;
|
||||
|
||||
// Indication of success of the print job.
|
||||
bool printing_succeeded_;
|
||||
|
||||
// Running an inner message loop inside RenderAllMissingPagesNow(). This means
|
||||
// we are _blocking_ until all the necessary pages have been rendered or the
|
||||
// print settings are being loaded.
|
||||
bool inside_inner_message_loop_;
|
||||
|
||||
#if defined(OS_POSIX) && !defined(OS_MACOSX)
|
||||
// Set to true when OnDidPrintPage() should be expecting the first page.
|
||||
bool expecting_first_page_;
|
||||
#endif
|
||||
|
||||
// The document cookie of the current PrinterQuery.
|
||||
int cookie_;
|
||||
|
||||
// Whether printing is enabled.
|
||||
BooleanPrefMember printing_enabled_;
|
||||
|
||||
scoped_refptr<printing::PrintQueriesQueue> queue_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintViewManagerBase);
|
||||
};
|
||||
|
||||
} // namespace printing
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASE_H_
|
|
@ -0,0 +1,446 @@
|
|||
// 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/printing_message_filter.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/browser/printing/printer_query.h"
|
||||
#include "chrome/browser/printing/print_job_manager.h"
|
||||
#include "chrome/common/print_messages.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/browser/web_contents_view.h"
|
||||
|
||||
#if defined(OS_CHROMEOS)
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "base/file_util.h"
|
||||
#include "base/lazy_instance.h"
|
||||
#include "chrome/browser/printing/print_dialog_cloud.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_ANDROID)
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "chrome/browser/printing/print_view_manager_basic.h"
|
||||
#include "printing/printing_context_android.h"
|
||||
#endif
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(OS_CHROMEOS)
|
||||
typedef std::map<int, base::FilePath> SequenceToPathMap;
|
||||
|
||||
struct PrintingSequencePathMap {
|
||||
SequenceToPathMap map;
|
||||
int sequence;
|
||||
};
|
||||
|
||||
// No locking, only access on the FILE thread.
|
||||
static base::LazyInstance<PrintingSequencePathMap>
|
||||
g_printing_file_descriptor_map = LAZY_INSTANCE_INITIALIZER;
|
||||
#endif
|
||||
|
||||
void RenderParamsFromPrintSettings(const printing::PrintSettings& settings,
|
||||
PrintMsg_Print_Params* params) {
|
||||
params->page_size = settings.page_setup_device_units().physical_size();
|
||||
params->content_size.SetSize(
|
||||
settings.page_setup_device_units().content_area().width(),
|
||||
settings.page_setup_device_units().content_area().height());
|
||||
params->printable_area.SetRect(
|
||||
settings.page_setup_device_units().printable_area().x(),
|
||||
settings.page_setup_device_units().printable_area().y(),
|
||||
settings.page_setup_device_units().printable_area().width(),
|
||||
settings.page_setup_device_units().printable_area().height());
|
||||
params->margin_top = settings.page_setup_device_units().content_area().y();
|
||||
params->margin_left = settings.page_setup_device_units().content_area().x();
|
||||
params->dpi = settings.dpi();
|
||||
// Currently hardcoded at 1.25. See PrintSettings' constructor.
|
||||
params->min_shrink = settings.min_shrink;
|
||||
// Currently hardcoded at 2.0. See PrintSettings' constructor.
|
||||
params->max_shrink = settings.max_shrink;
|
||||
// Currently hardcoded at 72dpi. See PrintSettings' constructor.
|
||||
params->desired_dpi = settings.desired_dpi;
|
||||
// Always use an invalid cookie.
|
||||
params->document_cookie = 0;
|
||||
params->selection_only = settings.selection_only;
|
||||
params->supports_alpha_blend = settings.supports_alpha_blend();
|
||||
params->should_print_backgrounds = settings.should_print_backgrounds;
|
||||
params->display_header_footer = settings.display_header_footer;
|
||||
params->date = settings.date;
|
||||
params->title = settings.title;
|
||||
params->url = settings.url;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PrintingMessageFilter::PrintingMessageFilter(int render_process_id)
|
||||
: render_process_id_(render_process_id),
|
||||
queue_(g_browser_process->print_job_manager()->queue()) {
|
||||
DCHECK(queue_);
|
||||
}
|
||||
|
||||
PrintingMessageFilter::~PrintingMessageFilter() {
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OverrideThreadForMessage(
|
||||
const IPC::Message& message, BrowserThread::ID* thread) {
|
||||
#if defined(OS_CHROMEOS)
|
||||
if (message.type() == PrintHostMsg_AllocateTempFileForPrinting::ID ||
|
||||
message.type() == PrintHostMsg_TempFileForPrintingWritten::ID) {
|
||||
*thread = BrowserThread::FILE;
|
||||
}
|
||||
#elif defined(OS_ANDROID)
|
||||
if (message.type() == PrintHostMsg_AllocateTempFileForPrinting::ID ||
|
||||
message.type() == PrintHostMsg_TempFileForPrintingWritten::ID) {
|
||||
*thread = BrowserThread::UI;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool PrintingMessageFilter::OnMessageReceived(const IPC::Message& message,
|
||||
bool* message_was_ok) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP_EX(PrintingMessageFilter, message, *message_was_ok)
|
||||
#if defined(OS_WIN)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_DuplicateSection, OnDuplicateSection)
|
||||
#endif
|
||||
#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_AllocateTempFileForPrinting,
|
||||
OnAllocateTempFileForPrinting)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_TempFileForPrintingWritten,
|
||||
OnTempFileForPrintingWritten)
|
||||
#endif
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_IsPrintingEnabled, OnIsPrintingEnabled)
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings,
|
||||
OnGetDefaultPrintSettings)
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint)
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_UpdatePrintSettings,
|
||||
OnUpdatePrintSettings)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
return handled;
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void PrintingMessageFilter::OnDuplicateSection(
|
||||
base::SharedMemoryHandle renderer_handle,
|
||||
base::SharedMemoryHandle* browser_handle) {
|
||||
// Duplicate the handle in this process right now so the memory is kept alive
|
||||
// (even if it is not mapped)
|
||||
base::SharedMemory shared_buf(renderer_handle, true, PeerHandle());
|
||||
shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), browser_handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
|
||||
void PrintingMessageFilter::OnAllocateTempFileForPrinting(
|
||||
int render_view_id,
|
||||
base::FileDescriptor* temp_file_fd,
|
||||
int* sequence_number) {
|
||||
#if defined(OS_CHROMEOS)
|
||||
// TODO(thestig): Use |render_view_id| for Chrome OS.
|
||||
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
||||
temp_file_fd->fd = *sequence_number = -1;
|
||||
temp_file_fd->auto_close = false;
|
||||
|
||||
SequenceToPathMap* map = &g_printing_file_descriptor_map.Get().map;
|
||||
*sequence_number = g_printing_file_descriptor_map.Get().sequence++;
|
||||
|
||||
base::FilePath path;
|
||||
if (file_util::CreateTemporaryFile(&path)) {
|
||||
int fd = open(path.value().c_str(), O_WRONLY);
|
||||
if (fd >= 0) {
|
||||
SequenceToPathMap::iterator it = map->find(*sequence_number);
|
||||
if (it != map->end()) {
|
||||
NOTREACHED() << "Sequence number already in use. seq=" <<
|
||||
*sequence_number;
|
||||
} else {
|
||||
(*map)[*sequence_number] = path;
|
||||
temp_file_fd->fd = fd;
|
||||
temp_file_fd->auto_close = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(OS_ANDROID)
|
||||
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
||||
content::WebContents* wc = GetWebContentsForRenderView(render_view_id);
|
||||
if (!wc)
|
||||
return;
|
||||
printing::PrintViewManagerBasic* print_view_manager =
|
||||
printing::PrintViewManagerBasic::FromWebContents(wc);
|
||||
// The file descriptor is originally created in & passed from the Android
|
||||
// side, and it will handle the closing.
|
||||
const base::FileDescriptor& file_descriptor =
|
||||
print_view_manager->file_descriptor();
|
||||
temp_file_fd->fd = file_descriptor.fd;
|
||||
temp_file_fd->auto_close = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OnTempFileForPrintingWritten(int render_view_id,
|
||||
int sequence_number) {
|
||||
#if defined(OS_CHROMEOS)
|
||||
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
||||
SequenceToPathMap* map = &g_printing_file_descriptor_map.Get().map;
|
||||
SequenceToPathMap::iterator it = map->find(sequence_number);
|
||||
if (it == map->end()) {
|
||||
NOTREACHED() << "Got a sequence that we didn't pass to the "
|
||||
"renderer: " << sequence_number;
|
||||
return;
|
||||
}
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&PrintingMessageFilter::CreatePrintDialogForFile,
|
||||
this, render_view_id, it->second));
|
||||
|
||||
// Erase the entry in the map.
|
||||
map->erase(it);
|
||||
#elif defined(OS_ANDROID)
|
||||
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
||||
content::WebContents* wc = GetWebContentsForRenderView(render_view_id);
|
||||
if (!wc)
|
||||
return;
|
||||
printing::PrintViewManagerBasic* print_view_manager =
|
||||
printing::PrintViewManagerBasic::FromWebContents(wc);
|
||||
const base::FileDescriptor& file_descriptor =
|
||||
print_view_manager->file_descriptor();
|
||||
printing::PrintingContextAndroid::PdfWritingDone(file_descriptor.fd, true);
|
||||
// Invalidate the file descriptor so it doesn't accidentally get reused.
|
||||
print_view_manager->set_file_descriptor(base::FileDescriptor(-1, false));
|
||||
#endif
|
||||
}
|
||||
#endif // defined(OS_CHROMEOS) || defined(OS_ANDROID)
|
||||
|
||||
#if defined(OS_CHROMEOS)
|
||||
void PrintingMessageFilter::CreatePrintDialogForFile(
|
||||
int render_view_id,
|
||||
const base::FilePath& path) {
|
||||
content::WebContents* wc = GetWebContentsForRenderView(render_view_id);
|
||||
if (!wc)
|
||||
return;
|
||||
print_dialog_cloud::CreatePrintDialogForFile(
|
||||
wc->GetBrowserContext(),
|
||||
wc->GetView()->GetTopLevelNativeWindow(),
|
||||
path,
|
||||
wc->GetTitle(),
|
||||
string16(),
|
||||
std::string("application/pdf"),
|
||||
false);
|
||||
}
|
||||
#endif // defined(OS_CHROMEOS)
|
||||
|
||||
content::WebContents* PrintingMessageFilter::GetWebContentsForRenderView(
|
||||
int render_view_id) {
|
||||
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
||||
content::RenderViewHost* view = content::RenderViewHost::FromID(
|
||||
render_process_id_, render_view_id);
|
||||
return view ? content::WebContents::FromRenderViewHost(view) : NULL;
|
||||
}
|
||||
|
||||
struct PrintingMessageFilter::GetPrintSettingsForRenderViewParams {
|
||||
printing::PrinterQuery::GetSettingsAskParam ask_user_for_settings;
|
||||
int expected_page_count;
|
||||
bool has_selection;
|
||||
printing::MarginType margin_type;
|
||||
};
|
||||
|
||||
void PrintingMessageFilter::GetPrintSettingsForRenderView(
|
||||
int render_view_id,
|
||||
GetPrintSettingsForRenderViewParams params,
|
||||
const base::Closure& callback,
|
||||
scoped_refptr<printing::PrinterQuery> printer_query) {
|
||||
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
||||
content::WebContents* wc = GetWebContentsForRenderView(render_view_id);
|
||||
if (wc) {
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&printing::PrinterQuery::GetSettings, printer_query,
|
||||
params.ask_user_for_settings, wc->GetView()->GetNativeView(),
|
||||
params.expected_page_count, params.has_selection,
|
||||
params.margin_type, callback));
|
||||
} else {
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&PrintingMessageFilter::OnGetPrintSettingsFailed, this,
|
||||
callback, printer_query));
|
||||
}
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OnGetPrintSettingsFailed(
|
||||
const base::Closure& callback,
|
||||
scoped_refptr<printing::PrinterQuery> printer_query) {
|
||||
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
||||
printer_query->GetSettingsDone(printing::PrintSettings(),
|
||||
printing::PrintingContext::FAILED);
|
||||
callback.Run();
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OnIsPrintingEnabled(bool* is_enabled) {
|
||||
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
||||
*is_enabled = true;
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) {
|
||||
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
||||
scoped_refptr<printing::PrinterQuery> printer_query;
|
||||
printer_query = queue_->PopPrinterQuery(0);
|
||||
if (!printer_query)
|
||||
printer_query = queue_->CreatePrinterQuery();
|
||||
|
||||
// Loads default settings. This is asynchronous, only the IPC message sender
|
||||
// will hang until the settings are retrieved.
|
||||
GetPrintSettingsForRenderViewParams params;
|
||||
params.ask_user_for_settings = printing::PrinterQuery::DEFAULTS;
|
||||
params.expected_page_count = 0;
|
||||
params.has_selection = false;
|
||||
params.margin_type = printing::DEFAULT_MARGINS;
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&PrintingMessageFilter::GetPrintSettingsForRenderView, this,
|
||||
reply_msg->routing_id(), params,
|
||||
base::Bind(&PrintingMessageFilter::OnGetDefaultPrintSettingsReply,
|
||||
this, printer_query, reply_msg),
|
||||
printer_query));
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OnGetDefaultPrintSettingsReply(
|
||||
scoped_refptr<printing::PrinterQuery> printer_query,
|
||||
IPC::Message* reply_msg) {
|
||||
PrintMsg_Print_Params params;
|
||||
if (!printer_query.get() ||
|
||||
printer_query->last_status() != printing::PrintingContext::OK) {
|
||||
params.Reset();
|
||||
} else {
|
||||
RenderParamsFromPrintSettings(printer_query->settings(), ¶ms);
|
||||
params.document_cookie = printer_query->cookie();
|
||||
}
|
||||
PrintHostMsg_GetDefaultPrintSettings::WriteReplyParams(reply_msg, params);
|
||||
Send(reply_msg);
|
||||
// If printing was enabled.
|
||||
if (printer_query.get()) {
|
||||
// If user hasn't cancelled.
|
||||
if (printer_query->cookie() && printer_query->settings().dpi()) {
|
||||
queue_->QueuePrinterQuery(printer_query.get());
|
||||
} else {
|
||||
printer_query->StopWorker();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OnScriptedPrint(
|
||||
const PrintHostMsg_ScriptedPrint_Params& params,
|
||||
IPC::Message* reply_msg) {
|
||||
scoped_refptr<printing::PrinterQuery> printer_query =
|
||||
queue_->PopPrinterQuery(params.cookie);
|
||||
if (!printer_query)
|
||||
printer_query = queue_->CreatePrinterQuery();
|
||||
GetPrintSettingsForRenderViewParams settings_params;
|
||||
settings_params.ask_user_for_settings = printing::PrinterQuery::ASK_USER;
|
||||
settings_params.expected_page_count = params.expected_pages_count;
|
||||
settings_params.has_selection = params.has_selection;
|
||||
settings_params.margin_type = params.margin_type;
|
||||
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&PrintingMessageFilter::GetPrintSettingsForRenderView, this,
|
||||
reply_msg->routing_id(), settings_params,
|
||||
base::Bind(&PrintingMessageFilter::OnScriptedPrintReply, this,
|
||||
printer_query, reply_msg),
|
||||
printer_query));
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OnScriptedPrintReply(
|
||||
scoped_refptr<printing::PrinterQuery> printer_query,
|
||||
IPC::Message* reply_msg) {
|
||||
PrintMsg_PrintPages_Params params;
|
||||
#if defined(OS_ANDROID)
|
||||
// We need to save the routing ID here because Send method below deletes the
|
||||
// |reply_msg| before we can get the routing ID for the Android code.
|
||||
int routing_id = reply_msg->routing_id();
|
||||
#endif
|
||||
if (printer_query->last_status() != printing::PrintingContext::OK ||
|
||||
!printer_query->settings().dpi()) {
|
||||
params.Reset();
|
||||
} else {
|
||||
RenderParamsFromPrintSettings(printer_query->settings(), ¶ms.params);
|
||||
params.params.document_cookie = printer_query->cookie();
|
||||
params.pages =
|
||||
printing::PageRange::GetPages(printer_query->settings().ranges);
|
||||
}
|
||||
PrintHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, params);
|
||||
Send(reply_msg);
|
||||
if (params.params.dpi && params.params.document_cookie) {
|
||||
#if defined(OS_ANDROID)
|
||||
int file_descriptor;
|
||||
const string16& device_name = printer_query->settings().device_name();
|
||||
if (base::StringToInt(device_name, &file_descriptor)) {
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&PrintingMessageFilter::UpdateFileDescriptor, this,
|
||||
routing_id, file_descriptor));
|
||||
}
|
||||
#endif
|
||||
queue_->QueuePrinterQuery(printer_query.get());
|
||||
} else {
|
||||
printer_query->StopWorker();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_ANDROID)
|
||||
void PrintingMessageFilter::UpdateFileDescriptor(int render_view_id, int fd) {
|
||||
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
||||
content::WebContents* wc = GetWebContentsForRenderView(render_view_id);
|
||||
if (!wc)
|
||||
return;
|
||||
printing::PrintViewManagerBasic* print_view_manager =
|
||||
printing::PrintViewManagerBasic::FromWebContents(wc);
|
||||
print_view_manager->set_file_descriptor(base::FileDescriptor(fd, false));
|
||||
}
|
||||
#endif
|
||||
|
||||
void PrintingMessageFilter::OnUpdatePrintSettings(
|
||||
int document_cookie, const DictionaryValue& job_settings,
|
||||
IPC::Message* reply_msg) {
|
||||
scoped_refptr<printing::PrinterQuery> printer_query;
|
||||
printer_query = queue_->PopPrinterQuery(document_cookie);
|
||||
if (!printer_query)
|
||||
printer_query = queue_->CreatePrinterQuery();
|
||||
printer_query->SetSettings(
|
||||
job_settings,
|
||||
base::Bind(&PrintingMessageFilter::OnUpdatePrintSettingsReply, this,
|
||||
printer_query, reply_msg));
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OnUpdatePrintSettingsReply(
|
||||
scoped_refptr<printing::PrinterQuery> printer_query,
|
||||
IPC::Message* reply_msg) {
|
||||
PrintMsg_PrintPages_Params params;
|
||||
if (!printer_query.get() ||
|
||||
printer_query->last_status() != printing::PrintingContext::OK) {
|
||||
params.Reset();
|
||||
} else {
|
||||
RenderParamsFromPrintSettings(printer_query->settings(), ¶ms.params);
|
||||
params.params.document_cookie = printer_query->cookie();
|
||||
params.pages =
|
||||
printing::PageRange::GetPages(printer_query->settings().ranges);
|
||||
}
|
||||
PrintHostMsg_UpdatePrintSettings::WriteReplyParams(reply_msg, params);
|
||||
Send(reply_msg);
|
||||
// If user hasn't cancelled.
|
||||
if (printer_query.get()) {
|
||||
if (printer_query->cookie() && printer_query->settings().dpi()) {
|
||||
queue_->QueuePrinterQuery(printer_query.get());
|
||||
} else {
|
||||
printer_query->StopWorker();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
// 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 CEF_LIBCEF_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_
|
||||
#define CEF_LIBCEF_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "content/public/browser/browser_message_filter.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "base/memory/shared_memory.h"
|
||||
#endif
|
||||
|
||||
struct PrintHostMsg_ScriptedPrint_Params;
|
||||
|
||||
namespace base {
|
||||
class DictionaryValue;
|
||||
class FilePath;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace printing {
|
||||
class PrinterQuery;
|
||||
class PrintJobManager;
|
||||
class PrintQueriesQueue;
|
||||
}
|
||||
|
||||
// This class filters out incoming printing related IPC messages for the
|
||||
// renderer process on the IPC thread.
|
||||
class PrintingMessageFilter : public content::BrowserMessageFilter {
|
||||
public:
|
||||
explicit PrintingMessageFilter(int render_process_id);
|
||||
|
||||
// content::BrowserMessageFilter methods.
|
||||
virtual void OverrideThreadForMessage(
|
||||
const IPC::Message& message,
|
||||
content::BrowserThread::ID* thread) OVERRIDE;
|
||||
virtual bool OnMessageReceived(const IPC::Message& message,
|
||||
bool* message_was_ok) OVERRIDE;
|
||||
|
||||
private:
|
||||
virtual ~PrintingMessageFilter();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Used to pass resulting EMF from renderer to browser in printing.
|
||||
void OnDuplicateSection(base::SharedMemoryHandle renderer_handle,
|
||||
base::SharedMemoryHandle* browser_handle);
|
||||
#endif
|
||||
|
||||
#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
|
||||
// Used to ask the browser allocate a temporary file for the renderer
|
||||
// to fill in resulting PDF in renderer.
|
||||
void OnAllocateTempFileForPrinting(int render_view_id,
|
||||
base::FileDescriptor* temp_file_fd,
|
||||
int* sequence_number);
|
||||
void OnTempFileForPrintingWritten(int render_view_id, int sequence_number);
|
||||
#endif
|
||||
|
||||
#if defined(OS_CHROMEOS)
|
||||
void CreatePrintDialogForFile(int render_view_id, const base::FilePath& path);
|
||||
#endif
|
||||
|
||||
#if defined(OS_ANDROID)
|
||||
// Updates the file descriptor for the PrintViewManagerBasic of a given
|
||||
// render_view_id.
|
||||
void UpdateFileDescriptor(int render_view_id, int fd);
|
||||
#endif
|
||||
|
||||
// Given a render_view_id get the corresponding WebContents.
|
||||
// Must be called on the UI thread.
|
||||
content::WebContents* GetWebContentsForRenderView(int render_view_id);
|
||||
|
||||
// GetPrintSettingsForRenderView must be called via PostTask and
|
||||
// base::Bind. Collapse the settings-specific params into a
|
||||
// struct to avoid running into issues with too many params
|
||||
// to base::Bind.
|
||||
struct GetPrintSettingsForRenderViewParams;
|
||||
|
||||
// Retrieve print settings. Uses |render_view_id| to get a parent
|
||||
// for any UI created if needed.
|
||||
void GetPrintSettingsForRenderView(
|
||||
int render_view_id,
|
||||
GetPrintSettingsForRenderViewParams params,
|
||||
const base::Closure& callback,
|
||||
scoped_refptr<printing::PrinterQuery> printer_query);
|
||||
|
||||
void OnGetPrintSettingsFailed(
|
||||
const base::Closure& callback,
|
||||
scoped_refptr<printing::PrinterQuery> printer_query);
|
||||
|
||||
// Checks if printing is enabled.
|
||||
void OnIsPrintingEnabled(bool* is_enabled);
|
||||
|
||||
// Get the default print setting.
|
||||
void OnGetDefaultPrintSettings(IPC::Message* reply_msg);
|
||||
void OnGetDefaultPrintSettingsReply(
|
||||
scoped_refptr<printing::PrinterQuery> printer_query,
|
||||
IPC::Message* reply_msg);
|
||||
|
||||
// The renderer host have to show to the user the print dialog and returns
|
||||
// the selected print settings. The task is handled by the print worker
|
||||
// thread and the UI thread. The reply occurs on the IO thread.
|
||||
void OnScriptedPrint(const PrintHostMsg_ScriptedPrint_Params& params,
|
||||
IPC::Message* reply_msg);
|
||||
void OnScriptedPrintReply(
|
||||
scoped_refptr<printing::PrinterQuery> printer_query,
|
||||
IPC::Message* reply_msg);
|
||||
|
||||
// Modify the current print settings based on |job_settings|. The task is
|
||||
// handled by the print worker thread and the UI thread. The reply occurs on
|
||||
// the IO thread.
|
||||
void OnUpdatePrintSettings(int document_cookie,
|
||||
const base::DictionaryValue& job_settings,
|
||||
IPC::Message* reply_msg);
|
||||
void OnUpdatePrintSettingsReply(
|
||||
scoped_refptr<printing::PrinterQuery> printer_query,
|
||||
IPC::Message* reply_msg);
|
||||
|
||||
const int render_process_id_;
|
||||
|
||||
scoped_refptr<printing::PrintQueriesQueue> queue_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintingMessageFilter);
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_
|
|
@ -218,3 +218,6 @@ struct ParamTraits<scoped_refptr<net::UploadData> > {
|
|||
} // namespace IPC
|
||||
|
||||
#endif // CEF_LIBCEF_COMMON_CEF_MESSAGES_H_
|
||||
|
||||
#include "chrome/common/prerender_messages.h"
|
||||
#include "chrome/common/print_messages.h"
|
||||
|
|
|
@ -33,6 +33,7 @@ MSVC_POP_WARNING();
|
|||
#include "base/path_service.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "chrome/renderer/loadtimes_extension_bindings.h"
|
||||
#include "chrome/renderer/printing/print_web_view_helper.h"
|
||||
#include "content/child/child_thread.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
|
@ -443,6 +444,7 @@ void CefContentRendererClient::RenderViewCreated(
|
|||
browsers_.insert(std::make_pair(render_view, browser));
|
||||
|
||||
new CefPrerendererClient(render_view);
|
||||
new printing::PrintWebViewHelper(render_view);
|
||||
|
||||
// Notify the render process handler.
|
||||
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<include name="IDR_CEF_CREDITS_SWIFTSHADER_JPG" file="..\..\..\chrome\browser\resources\swiftshader.jpg" type="BINDATA" />
|
||||
<include name="IDR_CEF_LICENSE_TXT" file="..\..\LICENSE.txt" type="BINDATA" />
|
||||
<include name="IDR_CEF_VERSION_HTML" file="about_version.html" type="BINDATA" />
|
||||
<include name="IDR_PRINT_PREVIEW_PAGE" file="print_preview_page_stub.html" type="BINDATA" />
|
||||
</includes>
|
||||
</release>
|
||||
</grit>
|
||||
|
|
|
@ -263,6 +263,20 @@ need to be translated for each locale.-->
|
|||
<message name="IDS_APP_VIDEO_FILES" desc="The text label for the Video Files filter in file open/save dialogs.">
|
||||
Video Files
|
||||
</message>
|
||||
|
||||
<!-- Print -->
|
||||
<message name="IDS_DEFAULT_PRINT_DOCUMENT_TITLE" desc="Default title for a print document">
|
||||
Untitled Document
|
||||
</message>
|
||||
<message name="IDS_PRINT_SPOOL_FAILED_TITLE_TEXT" desc="Title of a message box when printing fails because of printer issues.">
|
||||
Print Failed
|
||||
</message>
|
||||
<message name="IDS_PRINT_SPOOL_FAILED_ERROR_TEXT" desc="Text in a messagebox when printing fails because of printer issues.">
|
||||
Something went wrong when trying to print. Please check your printer and try again.
|
||||
</message>
|
||||
<message name="IDS_PRINT_PREVIEW_INVALID_PRINTER_SETTINGS" desc="Message to display when selected printer is not reachable or its settings are invalid.">
|
||||
The selected printer is not available or not installed correctly. Check your printer or try selecting another printer.
|
||||
</message>
|
||||
</messages>
|
||||
</release>
|
||||
</grit>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
#include <grit/cef_resources.h>
|
||||
#include <grit/cef_strings.h>
|
|
@ -0,0 +1,2 @@
|
|||
#include <grit/cef_resources.h>
|
||||
#include <grit/cef_strings.h>
|
|
@ -0,0 +1 @@
|
|||
<html></html>
|
|
@ -302,6 +302,17 @@ void CEF_CALLBACK browser_host_start_download(struct _cef_browser_host_t* self,
|
|||
CefString(url));
|
||||
}
|
||||
|
||||
void CEF_CALLBACK browser_host_print(struct _cef_browser_host_t* self) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
// Execute
|
||||
CefBrowserHostCppToC::Get(self)->Print();
|
||||
}
|
||||
|
||||
void CEF_CALLBACK browser_host_set_mouse_cursor_change_disabled(
|
||||
struct _cef_browser_host_t* self, int disabled) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
@ -586,6 +597,7 @@ CefBrowserHostCppToC::CefBrowserHostCppToC(CefBrowserHost* cls)
|
|||
struct_.struct_.set_zoom_level = browser_host_set_zoom_level;
|
||||
struct_.struct_.run_file_dialog = browser_host_run_file_dialog;
|
||||
struct_.struct_.start_download = browser_host_start_download;
|
||||
struct_.struct_.print = browser_host_print;
|
||||
struct_.struct_.set_mouse_cursor_change_disabled =
|
||||
browser_host_set_mouse_cursor_change_disabled;
|
||||
struct_.struct_.is_mouse_cursor_change_disabled =
|
||||
|
|
|
@ -250,6 +250,16 @@ void CefBrowserHostCToCpp::StartDownload(const CefString& url) {
|
|||
url.GetStruct());
|
||||
}
|
||||
|
||||
void CefBrowserHostCToCpp::Print() {
|
||||
if (CEF_MEMBER_MISSING(struct_, print))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
struct_->print(struct_);
|
||||
}
|
||||
|
||||
void CefBrowserHostCToCpp::SetMouseCursorChangeDisabled(bool disabled) {
|
||||
if (CEF_MEMBER_MISSING(struct_, set_mouse_cursor_change_disabled))
|
||||
return;
|
||||
|
|
|
@ -53,6 +53,7 @@ class CefBrowserHostCToCpp
|
|||
const std::vector<CefString>& accept_types,
|
||||
CefRefPtr<CefRunFileDialogCallback> callback) OVERRIDE;
|
||||
virtual void StartDownload(const CefString& url) OVERRIDE;
|
||||
virtual void Print() OVERRIDE;
|
||||
virtual void SetMouseCursorChangeDisabled(bool disabled) OVERRIDE;
|
||||
virtual bool IsMouseCursorChangeDisabled() OVERRIDE;
|
||||
virtual bool IsWindowRenderingDisabled() OVERRIDE;
|
||||
|
|
|
@ -78,6 +78,7 @@ BEGIN
|
|||
MENUITEM "Zoom Reset", ID_TESTS_ZOOM_RESET
|
||||
MENUITEM "Begin Tracing", ID_TESTS_TRACING_BEGIN
|
||||
MENUITEM "End Tracing", ID_TESTS_TRACING_END
|
||||
MENUITEM "Print", ID_TESTS_PRINT
|
||||
MENUITEM "Other Tests", ID_TESTS_OTHER_TESTS
|
||||
END
|
||||
END
|
||||
|
|
|
@ -149,6 +149,14 @@ gboolean EndTracingActivated(GtkWidget* widget) {
|
|||
return FALSE; // Don't stop this message.
|
||||
}
|
||||
|
||||
// Callback for Tests > Print menu item.
|
||||
gboolean PrintActivated(GtkWidget* widget) {
|
||||
if (g_handler.get())
|
||||
g_handler->GetBrowser()->GetHost()->Print();
|
||||
|
||||
return FALSE; // Don't stop this message.
|
||||
}
|
||||
|
||||
// Callback for Tests > Other Tests... menu item.
|
||||
gboolean OtherTestsActivated(GtkWidget* widget) {
|
||||
if (g_handler.get() && g_handler->GetBrowserId())
|
||||
|
@ -232,6 +240,8 @@ GtkWidget* CreateMenuBar() {
|
|||
G_CALLBACK(BeginTracingActivated));
|
||||
AddMenuEntry(debug_menu, "End Tracing",
|
||||
G_CALLBACK(EndTracingActivated));
|
||||
AddMenuEntry(debug_menu, "Print",
|
||||
G_CALLBACK(PrintActivated));
|
||||
AddMenuEntry(debug_menu, "Other Tests",
|
||||
G_CALLBACK(OtherTestsActivated));
|
||||
return menu_bar;
|
||||
|
|
|
@ -217,6 +217,7 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
|||
- (IBAction)testZoomReset:(id)sender;
|
||||
- (IBAction)testBeginTracing:(id)sender;
|
||||
- (IBAction)testEndTracing:(id)sender;
|
||||
- (IBAction)testPrint:(id)sender;
|
||||
- (IBAction)testOtherTests:(id)sender;
|
||||
@end
|
||||
|
||||
|
@ -266,6 +267,9 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
|||
[testMenu addItemWithTitle:@"End Tracing"
|
||||
action:@selector(testEndTracing:)
|
||||
keyEquivalent:@""];
|
||||
[testMenu addItemWithTitle:@"Print"
|
||||
action:@selector(testPrint:)
|
||||
keyEquivalent:@""];
|
||||
[testMenu addItemWithTitle:@"Other Tests"
|
||||
action:@selector(testOtherTests:)
|
||||
keyEquivalent:@""];
|
||||
|
@ -428,6 +432,11 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
|||
g_handler->EndTracing();
|
||||
}
|
||||
|
||||
- (IBAction)testPrint:(id)sender {
|
||||
if (g_handler.get() && g_handler->GetBrowserId())
|
||||
g_handler->GetBrowser()->GetHost()->Print();
|
||||
}
|
||||
|
||||
- (IBAction)testOtherTests:(id)sender {
|
||||
if (g_handler.get() && g_handler->GetBrowserId())
|
||||
RunOtherTests(g_handler->GetBrowser());
|
||||
|
|
|
@ -430,6 +430,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
|||
case ID_TESTS_TRACING_END:
|
||||
g_handler->EndTracing();
|
||||
return 0;
|
||||
case ID_TESTS_PRINT:
|
||||
if(browser.get())
|
||||
browser->GetHost()->Print();
|
||||
return 0;
|
||||
case ID_TESTS_OTHER_TESTS:
|
||||
if (browser.get())
|
||||
RunOtherTests(browser);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
<li><a href="http://webglsamples.googlecode.com/hg/field/field.html">WebGL</a></li>
|
||||
<li><a href="http://apprtc.appspot.com/">WebRTC</a> - requires "enable-media-stream" flag</li>
|
||||
<li><a href="http://tests/xmlhttprequest">XMLHttpRequest</a></li>
|
||||
<li><a href="javascript:window.print();">Print this page with "javascript:window.print();"</a></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -31,12 +31,13 @@
|
|||
#define ID_TESTS_OTHER_TESTS 32702
|
||||
#define ID_TESTS_PLUGIN_INFO 32703
|
||||
#define ID_TESTS_POPUP 32704
|
||||
#define ID_TESTS_REQUEST 32705
|
||||
#define ID_TESTS_TRACING_BEGIN 32706
|
||||
#define ID_TESTS_TRACING_END 32707
|
||||
#define ID_TESTS_ZOOM_IN 32708
|
||||
#define ID_TESTS_ZOOM_OUT 32709
|
||||
#define ID_TESTS_ZOOM_RESET 32710
|
||||
#define ID_TESTS_PRINT 32705
|
||||
#define ID_TESTS_REQUEST 32706
|
||||
#define ID_TESTS_TRACING_BEGIN 32707
|
||||
#define ID_TESTS_TRACING_END 32708
|
||||
#define ID_TESTS_ZOOM_IN 32709
|
||||
#define ID_TESTS_ZOOM_OUT 32710
|
||||
#define ID_TESTS_ZOOM_RESET 32711
|
||||
#define IDC_STATIC -1
|
||||
#define IDS_BINDING 1000
|
||||
#define IDS_DIALOGS 1001
|
||||
|
|
|
@ -368,7 +368,7 @@
|
|||
# gtk requires gmodule, but it does not list it as a dependency
|
||||
# in some misconfigured systems.
|
||||
# gtkglext is required by the cefclient OSR example.
|
||||
'gtk_packages': 'gmodule-2.0 gtk+-2.0 gthread-2.0 gtkglext-1.0',
|
||||
'gtk_packages': 'gmodule-2.0 gtk+-2.0 gthread-2.0 gtkglext-1.0 gtk+-unix-print-2.0',
|
||||
},
|
||||
'direct_dependent_settings': {
|
||||
'cflags': [
|
||||
|
|
Loading…
Reference in New Issue