summaryrefslogtreecommitdiff
path: root/android_webview/browser
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2013-12-18 16:25:09 +0000
committerTorne (Richard Coles) <torne@google.com>2013-12-18 16:25:09 +0000
commita3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7 (patch)
treedafc1c6417406a7fbd422ad0bb890e96909ef564 /android_webview/browser
parentd5f893c0bc79db3066bb5ae5d3d972ba1be7dd5f (diff)
downloadchromium_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')
-rw-r--r--android_webview/browser/DEPS2
-rw-r--r--android_webview/browser/aw_browser_context.cc33
-rw-r--r--android_webview/browser/aw_content_browser_client.cc77
-rw-r--r--android_webview/browser/aw_contents_client_bridge_base.h3
-rw-r--r--android_webview/browser/aw_resource_context.cc59
-rw-r--r--android_webview/browser/aw_resource_context.h45
-rw-r--r--android_webview/browser/net/aw_url_request_context_getter.cc2
-rw-r--r--android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc100
-rw-r--r--android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h8
-rw-r--r--android_webview/browser/renderer_host/print_manager.cc143
-rw-r--r--android_webview/browser/renderer_host/print_manager.h89
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_, &params);
+ 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_