Commit 83d116de authored by jochen's avatar jochen Committed by Commit bot

Hook up the scheduler component to html_viewer

BUG=477690
R=skyostil@chromium.org,sky@chromium.org

Review URL: https://codereview.chromium.org/1112573003

Cr-Commit-Position: refs/heads/master@{#327352}
parent 27a5d0a5
......@@ -82,16 +82,12 @@ source_set("lib") {
"web_mime_registry_impl.h",
"web_notification_manager_impl.cc",
"web_notification_manager_impl.h",
"web_scheduler_impl.cc",
"web_scheduler_impl.h",
"web_socket_handle_impl.cc",
"web_socket_handle_impl.h",
"web_storage_namespace_impl.cc",
"web_storage_namespace_impl.h",
"web_theme_engine_impl.cc",
"web_theme_engine_impl.h",
"web_thread_impl.cc",
"web_thread_impl.h",
"web_url_loader_impl.cc",
"web_url_loader_impl.h",
]
......@@ -106,6 +102,7 @@ source_set("lib") {
"//cc/surfaces",
"//components/clipboard/public/interfaces",
"//components/gpu/public/interfaces",
"//components/scheduler:scheduler",
"//components/surfaces/public/interfaces",
"//components/webcrypto",
"//gin",
......
......@@ -5,6 +5,7 @@ include_rules = [
"+cc",
"+components/clipboard",
"+components/gpu",
"+components/scheduler",
"+components/surfaces",
"+components/view_manager",
"+components/webcrypto",
......
......@@ -18,8 +18,10 @@
#include "components/html_viewer/web_cookie_jar_impl.h"
#include "components/html_viewer/web_message_port_channel_impl.h"
#include "components/html_viewer/web_socket_handle_impl.h"
#include "components/html_viewer/web_thread_impl.h"
#include "components/html_viewer/web_url_loader_impl.h"
#include "components/scheduler/child/webthread_impl_for_worker_scheduler.h"
#include "components/scheduler/renderer/renderer_scheduler.h"
#include "components/scheduler/renderer/webthread_impl_for_renderer_scheduler.h"
#include "net/base/data_url.h"
#include "net/base/mime_util.h"
#include "net/base/net_errors.h"
......@@ -59,13 +61,16 @@ class WebWaitableEventImpl : public blink::WebWaitableEvent {
} // namespace
BlinkPlatformImpl::BlinkPlatformImpl(mojo::ApplicationImpl* app)
: shared_timer_func_(NULL),
BlinkPlatformImpl::BlinkPlatformImpl(
mojo::ApplicationImpl* app,
scheduler::RendererScheduler* renderer_scheduler)
: main_thread_task_runner_(renderer_scheduler->DefaultTaskRunner()),
main_thread_(
new scheduler::WebThreadImplForRendererScheduler(renderer_scheduler)),
shared_timer_func_(NULL),
shared_timer_fire_time_(0.0),
shared_timer_fire_time_was_set_while_suspended_(false),
shared_timer_suspended_(0),
current_thread_slot_(&DestroyCurrentThread),
scheduler_(base::ThreadTaskRunnerHandle::Get()) {
shared_timer_suspended_(0) {
if (app) {
app->ConnectToService("mojo:network_service", &network_service_);
......@@ -79,6 +84,7 @@ BlinkPlatformImpl::BlinkPlatformImpl(mojo::ApplicationImpl* app)
mojo::ConnectToService(service_provider.get(), &clipboard);
clipboard_.reset(new WebClipboardImpl(clipboard.Pass()));
}
shared_timer_.SetTaskRunner(main_thread_task_runner_);
}
BlinkPlatformImpl::~BlinkPlatformImpl() {
......@@ -100,10 +106,6 @@ blink::WebThemeEngine* BlinkPlatformImpl::themeEngine() {
return &theme_engine_;
}
blink::WebScheduler* BlinkPlatformImpl::scheduler() {
return &scheduler_;
}
blink::WebString BlinkPlatformImpl::defaultLocale() {
return blink::WebString::fromUTF8("en-US");
}
......@@ -253,23 +255,18 @@ bool BlinkPlatformImpl::isReservedIPAddress(
}
blink::WebThread* BlinkPlatformImpl::createThread(const char* name) {
return new WebThreadImpl(name);
scheduler::WebThreadImplForWorkerScheduler* thread =
new scheduler::WebThreadImplForWorkerScheduler(name);
thread->TaskRunner()->PostTask(
FROM_HERE, base::Bind(&BlinkPlatformImpl::UpdateWebThreadTLS,
base::Unretained(this), thread));
return thread;
}
blink::WebThread* BlinkPlatformImpl::currentThread() {
WebThreadImplForMessageLoop* thread =
static_cast<WebThreadImplForMessageLoop*>(current_thread_slot_.Get());
if (thread)
return (thread);
scoped_refptr<base::MessageLoopProxy> message_loop =
base::MessageLoopProxy::current();
if (!message_loop.get())
return NULL;
thread = new WebThreadImplForMessageLoop(message_loop.get());
current_thread_slot_.Set(thread);
return thread;
if (main_thread_->isCurrentThread())
return main_thread_.get();
return static_cast<blink::WebThread*>(current_thread_slot_.Get());
}
void BlinkPlatformImpl::yieldCurrentThread() {
......@@ -311,11 +308,9 @@ BlinkPlatformImpl::notificationManager() {
return &web_notification_manager_;
}
// static
void BlinkPlatformImpl::DestroyCurrentThread(void* thread) {
WebThreadImplForMessageLoop* impl =
static_cast<WebThreadImplForMessageLoop*>(thread);
delete impl;
void BlinkPlatformImpl::UpdateWebThreadTLS(blink::WebThread* thread) {
DCHECK(!current_thread_slot_.Get());
current_thread_slot_.Set(thread);
}
} // namespace html_viewer
......@@ -13,13 +13,17 @@
#include "components/html_viewer/mock_web_blob_registry_impl.h"
#include "components/html_viewer/web_mime_registry_impl.h"
#include "components/html_viewer/web_notification_manager_impl.h"
#include "components/html_viewer/web_scheduler_impl.h"
#include "components/html_viewer/web_theme_engine_impl.h"
#include "components/webcrypto/webcrypto_impl.h"
#include "mojo/services/network/public/interfaces/network_service.mojom.h"
#include "third_party/WebKit/public/platform/Platform.h"
#include "third_party/WebKit/public/platform/WebScrollbarBehavior.h"
namespace scheduler {
class RendererScheduler;
class WebThreadImplForRendererScheduler;
}
namespace mojo {
class ApplicationImpl;
}
......@@ -32,7 +36,8 @@ class WebCookieJarImpl;
class BlinkPlatformImpl : public blink::Platform {
public:
// |app| may be null in tests.
explicit BlinkPlatformImpl(mojo::ApplicationImpl* app);
BlinkPlatformImpl(mojo::ApplicationImpl* app,
scheduler::RendererScheduler* renderer_scheduler);
virtual ~BlinkPlatformImpl();
// blink::Platform methods:
......@@ -40,7 +45,6 @@ class BlinkPlatformImpl : public blink::Platform {
virtual blink::WebClipboard* clipboard();
virtual blink::WebMimeRegistry* mimeRegistry();
virtual blink::WebThemeEngine* themeEngine();
virtual blink::WebScheduler* scheduler();
virtual blink::WebString defaultLocale();
virtual blink::WebBlobRegistry* blobRegistry();
virtual double currentTime();
......@@ -82,6 +86,7 @@ class BlinkPlatformImpl : public blink::Platform {
private:
void SuspendSharedTimer();
void ResumeSharedTimer();
void UpdateWebThreadTLS(blink::WebThread* thread);
void DoTimeout() {
if (shared_timer_func_ && !shared_timer_suspended_)
......@@ -90,6 +95,8 @@ class BlinkPlatformImpl : public blink::Platform {
static void DestroyCurrentThread(void*);
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
scoped_ptr<scheduler::WebThreadImplForRendererScheduler> main_thread_;
base::OneShotTimer<BlinkPlatformImpl> shared_timer_;
void (*shared_timer_func_)();
double shared_timer_fire_time_;
......@@ -99,7 +106,6 @@ class BlinkPlatformImpl : public blink::Platform {
cc_blink::WebCompositorSupportImpl compositor_support_;
WebThemeEngineImpl theme_engine_;
WebMimeRegistryImpl mime_registry_;
WebSchedulerImpl scheduler_;
webcrypto::WebCryptoImpl web_crypto_;
WebNotificationManagerImpl web_notification_manager_;
blink::WebScrollbarBehavior scrollbar_behavior_;
......
......@@ -14,6 +14,7 @@
#include "components/html_viewer/discardable_memory_allocator.h"
#include "components/html_viewer/html_document.h"
#include "components/html_viewer/web_media_player_factory.h"
#include "components/scheduler/renderer/renderer_scheduler.h"
#include "gin/v8_initializer.h"
#include "mojo/application/application_runner_chromium.h"
#include "mojo/services/network/public/interfaces/network_service.mojom.h"
......@@ -172,7 +173,9 @@ class HTMLViewer : public mojo::ApplicationDelegate,
base::DiscardableMemoryAllocator::SetInstance(
&discardable_memory_allocator_);
blink_platform_.reset(new BlinkPlatformImpl(app));
renderer_scheduler_ = scheduler::RendererScheduler::Create();
blink_platform_.reset(
new BlinkPlatformImpl(app, renderer_scheduler_.get()));
#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
// Note: this requires file system access.
gin::V8Initializer::LoadV8Snapshot();
......@@ -237,6 +240,7 @@ class HTMLViewer : public mojo::ApplicationDelegate,
// memory based purging allocator working here.
DiscardableMemoryAllocator discardable_memory_allocator_;
scoped_ptr<scheduler::RendererScheduler> renderer_scheduler_;
scoped_ptr<BlinkPlatformImpl> blink_platform_;
base::Thread compositor_thread_;
scoped_ptr<WebMediaPlayerFactory> web_media_player_factory_;
......
// Copyright 2015 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.
// An implementation of WebThread in terms of base::MessageLoop and
// base::Thread
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/tracked_objects.h"
#include "components/html_viewer/web_scheduler_impl.h"
namespace html_viewer {
WebSchedulerImpl::WebSchedulerImpl(
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: task_runner_(task_runner) {
}
WebSchedulerImpl::~WebSchedulerImpl() {
}
void WebSchedulerImpl::postIdleTask(const blink::WebTraceLocation& web_location,
blink::WebThread::IdleTask* task) {
scoped_ptr<blink::WebThread::IdleTask> scoped_task(task);
tracked_objects::Location location(web_location.functionName(),
web_location.fileName(), -1, nullptr);
task_runner_->PostTask(location, base::Bind(&WebSchedulerImpl::RunIdleTask,
base::Passed(&scoped_task)));
}
void WebSchedulerImpl::postLoadingTask(
const blink::WebTraceLocation& web_location,
blink::WebThread::Task* task) {
scoped_ptr<blink::WebThread::Task> scoped_task(task);
tracked_objects::Location location(web_location.functionName(),
web_location.fileName(), -1, nullptr);
task_runner_->PostTask(location, base::Bind(&WebSchedulerImpl::RunTask,
base::Passed(&scoped_task)));
}
void WebSchedulerImpl::postTimerTask(
const blink::WebTraceLocation& web_location,
blink::WebThread::Task* task,
long long delayMs) {
scoped_ptr<blink::WebThread::Task> scoped_task(task);
tracked_objects::Location location(web_location.functionName(),
web_location.fileName(), -1, nullptr);
task_runner_->PostDelayedTask(
location,
base::Bind(&WebSchedulerImpl::RunTask, base::Passed(&scoped_task)),
base::TimeDelta::FromMilliseconds(delayMs));
}
// static
void WebSchedulerImpl::RunIdleTask(
scoped_ptr<blink::WebThread::IdleTask> task) {
// TODO(davemoore) Implement idle scheduling.
task->run(0);
}
// static
void WebSchedulerImpl::RunTask(scoped_ptr<blink::WebThread::Task> task) {
task->run();
}
} // namespace html_viewer
// Copyright 2015 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 COMPONENTS_HTML_VIEWER_WEB_SCHEDULER_IMPL_H_
#define COMPONENTS_HTML_VIEWER_WEB_SCHEDULER_IMPL_H_
#include "third_party/WebKit/public/platform/WebScheduler.h"
#include "third_party/WebKit/public/platform/WebThread.h"
#include "third_party/WebKit/public/platform/WebTraceLocation.h"
namespace html_viewer {
class WebSchedulerImpl : public blink::WebScheduler {
public:
explicit WebSchedulerImpl(
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
virtual ~WebSchedulerImpl();
private:
// blink::WebScheduler overrides.
virtual void postIdleTask(const blink::WebTraceLocation& location,
blink::WebThread::IdleTask* task);
virtual void postLoadingTask(const blink::WebTraceLocation& location,
blink::WebThread::Task* task);
virtual void postTimerTask(const blink::WebTraceLocation& location,
blink::WebThread::Task* task,
long long delayMs);
static void RunIdleTask(scoped_ptr<blink::WebThread::IdleTask> task);
static void RunTask(scoped_ptr<blink::WebThread::Task> task);
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
DISALLOW_COPY_AND_ASSIGN(WebSchedulerImpl);
};
} // namespace html_viewer
#endif // COMPONENTS_HTML_VIEWER_WEB_SCHEDULER_IMPL_H_
// 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.
// An implementation of WebThread in terms of base::MessageLoop and
// base::Thread
#include "components/html_viewer/web_thread_impl.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/message_loop/message_loop.h"
#include "base/pending_task.h"
#include "base/threading/platform_thread.h"
#include "third_party/WebKit/public/platform/WebTraceLocation.h"
namespace html_viewer {
WebThreadBase::WebThreadBase() {}
WebThreadBase::~WebThreadBase() {}
class WebThreadBase::TaskObserverAdapter
: public base::MessageLoop::TaskObserver {
public:
TaskObserverAdapter(WebThread::TaskObserver* observer)
: observer_(observer) {}
void WillProcessTask(const base::PendingTask& pending_task) override {
observer_->willProcessTask();
}
void DidProcessTask(const base::PendingTask& pending_task) override {
observer_->didProcessTask();
}
private:
WebThread::TaskObserver* observer_;
};
void WebThreadBase::addTaskObserver(TaskObserver* observer) {
CHECK(isCurrentThread());
std::pair<TaskObserverMap::iterator, bool> result = task_observer_map_.insert(
std::make_pair(observer, static_cast<TaskObserverAdapter*>(NULL)));
if (result.second)
result.first->second = new TaskObserverAdapter(observer);
base::MessageLoop::current()->AddTaskObserver(result.first->second);
}
void WebThreadBase::removeTaskObserver(TaskObserver* observer) {
CHECK(isCurrentThread());
TaskObserverMap::iterator iter = task_observer_map_.find(observer);
if (iter == task_observer_map_.end())
return;
base::MessageLoop::current()->RemoveTaskObserver(iter->second);
delete iter->second;
task_observer_map_.erase(iter);
}
WebThreadImpl::WebThreadImpl(const char* name)
: thread_(new base::Thread(name)),
web_scheduler_(new WebSchedulerImpl(thread_->task_runner())) {
thread_->Start();
}
// RunWebThreadTask takes the ownership of |task| from base::Closure and
// deletes it on the first invocation of the closure for thread-safety.
// base::Closure made from RunWebThreadTask is copyable but Closure::Run
// should be called at most only once.
// This is because WebThread::Task can contain RefPtr to a
// thread-unsafe-reference-counted object (e.g. WorkerThreadTask can contain
// RefPtr to WebKit's StringImpl), and if we don't delete |task| here,
// it causes a race condition as follows:
// [A] In task->run(), more RefPtr's to the refcounted object can be created,
// and the reference counter of the object can be modified via these
// RefPtr's (as intended) on the thread where the task is executed.
// [B] However, base::Closure still retains the ownership of WebThread::Task
// even after RunWebThreadTask is called.
// When base::Closure is deleted, WebThread::Task is deleted and the
// reference counter of the object is decreased by one, possibly from a
// different thread from [A], which is a race condition.
// Taking the ownership of |task| here by using scoped_ptr and base::Passed
// removes the reference counter modification of [B] and the race condition.
// When the closure never runs at all, the corresponding WebThread::Task is
// destructed when base::Closure is deleted (like [B]). In this case, there
// are no reference counter modification like [A] (because task->run() is not
// executed), so there are no race conditions.
// See https://crbug.com/390851 for more details.
static void RunWebThreadTask(scoped_ptr<blink::WebThread::Task> task) {
task->run();
}
void WebThreadImpl::postTask(const blink::WebTraceLocation& location,
Task* task) {
postDelayedTask(location, task, 0);
}
void WebThreadImpl::postDelayedTask(const blink::WebTraceLocation& web_location,
Task* task,
long long delay_ms) {
tracked_objects::Location location(web_location.functionName(),
web_location.fileName(), -1, nullptr);
thread_->message_loop()->PostDelayedTask(
location,
base::Bind(RunWebThreadTask, base::Passed(make_scoped_ptr(task))),
base::TimeDelta::FromMilliseconds(delay_ms));
}
void WebThreadImpl::enterRunLoop() {
CHECK(isCurrentThread());
CHECK(!thread_->message_loop()->is_running()); // We don't support nesting.
thread_->message_loop()->Run();
}
void WebThreadImpl::exitRunLoop() {
CHECK(isCurrentThread());
CHECK(thread_->message_loop()->is_running());
thread_->message_loop()->Quit();
}
blink::WebScheduler* WebThreadImpl::scheduler() const {
return web_scheduler_.get();
}
bool WebThreadImpl::isCurrentThread() const {
return thread_->thread_id() == base::PlatformThread::CurrentId();
}
blink::PlatformThreadId WebThreadImpl::threadId() const {
return thread_->thread_id();
}
WebThreadImpl::~WebThreadImpl() {
thread_->Stop();
}
WebThreadImplForMessageLoop::WebThreadImplForMessageLoop(
base::MessageLoopProxy* message_loop)
: message_loop_(message_loop),
web_scheduler_(new WebSchedulerImpl(message_loop_)) {
}
void WebThreadImplForMessageLoop::postTask(
const blink::WebTraceLocation& location,
Task* task) {
postDelayedTask(location, task, 0);
}
void WebThreadImplForMessageLoop::postDelayedTask(
const blink::WebTraceLocation& web_location,
Task* task,
long long delay_ms) {
tracked_objects::Location location(web_location.functionName(),
web_location.fileName(), -1, nullptr);
message_loop_->PostDelayedTask(
location,
base::Bind(RunWebThreadTask, base::Passed(make_scoped_ptr(task))),
base::TimeDelta::FromMilliseconds(delay_ms));
}
void WebThreadImplForMessageLoop::enterRunLoop() {
CHECK(isCurrentThread());
// We don't support nesting.
CHECK(!base::MessageLoop::current()->is_running());
base::MessageLoop::current()->Run();
}
void WebThreadImplForMessageLoop::exitRunLoop() {
CHECK(isCurrentThread());
CHECK(base::MessageLoop::current()->is_running());
base::MessageLoop::current()->Quit();
}
blink::WebScheduler* WebThreadImplForMessageLoop::scheduler() const {
return web_scheduler_.get();
}
bool WebThreadImplForMessageLoop::isCurrentThread() const {
return message_loop_->BelongsToCurrentThread();
}
blink::PlatformThreadId WebThreadImplForMessageLoop::threadId() const {
return thread_id_;
}
WebThreadImplForMessageLoop::~WebThreadImplForMessageLoop() {}
} // namespace html_viewer
// 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 COMPONENTS_HTML_VIEWER_WEB_THREAD_IMPL_H_
#define COMPONENTS_HTML_VIEWER_WEB_THREAD_IMPL_H_
#include <map>
#include "base/memory/scoped_ptr.h"
#include "base/threading/thread.h"
#include "components/html_viewer/web_scheduler_impl.h"
#include "third_party/WebKit/public/platform/WebThread.h"
namespace html_viewer {
class WebThreadBase : public blink::WebThread {
public:
virtual ~WebThreadBase();
virtual void addTaskObserver(TaskObserver* observer);
virtual void removeTaskObserver(TaskObserver* observer);
virtual bool isCurrentThread() const = 0;
protected:
WebThreadBase();
private:
class TaskObserverAdapter;
typedef std::map<TaskObserver*, TaskObserverAdapter*> TaskObserverMap;
TaskObserverMap task_observer_map_;
};
class WebThreadImpl : public WebThreadBase {
public:
explicit WebThreadImpl(const char* name);
~WebThreadImpl() override;
virtual void postTask(const blink::WebTraceLocation& location, Task* task);
virtual void postDelayedTask(const blink::WebTraceLocation& location,
Task* task,
long long delay_ms);
virtual void enterRunLoop();
virtual void exitRunLoop();
virtual blink::WebScheduler* scheduler() const;
base::MessageLoop* message_loop() const { return thread_->message_loop(); }
bool isCurrentThread() const override;
virtual blink::PlatformThreadId threadId() const;
private:
scoped_ptr<base::Thread> thread_;
scoped_ptr<WebSchedulerImpl> web_scheduler_;
};
class WebThreadImplForMessageLoop : public WebThreadBase {
public:
explicit WebThreadImplForMessageLoop(
base::MessageLoopProxy* message_loop);
~WebThreadImplForMessageLoop() override;
virtual void postTask(const blink::WebTraceLocation& location, Task* task);
virtual void postDelayedTask(const blink::WebTraceLocation& location,
Task* task,
long long delay_ms);
virtual void enterRunLoop();
virtual void exitRunLoop();
virtual blink::WebScheduler* scheduler() const;
private:
bool isCurrentThread() const override;
virtual blink::PlatformThreadId threadId() const;
scoped_refptr<base::MessageLoopProxy> message_loop_;
scoped_ptr<WebSchedulerImpl> web_scheduler_;
blink::PlatformThreadId thread_id_;
};
} // namespace html_viewer
#endif // COMPONENTS_HTML_VIEWER_WEB_THREAD_IMPL_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment