diff options
author | Torne (Richard Coles) <torne@google.com> | 2014-06-03 10:58:34 +0100 |
---|---|---|
committer | Torne (Richard Coles) <torne@google.com> | 2014-06-03 10:58:34 +0100 |
commit | cedac228d2dd51db4b79ea1e72c7f249408ee061 (patch) | |
tree | aa4ff43d7fe316e95d12721ce5e17653a768a0dd /android_webview/browser | |
parent | 6a869ecff032b5bed299d661b078b0555034598b (diff) | |
download | chromium_org-cedac228d2dd51db4b79ea1e72c7f249408ee061.tar.gz |
Merge from Chromium at DEPS revision 273901
This commit was generated by merge_to_master.py.
Change-Id: I45745444894df927ffc1045ab8de88b9e52636a3
Diffstat (limited to 'android_webview/browser')
33 files changed, 1197 insertions, 487 deletions
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc index e4a2a1d08a..c6c020c5a4 100644 --- a/android_webview/browser/aw_browser_context.cc +++ b/android_webview/browser/aw_browser_context.cc @@ -41,6 +41,9 @@ AwBrowserContext* g_browser_context = NULL; } // namespace +// Data reduction proxy is disabled by default. +bool AwBrowserContext::data_reduction_proxy_enabled_ = false; + AwBrowserContext::AwBrowserContext( const FilePath path, JniDependencyFactory* native_factory) @@ -73,6 +76,22 @@ AwBrowserContext* AwBrowserContext::FromWebContents( return static_cast<AwBrowserContext*>(web_contents->GetBrowserContext()); } +// static +void AwBrowserContext::SetDataReductionProxyEnabled(bool enabled) { + // Cache the setting value. It is possible that data reduction proxy is + // not created yet. + data_reduction_proxy_enabled_ = enabled; + AwBrowserContext* context = AwBrowserContext::GetDefault(); + // Can't enable Data reduction proxy if user pref service is not ready. + if (context == NULL || context->user_pref_service_.get() == NULL) + return; + DataReductionProxySettings* proxy_settings = + context->GetDataReductionProxySettings(); + if (proxy_settings == NULL) + return; + proxy_settings->SetDataReductionProxyEnabled(data_reduction_proxy_enabled_); +} + void AwBrowserContext::PreMainMessageLoopRun() { cookie_store_ = CreateCookieStore(this); DataReductionProxySettings::SetAllowed(true); @@ -169,9 +188,8 @@ void AwBrowserContext::CreateUserPrefServiceIfNecessary() { user_pref_service_.get(), GetRequestContext()); - //TODO(sgurun): Attach this to the API. It is currently hard coded in a - // disabled state. - data_reduction_proxy_settings_->SetDataReductionProxyEnabled(false); + data_reduction_proxy_settings_->SetDataReductionProxyEnabled( + data_reduction_proxy_enabled_); } base::FilePath AwBrowserContext::GetPath() const { @@ -219,16 +237,16 @@ void AwBrowserContext::CancelMidiSysExPermissionRequest( void AwBrowserContext::RequestProtectedMediaIdentifierPermission( int render_process_id, int render_view_id, - int bridge_id, - int group_id, - const GURL& requesting_frame, + const GURL& origin, const ProtectedMediaIdentifierPermissionCallback& callback) { NOTIMPLEMENTED(); callback.Run(false); } void AwBrowserContext::CancelProtectedMediaIdentifierPermissionRequests( - int group_id) { + int render_process_id, + int render_view_id, + const GURL& origin) { NOTIMPLEMENTED(); } @@ -268,8 +286,7 @@ AwBrowserContext::GetGeolocationPermissionContext() { return geolocation_permission_context_.get(); } -content::BrowserPluginGuestManagerDelegate* -AwBrowserContext::GetGuestManagerDelegate() { +content::BrowserPluginGuestManager* AwBrowserContext::GetGuestManager() { return NULL; } diff --git a/android_webview/browser/aw_browser_context.h b/android_webview/browser/aw_browser_context.h index 94bbf4ac2f..8b0c068af9 100644 --- a/android_webview/browser/aw_browser_context.h +++ b/android_webview/browser/aw_browser_context.h @@ -64,6 +64,8 @@ class AwBrowserContext : public content::BrowserContext, static AwBrowserContext* FromWebContents( content::WebContents* web_contents); + static void SetDataReductionProxyEnabled(bool enabled); + // Maps to BrowserMainParts::PreMainMessageLoopRun. void PreMainMessageLoopRun(); @@ -112,19 +114,18 @@ class AwBrowserContext : public content::BrowserContext, virtual void RequestProtectedMediaIdentifierPermission( int render_process_id, int render_view_id, - int bridge_id, - int group_id, - const GURL& requesting_frame, + const GURL& origin, const ProtectedMediaIdentifierPermissionCallback& callback) OVERRIDE; - virtual void CancelProtectedMediaIdentifierPermissionRequests(int group_id) - OVERRIDE; + virtual void CancelProtectedMediaIdentifierPermissionRequests( + int render_process_id, + int render_view_id, + const GURL& origin) OVERRIDE; virtual content::ResourceContext* GetResourceContext() OVERRIDE; virtual content::DownloadManagerDelegate* GetDownloadManagerDelegate() OVERRIDE; virtual content::GeolocationPermissionContext* GetGeolocationPermissionContext() OVERRIDE; - virtual content::BrowserPluginGuestManagerDelegate* - GetGuestManagerDelegate() OVERRIDE; + virtual content::BrowserPluginGuestManager* GetGuestManager() OVERRIDE; virtual quota::SpecialStoragePolicy* GetSpecialStoragePolicy() OVERRIDE; // visitedlink::VisitedLinkDelegate implementation. @@ -132,6 +133,8 @@ class AwBrowserContext : public content::BrowserContext, const scoped_refptr<URLEnumerator>& enumerator) OVERRIDE; private: + static bool data_reduction_proxy_enabled_; + // The file path where data for this context is persisted. base::FilePath context_storage_path_; diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc index 653f8c5f90..0b04715432 100644 --- a/android_webview/browser/aw_browser_main_parts.cc +++ b/android_webview/browser/aw_browser_main_parts.cc @@ -6,6 +6,7 @@ #include "android_webview/browser/aw_browser_context.h" #include "android_webview/browser/aw_result_codes.h" +#include "android_webview/common/aw_switches.h" #include "base/android/build_info.h" #include "base/android/memory_pressure_listener_android.h" #include "base/command_line.h" @@ -62,9 +63,13 @@ int AwBrowserMainParts::PreCreateThreads() { } void AwBrowserMainParts::PreMainMessageLoopRun() { - if (!gpu::gles2::MailboxSynchronizer::Initialize()) { - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kDisableAccelerated2dCanvas); + // TODO(boliu): Can't support accelerated 2d canvas and WebGL with ubercomp + // yet: crbug.com/352424. + if (!switches::UbercompEnabled() && + !gpu::gles2::MailboxSynchronizer::Initialize()) { + CommandLine* cl = CommandLine::ForCurrentProcess(); + cl->AppendSwitch(switches::kDisableAccelerated2dCanvas); + cl->AppendSwitch(switches::kDisableExperimentalWebGL); } browser_context_->PreMainMessageLoopRun(); diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc index 1ba73c75ef..62aff355d1 100644 --- a/android_webview/browser/aw_content_browser_client.cc +++ b/android_webview/browser/aw_content_browser_client.cc @@ -52,8 +52,7 @@ public: const IPC::Message& message, BrowserThread::ID* thread) OVERRIDE; virtual bool OnMessageReceived( - const IPC::Message& message, - bool* message_was_ok) OVERRIDE; + const IPC::Message& message) OVERRIDE; void OnShouldOverrideUrlLoading(int routing_id, const base::string16& url, @@ -83,14 +82,13 @@ void AwContentsMessageFilter::OverrideThreadForMessage( } } -bool AwContentsMessageFilter::OnMessageReceived(const IPC::Message& message, - bool* message_was_ok) { +bool AwContentsMessageFilter::OnMessageReceived(const IPC::Message& message) { bool handled = true; - IPC_BEGIN_MESSAGE_MAP_EX(AwContentsMessageFilter, message, *message_was_ok) - IPC_MESSAGE_HANDLER(AwViewHostMsg_ShouldOverrideUrlLoading, - OnShouldOverrideUrlLoading) - IPC_MESSAGE_HANDLER(AwViewHostMsg_SubFrameCreated, OnSubFrameCreated) - IPC_MESSAGE_UNHANDLED(handled = false) + IPC_BEGIN_MESSAGE_MAP(AwContentsMessageFilter, message) + IPC_MESSAGE_HANDLER(AwViewHostMsg_ShouldOverrideUrlLoading, + OnShouldOverrideUrlLoading) + IPC_MESSAGE_HANDLER(AwViewHostMsg_SubFrameCreated, OnSubFrameCreated) + IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } @@ -205,7 +203,7 @@ void AwContentBrowserClient::RenderProcessWillLaunch( content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme( host->GetID(), android_webview::kContentScheme); content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme( - host->GetID(), content::kFileScheme); + host->GetID(), url::kFileScheme); host->AddFilter(new AwContentsMessageFilter(host->GetID())); host->AddFilter(new cdm::CdmMessageFilterAndroid()); @@ -214,9 +212,9 @@ void AwContentBrowserClient::RenderProcessWillLaunch( net::URLRequestContextGetter* AwContentBrowserClient::CreateRequestContext( content::BrowserContext* browser_context, content::ProtocolHandlerMap* protocol_handlers, - content::ProtocolHandlerScopedVector protocol_interceptors) { + content::URLRequestInterceptorScopedVector request_interceptors) { DCHECK(browser_context_.get() == browser_context); - // TODO(mkosiba,kinuko): protocol_interceptors should be hooked up in the + // TODO(mkosiba,kinuko): request_interceptors should be hooked up in the // downstream. (crbug.com/350286) return browser_context_->CreateRequestContext(protocol_handlers); } @@ -227,8 +225,10 @@ AwContentBrowserClient::CreateRequestContextForStoragePartition( const base::FilePath& partition_path, bool in_memory, content::ProtocolHandlerMap* protocol_handlers, - content::ProtocolHandlerScopedVector protocol_interceptors) { + content::URLRequestInterceptorScopedVector request_interceptors) { DCHECK(browser_context_.get() == browser_context); + // TODO(mkosiba,kinuko): request_interceptors should be hooked up in the + // downstream. (crbug.com/350286) return browser_context_->CreateRequestContextForStoragePartition( partition_path, in_memory, protocol_handlers); } @@ -400,7 +400,6 @@ bool AwContentBrowserClient::CanCreateWindow( bool opener_suppressed, content::ResourceContext* context, int render_process_id, - bool is_guest, int opener_id, bool* no_javascript_access) { // We unconditionally allow popup windows at this stage and will give diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h index 9e4f5f3086..b313e58ebf 100644 --- a/android_webview/browser/aw_content_browser_client.h +++ b/android_webview/browser/aw_content_browser_client.h @@ -10,7 +10,6 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "content/public/browser/content_browser_client.h" -#include "net/url_request/url_request_job_factory.h" struct WebPreferences; @@ -46,13 +45,13 @@ class AwContentBrowserClient : public content::ContentBrowserClient { virtual net::URLRequestContextGetter* CreateRequestContext( content::BrowserContext* browser_context, content::ProtocolHandlerMap* protocol_handlers, - content::ProtocolHandlerScopedVector protocol_interceptors) OVERRIDE; + content::URLRequestInterceptorScopedVector request_interceptors) OVERRIDE; virtual net::URLRequestContextGetter* CreateRequestContextForStoragePartition( content::BrowserContext* browser_context, const base::FilePath& partition_path, bool in_memory, content::ProtocolHandlerMap* protocol_handlers, - content::ProtocolHandlerScopedVector protocol_interceptors) OVERRIDE; + content::URLRequestInterceptorScopedVector request_interceptors) OVERRIDE; virtual std::string GetCanonicalEncodingNameByAliasName( const std::string& alias_name) OVERRIDE; virtual void AppendExtraCommandLineSwitches(base::CommandLine* command_line, @@ -133,7 +132,6 @@ class AwContentBrowserClient : public content::ContentBrowserClient { bool opener_suppressed, content::ResourceContext* context, int render_process_id, - bool is_guest, int opener_id, bool* no_javascript_access) OVERRIDE; virtual std::string GetWorkerProcessTitle( diff --git a/android_webview/browser/aw_contents_io_thread_client.h b/android_webview/browser/aw_contents_io_thread_client.h index 8186739f1a..0ac29fcb46 100644 --- a/android_webview/browser/aw_contents_io_thread_client.h +++ b/android_webview/browser/aw_contents_io_thread_client.h @@ -84,6 +84,9 @@ class AwContentsIoThreadClient { // This method is called on the IO thread only. virtual bool ShouldBlockNetworkLoads() const = 0; + // Retrieve the AcceptThirdPartyCookies setting value of this AwContents. + virtual bool ShouldAcceptThirdPartyCookies() const = 0; + // Called when ResourceDispathcerHost detects a download request. // The download is already cancelled when this is called, since // relevant for DownloadListener is already extracted. diff --git a/android_webview/browser/aw_cookie_access_policy.cc b/android_webview/browser/aw_cookie_access_policy.cc index 06e3060530..e07db11b96 100644 --- a/android_webview/browser/aw_cookie_access_policy.cc +++ b/android_webview/browser/aw_cookie_access_policy.cc @@ -4,13 +4,17 @@ #include "android_webview/browser/aw_cookie_access_policy.h" +#include "android_webview/browser/aw_contents_io_thread_client.h" + #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/resource_request_info.h" #include "net/base/net_errors.h" using base::AutoLock; using content::BrowserThread; +using content::ResourceRequestInfo; using net::StaticCookiePolicy; namespace android_webview { @@ -23,43 +27,59 @@ AwCookieAccessPolicy::~AwCookieAccessPolicy() { } AwCookieAccessPolicy::AwCookieAccessPolicy() - : allow_access_(true), - allow_third_party_access_(true) { + : accept_cookies_(true) { } AwCookieAccessPolicy* AwCookieAccessPolicy::GetInstance() { return g_lazy_instance.Pointer(); } -bool AwCookieAccessPolicy::GetGlobalAllowAccess() { +bool AwCookieAccessPolicy::GetShouldAcceptCookies() { AutoLock lock(lock_); - return allow_access_; + return accept_cookies_; } -void AwCookieAccessPolicy::SetGlobalAllowAccess(bool allow) { +void AwCookieAccessPolicy::SetShouldAcceptCookies(bool allow) { AutoLock lock(lock_); - allow_access_ = allow; + accept_cookies_ = allow; } -bool AwCookieAccessPolicy::GetThirdPartyAllowAccess() { - AutoLock lock(lock_); - return allow_third_party_access_; +bool AwCookieAccessPolicy::GetShouldAcceptThirdPartyCookies( + int render_process_id, + int render_frame_id) { + scoped_ptr<AwContentsIoThreadClient> io_thread_client = + AwContentsIoThreadClient::FromID(render_process_id, render_frame_id); + if (!io_thread_client) { + return false; + } + return io_thread_client->ShouldAcceptThirdPartyCookies(); } -void AwCookieAccessPolicy::SetThirdPartyAllowAccess(bool allow) { - AutoLock lock(lock_); - allow_third_party_access_ = allow; +bool AwCookieAccessPolicy::GetShouldAcceptThirdPartyCookies( + const net::URLRequest& request) { + const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(&request); + if (!info) { + return false; + } + return GetShouldAcceptThirdPartyCookies(info->GetChildID(), + info->GetRenderFrameID()); } bool AwCookieAccessPolicy::OnCanGetCookies(const net::URLRequest& request, const net::CookieList& cookie_list) { - return AllowGet(request.url(), request.first_party_for_cookies()); + bool global = GetShouldAcceptCookies(); + bool thirdParty = GetShouldAcceptThirdPartyCookies(request); + return AwStaticCookiePolicy(global, thirdParty) + .AllowGet(request.url(), request.first_party_for_cookies()); } bool AwCookieAccessPolicy::OnCanSetCookie(const net::URLRequest& request, const std::string& cookie_line, net::CookieOptions* options) { - return AllowSet(request.url(), request.first_party_for_cookies()); + bool global = GetShouldAcceptCookies(); + bool thirdParty = GetShouldAcceptThirdPartyCookies(request); + return AwStaticCookiePolicy(global, thirdParty) + .AllowSet(request.url(), request.first_party_for_cookies()); } bool AwCookieAccessPolicy::AllowGetCookie(const GURL& url, @@ -68,7 +88,10 @@ bool AwCookieAccessPolicy::AllowGetCookie(const GURL& url, content::ResourceContext* context, int render_process_id, int render_frame_id) { - return AllowGet(url, first_party); + bool global = GetShouldAcceptCookies(); + bool thirdParty = + GetShouldAcceptThirdPartyCookies(render_process_id, render_frame_id); + return AwStaticCookiePolicy(global, thirdParty).AllowGet(url, first_party); } bool AwCookieAccessPolicy::AllowSetCookie(const GURL& url, @@ -78,26 +101,37 @@ bool AwCookieAccessPolicy::AllowSetCookie(const GURL& url, int render_process_id, int render_frame_id, net::CookieOptions* options) { - return AllowSet(url, first_party); + bool global = GetShouldAcceptCookies(); + bool thirdParty = + GetShouldAcceptThirdPartyCookies(render_process_id, render_frame_id); + return AwStaticCookiePolicy(global, thirdParty).AllowSet(url, first_party); +} + +AwStaticCookiePolicy::AwStaticCookiePolicy(bool accept_cookies, + bool accept_third_party_cookies) + : accept_cookies_(accept_cookies), + accept_third_party_cookies_(accept_third_party_cookies) { } -StaticCookiePolicy::Type AwCookieAccessPolicy::GetPolicy() { - if (!GetGlobalAllowAccess()) { +StaticCookiePolicy::Type AwStaticCookiePolicy::GetPolicy() const { + if (!accept_cookies()) { return StaticCookiePolicy::BLOCK_ALL_COOKIES; - } else if (!GetThirdPartyAllowAccess()) { + } else if (!accept_third_party_cookies()) { return StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES; } return StaticCookiePolicy::ALLOW_ALL_COOKIES; } -bool AwCookieAccessPolicy::AllowSet(const GURL& url, const GURL& first_party) { - return StaticCookiePolicy(GetPolicy()).CanSetCookie(url, first_party) - == net::OK; +bool AwStaticCookiePolicy::AllowSet(const GURL& url, + const GURL& first_party) const { + return StaticCookiePolicy(GetPolicy()).CanSetCookie(url, first_party) == + net::OK; } -bool AwCookieAccessPolicy::AllowGet(const GURL& url, const GURL& first_party) { - return StaticCookiePolicy(GetPolicy()).CanGetCookies(url, first_party) - == net::OK; +bool AwStaticCookiePolicy::AllowGet(const GURL& url, + const GURL& first_party) const { + return StaticCookiePolicy(GetPolicy()).CanGetCookies(url, first_party) == + net::OK; } } // namespace android_webview diff --git a/android_webview/browser/aw_cookie_access_policy.h b/android_webview/browser/aw_cookie_access_policy.h index 7fd7b59b3a..480eddd2d4 100644 --- a/android_webview/browser/aw_cookie_access_policy.h +++ b/android_webview/browser/aw_cookie_access_policy.h @@ -25,19 +25,20 @@ class GURL; namespace android_webview { // Manages the cookie access (both setting and getting) policy for WebView. +// Currently we don't distinguish between sources (i.e. network vs. JavaScript) +// or between reading vs. writing cookies. class AwCookieAccessPolicy { public: static AwCookieAccessPolicy* GetInstance(); - // These manage the global access state shared across requests regardless of - // source (i.e. network or JavaScript). - bool GetGlobalAllowAccess(); - void SetGlobalAllowAccess(bool allow); + // Can we read/write any cookies? + bool GetShouldAcceptCookies(); + void SetShouldAcceptCookies(bool allow); - // These allow more fine grained control over requests depending on whether - // the cookie is third party or not. - bool GetThirdPartyAllowAccess(); - void SetThirdPartyAllowAccess(bool allow); + // Can we read/write third party cookies? + bool GetShouldAcceptThirdPartyCookies(int render_process_id, + int render_frame_id); + bool GetShouldAcceptThirdPartyCookies(const net::URLRequest& request); // These are the functions called when operating over cookies from the // network. See NetworkDelegate for further descriptions. @@ -68,20 +69,42 @@ class AwCookieAccessPolicy { AwCookieAccessPolicy(); ~AwCookieAccessPolicy(); - bool allow_access_; - bool allow_third_party_access_; + bool accept_cookies_; base::Lock lock_; - // We have two bits of state but only three different cases: - // If !GlobalAllowAccess then reject all cookies. - // If GlobalAllowAccess and !ThirdPartyAllowAccess then reject third party. - // If GlobalAllowAccess and ThirdPartyAllowAccess then allow all cookies. - net::StaticCookiePolicy::Type GetPolicy(void); + DISALLOW_COPY_AND_ASSIGN(AwCookieAccessPolicy); +}; - bool AllowGet(const GURL& url, const GURL& first_party); - bool AllowSet(const GURL& url, const GURL& first_party); +class AwStaticCookiePolicy { + public: + AwStaticCookiePolicy(bool allow_global_access, + bool allow_third_party_access); - DISALLOW_COPY_AND_ASSIGN(AwCookieAccessPolicy); + bool accept_cookies() const { + return accept_cookies_; + } + + bool accept_third_party_cookies() const { + return accept_third_party_cookies_; + } + + bool AllowGet(const GURL& url, const GURL& first_party) const; + bool AllowSet(const GURL& url, const GURL& first_party) const; + + private: + const bool accept_cookies_; + const bool accept_third_party_cookies_; + + // We have two bits of state but only three different cases: + // If !ShouldAcceptCookies + // then reject all cookies. + // If ShouldAcceptCookies and !ShouldAcceptThirdPartyCookies + // then reject third party. + // If ShouldAcceptCookies and ShouldAcceptThirdPartyCookies + // then allow all cookies. + net::StaticCookiePolicy::Type GetPolicy() const; + + DISALLOW_COPY_AND_ASSIGN(AwStaticCookiePolicy); }; } // namespace android_webview diff --git a/android_webview/browser/aw_cookie_access_policy_unittest.cc b/android_webview/browser/aw_cookie_access_policy_unittest.cc deleted file mode 100644 index 6f8a1f1c85..0000000000 --- a/android_webview/browser/aw_cookie_access_policy_unittest.cc +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "android_webview/browser/aw_cookie_access_policy.h" - -#include "base/run_loop.h" -#include "net/base/request_priority.h" -#include "net/cookies/canonical_cookie.h" -#include "net/url_request/url_request_test_util.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace content { -class ResourceContext; -} - -namespace net { -class CookieOptions; -} - -class GURL; - -using android_webview::AwCookieAccessPolicy; -using net::CookieList; -using net::TestDelegate; -using net::TestJobInterceptor; -using net::TestNetworkDelegate; -using net::TestURLRequestContext; -using net::TestURLRequest; -using testing::Test; - -class AwCookieAccessPolicyTest : public Test { - public: - static const GURL kUrlFirstParty; - static const GURL kUrlThirdParty; - - AwCookieAccessPolicyTest() - : loop_(), - context_(), - url_request_delegate_(), - network_delegate_(), - first_party_request_() {} - - virtual void SetUp() { - context_.set_network_delegate(&network_delegate_); - first_party_request_.reset(new TestURLRequest(kUrlFirstParty, - net::DEFAULT_PRIORITY, - &url_request_delegate_, - &context_)); - first_party_request_->set_method("GET"); - - third_party_request_.reset(new TestURLRequest(kUrlThirdParty, - net::DEFAULT_PRIORITY, - &url_request_delegate_, - &context_)); - third_party_request_->set_method("GET"); - third_party_request_->set_first_party_for_cookies(kUrlFirstParty); - } - - AwCookieAccessPolicy* policy() { - return AwCookieAccessPolicy::GetInstance(); - } - - bool GetGlobalAllowAccess() { - return policy()->GetGlobalAllowAccess(); - } - - void SetGlobalAllowAccess(bool allow) { - policy()->SetGlobalAllowAccess(allow); - } - - bool GetThirdPartyAllowAccess() { - return policy()->GetThirdPartyAllowAccess(); - } - - void SetThirdPartyAllowAccess(bool allow) { - policy()->SetThirdPartyAllowAccess(allow); - } - - bool OnCanGetCookies(const net::URLRequest& request) { - return policy()->OnCanGetCookies(request, CookieList()); - } - - bool OnCanSetCookie(const net::URLRequest& request) { - return policy()->OnCanSetCookie(request, "", NULL); - } - - bool AllowGetCookie(const GURL& url, const GURL& first_party) { - return policy()->AllowGetCookie(url, first_party, CookieList(), NULL, 0, 0); - } - - bool AllowSetCookie(const GURL& url, const GURL& first_party) { - return policy()->AllowSetCookie(url, first_party, "", NULL, 0, 0, NULL); - } - - void expectFirstPartyAccess(bool expectedResult) { - EXPECT_EQ(expectedResult, AllowSetCookie(kUrlFirstParty, kUrlFirstParty)); - EXPECT_EQ(expectedResult, AllowGetCookie(kUrlFirstParty, kUrlFirstParty)); - EXPECT_EQ(expectedResult, OnCanGetCookies(*first_party_request_)); - EXPECT_EQ(expectedResult, OnCanSetCookie(*first_party_request_)); - } - - void expectThirdPartyAccess(bool expectedResult) { - EXPECT_EQ(expectedResult, AllowSetCookie(kUrlFirstParty, kUrlThirdParty)); - EXPECT_EQ(expectedResult, AllowGetCookie(kUrlFirstParty, kUrlThirdParty)); - EXPECT_EQ(expectedResult, OnCanGetCookies(*third_party_request_)); - EXPECT_EQ(expectedResult, OnCanSetCookie(*third_party_request_)); - } - - protected: - base::MessageLoopForIO loop_; - TestURLRequestContext context_; - TestDelegate url_request_delegate_; - TestNetworkDelegate network_delegate_; - scoped_ptr<TestURLRequest> first_party_request_; - scoped_ptr<TestURLRequest> third_party_request_; -}; - -const GURL AwCookieAccessPolicyTest::kUrlFirstParty = - GURL("http://first.example"); -const GURL AwCookieAccessPolicyTest::kUrlThirdParty = - GURL("http://third.example"); - -TEST_F(AwCookieAccessPolicyTest, BlockAllCookies) { - SetGlobalAllowAccess(false); - SetThirdPartyAllowAccess(false); - expectFirstPartyAccess(false); - expectThirdPartyAccess(false); -} - -TEST_F(AwCookieAccessPolicyTest, BlockAllCookiesWithThirdPartySet) { - SetGlobalAllowAccess(false); - SetThirdPartyAllowAccess(true); - expectFirstPartyAccess(false); - expectThirdPartyAccess(false); -} - -TEST_F(AwCookieAccessPolicyTest, FirstPartyCookiesOnly) { - SetGlobalAllowAccess(true); - SetThirdPartyAllowAccess(false); - expectFirstPartyAccess(true); - expectThirdPartyAccess(false); -} - -TEST_F(AwCookieAccessPolicyTest, AllowAllCookies) { - SetGlobalAllowAccess(true); - SetThirdPartyAllowAccess(true); - expectFirstPartyAccess(true); - expectThirdPartyAccess(true); -} diff --git a/android_webview/browser/aw_login_delegate.cc b/android_webview/browser/aw_login_delegate.cc index d8d894bbe1..9c8a7c15ea 100644 --- a/android_webview/browser/aw_login_delegate.cc +++ b/android_webview/browser/aw_login_delegate.cc @@ -105,7 +105,8 @@ void AwLoginDelegate::HandleHttpAuthRequestOnUIThread( // auth attempt, because it maintains internal state to cancel if there have // been too many attempts. if (!drp_auth_handler_.get()) { - drp_auth_handler_.reset(new DataReductionProxyAuthRequestHandler()); + drp_auth_handler_.reset(new DataReductionProxyAuthRequestHandler( + drp_settings)); } DCHECK(drp_auth_handler_.get()); base::string16 user, password; diff --git a/android_webview/browser/aw_request_interceptor.cc b/android_webview/browser/aw_request_interceptor.cc index e61d04b5d4..a53061b684 100644 --- a/android_webview/browser/aw_request_interceptor.cc +++ b/android_webview/browser/aw_request_interceptor.cc @@ -53,7 +53,7 @@ AwRequestInterceptor::QueryForInterceptedRequestData( return io_thread_client->ShouldInterceptRequest(location, request).Pass(); } -net::URLRequestJob* AwRequestInterceptor::MaybeCreateJob( +net::URLRequestJob* AwRequestInterceptor::MaybeInterceptRequest( net::URLRequest* request, net::NetworkDelegate* network_delegate) const { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); diff --git a/android_webview/browser/aw_request_interceptor.h b/android_webview/browser/aw_request_interceptor.h index 51a7af84e6..b83ab32e23 100644 --- a/android_webview/browser/aw_request_interceptor.h +++ b/android_webview/browser/aw_request_interceptor.h @@ -6,7 +6,7 @@ #define ANDROID_WEBVIEW_BROWSER_AW_REQUEST_INTERCEPTOR_H_ #include "base/memory/scoped_ptr.h" -#include "net/url_request/url_request_job_factory.h" +#include "net/url_request/url_request_interceptor.h" class GURL; @@ -24,13 +24,13 @@ class InterceptedRequestData; // This class allows the Java-side embedder to substitute the default // URLRequest of a given request for an alternative job that will read data // from a Java stream. -class AwRequestInterceptor : public net::URLRequestJobFactory::ProtocolHandler { +class AwRequestInterceptor : public net::URLRequestInterceptor { public: AwRequestInterceptor(); virtual ~AwRequestInterceptor(); - // net::URLRequestJobFactory::ProtocolHandler override ----------------------- - virtual net::URLRequestJob* MaybeCreateJob( + // net::URLRequestInterceptor override -------------------------------------- + virtual net::URLRequestJob* MaybeInterceptRequest( net::URLRequest* request, net::NetworkDelegate* network_delegate) const OVERRIDE; diff --git a/android_webview/browser/aw_static_cookie_policy_unittest.cc b/android_webview/browser/aw_static_cookie_policy_unittest.cc new file mode 100644 index 0000000000..edeb315806 --- /dev/null +++ b/android_webview/browser/aw_static_cookie_policy_unittest.cc @@ -0,0 +1,66 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "android_webview/browser/aw_cookie_access_policy.h" + +#include "testing/gtest/include/gtest/gtest.h" + +class GURL; + +using android_webview::AwStaticCookiePolicy; +using testing::Test; + +class AwStaticCookiePolicyTest : public Test { + public: + static const GURL kUrlFirstParty; + static const GURL kUrlThirdParty; + + AwStaticCookiePolicyTest() {} + + void expectFirstPartyAccess(const AwStaticCookiePolicy& policy, + bool expectedResult) { + EXPECT_EQ(expectedResult, policy.AllowSet(kUrlFirstParty, kUrlFirstParty)); + EXPECT_EQ(expectedResult, policy.AllowGet(kUrlFirstParty, kUrlFirstParty)); + } + + void expectThirdPartyAccess(const AwStaticCookiePolicy& policy, + bool expectedResult) { + EXPECT_EQ(expectedResult, policy.AllowSet(kUrlFirstParty, kUrlThirdParty)); + EXPECT_EQ(expectedResult, policy.AllowGet(kUrlFirstParty, kUrlThirdParty)); + } +}; + +const GURL AwStaticCookiePolicyTest::kUrlFirstParty = + GURL("http://first.example"); +const GURL AwStaticCookiePolicyTest::kUrlThirdParty = + GURL("http://third.example"); + +TEST_F(AwStaticCookiePolicyTest, BlockAllCookies) { + AwStaticCookiePolicy policy(false /* allow_cookies */, + false /* allow_third_party_cookies */); + expectFirstPartyAccess(policy, false); + expectThirdPartyAccess(policy, false); +} + +TEST_F(AwStaticCookiePolicyTest, BlockAllCookiesWithThirdPartySet) { + AwStaticCookiePolicy policy(false /* allow_cookies */, + true /* allow_third_party_cookies */); + expectFirstPartyAccess(policy, false); + expectThirdPartyAccess(policy, false); +} + +TEST_F(AwStaticCookiePolicyTest, FirstPartyCookiesOnly) { + AwStaticCookiePolicy policy(true /* allow_cookies */, + false /* allow_third_party_cookies */); + expectFirstPartyAccess(policy, true); + expectThirdPartyAccess(policy, false); +} + +TEST_F(AwStaticCookiePolicyTest, AllowAllCookies) { + AwStaticCookiePolicy policy(true /* allow_cookies */, + true /* allow_third_party_cookies */); + expectFirstPartyAccess(policy, true); + expectThirdPartyAccess(policy, true); +} + diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc index 2fc80229d6..3c1ceb42be 100644 --- a/android_webview/browser/browser_view_renderer.cc +++ b/android_webview/browser/browser_view_renderer.cc @@ -6,14 +6,17 @@ #include "android_webview/browser/browser_view_renderer_client.h" #include "android_webview/browser/shared_renderer_state.h" +#include "android_webview/common/aw_switches.h" #include "android_webview/public/browser/draw_gl.h" #include "base/android/jni_android.h" #include "base/auto_reset.h" #include "base/command_line.h" #include "base/debug/trace_event.h" +#include "base/json/json_writer.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" +#include "cc/output/compositor_frame.h" #include "content/public/browser/android/synchronous_compositor.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" @@ -73,6 +76,27 @@ class AutoResetWithLock { DISALLOW_COPY_AND_ASSIGN(AutoResetWithLock); }; +class TracedValue : public base::debug::ConvertableToTraceFormat { + public: + explicit TracedValue(base::Value* value) : value_(value) {} + static scoped_refptr<base::debug::ConvertableToTraceFormat> FromValue( + base::Value* value) { + return scoped_refptr<base::debug::ConvertableToTraceFormat>( + new TracedValue(value)); + } + virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE { + std::string tmp; + base::JSONWriter::Write(value_.get(), &tmp); + *out += tmp; + } + + private: + virtual ~TracedValue() {} + scoped_ptr<base::Value> value_; + + DISALLOW_COPY_AND_ASSIGN(TracedValue); +}; + } // namespace // static @@ -107,6 +131,7 @@ BrowserViewRenderer::BrowserViewRenderer( view_visible_(false), window_visible_(false), attached_to_window_(false), + hardware_enabled_(false), dip_scale_(0.0), page_scale_factor_(1.0), on_new_picture_enable_(false), @@ -166,8 +191,8 @@ void BrowserViewRenderer::TrimMemory(const int level, const bool visible) { SynchronousCompositorMemoryPolicy BrowserViewRenderer::CalculateDesiredMemoryPolicy() { SynchronousCompositorMemoryPolicy policy; - size_t width = draw_gl_input_.global_visible_rect.width(); - size_t height = draw_gl_input_.global_visible_rect.height(); + size_t width = last_on_draw_global_visible_rect_.width(); + size_t height = last_on_draw_global_visible_rect_.height(); policy.bytes_limit = kMemoryMultiplier * kBytesPerPixel * width * height; // Round up to a multiple of kMemoryAllocationStep. policy.bytes_limit = @@ -225,39 +250,132 @@ bool BrowserViewRenderer::OnDraw(jobject java_canvas, const gfx::Vector2d& scroll, const gfx::Rect& global_visible_rect, const gfx::Rect& clip) { - draw_gl_input_.frame_id++; - draw_gl_input_.scroll_offset = scroll; - draw_gl_input_.global_visible_rect = global_visible_rect; - draw_gl_input_.width = width_; - draw_gl_input_.height = height_; + last_on_draw_scroll_offset_ = scroll; + last_on_draw_global_visible_rect_ = global_visible_rect; + if (clear_view_) return false; + if (is_hardware_canvas && attached_to_window_) { - shared_renderer_state_->SetDrawGLInput(draw_gl_input_); - - SynchronousCompositorMemoryPolicy old_policy = - shared_renderer_state_->GetMemoryPolicy(); - SynchronousCompositorMemoryPolicy new_policy = - CalculateDesiredMemoryPolicy(); - RequestMemoryPolicy(new_policy); - // We should be performing a hardware draw here. If we don't have the - // compositor yet or if RequestDrawGL fails, it means we failed this draw - // and thus return false here to clear to background color for this draw. - bool did_draw_gl = - has_compositor_ && client_->RequestDrawGL(java_canvas, false); - if (did_draw_gl) - GlobalTileManager::GetInstance()->DidUse(tile_manager_key_); - else - RequestMemoryPolicy(old_policy); - - return did_draw_gl; + if (switches::UbercompEnabled()) { + return OnDrawHardware(java_canvas); + } else { + return OnDrawHardwareLegacy(java_canvas); + } } // Perform a software draw return DrawSWInternal(java_canvas, clip); } -void BrowserViewRenderer::DidDrawGL(const DrawGLResult& result) { - DidComposite(!result.clip_contains_visible_rect); +bool BrowserViewRenderer::OnDrawHardwareLegacy(jobject java_canvas) { + scoped_ptr<DrawGLInput> draw_gl_input(new DrawGLInput); + draw_gl_input->scroll_offset = last_on_draw_scroll_offset_; + draw_gl_input->global_visible_rect = last_on_draw_global_visible_rect_; + draw_gl_input->width = width_; + draw_gl_input->height = height_; + + SynchronousCompositorMemoryPolicy old_policy = + shared_renderer_state_->GetMemoryPolicy(); + SynchronousCompositorMemoryPolicy new_policy = CalculateDesiredMemoryPolicy(); + RequestMemoryPolicy(new_policy); + // We should be performing a hardware draw here. If we don't have the + // compositor yet or if RequestDrawGL fails, it means we failed this draw + // and thus return false here to clear to background color for this draw. + bool did_draw_gl = + has_compositor_ && client_->RequestDrawGL(java_canvas, false); + if (did_draw_gl) { + GlobalTileManager::GetInstance()->DidUse(tile_manager_key_); + shared_renderer_state_->SetDrawGLInput(draw_gl_input.Pass()); + } else { + RequestMemoryPolicy(old_policy); + } + + return did_draw_gl; +} + +void BrowserViewRenderer::DidDrawGL(scoped_ptr<DrawGLResult> result) { + DidComposite(!result->clip_contains_visible_rect); +} + +bool BrowserViewRenderer::OnDrawHardware(jobject java_canvas) { + if (!has_compositor_) + return false; + + if (!hardware_enabled_) { + hardware_enabled_ = + shared_renderer_state_->GetCompositor()->InitializeHwDraw(NULL); + if (hardware_enabled_) { + gpu::GLInProcessContext* share_context = + shared_renderer_state_->GetCompositor()->GetShareContext(); + DCHECK(share_context); + shared_renderer_state_->SetSharedContext(share_context); + } + } + if (!hardware_enabled_) + return false; + + ReturnResources(); + SynchronousCompositorMemoryPolicy new_policy = CalculateDesiredMemoryPolicy(); + RequestMemoryPolicy(new_policy); + shared_renderer_state_->GetCompositor()->SetMemoryPolicy( + shared_renderer_state_->GetMemoryPolicy()); + + scoped_ptr<DrawGLInput> draw_gl_input(new DrawGLInput); + draw_gl_input->scroll_offset = last_on_draw_scroll_offset_; + draw_gl_input->global_visible_rect = last_on_draw_global_visible_rect_; + draw_gl_input->width = width_; + draw_gl_input->height = height_; + + gfx::Transform transform; + gfx::Size surface_size(width_, height_); + gfx::Rect viewport(surface_size); + // TODO(boliu): Should really be |last_on_draw_global_visible_rect_|. + // See crbug.com/372073. + gfx::Rect clip = viewport; + bool stencil_enabled = false; + scoped_ptr<cc::CompositorFrame> frame = + shared_renderer_state_->GetCompositor()->DemandDrawHw( + surface_size, transform, viewport, clip, stencil_enabled); + if (!frame.get()) + return false; + + GlobalTileManager::GetInstance()->DidUse(tile_manager_key_); + + frame->AssignTo(&draw_gl_input->frame); + scoped_ptr<DrawGLInput> old_input = shared_renderer_state_->PassDrawGLInput(); + if (old_input.get()) { + shared_renderer_state_->ReturnResources( + old_input->frame.delegated_frame_data->resource_list); + } + shared_renderer_state_->SetDrawGLInput(draw_gl_input.Pass()); + + DidComposite(false); + bool did_request = client_->RequestDrawGL(java_canvas, false); + if (did_request) + return true; + + ReturnResources(); + return false; +} + +void BrowserViewRenderer::DidDrawDelegated(scoped_ptr<DrawGLResult> result) { + if (!ui_task_runner_->BelongsToCurrentThread()) { + // TODO(boliu): This should be a cancelable callback. + ui_task_runner_->PostTask(FROM_HERE, + base::Bind(&BrowserViewRenderer::DidDrawDelegated, + ui_thread_weak_ptr_, + base::Passed(&result))); + return; + } + ReturnResources(); +} + +void BrowserViewRenderer::ReturnResources() { + cc::CompositorFrameAck frame_ack; + shared_renderer_state_->SwapReturnedResources(&frame_ack.resources); + if (!frame_ack.resources.empty()) { + shared_renderer_state_->GetCompositor()->ReturnResources(frame_ack); + } } bool BrowserViewRenderer::DrawSWInternal(jobject java_canvas, @@ -277,7 +395,7 @@ bool BrowserViewRenderer::DrawSWInternal(jobject java_canvas, return BrowserViewRendererJavaHelper::GetInstance() ->RenderViaAuxilaryBitmapIfNeeded( java_canvas, - draw_gl_input_.scroll_offset, + last_on_draw_scroll_offset_, clip, base::Bind(&BrowserViewRenderer::CompositeSW, base::Unretained(this))); @@ -377,6 +495,20 @@ void BrowserViewRenderer::OnAttachedToWindow(int width, int height) { void BrowserViewRenderer::OnDetachedFromWindow() { TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow"); attached_to_window_ = false; + if (hardware_enabled_) { + scoped_ptr<DrawGLInput> input = shared_renderer_state_->PassDrawGLInput(); + if (input.get()) { + shared_renderer_state_->ReturnResources( + input->frame.delegated_frame_data->resource_list); + } + ReturnResources(); + DCHECK(shared_renderer_state_->ReturnedResourcesEmpty()); + + if (switches::UbercompEnabled()) + shared_renderer_state_->GetCompositor()->ReleaseHwDraw(); + shared_renderer_state_->SetSharedContext(NULL); + hardware_enabled_ = false; + } SynchronousCompositorMemoryPolicy zero_policy; RequestMemoryPolicy(zero_policy); GlobalTileManager::GetInstance()->Remove(tile_manager_key_); @@ -485,6 +617,14 @@ void BrowserViewRenderer::ScrollTo(gfx::Vector2d scroll_offset) { scroll_offset_dip_ = scroll_offset_dip; } + TRACE_EVENT_INSTANT2("android_webview", + "BrowserViewRenderer::ScrollTo", + TRACE_EVENT_SCOPE_THREAD, + "x", + scroll_offset_dip.x(), + "y", + scroll_offset_dip.y()); + if (has_compositor_) shared_renderer_state_->GetCompositor()-> DidChangeRootLayerScrollOffset(); @@ -505,35 +645,8 @@ void BrowserViewRenderer::DidUpdateContent() { client_->OnNewPicture(); } -void BrowserViewRenderer::SetMaxRootLayerScrollOffset( - gfx::Vector2dF new_value_dip) { - if (!ui_task_runner_->BelongsToCurrentThread()) { - ui_task_runner_->PostTask( - FROM_HERE, - base::Bind(&BrowserViewRenderer::SetMaxRootLayerScrollOffset, - ui_thread_weak_ptr_, - new_value_dip)); - return; - } - DCHECK_GT(dip_scale_, 0); - - max_scroll_offset_dip_ = new_value_dip; - DCHECK_LE(0, max_scroll_offset_dip_.x()); - DCHECK_LE(0, max_scroll_offset_dip_.y()); - - client_->SetMaxContainerViewScrollOffset(max_scroll_offset()); -} - void BrowserViewRenderer::SetTotalRootLayerScrollOffset( gfx::Vector2dF scroll_offset_dip) { - if (!ui_task_runner_->BelongsToCurrentThread()) { - ui_task_runner_->PostTask( - FROM_HERE, - base::Bind(&BrowserViewRenderer::SetTotalRootLayerScrollOffset, - ui_thread_weak_ptr_, - scroll_offset_dip)); - return; - } { base::AutoLock lock(render_thread_lock_); @@ -561,10 +674,8 @@ void BrowserViewRenderer::SetTotalRootLayerScrollOffset( DCHECK(0 <= scroll_offset.x()); DCHECK(0 <= scroll_offset.y()); - // Disabled because the conditions are being violated while running - // AwZoomTest.testMagnification, see http://crbug.com/340648 - // DCHECK(scroll_offset.x() <= max_offset.x()); - // DCHECK(scroll_offset.y() <= max_offset.y()); + DCHECK(scroll_offset.x() <= max_offset.x()); + DCHECK(scroll_offset.y() <= max_offset.y()); client_->ScrollContainerViewTo(scroll_offset); } @@ -583,38 +694,68 @@ bool BrowserViewRenderer::IsExternalFlingActive() const { return client_->IsFlingActive(); } -void BrowserViewRenderer::SetRootLayerPageScaleFactorAndLimits( +void BrowserViewRenderer::UpdateRootLayerState( + const gfx::Vector2dF& total_scroll_offset_dip, + const gfx::Vector2dF& max_scroll_offset_dip, + const gfx::SizeF& scrollable_size_dip, float page_scale_factor, float min_page_scale_factor, float max_page_scale_factor) { if (!ui_task_runner_->BelongsToCurrentThread()) { ui_task_runner_->PostTask( FROM_HERE, - base::Bind(&BrowserViewRenderer::SetRootLayerPageScaleFactorAndLimits, + base::Bind(&BrowserViewRenderer::UpdateRootLayerState, ui_thread_weak_ptr_, + total_scroll_offset_dip, + max_scroll_offset_dip, + scrollable_size_dip, page_scale_factor, min_page_scale_factor, max_page_scale_factor)); return; } + TRACE_EVENT_INSTANT1( + "android_webview", + "BrowserViewRenderer::UpdateRootLayerState", + TRACE_EVENT_SCOPE_THREAD, + "state", + TracedValue::FromValue( + RootLayerStateAsValue(total_scroll_offset_dip, scrollable_size_dip) + .release())); + + DCHECK_GT(dip_scale_, 0); + + max_scroll_offset_dip_ = max_scroll_offset_dip; + DCHECK_LE(0, max_scroll_offset_dip_.x()); + DCHECK_LE(0, max_scroll_offset_dip_.y()); + page_scale_factor_ = page_scale_factor; DCHECK_GT(page_scale_factor_, 0); - client_->SetPageScaleFactorAndLimits( - page_scale_factor, min_page_scale_factor, max_page_scale_factor); - client_->SetMaxContainerViewScrollOffset(max_scroll_offset()); + + client_->UpdateScrollState(max_scroll_offset(), + scrollable_size_dip, + page_scale_factor, + min_page_scale_factor, + max_page_scale_factor); + SetTotalRootLayerScrollOffset(total_scroll_offset_dip); } -void BrowserViewRenderer::SetRootLayerScrollableSize( - gfx::SizeF scrollable_size) { - if (!ui_task_runner_->BelongsToCurrentThread()) { - ui_task_runner_->PostTask( - FROM_HERE, - base::Bind(&BrowserViewRenderer::SetRootLayerScrollableSize, - ui_thread_weak_ptr_, - scrollable_size)); - return; - } - client_->SetContentsSize(scrollable_size); +scoped_ptr<base::Value> BrowserViewRenderer::RootLayerStateAsValue( + const gfx::Vector2dF& total_scroll_offset_dip, + const gfx::SizeF& scrollable_size_dip) { + scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); + + state->SetDouble("total_scroll_offset_dip.x", total_scroll_offset_dip.x()); + state->SetDouble("total_scroll_offset_dip.y", total_scroll_offset_dip.y()); + + state->SetDouble("max_scroll_offset_dip.x", max_scroll_offset_dip_.x()); + state->SetDouble("max_scroll_offset_dip.y", max_scroll_offset_dip_.y()); + + state->SetDouble("scrollable_size_dip.width", scrollable_size_dip.width()); + state->SetDouble("scrollable_size_dip.height", scrollable_size_dip.height()); + + state->SetDouble("page_scale_factor", page_scale_factor_); + return state.PassAs<base::Value>(); } void BrowserViewRenderer::DidOverscroll(gfx::Vector2dF accumulated_overscroll, @@ -664,7 +805,10 @@ void BrowserViewRenderer::EnsureContinuousInvalidation(bool force_invalidate) { if (throttle_fallback_tick) return; - block_invalidates_ = compositor_needs_continuous_invalidate_; + { + base::AutoLock lock(render_thread_lock_); + block_invalidates_ = compositor_needs_continuous_invalidate_; + } // Unretained here is safe because the callback is cancelled when // |fallback_tick_| is destroyed. @@ -713,8 +857,21 @@ bool BrowserViewRenderer::CompositeSW(SkCanvas* canvas) { } void BrowserViewRenderer::DidComposite(bool force_invalidate) { + { + base::AutoLock lock(render_thread_lock_); + block_invalidates_ = false; + } + + if (!ui_task_runner_->BelongsToCurrentThread()) { + ui_task_runner_->PostTask( + FROM_HERE, + base::Bind(&BrowserViewRenderer::EnsureContinuousInvalidation, + ui_thread_weak_ptr_, + force_invalidate)); + return; + } + fallback_tick_.Cancel(); - block_invalidates_ = false; EnsureContinuousInvalidation(force_invalidate); } @@ -733,7 +890,7 @@ std::string BrowserViewRenderer::ToString(AwDrawGLInfo* draw_info) const { base::StringAppendF(&str, "attached_to_window: %d ", attached_to_window_); base::StringAppendF(&str, "global visible rect: %s ", - draw_gl_input_.global_visible_rect.ToString().c_str()); + last_on_draw_global_visible_rect_.ToString().c_str()); base::StringAppendF( &str, "scroll_offset_dip: %s ", scroll_offset_dip_.ToString().c_str()); base::StringAppendF(&str, diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h index 991075f3ac..7195ad3adb 100644 --- a/android_webview/browser/browser_view_renderer.h +++ b/android_webview/browser/browser_view_renderer.h @@ -11,6 +11,7 @@ #include "base/android/scoped_java_ref.h" #include "base/callback.h" #include "base/cancelable_callback.h" +#include "base/values.h" #include "content/public/browser/android/synchronous_compositor_client.h" #include "skia/ext/refptr.h" #include "ui/gfx/rect.h" @@ -80,7 +81,8 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient, const gfx::Vector2d& scroll, const gfx::Rect& global_visible_rect, const gfx::Rect& clip); - void DidDrawGL(const DrawGLResult& result); + void DidDrawGL(scoped_ptr<DrawGLResult> result); + void DidDrawDelegated(scoped_ptr<DrawGLResult> result); // CapturePicture API methods. skia::RefPtr<SkPicture> CapturePicture(int width, int height); @@ -120,17 +122,16 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient, virtual void DidDestroyCompositor(content::SynchronousCompositor* compositor) OVERRIDE; virtual void SetContinuousInvalidate(bool invalidate) OVERRIDE; - virtual void SetMaxRootLayerScrollOffset(gfx::Vector2dF new_value) OVERRIDE; - virtual void SetTotalRootLayerScrollOffset(gfx::Vector2dF new_value_css) - OVERRIDE; virtual void DidUpdateContent() OVERRIDE; virtual gfx::Vector2dF GetTotalRootLayerScrollOffset() OVERRIDE; + virtual void UpdateRootLayerState( + const gfx::Vector2dF& total_scroll_offset_dip, + const gfx::Vector2dF& max_scroll_offset_dip, + const gfx::SizeF& scrollable_size_dip, + float page_scale_factor, + float min_page_scale_factor, + float max_page_scale_factor) OVERRIDE; virtual bool IsExternalFlingActive() const OVERRIDE; - virtual void SetRootLayerPageScaleFactorAndLimits(float page_scale_factor, - float min_page_scale_factor, - float max_page_scale_factor) - OVERRIDE; - virtual void SetRootLayerScrollableSize(gfx::SizeF scrollable_size) OVERRIDE; virtual void DidOverscroll(gfx::Vector2dF accumulated_overscroll, gfx::Vector2dF latest_overscroll_delta, gfx::Vector2dF current_fling_velocity) OVERRIDE; @@ -141,6 +142,7 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient, bool effective_immediately) OVERRIDE; private: + void SetTotalRootLayerScrollOffset(gfx::Vector2dF new_value_dip); // Checks the continuous invalidate and block invalidate state, and schedule // invalidates appropriately. If |force_invalidate| is true, then send a view // invalidate regardless of compositor expectation. @@ -148,6 +150,13 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient, bool DrawSWInternal(jobject java_canvas, const gfx::Rect& clip_bounds); bool CompositeSW(SkCanvas* canvas); void DidComposite(bool force_invalidate); + scoped_ptr<base::Value> RootLayerStateAsValue( + const gfx::Vector2dF& total_scroll_offset_dip, + const gfx::SizeF& scrollable_size_dip); + + bool OnDrawHardwareLegacy(jobject java_canvas); + bool OnDrawHardware(jobject java_canvas); + void ReturnResources(); // If we call up view invalidate and OnDraw is not called before a deadline, // then we keep ticking the SynchronousCompositor so it can make progress. @@ -185,11 +194,15 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient, bool view_visible_; bool window_visible_; // Only applicable if |attached_to_window_| is true. bool attached_to_window_; + bool hardware_enabled_; float dip_scale_; float page_scale_factor_; bool on_new_picture_enable_; bool clear_view_; + gfx::Vector2d last_on_draw_scroll_offset_; + gfx::Rect last_on_draw_global_visible_rect_; + // When true, we should continuously invalidate and keep drawing, for example // to drive animation. This value is set by the compositor and should always // reflect the expectation of the compositor and not be reused for other @@ -205,8 +218,6 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient, int width_; int height_; - DrawGLInput draw_gl_input_; - // Current scroll offset in CSS pixels. gfx::Vector2dF scroll_offset_dip_; diff --git a/android_webview/browser/browser_view_renderer_client.h b/android_webview/browser/browser_view_renderer_client.h index fce1c80332..41fbf5a4b3 100644 --- a/android_webview/browser/browser_view_renderer_client.h +++ b/android_webview/browser/browser_view_renderer_client.h @@ -34,20 +34,19 @@ class BrowserViewRendererClient { // Try to set the view's scroll offset to |new_value|. virtual void ScrollContainerViewTo(gfx::Vector2d new_value) = 0; - // Set the view's scroll offset cap to |new_value|. - virtual void SetMaxContainerViewScrollOffset(gfx::Vector2d new_value) = 0; - // Is a Android view system managed fling in progress? virtual bool IsFlingActive() const = 0; - // Set the current page scale to |page_scale_factor| and page scale limits + // Sets the following: + // view's scroll offset cap to |max_scroll_offset|, + // current contents_size to |contents_size_dip|, + // the current page scale to |page_scale_factor| and page scale limits // to |min_page_scale_factor|..|max_page_scale_factor|. - virtual void SetPageScaleFactorAndLimits(float page_scale_factor, - float min_page_scale_factor, - float max_page_scale_factor) = 0; - - // Set the current contents_size to |contents_size_dip|. - virtual void SetContentsSize(gfx::SizeF contents_size_dip) = 0; + virtual void UpdateScrollState(gfx::Vector2d max_scroll_offset, + gfx::SizeF contents_size_dip, + float page_scale_factor, + float min_page_scale_factor, + float max_page_scale_factor) = 0; // Handle overscroll. virtual void DidOverscroll(gfx::Vector2d overscroll_delta) = 0; diff --git a/android_webview/browser/deferred_gpu_command_service.cc b/android_webview/browser/deferred_gpu_command_service.cc index 601334ae7f..cb31954c18 100644 --- a/android_webview/browser/deferred_gpu_command_service.cc +++ b/android_webview/browser/deferred_gpu_command_service.cc @@ -6,12 +6,43 @@ #include "android_webview/browser/gl_view_renderer_manager.h" #include "android_webview/browser/shared_renderer_state.h" +#include "base/synchronization/lock.h" #include "content/public/browser/android/synchronous_compositor.h" #include "gpu/command_buffer/service/shader_translator_cache.h" namespace android_webview { namespace { + +// TODO(boliu): Consider using base/atomicops.h. +class ThreadSafeBool { + public: + ThreadSafeBool(); + void Set(bool boolean); + bool Get(); + + private: + base::Lock lock_; + bool boolean_; + DISALLOW_COPY_AND_ASSIGN(ThreadSafeBool); +}; + +ThreadSafeBool::ThreadSafeBool() : boolean_(false) { +} + +void ThreadSafeBool::Set(bool boolean) { + base::AutoLock lock(lock_); + boolean_ = boolean; +} + +bool ThreadSafeBool::Get() { + base::AutoLock lock(lock_); + return boolean_; +} + +base::LazyInstance<ThreadSafeBool> g_request_pending = + LAZY_INSTANCE_INITIALIZER; + base::LazyInstance<scoped_refptr<DeferredGpuCommandService> > g_service = LAZY_INSTANCE_INITIALIZER; } // namespace @@ -31,16 +62,31 @@ ScopedAllowGL::ScopedAllowGL() { g_service.Get()->RunTasks(); } -ScopedAllowGL::~ScopedAllowGL() { allow_gl.Get().Set(false); } +ScopedAllowGL::~ScopedAllowGL() { + allow_gl.Get().Set(false); + g_request_pending.Get().Set(false); + + if (g_service.Get()) + g_service.Get()->RunTasks(); +} // static void DeferredGpuCommandService::SetInstance() { if (!g_service.Get()) { g_service.Get() = new DeferredGpuCommandService; content::SynchronousCompositor::SetGpuService(g_service.Get()); + + // Initialize global booleans. + g_request_pending.Get().Set(false); } } +// static +DeferredGpuCommandService* DeferredGpuCommandService::GetInstance() { + DCHECK(g_service.Get().get()); + return g_service.Get().get(); +} + DeferredGpuCommandService::DeferredGpuCommandService() {} DeferredGpuCommandService::~DeferredGpuCommandService() { @@ -48,15 +94,20 @@ DeferredGpuCommandService::~DeferredGpuCommandService() { DCHECK(tasks_.empty()); } +// This method can be called on any thread. // static -void DeferredGpuCommandService::RequestProcessGLOnUIThread() { +void DeferredGpuCommandService::RequestProcessGL() { SharedRendererState* renderer_state = GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn(); if (!renderer_state) { LOG(ERROR) << "No hardware renderer. Deadlock likely"; return; } - renderer_state->ClientRequestDrawGL(); + + if (!g_request_pending.Get().Get()) { + g_request_pending.Get().Set(true); + renderer_state->ClientRequestDrawGL(); + } } // Called from different threads! @@ -68,7 +119,7 @@ void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) { if (ScopedAllowGL::IsAllowed()) { RunTasks(); } else { - RequestProcessGLOnUIThread(); + RequestProcessGL(); } } diff --git a/android_webview/browser/deferred_gpu_command_service.h b/android_webview/browser/deferred_gpu_command_service.h index bbfe9475da..696854db99 100644 --- a/android_webview/browser/deferred_gpu_command_service.h +++ b/android_webview/browser/deferred_gpu_command_service.h @@ -27,12 +27,12 @@ class ScopedAllowGL { DISALLOW_COPY_AND_ASSIGN(ScopedAllowGL); }; -// TODO(boliu): Teach this class about RT. class DeferredGpuCommandService : public gpu::InProcessCommandBuffer::Service, public base::RefCountedThreadSafe<DeferredGpuCommandService> { public: static void SetInstance(); + static DeferredGpuCommandService* GetInstance(); virtual void ScheduleTask(const base::Closure& task) OVERRIDE; virtual void ScheduleIdleWork(const base::Closure& task) OVERRIDE; @@ -50,7 +50,7 @@ class DeferredGpuCommandService friend class base::RefCountedThreadSafe<DeferredGpuCommandService>; private: - static void RequestProcessGLOnUIThread(); + static void RequestProcessGL(); DeferredGpuCommandService(); diff --git a/android_webview/browser/gl_view_renderer_manager.cc b/android_webview/browser/gl_view_renderer_manager.cc index b9d1a83fe1..204239c8af 100644 --- a/android_webview/browser/gl_view_renderer_manager.cc +++ b/android_webview/browser/gl_view_renderer_manager.cc @@ -25,6 +25,11 @@ GLViewRendererManager::GLViewRendererManager() {} GLViewRendererManager::~GLViewRendererManager() {} +GLViewRendererManager::Key GLViewRendererManager::NullKey() { + AutoLock auto_lock(lock_); + return mru_list_.end(); +} + GLViewRendererManager::Key GLViewRendererManager::PushBack(RendererType view) { AutoLock auto_lock(lock_); DCHECK(mru_list_.end() == diff --git a/android_webview/browser/gl_view_renderer_manager.h b/android_webview/browser/gl_view_renderer_manager.h index 5d6cb8da4f..f34d9cb261 100644 --- a/android_webview/browser/gl_view_renderer_manager.h +++ b/android_webview/browser/gl_view_renderer_manager.h @@ -28,9 +28,7 @@ class GLViewRendererManager { static GLViewRendererManager* GetInstance(); - Key NullKey() { - return mru_list_.end(); - } + Key NullKey(); Key PushBack(RendererType view); diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc index f2cf8e90b1..d1d2253101 100644 --- a/android_webview/browser/hardware_renderer.cc +++ b/android_webview/browser/hardware_renderer.cc @@ -5,35 +5,125 @@ #include "android_webview/browser/hardware_renderer.h" #include "android_webview/browser/aw_gl_surface.h" -#include "android_webview/browser/browser_view_renderer_client.h" +#include "android_webview/browser/deferred_gpu_command_service.h" +#include "android_webview/browser/parent_output_surface.h" +#include "android_webview/browser/shared_renderer_state.h" #include "android_webview/public/browser/draw_gl.h" +#include "base/auto_reset.h" #include "base/debug/trace_event.h" #include "base/strings/string_number_conversions.h" -#include "content/public/browser/android/synchronous_compositor.h" -#include "content/public/browser/browser_thread.h" -#include "gpu/command_buffer/service/shader_translator_cache.h" +#include "cc/layers/delegated_frame_provider.h" +#include "cc/layers/delegated_renderer_layer.h" +#include "cc/layers/layer.h" +#include "cc/output/compositor_frame.h" +#include "cc/output/output_surface.h" +#include "cc/trees/layer_tree_host.h" +#include "cc/trees/layer_tree_settings.h" +#include "gpu/command_buffer/client/gl_in_process_context.h" +#include "ui/gfx/frame_time.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/transform.h" #include "ui/gl/gl_bindings.h" +#include "webkit/common/gpu/context_provider_in_process.h" +#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" namespace android_webview { +namespace { + +using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl; + +scoped_refptr<cc::ContextProvider> CreateContext( + scoped_refptr<gfx::GLSurface> surface, + scoped_refptr<gpu::InProcessCommandBuffer::Service> service, + gpu::GLInProcessContext* share_context) { + const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; + + blink::WebGraphicsContext3D::Attributes attributes; + attributes.antialias = false; + attributes.depth = false; + attributes.stencil = false; + attributes.shareResources = true; + attributes.noAutomaticFlushes = true; + gpu::GLInProcessContextAttribs in_process_attribs; + WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes( + attributes, &in_process_attribs); + in_process_attribs.lose_context_when_out_of_memory = 1; + + scoped_ptr<gpu::GLInProcessContext> context( + gpu::GLInProcessContext::Create(service, + surface, + surface->IsOffscreen(), + gfx::kNullAcceleratedWidget, + surface->GetSize(), + share_context, + false /* share_resources */, + in_process_attribs, + gpu_preference)); + DCHECK(context.get()); + + return webkit::gpu::ContextProviderInProcess::Create( + WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext( + context.Pass(), attributes), + "Parent-Compositor"); +} + +} // namespace + HardwareRenderer::HardwareRenderer(SharedRendererState* state) : shared_renderer_state_(state), - last_egl_context_(eglGetCurrentContext()) { + last_egl_context_(eglGetCurrentContext()), + view_width_(-1), + view_height_(-1), + viewport_clip_valid_for_dcheck_(false), + root_layer_(cc::Layer::Create()), + output_surface_(NULL) { DCHECK(last_egl_context_); gl_surface_ = new AwGLSurface; - bool success = - shared_renderer_state_->GetCompositor()-> - InitializeHwDraw(gl_surface_); - DCHECK(success); + + cc::LayerTreeSettings settings; + + // Should be kept in sync with compositor_impl_android.cc. + settings.allow_antialiasing = false; + settings.highp_threshold_min = 2048; + + // Webview does not own the surface so should not clear it. + settings.should_clear_root_render_pass = false; + + layer_tree_host_ = + cc::LayerTreeHost::CreateSingleThreaded(this, this, NULL, settings); + layer_tree_host_->SetRootLayer(root_layer_); + layer_tree_host_->SetLayerTreeHostClientReady(); } HardwareRenderer::~HardwareRenderer() { - shared_renderer_state_->GetCompositor()->ReleaseHwDraw(); - gl_surface_ = NULL; + // Must reset everything before |resource_collection_| to ensure all + // resources are returned before resetting |resource_collection_| client. + layer_tree_host_.reset(); + root_layer_ = NULL; + delegated_layer_ = NULL; + frame_provider_ = NULL; + if (resource_collection_.get()) { +#if DCHECK_IS_ON + // Check collection is empty. + cc::ReturnedResourceArray returned_resources; + resource_collection_->TakeUnusedResourcesForChildCompositor( + &returned_resources); + DCHECK_EQ(0u, returned_resources.size()); +#endif // DCHECK_IS_ON + + resource_collection_->SetClient(NULL); + } +} + +void HardwareRenderer::DidBeginMainFrame() { + // This is called after OutputSurface is created, but before the impl frame + // starts. We set the draw constraints here. + DCHECK(output_surface_); + DCHECK(viewport_clip_valid_for_dcheck_); + output_surface_->SetDrawConstraints(viewport_, clip_); } bool HardwareRenderer::DrawGL(bool stencil_enabled, @@ -54,54 +144,84 @@ bool HardwareRenderer::DrawGL(bool stencil_enabled, if (last_egl_context_ != current_context) DLOG(WARNING) << "EGLContextChanged"; - if (draw_info->mode != AwDrawGLInfo::kModeDraw) - return false; + scoped_ptr<DrawGLInput> input = shared_renderer_state_->PassDrawGLInput(); + if (!resource_collection_.get()) { + resource_collection_ = new cc::DelegatedFrameResourceCollection; + resource_collection_->SetClient(this); + } - // Should only need to access SharedRendererState in kModeDraw and kModeSync. - const DrawGLInput input = shared_renderer_state_->GetDrawGLInput(); - SetCompositorMemoryPolicy(); + if (input.get()) { + DCHECK(!input->frame.gl_frame_data); + DCHECK(!input->frame.software_frame_data); + + bool size_changed = + input->width != view_width_ || input->height != view_height_; + view_width_ = input->width; + view_height_ = input->height; + scroll_offset_ = input->scroll_offset; + + if (!frame_provider_ || size_changed) { + if (delegated_layer_) { + delegated_layer_->RemoveFromParent(); + } + + frame_provider_ = new cc::DelegatedFrameProvider( + resource_collection_.get(), input->frame.delegated_frame_data.Pass()); + + delegated_layer_ = cc::DelegatedRendererLayer::Create(frame_provider_); + delegated_layer_->SetBounds(gfx::Size(view_width_, view_height_)); + delegated_layer_->SetIsDrawable(true); + delegated_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f)); + + root_layer_->AddChild(delegated_layer_); + } else { + frame_provider_->SetFrameData(input->frame.delegated_frame_data.Pass()); + } + } - gl_surface_->SetBackingFrameBufferObject(framebuffer_binding_ext); + viewport_.SetSize(draw_info->width, draw_info->height); + layer_tree_host_->SetViewportSize(viewport_); + clip_.SetRect(draw_info->clip_left, + draw_info->clip_top, + draw_info->clip_right - draw_info->clip_left, + draw_info->clip_bottom - draw_info->clip_top); - gfx::Transform transform; + gfx::Transform transform(gfx::Transform::kSkipInitialization); transform.matrix().setColMajorf(draw_info->transform); - transform.Translate(input.scroll_offset.x(), input.scroll_offset.y()); - gfx::Rect clip_rect(draw_info->clip_left, - draw_info->clip_top, - draw_info->clip_right - draw_info->clip_left, - draw_info->clip_bottom - draw_info->clip_top); - - gfx::Rect viewport(draw_info->width, draw_info->height); - if (!draw_info->is_layer) { - gfx::RectF view_rect(input.width, input.height); - transform.TransformRect(&view_rect); - viewport.Intersect(gfx::ToEnclosingRect(view_rect)); - } + transform.Translate(scroll_offset_.x(), scroll_offset_.y()); + delegated_layer_->SetTransform(transform); - bool did_draw = shared_renderer_state_->GetCompositor()->DemandDrawHw( - gfx::Size(draw_info->width, draw_info->height), - transform, - viewport, - clip_rect, - stencil_enabled); + gl_surface_->SetBackingFrameBufferObject(framebuffer_binding_ext); + { + base::AutoReset<bool> frame_resetter(&viewport_clip_valid_for_dcheck_, + true); + layer_tree_host_->SetNeedsRedrawRect(clip_); + layer_tree_host_->Composite(gfx::FrameTime::Now()); + } gl_surface_->ResetBackingFrameBufferObject(); - if (did_draw) { - result->frame_id = input.frame_id; - result->clip_contains_visible_rect = - clip_rect.Contains(input.global_visible_rect); - } - return did_draw; + return true; } -void HardwareRenderer::SetCompositorMemoryPolicy() { - if (shared_renderer_state_->IsMemoryPolicyDirty()) { - content::SynchronousCompositorMemoryPolicy policy = - shared_renderer_state_->GetMemoryPolicy(); - // Memory policy is set by BrowserViewRenderer on UI thread. - shared_renderer_state_->GetCompositor()->SetMemoryPolicy(policy); - shared_renderer_state_->SetMemoryPolicyDirty(false); - } +scoped_ptr<cc::OutputSurface> HardwareRenderer::CreateOutputSurface( + bool fallback) { + // Android webview does not support losing output surface. + DCHECK(!fallback); + scoped_refptr<cc::ContextProvider> context_provider = + CreateContext(gl_surface_, + DeferredGpuCommandService::GetInstance(), + shared_renderer_state_->GetSharedContext()); + scoped_ptr<ParentOutputSurface> output_surface_holder( + new ParentOutputSurface(context_provider)); + output_surface_ = output_surface_holder.get(); + return output_surface_holder.PassAs<cc::OutputSurface>(); +} + +void HardwareRenderer::UnusedResourcesAreAvailable() { + cc::ReturnedResourceArray returned_resources; + resource_collection_->TakeUnusedResourcesForChildCompositor( + &returned_resources); + shared_renderer_state_->InsertReturnedResources(returned_resources); } } // namespace android_webview diff --git a/android_webview/browser/hardware_renderer.h b/android_webview/browser/hardware_renderer.h index 169bbd3a5c..8adbf0e9e3 100644 --- a/android_webview/browser/hardware_renderer.h +++ b/android_webview/browser/hardware_renderer.h @@ -5,46 +5,93 @@ #ifndef ANDROID_WEBVIEW_BROWSER_HARDWARE_RENDERER_H_ #define ANDROID_WEBVIEW_BROWSER_HARDWARE_RENDERER_H_ -#include <queue> - +#include "android_webview/browser/hardware_renderer_interface.h" #include "android_webview/browser/shared_renderer_state.h" -#include "base/lazy_instance.h" -#include "base/memory/ref_counted.h" -#include "base/threading/thread_local.h" +#include "base/memory/scoped_ptr.h" +#include "cc/layers/delegated_frame_resource_collection.h" +#include "cc/trees/layer_tree_host_client.h" +#include "cc/trees/layer_tree_host_single_thread_client.h" struct AwDrawGLInfo; +namespace cc { +class DelegatedFrameProvider; +class DelegatedRendererLayer; +class Layer; +class LayerTreeHost; +} + namespace android_webview { class AwGLSurface; -class BrowserViewRendererClient; - -namespace internal { -class DeferredGpuCommandService; -} // namespace internal +class ParentOutputSurface; -class HardwareRenderer { +class HardwareRenderer : public HardwareRendererInterface, + public cc::LayerTreeHostClient, + public cc::LayerTreeHostSingleThreadClient, + public cc::DelegatedFrameResourceCollectionClient { public: explicit HardwareRenderer(SharedRendererState* state); - ~HardwareRenderer(); - - bool DrawGL(bool stencil_enabled, - int framebuffer_binding_ext, - AwDrawGLInfo* draw_info, - DrawGLResult* result); + virtual ~HardwareRenderer(); + + // HardwareRendererInterface overrides. + virtual bool DrawGL(bool stencil_enabled, + int framebuffer_binding_ext, + AwDrawGLInfo* draw_info, + DrawGLResult* result) OVERRIDE; + + // cc::LayerTreeHostClient overrides. + virtual void WillBeginMainFrame(int frame_id) OVERRIDE {} + virtual void DidBeginMainFrame() OVERRIDE; + virtual void Animate(base::TimeTicks frame_begin_time) OVERRIDE {} + virtual void Layout() OVERRIDE {} + virtual void ApplyScrollAndScale(const gfx::Vector2d& scroll_delta, + float page_scale) OVERRIDE {} + virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface( + bool fallback) OVERRIDE; + virtual void DidInitializeOutputSurface() OVERRIDE {} + virtual void WillCommit() OVERRIDE {} + virtual void DidCommit() OVERRIDE {} + virtual void DidCommitAndDrawFrame() OVERRIDE {} + virtual void DidCompleteSwapBuffers() OVERRIDE {} + + // cc::LayerTreeHostSingleThreadClient overrides. + virtual void ScheduleComposite() OVERRIDE {} + virtual void ScheduleAnimation() OVERRIDE {} + virtual void DidPostSwapBuffers() OVERRIDE {} + virtual void DidAbortSwapBuffers() OVERRIDE {} + + // cc::DelegatedFrameResourceCollectionClient overrides. + virtual void UnusedResourcesAreAvailable() OVERRIDE; private: - friend class internal::DeferredGpuCommandService; - - void SetCompositorMemoryPolicy(); - SharedRendererState* shared_renderer_state_; typedef void* EGLContext; EGLContext last_egl_context_; + // Information about last delegated frame. + int view_width_; + int view_height_; + gfx::Vector2d scroll_offset_; + + // Information from draw. + gfx::Size viewport_; + gfx::Rect clip_; + bool viewport_clip_valid_for_dcheck_; + scoped_refptr<AwGLSurface> gl_surface_; + scoped_ptr<cc::LayerTreeHost> layer_tree_host_; + scoped_refptr<cc::Layer> root_layer_; + + scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection_; + scoped_refptr<cc::DelegatedFrameProvider> frame_provider_; + scoped_refptr<cc::DelegatedRendererLayer> delegated_layer_; + + // This is owned indirectly by |layer_tree_host_|. + ParentOutputSurface* output_surface_; + DISALLOW_COPY_AND_ASSIGN(HardwareRenderer); }; diff --git a/android_webview/browser/hardware_renderer_interface.h b/android_webview/browser/hardware_renderer_interface.h new file mode 100644 index 0000000000..c827243a1f --- /dev/null +++ b/android_webview/browser/hardware_renderer_interface.h @@ -0,0 +1,26 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ANDROID_WEBVIEW_BROWSER_HARDWARE_RENDERER_INTERFACE_H_ +#define ANDROID_WEBVIEW_BROWSER_HARDWARE_RENDERER_INTERFACE_H_ + +struct AwDrawGLInfo; + +namespace android_webview { + +struct DrawGLResult; + +class HardwareRendererInterface { + public: + virtual ~HardwareRendererInterface() {} + + virtual bool DrawGL(bool stencil_enabled, + int framebuffer_binding_ext, + AwDrawGLInfo* draw_info, + DrawGLResult* result) = 0; +}; + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_BROWSER_HARDWARE_RENDERER_INTERFACE_H_ diff --git a/android_webview/browser/hardware_renderer_legacy.cc b/android_webview/browser/hardware_renderer_legacy.cc new file mode 100644 index 0000000000..ade6be94fa --- /dev/null +++ b/android_webview/browser/hardware_renderer_legacy.cc @@ -0,0 +1,106 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "android_webview/browser/hardware_renderer_legacy.h" + +#include "android_webview/browser/aw_gl_surface.h" +#include "android_webview/browser/shared_renderer_state.h" +#include "android_webview/public/browser/draw_gl.h" +#include "base/debug/trace_event.h" +#include "base/strings/string_number_conversions.h" +#include "cc/output/compositor_frame.h" +#include "content/public/browser/android/synchronous_compositor.h" +#include "content/public/browser/browser_thread.h" +#include "ui/gfx/geometry/rect_conversions.h" +#include "ui/gfx/geometry/rect_f.h" +#include "ui/gfx/transform.h" +#include "ui/gl/gl_bindings.h" + +namespace android_webview { + +HardwareRendererLegacy::HardwareRendererLegacy(SharedRendererState* state) + : shared_renderer_state_(state), last_egl_context_(eglGetCurrentContext()) { + DCHECK(last_egl_context_); + + gl_surface_ = new AwGLSurface; + bool success = + shared_renderer_state_->GetCompositor()->InitializeHwDraw(gl_surface_); + DCHECK(success); +} + +HardwareRendererLegacy::~HardwareRendererLegacy() { + draw_gl_input_ = shared_renderer_state_->PassDrawGLInput(); + shared_renderer_state_->GetCompositor()->ReleaseHwDraw(); + gl_surface_ = NULL; +} + +bool HardwareRendererLegacy::DrawGL(bool stencil_enabled, + int framebuffer_binding_ext, + AwDrawGLInfo* draw_info, + DrawGLResult* result) { + TRACE_EVENT0("android_webview", "HardwareRendererLegacy::DrawGL"); + + // We need to watch if the current Android context has changed and enforce + // a clean-up in the compositor. + EGLContext current_context = eglGetCurrentContext(); + if (!current_context) { + DLOG(ERROR) << "DrawGL called without EGLContext"; + return false; + } + + // TODO(boliu): Handle context loss. + if (last_egl_context_ != current_context) + DLOG(WARNING) << "EGLContextChanged"; + + // Should only need to access SharedRendererState in kModeDraw and kModeSync. + scoped_ptr<DrawGLInput> input = shared_renderer_state_->PassDrawGLInput(); + if (input.get()) + draw_gl_input_ = input.Pass(); + SetCompositorMemoryPolicy(); + + gl_surface_->SetBackingFrameBufferObject(framebuffer_binding_ext); + + gfx::Transform transform; + transform.matrix().setColMajorf(draw_info->transform); + transform.Translate(draw_gl_input_->scroll_offset.x(), + draw_gl_input_->scroll_offset.y()); + gfx::Rect clip_rect(draw_info->clip_left, + draw_info->clip_top, + draw_info->clip_right - draw_info->clip_left, + draw_info->clip_bottom - draw_info->clip_top); + + gfx::Rect viewport(draw_info->width, draw_info->height); + if (!draw_info->is_layer) { + gfx::RectF view_rect(draw_gl_input_->width, draw_gl_input_->height); + transform.TransformRect(&view_rect); + viewport.Intersect(gfx::ToEnclosingRect(view_rect)); + } + + scoped_ptr<cc::CompositorFrame> frame = + shared_renderer_state_->GetCompositor()->DemandDrawHw( + gfx::Size(draw_info->width, draw_info->height), + transform, + viewport, + clip_rect, + framebuffer_binding_ext); + gl_surface_->ResetBackingFrameBufferObject(); + + if (frame.get()) { + result->clip_contains_visible_rect = + clip_rect.Contains(draw_gl_input_->global_visible_rect); + } + return !!frame.get(); +} + +void HardwareRendererLegacy::SetCompositorMemoryPolicy() { + if (shared_renderer_state_->IsMemoryPolicyDirty()) { + content::SynchronousCompositorMemoryPolicy policy = + shared_renderer_state_->GetMemoryPolicy(); + // Memory policy is set by BrowserViewRenderer on UI thread. + shared_renderer_state_->GetCompositor()->SetMemoryPolicy(policy); + shared_renderer_state_->SetMemoryPolicyDirty(false); + } +} + +} // namespace android_webview diff --git a/android_webview/browser/hardware_renderer_legacy.h b/android_webview/browser/hardware_renderer_legacy.h new file mode 100644 index 0000000000..a92fe9b32a --- /dev/null +++ b/android_webview/browser/hardware_renderer_legacy.h @@ -0,0 +1,46 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ANDROID_WEBVIEW_BROWSER_HARDWARE_RENDERER_LEGACY_H_ +#define ANDROID_WEBVIEW_BROWSER_HARDWARE_RENDERER_LEGACY_H_ + +#include "android_webview/browser/hardware_renderer_interface.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" + +struct AwDrawGLInfo; + +namespace android_webview { + +class AwGLSurface; +class SharedRendererState; +struct DrawGLInput; + +class HardwareRendererLegacy : public HardwareRendererInterface { + public: + explicit HardwareRendererLegacy(SharedRendererState* state); + virtual ~HardwareRendererLegacy(); + + virtual bool DrawGL(bool stencil_enabled, + int framebuffer_binding_ext, + AwDrawGLInfo* draw_info, + DrawGLResult* result) OVERRIDE; + + private: + void SetCompositorMemoryPolicy(); + + SharedRendererState* shared_renderer_state_; + scoped_ptr<DrawGLInput> draw_gl_input_; + + typedef void* EGLContext; + EGLContext last_egl_context_; + + scoped_refptr<AwGLSurface> gl_surface_; + + DISALLOW_COPY_AND_ASSIGN(HardwareRendererLegacy); +}; + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_BROWSER_HARDWARE_RENDERER_LEGACY_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 2850b4459d..d456af2ef1 100644 --- a/android_webview/browser/net/aw_url_request_context_getter.cc +++ b/android_webview/browser/net/aw_url_request_context_getter.cc @@ -6,6 +6,7 @@ #include <vector> +#include "android_webview/browser/aw_browser_context.h" #include "android_webview/browser/aw_content_browser_client.h" #include "android_webview/browser/aw_request_interceptor.h" #include "android_webview/browser/net/aw_network_delegate.h" @@ -30,11 +31,13 @@ #include "net/http/http_cache.h" #include "net/http/http_stream_factory.h" #include "net/proxy/proxy_service.h" +#include "net/socket/next_proto.h" #include "net/url_request/data_protocol_handler.h" #include "net/url_request/file_protocol_handler.h" -#include "net/url_request/protocol_intercept_job_factory.h" #include "net/url_request/url_request_context_builder.h" #include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_intercepting_job_factory.h" +#include "net/url_request/url_request_interceptor.h" using content::BrowserThread; using data_reduction_proxy::DataReductionProxySettings; @@ -89,6 +92,11 @@ void PopulateNetworkSessionParams( params->network_delegate = context->network_delegate(); params->http_server_properties = context->http_server_properties(); params->net_log = context->net_log(); + + // TODO(sgurun) remove once crbug.com/329681 is fixed. + params->next_protos = net::NextProtosSpdy31(); + params->use_alternate_protocols = true; + ApplyCmdlineOverridesToNetworkSessionParams(params); } @@ -96,22 +104,22 @@ scoped_ptr<net::URLRequestJobFactory> CreateJobFactory( content::ProtocolHandlerMap* protocol_handlers) { scoped_ptr<AwURLRequestJobFactory> aw_job_factory(new AwURLRequestJobFactory); bool set_protocol = aw_job_factory->SetProtocolHandler( - content::kFileScheme, + url::kFileScheme, new net::FileProtocolHandler( content::BrowserThread::GetBlockingPool()-> GetTaskRunnerWithShutdownBehavior( base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))); DCHECK(set_protocol); set_protocol = aw_job_factory->SetProtocolHandler( - content::kDataScheme, new net::DataProtocolHandler()); + url::kDataScheme, new net::DataProtocolHandler()); DCHECK(set_protocol); set_protocol = aw_job_factory->SetProtocolHandler( - content::kBlobScheme, - (*protocol_handlers)[content::kBlobScheme].release()); + url::kBlobScheme, + (*protocol_handlers)[url::kBlobScheme].release()); DCHECK(set_protocol); set_protocol = aw_job_factory->SetProtocolHandler( - content::kFileSystemScheme, - (*protocol_handlers)[content::kFileSystemScheme].release()); + url::kFileSystemScheme, + (*protocol_handlers)[url::kFileSystemScheme].release()); DCHECK(set_protocol); set_protocol = aw_job_factory->SetProtocolHandler( content::kChromeUIScheme, @@ -124,36 +132,36 @@ scoped_ptr<net::URLRequestJobFactory> CreateJobFactory( protocol_handlers->clear(); // Create a chain of URLRequestJobFactories. The handlers will be invoked - // in the order in which they appear in the protocol_handlers vector. - typedef std::vector<net::URLRequestJobFactory::ProtocolHandler*> - ProtocolHandlerVector; - ProtocolHandlerVector protocol_interceptors; + // in the order in which they appear in the |request_interceptors| vector. + typedef std::vector<net::URLRequestInterceptor*> + URLRequestInterceptorVector; + URLRequestInterceptorVector request_interceptors; // Note that even though the content:// scheme handler is created here, // it cannot be used by child processes until access to it is granted via // ChildProcessSecurityPolicy::GrantScheme(). This is done in // AwContentBrowserClient. - protocol_interceptors.push_back( - CreateAndroidContentProtocolHandler().release()); - protocol_interceptors.push_back( - CreateAndroidAssetFileProtocolHandler().release()); + request_interceptors.push_back( + CreateAndroidContentRequestInterceptor().release()); + request_interceptors.push_back( + CreateAndroidAssetFileRequestInterceptor().release()); // The AwRequestInterceptor must come after the content and asset file job // factories. This for WebViewClassic compatibility where it was not // possible to intercept resource loads to resolvable content:// and // file:// URIs. // This logical dependency is also the reason why the Content - // ProtocolHandler has to be added as a ProtocolInterceptJobFactory rather - // than via SetProtocolHandler. - protocol_interceptors.push_back(new AwRequestInterceptor()); + // URLRequestInterceptor has to be added as an interceptor rather than as a + // ProtocolHandler. + request_interceptors.push_back(new AwRequestInterceptor()); // The chain of responsibility will execute the handlers in reverse to the // order in which the elements of the chain are created. scoped_ptr<net::URLRequestJobFactory> job_factory(aw_job_factory.Pass()); - for (ProtocolHandlerVector::reverse_iterator - i = protocol_interceptors.rbegin(); - i != protocol_interceptors.rend(); + for (URLRequestInterceptorVector::reverse_iterator + i = request_interceptors.rbegin(); + i != request_interceptors.rend(); ++i) { - job_factory.reset(new net::ProtocolInterceptJobFactory( + job_factory.reset(new net::URLRequestInterceptingJobFactory( job_factory.Pass(), make_scoped_ptr(*i))); } @@ -215,8 +223,18 @@ void AwURLRequestContextGetter::InitializeURLRequestContext() { 20 * 1024 * 1024, // 20M BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE))); + AwBrowserContext* browser_context = AwBrowserContext::GetDefault(); + DCHECK(browser_context); + DataReductionProxySettings* drp_settings = + browser_context->GetDataReductionProxySettings(); + DCHECK(drp_settings); + std::string drp_key = drp_settings->key(); + // Only precache credentials if a key is available at URLRequestContext + // initialization. + if (!drp_key.empty()) { DataReductionProxySettings::InitDataReductionProxySession( - main_cache->GetSession()); + main_cache->GetSession(), drp_settings->key()); + } main_http_factory_.reset(main_cache); url_request_context_->set_http_transaction_factory(main_cache); @@ -224,10 +242,6 @@ void AwURLRequestContextGetter::InitializeURLRequestContext() { job_factory_ = CreateJobFactory(&protocol_handlers_); url_request_context_->set_job_factory(job_factory_.get()); - - // TODO(sgurun) remove once crbug.com/329681 is fixed. Should be - // called only once. - net::HttpStreamFactory::EnableNpnSpdy31(); } net::URLRequestContext* AwURLRequestContextGetter::GetURLRequestContext() { diff --git a/android_webview/browser/net/init_native_callback.h b/android_webview/browser/net/init_native_callback.h index 5f48e4cb83..d98867cff4 100644 --- a/android_webview/browser/net/init_native_callback.h +++ b/android_webview/browser/net/init_native_callback.h @@ -7,10 +7,10 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "net/url_request/url_request_job_factory.h" namespace net { class CookieStore; +class URLRequestInterceptor; } // namespace net namespace android_webview { @@ -21,12 +21,12 @@ scoped_refptr<net::CookieStore> CreateCookieStore( AwBrowserContext* browser_context); // Called lazily when the job factory is being constructed. -scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> - CreateAndroidAssetFileProtocolHandler(); +scoped_ptr<net::URLRequestInterceptor> + CreateAndroidAssetFileRequestInterceptor(); // Called lazily when the job factory is being constructed. -scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> - CreateAndroidContentProtocolHandler(); +scoped_ptr<net::URLRequestInterceptor> + CreateAndroidContentRequestInterceptor(); } // namespace android_webview diff --git a/android_webview/browser/parent_output_surface.cc b/android_webview/browser/parent_output_surface.cc new file mode 100644 index 0000000000..0150eaa555 --- /dev/null +++ b/android_webview/browser/parent_output_surface.cc @@ -0,0 +1,35 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "android_webview/browser/parent_output_surface.h" + +#include "cc/output/output_surface_client.h" +#include "gpu/command_buffer/client/gles2_interface.h" + +namespace android_webview { + +ParentOutputSurface::ParentOutputSurface( + scoped_refptr<cc::ContextProvider> context_provider) + : cc::OutputSurface(context_provider) { + capabilities_.draw_and_swap_full_viewport_every_frame = true; +} + +ParentOutputSurface::~ParentOutputSurface() { +} + +void ParentOutputSurface::SwapBuffers(cc::CompositorFrame* frame) { + context_provider_->ContextGL()->ShallowFlushCHROMIUM(); + client_->DidSwapBuffers(); +} + +void ParentOutputSurface::SetDrawConstraints(const gfx::Size& surface_size, + const gfx::Rect& clip) { + DCHECK(client_); + surface_size_ = surface_size; + gfx::Transform identity; + gfx::Rect empty; + SetExternalDrawConstraints(identity, empty, clip, true); +} + +} // namespace android_webview diff --git a/android_webview/browser/parent_output_surface.h b/android_webview/browser/parent_output_surface.h new file mode 100644 index 0000000000..88dabae040 --- /dev/null +++ b/android_webview/browser/parent_output_surface.h @@ -0,0 +1,30 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ANDROID_WEBVIEW_BROWSER_PARENT_OUTPUT_SURFACE_H_ +#define ANDROID_WEBVIEW_BROWSER_PARENT_OUTPUT_SURFACE_H_ + +#include "cc/output/output_surface.h" + +namespace android_webview { + +class ParentOutputSurface : NON_EXPORTED_BASE(public cc::OutputSurface) { + public: + explicit ParentOutputSurface( + scoped_refptr<cc::ContextProvider> context_provider); + virtual ~ParentOutputSurface(); + + // OutputSurface overrides. + virtual void Reshape(const gfx::Size& size, float scale_factor) OVERRIDE {} + virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE; + + void SetDrawConstraints(const gfx::Size& surface_size, const gfx::Rect& clip); + + private: + DISALLOW_COPY_AND_ASSIGN(ParentOutputSurface); +}; + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_BROWSER_PARENT_OUTPUT_SURFACE_H_ 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 05eb520945..8872dd776d 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 @@ -20,11 +20,11 @@ #include "content/public/browser/resource_dispatcher_host_login_delegate.h" #include "content/public/browser/resource_request_info.h" #include "content/public/browser/resource_throttle.h" -#include "content/public/common/url_constants.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/http/http_response_headers.h" #include "net/url_request/url_request.h" +#include "url/url_constants.h" using android_webview::AwContentsIoThreadClient; using content::BrowserThread; @@ -170,7 +170,7 @@ bool IoThreadClientThrottle::ShouldBlockRequest() { } if (io_client->ShouldBlockNetworkLoads()) { - if (request_->url().SchemeIs(content::kFtpScheme)) { + if (request_->url().SchemeIs(url::kFtpScheme)) { return true; } SetCacheControlFlag(request_, net::LOAD_ONLY_FROM_CACHE); diff --git a/android_webview/browser/scoped_app_gl_state_restore.cc b/android_webview/browser/scoped_app_gl_state_restore.cc index 71a5711a26..399b36aaf0 100644 --- a/android_webview/browser/scoped_app_gl_state_restore.cc +++ b/android_webview/browser/scoped_app_gl_state_restore.cc @@ -51,6 +51,17 @@ void GLEnableDisable(GLenum cap, bool enable) { glDisable(cap); } +bool ClearGLErrors(bool warn, const char* msg) { + bool no_error = true; + GLenum error; + while ((error = glGetError()) != GL_NO_ERROR) { + DLOG_IF(WARNING, warn) << error << " " << msg; + no_error = false; + } + + return no_error; +} + bool g_globals_initialized = false; GLint g_gl_max_texture_units = 0; bool g_supports_oes_vertex_array_object = false; @@ -148,6 +159,8 @@ ScopedAppGLStateRestoreImpl::ScopedAppGLStateRestoreImpl( TRACE_EVENT0("android_webview", "AppGLStateSave"); MakeAppContextCurrent(); + ClearGLErrors(true, "Incoming GLError"); + if (!g_globals_initialized) { g_globals_initialized = true; @@ -251,12 +264,15 @@ ScopedAppGLStateRestoreImpl::ScopedAppGLStateRestoreImpl( glGetVertexAttribfv( i, GL_CURRENT_VERTEX_ATTRIB, vertex_attrib_[i].current_vertex_attrib); } + DCHECK(ClearGLErrors(false, NULL)); } ScopedAppGLStateRestoreImpl::~ScopedAppGLStateRestoreImpl() { TRACE_EVENT0("android_webview", "AppGLStateRestore"); MakeAppContextCurrent(); + DCHECK(ClearGLErrors(false, NULL)); + glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_binding_ext_); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_buffer_binding_); @@ -347,6 +363,9 @@ ScopedAppGLStateRestoreImpl::~ScopedAppGLStateRestoreImpl() { GLEnableDisable(GL_STENCIL_TEST, stencil_test_); glStencilFunc(stencil_func_, stencil_mask_, stencil_ref_); + + // Do not leak GLError out of chromium. + ClearGLErrors(true, "Chromium GLError"); } } // namespace internal diff --git a/android_webview/browser/shared_renderer_state.cc b/android_webview/browser/shared_renderer_state.cc index 3483d630e7..42a42450ac 100644 --- a/android_webview/browser/shared_renderer_state.cc +++ b/android_webview/browser/shared_renderer_state.cc @@ -10,9 +10,14 @@ namespace android_webview { -DrawGLInput::DrawGLInput() : frame_id(0), width(0), height(0) {} +DrawGLInput::DrawGLInput() : width(0), height(0) { +} + +DrawGLInput::~DrawGLInput() { +} -DrawGLResult::DrawGLResult() : frame_id(0), clip_contains_visible_rect(false) {} +DrawGLResult::DrawGLResult() : clip_contains_visible_rect(false) { +} SharedRendererState::SharedRendererState( scoped_refptr<base::MessageLoopProxy> ui_loop, @@ -23,7 +28,9 @@ SharedRendererState::SharedRendererState( ui_thread_weak_ptr_(weak_factory_on_ui_thread_.GetWeakPtr()), compositor_(NULL), memory_policy_dirty_(false), - hardware_initialized_(false) { + hardware_allowed_(false), + hardware_initialized_(false), + share_context_(NULL) { DCHECK(ui_loop_->BelongsToCurrentThread()); DCHECK(client_on_ui_); } @@ -76,37 +83,25 @@ SharedRendererState::GetMemoryPolicy() const { return memory_policy_; } -void SharedRendererState::SetDrawGLInput(const DrawGLInput& input) { - base::AutoLock lock(lock_); - draw_gl_input_ = input; -} - -DrawGLInput SharedRendererState::GetDrawGLInput() const { +void SharedRendererState::SetDrawGLInput(scoped_ptr<DrawGLInput> input) { base::AutoLock lock(lock_); - return draw_gl_input_; + DCHECK(!draw_gl_input_.get()); + draw_gl_input_ = input.Pass(); } -void SharedRendererState::ClearClosureQueue() { +scoped_ptr<DrawGLInput> SharedRendererState::PassDrawGLInput() { base::AutoLock lock(lock_); - std::queue<base::Closure> empty; - std::swap(closure_queue_, empty); + return draw_gl_input_.Pass(); } -void SharedRendererState::AppendClosure(const base::Closure& closure) { +void SharedRendererState::SetHardwareAllowed(bool allowed) { base::AutoLock lock(lock_); - closure_queue_.push(closure); + hardware_allowed_ = allowed; } -base::Closure SharedRendererState::PopFrontClosure() { - base::Closure closure; - +bool SharedRendererState::IsHardwareAllowed() const { base::AutoLock lock(lock_); - if (!closure_queue_.empty()) { - closure = closure_queue_.front(); - closure_queue_.pop(); - } - - return closure; + return hardware_allowed_; } void SharedRendererState::SetHardwareInitialized(bool initialized) { @@ -119,6 +114,18 @@ bool SharedRendererState::IsHardwareInitialized() const { return hardware_initialized_; } +void SharedRendererState::SetSharedContext(gpu::GLInProcessContext* context) { + base::AutoLock lock(lock_); + DCHECK(!share_context_ || !context); + share_context_ = context; +} + +gpu::GLInProcessContext* SharedRendererState::GetSharedContext() const { + base::AutoLock lock(lock_); + DCHECK(share_context_); + return share_context_; +} + void SharedRendererState::SetMemoryPolicyDirty(bool is_dirty) { base::AutoLock lock(lock_); memory_policy_dirty_ = is_dirty; @@ -129,4 +136,28 @@ bool SharedRendererState::IsMemoryPolicyDirty() const { return memory_policy_dirty_; } +void SharedRendererState::ReturnResources( + const cc::TransferableResourceArray& input) { + base::AutoLock lock(lock_); + cc::TransferableResource::ReturnResources(input, &returned_resources_); +} + +void SharedRendererState::InsertReturnedResources( + const cc::ReturnedResourceArray& resources) { + base::AutoLock lock(lock_); + returned_resources_.insert( + returned_resources_.end(), resources.begin(), resources.end()); +} + +void SharedRendererState::SwapReturnedResources( + cc::ReturnedResourceArray* resources) { + base::AutoLock lock(lock_); + resources->swap(returned_resources_); +} + +bool SharedRendererState::ReturnedResourcesEmpty() const { + base::AutoLock lock(lock_); + return returned_resources_.empty(); +} + } // namespace android_webview diff --git a/android_webview/browser/shared_renderer_state.h b/android_webview/browser/shared_renderer_state.h index 9c90731d7a..8350c9dfc3 100644 --- a/android_webview/browser/shared_renderer_state.h +++ b/android_webview/browser/shared_renderer_state.h @@ -5,33 +5,40 @@ #ifndef ANDROID_WEBVIEW_BROWSER_SHARED_RENDERER_STATE_H_ #define ANDROID_WEBVIEW_BROWSER_SHARED_RENDERER_STATE_H_ -#include <queue> - -#include "base/callback.h" #include "base/message_loop/message_loop_proxy.h" #include "base/synchronization/lock.h" +#include "cc/output/compositor_frame.h" +#include "cc/output/compositor_frame_ack.h" #include "content/public/browser/android/synchronous_compositor.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/vector2d.h" +namespace cc { +class CompositorFrameAck; +} + +namespace gpu { +class GLInProcessContext; +} + namespace android_webview { class BrowserViewRendererClient; // Set by BrowserViewRenderer and read by HardwareRenderer. struct DrawGLInput { - unsigned int frame_id; gfx::Rect global_visible_rect; gfx::Vector2d scroll_offset; int width; int height; + cc::CompositorFrame frame; DrawGLInput(); + ~DrawGLInput(); }; // Set by HardwareRenderer and read by BrowserViewRenderer. struct DrawGLResult { - unsigned int frame_id; bool clip_contains_visible_rect; DrawGLResult(); @@ -61,17 +68,25 @@ class SharedRendererState { void SetMemoryPolicyDirty(bool is_dirty); bool IsMemoryPolicyDirty() const; - void SetDrawGLInput(const DrawGLInput& input); - DrawGLInput GetDrawGLInput() const; + void SetDrawGLInput(scoped_ptr<DrawGLInput> input); + scoped_ptr<DrawGLInput> PassDrawGLInput(); - void ClearClosureQueue(); - void AppendClosure(const base::Closure& closure); - // Will return empty closure if queue empty. - base::Closure PopFrontClosure(); + // Set by UI and read by RT. + void SetHardwareAllowed(bool allowed); + bool IsHardwareAllowed() const; + // Set by RT and read by UI. void SetHardwareInitialized(bool initialized); bool IsHardwareInitialized() const; + void SetSharedContext(gpu::GLInProcessContext* context); + gpu::GLInProcessContext* GetSharedContext() const; + + void ReturnResources(const cc::TransferableResourceArray& input); + void InsertReturnedResources(const cc::ReturnedResourceArray& resources); + void SwapReturnedResources(cc::ReturnedResourceArray* resources); + bool ReturnedResourcesEmpty() const; + private: void ClientRequestDrawGLOnUIThread(); @@ -88,9 +103,11 @@ class SharedRendererState { // Set to true when SetMemoryPolicy called with a different memory policy. // Set to false when memory policy is read and enforced to compositor. bool memory_policy_dirty_; - DrawGLInput draw_gl_input_; - std::queue<base::Closure> closure_queue_; + scoped_ptr<DrawGLInput> draw_gl_input_; + bool hardware_allowed_; bool hardware_initialized_; + gpu::GLInProcessContext* share_context_; + cc::ReturnedResourceArray returned_resources_; }; } // namespace android_webview |