diff options
author | Torne (Richard Coles) <torne@google.com> | 2013-12-18 16:25:09 +0000 |
---|---|---|
committer | Torne (Richard Coles) <torne@google.com> | 2013-12-18 16:25:09 +0000 |
commit | a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7 (patch) | |
tree | dafc1c6417406a7fbd422ad0bb890e96909ef564 /android_webview/browser | |
parent | d5f893c0bc79db3066bb5ae5d3d972ba1be7dd5f (diff) | |
download | chromium_org-a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7.tar.gz |
Merge from Chromium at DEPS revision 240154
This commit was generated by merge_to_master.py.
Change-Id: I8f2ba858cf0e7f413dddedc2ae91dc37f7136c2e
Diffstat (limited to 'android_webview/browser')
11 files changed, 490 insertions, 71 deletions
diff --git a/android_webview/browser/DEPS b/android_webview/browser/DEPS index 891ec4fa23..64fb2cfc74 100644 --- a/android_webview/browser/DEPS +++ b/android_webview/browser/DEPS @@ -18,6 +18,8 @@ include_rules = [ "+content/public/browser", "+content/public/test", + "+printing", + "+ui/gfx", "+ui/gl", diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc index 9cf4c6abbe..e54bd55977 100644 --- a/android_webview/browser/aw_browser_context.cc +++ b/android_webview/browser/aw_browser_context.cc @@ -7,6 +7,7 @@ #include "android_webview/browser/aw_form_database_service.h" #include "android_webview/browser/aw_pref_store.h" #include "android_webview/browser/aw_quota_manager_bridge.h" +#include "android_webview/browser/aw_resource_context.h" #include "android_webview/browser/jni_dependency_factory.h" #include "android_webview/browser/net/aw_url_request_context_getter.h" #include "android_webview/browser/net/init_native_callback.h" @@ -17,11 +18,9 @@ #include "components/user_prefs/user_prefs.h" #include "components/visitedlink/browser/visitedlink_master.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/resource_context.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "net/cookies/cookie_store.h" -#include "net/url_request/url_request_context.h" using base::FilePath; using content::BrowserThread; @@ -34,36 +33,6 @@ namespace { void HandleReadError(PersistentPrefStore::PrefReadError error) { } -class AwResourceContext : public content::ResourceContext { - public: - explicit AwResourceContext(net::URLRequestContextGetter* getter) - : getter_(getter) { - DCHECK(getter_); - } - virtual ~AwResourceContext() {} - - // content::ResourceContext implementation. - virtual net::HostResolver* GetHostResolver() OVERRIDE { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - return getter_->GetURLRequestContext()->host_resolver(); - } - virtual net::URLRequestContext* GetRequestContext() OVERRIDE { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - return getter_->GetURLRequestContext(); - } - virtual bool AllowMicAccess(const GURL& origin) OVERRIDE { - return false; - } - virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE { - return false; - } - - private: - net::URLRequestContextGetter* getter_; - - DISALLOW_COPY_AND_ASSIGN(AwResourceContext); -}; - AwBrowserContext* g_browser_context = NULL; } // namespace diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc index e71fddbcee..c590984c21 100644 --- a/android_webview/browser/aw_content_browser_client.cc +++ b/android_webview/browser/aw_content_browser_client.cc @@ -13,10 +13,13 @@ #include "android_webview/browser/jni_dependency_factory.h" #include "android_webview/browser/net_disk_cache_remover.h" #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h" +#include "android_webview/common/render_view_messages.h" #include "android_webview/common/url_constants.h" #include "base/base_paths_android.h" #include "base/path_service.h" #include "content/public/browser/access_token_store.h" +#include "content/public/browser/browser_message_filter.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" @@ -30,9 +33,79 @@ #include "ui/base/resource/resource_bundle.h" #include "webkit/common/webpreferences.h" +using content::BrowserThread; + namespace android_webview { namespace { +// TODO(sgurun) move this to its own file. +// This class filters out incoming aw_contents related IPC messages for the +// renderer process on the IPC thread. +class AwContentsMessageFilter : public content::BrowserMessageFilter { +public: + explicit AwContentsMessageFilter(int process_id); + + // BrowserMessageFilter methods. + virtual void OverrideThreadForMessage( + const IPC::Message& message, + BrowserThread::ID* thread) OVERRIDE; + virtual bool OnMessageReceived( + const IPC::Message& message, + bool* message_was_ok) OVERRIDE; + + void OnShouldOverrideUrlLoading(int routing_id, + const base::string16& url, + bool* ignore_navigation); + +private: + virtual ~AwContentsMessageFilter(); + + int process_id_; + + DISALLOW_COPY_AND_ASSIGN(AwContentsMessageFilter); +}; + +AwContentsMessageFilter::AwContentsMessageFilter(int process_id) + : process_id_(process_id) { +} + +AwContentsMessageFilter::~AwContentsMessageFilter() { +} + +void AwContentsMessageFilter::OverrideThreadForMessage( + const IPC::Message& message, BrowserThread::ID* thread) { + if (message.type() == AwViewHostMsg_ShouldOverrideUrlLoading::ID) { + *thread = BrowserThread::UI; + } +} + +bool AwContentsMessageFilter::OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP_EX(AwContentsMessageFilter, message, *message_was_ok) + IPC_MESSAGE_HANDLER(AwViewHostMsg_ShouldOverrideUrlLoading, + OnShouldOverrideUrlLoading) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void AwContentsMessageFilter::OnShouldOverrideUrlLoading( + int routing_id, + const base::string16& url, + bool* ignore_navigation) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + *ignore_navigation = false; + AwContentsClientBridgeBase* client = + AwContentsClientBridgeBase::FromID(process_id_, routing_id); + if (client) { + *ignore_navigation = client->ShouldOverrideUrlLoading(url); + } else { + LOG(WARNING) << "Failed to find the associated render view host for url: " + << url; + } +} + class AwAccessTokenStore : public content::AccessTokenStore { public: AwAccessTokenStore() { } @@ -122,6 +195,8 @@ void AwContentBrowserClient::RenderProcessHostCreated( host->GetID(), android_webview::kContentScheme); content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme( host->GetID(), chrome::kFileScheme); + + host->AddFilter(new AwContentsMessageFilter(host->GetID())); } net::URLRequestContextGetter* @@ -272,7 +347,7 @@ void AwContentBrowserClient::SelectClientCertificate( const net::HttpNetworkSession* network_session, net::SSLCertRequestInfo* cert_request_info, const base::Callback<void(net::X509Certificate*)>& callback) { - LOG(INFO) << "Client certificate request from " + LOG(WARNING) << "Client certificate request from " << cert_request_info->host_and_port << " rejected. (Client certificates not supported in WebView)"; callback.Run(NULL); diff --git a/android_webview/browser/aw_contents_client_bridge_base.h b/android_webview/browser/aw_contents_client_bridge_base.h index c9ab34d960..3166f6be31 100644 --- a/android_webview/browser/aw_contents_client_bridge_base.h +++ b/android_webview/browser/aw_contents_client_bridge_base.h @@ -51,11 +51,14 @@ class AwContentsClientBridgeBase { const string16& default_prompt_text, const content::JavaScriptDialogManager::DialogClosedCallback& callback) = 0; + virtual void RunBeforeUnloadDialog( const GURL& origin_url, const string16& message_text, const content::JavaScriptDialogManager::DialogClosedCallback& callback) = 0; + + virtual bool ShouldOverrideUrlLoading(const base::string16& url) = 0; }; } // namespace android_webview diff --git a/android_webview/browser/aw_resource_context.cc b/android_webview/browser/aw_resource_context.cc new file mode 100644 index 0000000000..dc0a1598a9 --- /dev/null +++ b/android_webview/browser/aw_resource_context.cc @@ -0,0 +1,59 @@ +// 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 "android_webview/browser/aw_resource_context.h" + +#include "content/public/browser/browser_thread.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_getter.h" + +namespace android_webview { + +AwResourceContext::AwResourceContext(net::URLRequestContextGetter* getter) + : getter_(getter) { + DCHECK(getter_); +} + +AwResourceContext::~AwResourceContext() { +} + +void AwResourceContext::SetExtraHeaders( + const GURL& url, const std::string& headers) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + if (!url.is_valid()) return; + base::AutoLock scoped_lock(extra_headers_lock_); + if (!headers.empty()) + extra_headers_[url.spec()] = headers; + else + extra_headers_.erase(url.spec()); +} + +std::string AwResourceContext::GetExtraHeaders(const GURL& url) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + if (!url.is_valid()) return std::string(); + base::AutoLock scoped_lock(extra_headers_lock_); + std::map<std::string, std::string>::iterator iter = + extra_headers_.find(url.spec()); + return iter != extra_headers_.end() ? iter->second : std::string(); +} + +net::HostResolver* AwResourceContext::GetHostResolver() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + return getter_->GetURLRequestContext()->host_resolver(); +} + +net::URLRequestContext* AwResourceContext::GetRequestContext() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + return getter_->GetURLRequestContext(); +} + +bool AwResourceContext::AllowMicAccess(const GURL& origin) { + return false; +} + +bool AwResourceContext::AllowCameraAccess(const GURL& origin) { + return false; +} + +} // namespace android_webview diff --git a/android_webview/browser/aw_resource_context.h b/android_webview/browser/aw_resource_context.h new file mode 100644 index 0000000000..fdec09358e --- /dev/null +++ b/android_webview/browser/aw_resource_context.h @@ -0,0 +1,45 @@ +// 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 ANDROID_WEBVIEW_BROWSER_AW_RESOURCE_CONTEXT_H_ +#define ANDROID_WEBVIEW_BROWSER_AW_RESOURCE_CONTEXT_H_ + +#include <map> +#include <string> + +#include "base/synchronization/lock.h" +#include "content/public/browser/resource_context.h" + +namespace net { +class URLRequestContextGetter; +} + +namespace android_webview { + +class AwResourceContext : public content::ResourceContext { + public: + explicit AwResourceContext(net::URLRequestContextGetter* getter); + virtual ~AwResourceContext(); + + void SetExtraHeaders(const GURL& url, const std::string& headers); + std::string GetExtraHeaders(const GURL& url); + + // content::ResourceContext implementation. + virtual net::HostResolver* GetHostResolver() OVERRIDE; + virtual net::URLRequestContext* GetRequestContext() OVERRIDE; + virtual bool AllowMicAccess(const GURL& origin) OVERRIDE; + virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE; + + private: + net::URLRequestContextGetter* getter_; + + base::Lock extra_headers_lock_; + std::map<std::string, std::string> extra_headers_; + + DISALLOW_COPY_AND_ASSIGN(AwResourceContext); +}; + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_BROWSER_AW_RESOURCE_CONTEXT_H_ diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc index 97c4afa999..a738672d3e 100644 --- a/android_webview/browser/net/aw_url_request_context_getter.cc +++ b/android_webview/browser/net/aw_url_request_context_getter.cc @@ -202,7 +202,7 @@ void AwURLRequestContextGetter::InitializeURLRequestContext() { net::DISK_CACHE, cache_type, partition_path_.Append(FILE_PATH_LITERAL("Cache")), - 10 * 1024 * 1024, // 10M + 20 * 1024 * 1024, // 20M BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE))); main_http_factory_.reset(main_cache); url_request_context_->set_http_transaction_factory(main_cache); diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc index 80fdad483a..5042dcdbe0 100644 --- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc +++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc @@ -8,6 +8,7 @@ #include "android_webview/browser/aw_contents_io_thread_client.h" #include "android_webview/browser/aw_login_delegate.h" +#include "android_webview/browser/aw_resource_context.h" #include "android_webview/common/url_constants.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" @@ -65,8 +66,8 @@ class IoThreadClientThrottle : public content::ResourceThrottle { // From content::ResourceThrottle virtual void WillStartRequest(bool* defer) OVERRIDE; virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE; + virtual const char* GetNameForLogging() const OVERRIDE; - bool MaybeDeferRequest(bool* defer); void OnIoThreadClientReady(int new_child_id, int new_route_id); bool MaybeBlockRequest(); bool ShouldBlockRequest(); @@ -92,7 +93,12 @@ IoThreadClientThrottle::~IoThreadClientThrottle() { RemovePendingThrottleOnIoThread(this); } +const char* IoThreadClientThrottle::GetNameForLogging() const { + return "IoThreadClientThrottle"; +} + void IoThreadClientThrottle::WillStartRequest(bool* defer) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); // TODO(sgurun): This block can be removed when crbug.com/277937 is fixed. if (route_id_ < 1) { // OPTIONS is used for preflighted requests which are generated internally. @@ -100,17 +106,6 @@ void IoThreadClientThrottle::WillStartRequest(bool* defer) { return; } DCHECK(child_id_); - if (!MaybeDeferRequest(defer)) { - MaybeBlockRequest(); - } -} - -void IoThreadClientThrottle::WillRedirectRequest(const GURL& new_url, - bool* defer) { - WillStartRequest(defer); -} - -bool IoThreadClientThrottle::MaybeDeferRequest(bool* defer) { *defer = false; // Defer all requests of a pop up that is still not associated with Java @@ -121,8 +116,14 @@ bool IoThreadClientThrottle::MaybeDeferRequest(bool* defer) { *defer = true; AwResourceDispatcherHostDelegate::AddPendingThrottle( child_id_, route_id_, this); + } else { + MaybeBlockRequest(); } - return *defer; +} + +void IoThreadClientThrottle::WillRedirectRequest(const GURL& new_url, + bool* defer) { + WillStartRequest(defer); } void IoThreadClientThrottle::OnIoThreadClientReady(int new_child_id, @@ -167,7 +168,7 @@ bool IoThreadClientThrottle::ShouldBlockRequest() { } if (io_client->ShouldBlockNetworkLoads()) { - if (request_->url().SchemeIs(chrome::kFtpScheme)) { + if (request_->url().SchemeIs(content::kFtpScheme)) { return true; } SetCacheControlFlag(request_, net::LOAD_ONLY_FROM_CACHE); @@ -211,37 +212,34 @@ void AwResourceDispatcherHostDelegate::RequestBeginning( int child_id, int route_id, ScopedVector<content::ResourceThrottle>* throttles) { - // If io_client is NULL, then the browser side objects have already been - // destroyed, so do not do anything to the request. Conversely if the - // request relates to a not-yet-created popup window, then the client will - // be non-NULL but PopupPendingAssociation() will be set. - scoped_ptr<AwContentsIoThreadClient> io_client = - AwContentsIoThreadClient::FromID(child_id, route_id); - if (!io_client) - return; + AddExtraHeadersIfNeeded(request, resource_context); + + // We always push the throttles here. Checking the existence of io_client + // is racy when a popup window is created. That is because RequestBeginning + // is called whether or not requests are blocked via BlockRequestForRoute() + // however io_client may or may not be ready at the time depending on whether + // webcontents is created. throttles->push_back(new IoThreadClientThrottle( child_id, route_id, request)); - bool allow_intercepting = - // We allow intercepting navigations within subframes, but only if the - // scheme other than http or https. This is because the embedder - // can't distinguish main frame and subframe callbacks (which could lead - // to broken content if the embedder decides to not ignore the main frame - // navigation, but ignores the subframe navigation). - // The reason this is supported at all is that certain JavaScript-based - // frameworks use iframe navigation as a form of communication with the - // embedder. - (resource_type == ResourceType::MAIN_FRAME || - (resource_type == ResourceType::SUB_FRAME && - !request->url().SchemeIs(content::kHttpScheme) && - !request->url().SchemeIs(content::kHttpsScheme))); - if (allow_intercepting) { + // We allow intercepting only navigations within main frames. This + // is used to post onPageStarted. We handle shouldOverrideUrlLoading + // via a sync IPC. + if (resource_type == ResourceType::MAIN_FRAME) throttles->push_back(InterceptNavigationDelegate::CreateThrottleFor( request)); - } } +void AwResourceDispatcherHostDelegate::OnRequestRedirected( + const GURL& redirect_url, + net::URLRequest* request, + content::ResourceContext* resource_context, + content::ResourceResponse* response) { + AddExtraHeadersIfNeeded(request, resource_context); +} + + void AwResourceDispatcherHostDelegate::DownloadStarting( net::URLRequest* request, content::ResourceContext* resource_context, @@ -407,4 +405,32 @@ void AwResourceDispatcherHostDelegate::OnIoThreadClientReadyInternal( } } +void AwResourceDispatcherHostDelegate::AddExtraHeadersIfNeeded( + net::URLRequest* request, + content::ResourceContext* resource_context) { + const content::ResourceRequestInfo* request_info = + content::ResourceRequestInfo::ForRequest(request); + if (!request_info) return; + if (request_info->GetResourceType() != ResourceType::MAIN_FRAME) return; + + const content::PageTransition transition = request_info->GetPageTransition(); + const bool is_load_url = + transition & content::PAGE_TRANSITION_FROM_API; + const bool is_go_back_forward = + transition & content::PAGE_TRANSITION_FORWARD_BACK; + const bool is_reload = content::PageTransitionCoreTypeIs( + transition, content::PAGE_TRANSITION_RELOAD); + if (is_load_url || is_go_back_forward || is_reload) { + AwResourceContext* awrc = static_cast<AwResourceContext*>(resource_context); + std::string extra_headers = awrc->GetExtraHeaders(request->url()); + if (!extra_headers.empty()) { + net::HttpRequestHeaders headers; + headers.AddHeadersFromString(extra_headers); + for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext(); ) { + request->SetExtraRequestHeaderByName(it.name(), it.value(), false); + } + } + } +} + } // namespace android_webview diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h index b5009e0235..1ae33336c7 100644 --- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h +++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h @@ -64,6 +64,12 @@ class AwResourceDispatcherHostDelegate content::ResourceResponse* response, IPC::Sender* sender) OVERRIDE; + virtual void OnRequestRedirected( + const GURL& redirect_url, + net::URLRequest* request, + content::ResourceContext* resource_context, + content::ResourceResponse* response) OVERRIDE; + void RemovePendingThrottleOnIoThread(IoThreadClientThrottle* throttle); static void OnIoThreadClientReady(int new_child_id, int new_route_id); @@ -82,6 +88,8 @@ class AwResourceDispatcherHostDelegate void AddPendingThrottleOnIoThread(int child_id, int route_id, IoThreadClientThrottle* pending_throttle); + void AddExtraHeadersIfNeeded(net::URLRequest* request, + content::ResourceContext* resource_context); typedef std::pair<int, int> ChildRouteIDPair; typedef std::map<ChildRouteIDPair, IoThreadClientThrottle*> diff --git a/android_webview/browser/renderer_host/print_manager.cc b/android_webview/browser/renderer_host/print_manager.cc new file mode 100644 index 0000000000..53c3ba4ded --- /dev/null +++ b/android_webview/browser/renderer_host/print_manager.cc @@ -0,0 +1,143 @@ +// 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 "android_webview/browser/renderer_host/print_manager.h" + +#include "android_webview/browser/aw_browser_context.h" +#include "android_webview/common/print_messages.h" +#include "android_webview/common/render_view_messages.h" +#include "base/android/scoped_java_ref.h" +#include "base/callback.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "content/public/browser/browser_thread.h" +#include "printing/print_settings.h" + +using content::BrowserThread; +using printing::PrintSettings; + +namespace android_webview { + +PrintManager::PrintManager(content::WebContents* contents, + PrintSettings* settings, + int fd, + PrintManagerDelegate* delegate) + : content::WebContentsObserver(contents), + settings_(settings), + fd_(fd), + delegate_(delegate), + number_pages_(0), + cookie_(1), + printing_(false) { + DCHECK(delegate_); +} + +PrintManager::~PrintManager() {} + +bool PrintManager::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PrintManager, message) + IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPrintedPagesCount, + OnDidGetPrintedPagesCount) + IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetDocumentCookie, + OnDidGetDocumentCookie) + IPC_MESSAGE_HANDLER(PrintHostMsg_PrintingFailed, OnPrintingFailed) + IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings, + OnGetDefaultPrintSettings) + IPC_MESSAGE_HANDLER(PrintHostMsg_AllocateTempFileForPrinting, + OnAllocateTempFileForPrinting) + IPC_MESSAGE_HANDLER(PrintHostMsg_TempFileForPrintingWritten, + OnTempFileForPrintingWritten) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + return handled ? true : WebContentsObserver::OnMessageReceived(message); +} + +void PrintManager::OnAllocateTempFileForPrinting( + base::FileDescriptor* temp_file_fd, + int* sequence_number) { + // we don't really use the sequence number. + *sequence_number = 0; + temp_file_fd->fd = fd_; + temp_file_fd->auto_close = false; +} + +void PrintManager::OnTempFileForPrintingWritten(int sequence_number) { + delegate_->DidExportPdf(true); +} + +void PrintManager::OnDidGetPrintedPagesCount(int cookie, + int number_pages) { + DCHECK_GT(cookie, 0); + DCHECK_GT(number_pages, 0); + number_pages_ = number_pages; +} + +void PrintManager::OnDidGetDocumentCookie(int cookie) { + cookie_ = cookie; +} + +void PrintManager::OnGetDefaultPrintSettings(IPC::Message* reply_msg) { + // Unlike the printing_message_filter, we do process this in ui thread + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + OnGetDefaultPrintSettingsReply(reply_msg); +} + +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->title = settings.title(); + params->url = settings.url(); +} + +void PrintManager::OnGetDefaultPrintSettingsReply(IPC::Message* reply_msg) { + PrintMsg_Print_Params params; + RenderParamsFromPrintSettings(*settings_, ¶ms); + params.document_cookie = cookie_; + PrintHostMsg_GetDefaultPrintSettings::WriteReplyParams(reply_msg, params); + Send(reply_msg); +} + +void PrintManager::OnPrintingFailed(int cookie) { + if (cookie != cookie_) { + NOTREACHED(); + return; + } + delegate_->DidExportPdf(false); +} + +bool PrintManager::PrintNow() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (printing_) + return false; + + printing_ = true; + return Send(new PrintMsg_PrintPages(routing_id())); +} + +} // namespace android_webview diff --git a/android_webview/browser/renderer_host/print_manager.h b/android_webview/browser/renderer_host/print_manager.h new file mode 100644 index 0000000000..7cee58778a --- /dev/null +++ b/android_webview/browser/renderer_host/print_manager.h @@ -0,0 +1,89 @@ +// 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 ANDROID_WEBVIEW_BROWSER_RENDER_HOST_PRINT_MANAGER_H_ +#define ANDROID_WEBVIEW_BROWSER_RENDER_HOST_PRINT_MANAGER_H_ + +#include "base/callback_forward.h" +#include "base/threading/non_thread_safe.h" +#include "content/public/browser/web_contents_observer.h" + +class GURL; + +namespace base { +struct FileDescriptor; +} + +namespace printing { +class PrintSettings; +} + +namespace android_webview { + +class PrintManagerDelegate { + public: + virtual ~PrintManagerDelegate() { } + virtual void DidExportPdf(bool success) = 0; + virtual bool IsCancelled() = 0; + + private: + // DISALLOW_COPY_AND_ASSIGN(PrintManagerDelegate); +}; + +// Provides RenderViewHost wrapper functionality for sending WebView-specific +// IPC messages to the renderer and from there to WebKit. +// +// Note for android_webview: +// This class manages the print (an export to PDF file essentially) task for +// a webview. There can be at most one active print task per webview. +class PrintManager : public content::WebContentsObserver, + public base::NonThreadSafe { + public: + // To send receive messages to a RenderView we take the WebContents instance, + // as it internally handles RenderViewHost instances changing underneath us. + PrintManager(content::WebContents* contents, + printing::PrintSettings* settings, + int fd, + PrintManagerDelegate* delegate); + virtual ~PrintManager(); + + // 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. + // + // Note for webview: Returns false immediately if this print manager is + // already busy printing. + bool PrintNow(); + + private: + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + void OnDidGetPrintedPagesCount(int cookie, int number_pages); + void OnDidGetDocumentCookie(int cookie); + void OnPrintingFailed(int cookie); + void OnGetDefaultPrintSettingsReply(IPC::Message* reply_msg); + void OnGetDefaultPrintSettings(IPC::Message* reply_msg); + void OnAllocateTempFileForPrinting(base::FileDescriptor* temp_file_fd, + int* sequence_number); + void OnTempFileForPrintingWritten(int sequence_number); + + // Print Settings. + printing::PrintSettings* settings_; + + // File descriptor to export to. + int fd_; + // Print manager delegate + PrintManagerDelegate* delegate_; + // Number of pages to print in the print job. + int number_pages_; + // The document cookie of the current PrinterQuery. + int cookie_; + // Whether a print task is pending. + int printing_; + + DISALLOW_COPY_AND_ASSIGN(PrintManager); +}; + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_BROWSER_RENDER_HOST_PRINT_MANAGER_H_ |