summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorboliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-21 20:03:26 +0000
committerboliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-21 20:03:26 +0000
commit596f7e7939f195288d621f18302f4cc5a2e97b17 (patch)
tree251d267142090068c60788b2e175d41d02aab28f
parent80f2fa72c7a3fb0c7fca3e29e35d149a6bb100b0 (diff)
downloadchromium_src-596f7e7939f195288d621f18302f4cc5a2e97b17.zip
chromium_src-596f7e7939f195288d621f18302f4cc5a2e97b17.tar.gz
chromium_src-596f7e7939f195288d621f18302f4cc5a2e97b17.tar.bz2
aw: Post SynchronousCompositorClient to UI
Do not assume that the callbacks happen on the UI thread, and instead post them back to UI thread when needed. For accessors, just return canned value if it involves the view system, or lock protect the access if it is not This is a temporary hack until SynchronousCompositor is moved back to only accessed on UI thread. BUG=344087 Review URL: https://codereview.chromium.org/203723009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@258654 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--android_webview/browser/browser_view_renderer.cc127
-rw-r--r--android_webview/browser/browser_view_renderer.h19
-rw-r--r--android_webview/native/aw_contents.cc8
3 files changed, 134 insertions, 20 deletions
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc
index 32cb906..7944934 100644
--- a/android_webview/browser/browser_view_renderer.cc
+++ b/android_webview/browser/browser_view_renderer.cc
@@ -13,7 +13,6 @@
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "content/public/browser/android/synchronous_compositor.h"
-#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
@@ -23,7 +22,6 @@
using base::android::AttachCurrentThread;
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;
-using content::BrowserThread;
namespace android_webview {
@@ -31,15 +29,44 @@ namespace {
const int64 kFallbackTickTimeoutInMilliseconds = 20;
+class AutoResetWithLock {
+ public:
+ AutoResetWithLock(gfx::Vector2dF* scoped_variable,
+ gfx::Vector2dF new_value,
+ base::Lock& lock)
+ : scoped_variable_(scoped_variable),
+ original_value_(*scoped_variable),
+ lock_(lock) {
+ base::AutoLock auto_lock(lock_);
+ *scoped_variable_ = new_value;
+ }
+
+ ~AutoResetWithLock() {
+ base::AutoLock auto_lock(lock_);
+ *scoped_variable_ = original_value_;
+ }
+
+ private:
+ gfx::Vector2dF* scoped_variable_;
+ gfx::Vector2dF original_value_;
+ base::Lock& lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutoResetWithLock);
+};
+
} // namespace
BrowserViewRenderer::BrowserViewRenderer(
BrowserViewRendererClient* client,
SharedRendererState* shared_renderer_state,
- content::WebContents* web_contents)
+ content::WebContents* web_contents,
+ const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner)
: client_(client),
shared_renderer_state_(shared_renderer_state),
web_contents_(web_contents),
+ weak_factory_on_ui_thread_(this),
+ ui_thread_weak_ptr_(weak_factory_on_ui_thread_.GetWeakPtr()),
+ ui_task_runner_(ui_task_runner),
has_compositor_(false),
is_paused_(false),
view_visible_(false),
@@ -124,8 +151,8 @@ skia::RefPtr<SkPicture> BrowserViewRenderer::CapturePicture(int width,
// Reset scroll back to the origin, will go back to the old
// value when scroll_reset is out of scope.
- base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_dip_,
- gfx::Vector2d());
+ AutoResetWithLock scroll_reset(
+ &scroll_offset_dip_, gfx::Vector2dF(), scroll_offset_dip_lock_);
SkCanvas* rec_canvas = picture->beginRecording(width, height, 0);
if (has_compositor_)
@@ -227,6 +254,7 @@ void BrowserViewRenderer::DidInitializeCompositor(
"BrowserViewRenderer::DidInitializeCompositor");
DCHECK(compositor);
DCHECK(!has_compositor_);
+ DCHECK(ui_task_runner_->BelongsToCurrentThread());
has_compositor_ = true;
shared_renderer_state_->SetCompositorOnUiThread(compositor);
}
@@ -235,11 +263,20 @@ void BrowserViewRenderer::DidDestroyCompositor(
content::SynchronousCompositor* compositor) {
TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor");
DCHECK(has_compositor_);
+ DCHECK(ui_task_runner_->BelongsToCurrentThread());
has_compositor_ = false;
shared_renderer_state_->SetCompositorOnUiThread(NULL);
}
void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) {
+ if (!ui_task_runner_->BelongsToCurrentThread()) {
+ ui_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&BrowserViewRenderer::SetContinuousInvalidate,
+ ui_thread_weak_ptr_,
+ invalidate));
+ return;
+ }
if (compositor_needs_continuous_invalidate_ == invalidate)
return;
@@ -284,16 +321,25 @@ void BrowserViewRenderer::ScrollTo(gfx::Vector2d scroll_offset) {
DCHECK_LE(scroll_offset_dip.x(), max_scroll_offset_dip_.x());
DCHECK_LE(scroll_offset_dip.y(), max_scroll_offset_dip_.y());
- if (scroll_offset_dip_ == scroll_offset_dip)
- return;
+ {
+ base::AutoLock lock(scroll_offset_dip_lock_);
+ if (scroll_offset_dip_ == scroll_offset_dip)
+ return;
- scroll_offset_dip_ = scroll_offset_dip;
+ scroll_offset_dip_ = scroll_offset_dip;
+ }
if (has_compositor_)
shared_renderer_state_->CompositorDidChangeRootLayerScrollOffset();
}
void BrowserViewRenderer::DidUpdateContent() {
+ if (!ui_task_runner_->BelongsToCurrentThread()) {
+ ui_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&BrowserViewRenderer::DidUpdateContent,
+ ui_thread_weak_ptr_));
+ return;
+ }
TRACE_EVENT_INSTANT0("android_webview",
"BrowserViewRenderer::DidUpdateContent",
TRACE_EVENT_SCOPE_THREAD);
@@ -304,6 +350,14 @@ void BrowserViewRenderer::DidUpdateContent() {
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;
@@ -315,12 +369,24 @@ void BrowserViewRenderer::SetMaxRootLayerScrollOffset(
void BrowserViewRenderer::SetTotalRootLayerScrollOffset(
gfx::Vector2dF scroll_offset_dip) {
- // TOOD(mkosiba): Add a DCHECK to say that this does _not_ get called during
- // DrawGl when http://crbug.com/249972 is fixed.
- if (scroll_offset_dip_ == 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;
+ }
- scroll_offset_dip_ = scroll_offset_dip;
+ {
+ base::AutoLock lock(scroll_offset_dip_lock_);
+ // TOOD(mkosiba): Add a DCHECK to say that this does _not_ get called during
+ // DrawGl when http://crbug.com/249972 is fixed.
+ if (scroll_offset_dip_ == scroll_offset_dip)
+ return;
+
+ scroll_offset_dip_ = scroll_offset_dip;
+ }
gfx::Vector2d max_offset = max_scroll_offset();
gfx::Vector2d scroll_offset;
@@ -347,10 +413,16 @@ void BrowserViewRenderer::SetTotalRootLayerScrollOffset(
}
gfx::Vector2dF BrowserViewRenderer::GetTotalRootLayerScrollOffset() {
+ base::AutoLock lock(scroll_offset_dip_lock_);
return scroll_offset_dip_;
}
bool BrowserViewRenderer::IsExternalFlingActive() const {
+ if (!ui_task_runner_->BelongsToCurrentThread()) {
+ // TODO(boliu): This is short term hack since we cannot call into
+ // view system on non-UI thread.
+ return false;
+ }
return client_->IsFlingActive();
}
@@ -358,6 +430,16 @@ void BrowserViewRenderer::SetRootLayerPageScaleFactorAndLimits(
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,
+ ui_thread_weak_ptr_,
+ page_scale_factor,
+ min_page_scale_factor,
+ max_page_scale_factor));
+ return;
+ }
page_scale_factor_ = page_scale_factor;
DCHECK_GT(page_scale_factor_, 0);
client_->SetPageScaleFactorAndLimits(
@@ -366,12 +448,30 @@ void BrowserViewRenderer::SetRootLayerPageScaleFactorAndLimits(
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);
}
void BrowserViewRenderer::DidOverscroll(gfx::Vector2dF accumulated_overscroll,
gfx::Vector2dF latest_overscroll_delta,
gfx::Vector2dF current_fling_velocity) {
+ if (!ui_task_runner_->BelongsToCurrentThread()) {
+ ui_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&BrowserViewRenderer::DidOverscroll,
+ ui_thread_weak_ptr_,
+ accumulated_overscroll,
+ latest_overscroll_delta,
+ current_fling_velocity));
+ return;
+ }
const float physical_pixel_scale = dip_scale_ * page_scale_factor_;
if (accumulated_overscroll == latest_overscroll_delta)
overscroll_rounding_error_ = gfx::Vector2dF();
@@ -417,8 +517,7 @@ void BrowserViewRenderer::EnsureContinuousInvalidation(bool force_invalidate) {
// ticked. This can happen if this is reached because force_invalidate is
// true.
if (compositor_needs_continuous_invalidate_) {
- BrowserThread::PostDelayedTask(
- BrowserThread::UI,
+ ui_task_runner_->PostDelayedTask(
FROM_HERE,
fallback_tick_.callback(),
base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds));
diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h
index 5ae1d9b..da82fce 100644
--- a/android_webview/browser/browser_view_renderer.h
+++ b/android_webview/browser/browser_view_renderer.h
@@ -54,9 +54,11 @@ class BrowserViewRendererJavaHelper {
// Provides software and hardware rendering and the Capture Picture API.
class BrowserViewRenderer : public content::SynchronousCompositorClient {
public:
- BrowserViewRenderer(BrowserViewRendererClient* client,
- SharedRendererState* shared_renderer_state,
- content::WebContents* web_contents);
+ BrowserViewRenderer(
+ BrowserViewRendererClient* client,
+ SharedRendererState* shared_renderer_state,
+ content::WebContents* web_contents,
+ const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner);
virtual ~BrowserViewRenderer();
@@ -147,6 +149,14 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient {
BrowserViewRendererClient* client_;
SharedRendererState* shared_renderer_state_;
content::WebContents* web_contents_;
+ // TODO(boliu): This class should only be used on the UI thread. However in
+ // short term to supporting HardwareRenderer, some callbacks on
+ // SynchronousCompositorClient may be called on non-UI thread. These are
+ // used to detect this and post them back to UI thread.
+ base::WeakPtrFactory<BrowserViewRenderer> weak_factory_on_ui_thread_;
+ base::WeakPtr<BrowserViewRenderer> ui_thread_weak_ptr_;
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
+
bool has_compositor_;
bool is_paused_;
@@ -175,6 +185,9 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient {
DrawGLInput draw_gl_input_;
+ // TODO(boliu): This is a short term solution to support
+ // SynchronousCompositorClient methods called on non-UI thread.
+ base::Lock scroll_offset_dip_lock_;
// Current scroll offset in CSS pixels.
gfx::Vector2dF scroll_offset_dip_;
diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc
index 7eceea1..30f3a3fb 100644
--- a/android_webview/native/aw_contents.cc
+++ b/android_webview/native/aw_contents.cc
@@ -191,9 +191,11 @@ AwContents::AwContents(scoped_ptr<WebContents> web_contents)
shared_renderer_state_(
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
this),
- browser_view_renderer_(this,
- &shared_renderer_state_,
- web_contents_.get()) {
+ browser_view_renderer_(
+ this,
+ &shared_renderer_state_,
+ web_contents_.get(),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)) {
base::subtle::NoBarrier_AtomicIncrement(&g_instance_count, 1);
icon_helper_.reset(new IconHelper(web_contents_.get()));
icon_helper_->SetListener(this);