diff --git a/DEPS b/DEPS index cb0b98e..78524f0b 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'a07741a75aa694c0e7c00c2301c9de2daf9b5f9e', + 'skia_revision': '9eac2ea77340d13bac58c7171e2e3971028ef8f8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'eda659cc5e307f20ac1ad542ba12ab32eaf4c7ef', + 'v8_revision': '2cba63960054ce9a88d4e3f1f5117b87566f6beb', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other.
diff --git a/WATCHLISTS b/WATCHLISTS index 6712d66..9fa9e6ed 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1379,6 +1379,9 @@ '|third_party/WebKit/LayoutTests/fast/file' \ '|third_party/WebKit/public/.*File' }, + 'blink_frames': { + 'filepath': 'third_party/WebKit/Source/core/frame/' + }, 'blink_quota': { 'filepath': 'third_party/WebKit/Source/modules/quota/' \ '|third_party/WebKit/Source/web/.*Quota' \ @@ -1646,6 +1649,7 @@ 'blink_fileapi': ['kinuko+fileapi@chromium.org', 'nhiroki@chromium.org', 'tzik@chromium.org'], + 'blink_frames': ['blink-reviews-frames@chromium.org'], 'blink_geolocation': ['mlamouri+watch-blink@chromium.org', 'mvanouwerkerk+watch@chromium.org', 'timvolodine@chromium.org'],
diff --git a/base/BUILD.gn b/base/BUILD.gn index 66d31ad..96ddf2f 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -846,6 +846,8 @@ "task_scheduler/scheduler_lock.h", "task_scheduler/scheduler_lock_impl.cc", "task_scheduler/scheduler_lock_impl.h", + "task_scheduler/scheduler_single_thread_task_runner_manager.cc", + "task_scheduler/scheduler_single_thread_task_runner_manager.h", "task_scheduler/scheduler_worker.cc", "task_scheduler/scheduler_worker.h", "task_scheduler/scheduler_worker_pool.h", @@ -2090,6 +2092,7 @@ "task_scheduler/delayed_task_manager_unittest.cc", "task_scheduler/priority_queue_unittest.cc", "task_scheduler/scheduler_lock_unittest.cc", + "task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc", "task_scheduler/scheduler_worker_pool_impl_unittest.cc", "task_scheduler/scheduler_worker_stack_unittest.cc", "task_scheduler/scheduler_worker_unittest.cc",
diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc b/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc new file mode 100644 index 0000000..71f9c0b --- /dev/null +++ b/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc
@@ -0,0 +1,274 @@ +// Copyright 2017 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 "base/task_scheduler/scheduler_single_thread_task_runner_manager.h" + +#include <algorithm> +#include <memory> +#include <string> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/memory/ptr_util.h" +#include "base/single_thread_task_runner.h" +#include "base/strings/stringprintf.h" +#include "base/synchronization/atomic_flag.h" +#include "base/task_scheduler/delayed_task_manager.h" +#include "base/task_scheduler/scheduler_worker.h" +#include "base/task_scheduler/sequence.h" +#include "base/task_scheduler/task.h" +#include "base/task_scheduler/task_tracker.h" +#include "base/task_scheduler/task_traits.h" +#include "base/threading/platform_thread.h" +#include "base/time/time.h" + +namespace base { +namespace internal { + +namespace { + +// Allows for checking the PlatformThread::CurrentRef() against a set +// PlatformThreadRef atomically without using locks. +class AtomicThreadRefChecker { + public: + AtomicThreadRefChecker() = default; + ~AtomicThreadRefChecker() = default; + + void Set() { + thread_ref_ = PlatformThread::CurrentRef(); + is_set_.Set(); + } + + bool IsCurrentThreadSameAsSetThread() { + return is_set_.IsSet() && thread_ref_ == PlatformThread::CurrentRef(); + } + + private: + AtomicFlag is_set_; + PlatformThreadRef thread_ref_; + + DISALLOW_COPY_AND_ASSIGN(AtomicThreadRefChecker); +}; + +class SchedulerWorkerDelegate : public SchedulerWorker::Delegate { + public: + SchedulerWorkerDelegate(const std::string& thread_name) + : thread_name_(thread_name) {} + + // SchedulerWorker::Delegate: + void OnMainEntry(SchedulerWorker* worker) override { + thread_ref_checker_.Set(); + PlatformThread::SetName(thread_name_); + } + + scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override { + AutoSchedulerLock auto_lock(sequence_lock_); + return std::move(sequence_); + } + + void DidRunTask() override {} + + void ReEnqueueSequence(scoped_refptr<Sequence> sequence) override { + AutoSchedulerLock auto_lock(sequence_lock_); + DCHECK(!sequence_); + sequence_ = std::move(sequence); + } + + TimeDelta GetSleepTimeout() override { return TimeDelta::Max(); } + + bool CanDetach(SchedulerWorker* worker) override { return false; } + + void OnDetach() override { NOTREACHED(); } + + bool RunsTasksOnCurrentThread() { + // We check the thread ref instead of the sequence for the benefit of COM + // callbacks which may execute without a sequence context. + return thread_ref_checker_.IsCurrentThreadSameAsSetThread(); + } + + private: + const std::string thread_name_; + + // Synchronizes access to |sequence_| and handles the fact that + // ReEnqueueSequence() is called on both the worker thread for reenqueuing + // the sequence and off of the worker thread to seed the sequence for + // GetWork(). + SchedulerLock sequence_lock_; + scoped_refptr<Sequence> sequence_; + + AtomicThreadRefChecker thread_ref_checker_; + + DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDelegate); +}; + +} // namespace + +class SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunner + : public SingleThreadTaskRunner { + public: + // Constructs a SchedulerSingleThreadTaskRunner that indirectly controls the + // lifetime of a dedicated |worker| for |traits|. + SchedulerSingleThreadTaskRunner( + SchedulerSingleThreadTaskRunnerManager* const outer, + const TaskTraits& traits, + SchedulerWorker* worker) + : outer_(outer), traits_(traits), worker_(worker) { + DCHECK(outer_); + DCHECK(worker_); + } + + // SingleThreadTaskRunner: + bool PostDelayedTask(const tracked_objects::Location& from_here, + const Closure& closure, + TimeDelta delay) override; + + bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, + const Closure& closure, + base::TimeDelta delay) override { + // Tasks are never nested within the task scheduler. + return PostDelayedTask(from_here, closure, delay); + } + + bool RunsTasksOnCurrentThread() const override { + auto* delegate = static_cast<SchedulerWorkerDelegate*>(worker_->delegate()); + return delegate->RunsTasksOnCurrentThread(); + } + + private: + ~SchedulerSingleThreadTaskRunner() override { + outer_->UnregisterSchedulerWorker(worker_); + } + + void PostTaskNow(std::unique_ptr<Task> task); + + // Sequence for all Tasks posted through this TaskRunner. + const scoped_refptr<Sequence> sequence_ = new Sequence; + + SchedulerSingleThreadTaskRunnerManager* const outer_; + const TaskTraits traits_; + SchedulerWorker* const worker_; + + DISALLOW_COPY_AND_ASSIGN(SchedulerSingleThreadTaskRunner); +}; + +bool SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunner:: + PostDelayedTask(const tracked_objects::Location& from_here, + const Closure& closure, + TimeDelta delay) { + auto task = MakeUnique<Task>(from_here, closure, traits_, delay); + task->single_thread_task_runner_ref = this; + + if (!outer_->task_tracker_->WillPostTask(task.get())) + return false; + + if (task->delayed_run_time.is_null()) { + PostTaskNow(std::move(task)); + } else { + outer_->delayed_task_manager_->AddDelayedTask( + std::move(task), + Bind(&SchedulerSingleThreadTaskRunner::PostTaskNow, Unretained(this))); + } + return true; +} + +void SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunner:: + PostTaskNow(std::unique_ptr<Task> task) { + const bool sequence_was_empty = sequence_->PushTask(std::move(task)); + if (sequence_was_empty) { + auto* delegate = static_cast<SchedulerWorkerDelegate*>(worker_->delegate()); + delegate->ReEnqueueSequence(sequence_); + worker_->WakeUp(); + } +} + +SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunnerManager( + const std::vector<SchedulerWorkerPoolParams>& worker_pool_params_vector, + const TaskScheduler::WorkerPoolIndexForTraitsCallback& + worker_pool_index_for_traits_callback, + TaskTracker* task_tracker, + DelayedTaskManager* delayed_task_manager) + : worker_pool_params_vector_(worker_pool_params_vector), + worker_pool_index_for_traits_callback_( + worker_pool_index_for_traits_callback), + task_tracker_(task_tracker), + delayed_task_manager_(delayed_task_manager) { + DCHECK_GT(worker_pool_params_vector_.size(), 0U); + DCHECK(worker_pool_index_for_traits_callback_); + DCHECK(task_tracker_); + DCHECK(delayed_task_manager_); +} + +SchedulerSingleThreadTaskRunnerManager:: + ~SchedulerSingleThreadTaskRunnerManager() { + DCHECK(workers_.empty()) << "SchedulerSingleThreadTaskRunners must outlive " + "SchedulerSingleThreadTaskRunnerManager"; +} + +scoped_refptr<SingleThreadTaskRunner> +SchedulerSingleThreadTaskRunnerManager::CreateSingleThreadTaskRunnerWithTraits( + const TaskTraits& traits) { + size_t index = worker_pool_index_for_traits_callback_.Run(traits); + DCHECK_LT(index, worker_pool_params_vector_.size()); + return new SchedulerSingleThreadTaskRunner( + this, traits, + CreateAndRegisterSchedulerWorker(worker_pool_params_vector_[index])); +} + +void SchedulerSingleThreadTaskRunnerManager::JoinForTesting() { + decltype(workers_) local_workers; + { + AutoSchedulerLock auto_lock(workers_lock_); + local_workers = std::move(workers_); + } + + for (const auto& worker : local_workers) + worker->JoinForTesting(); + + { + AutoSchedulerLock auto_lock(workers_lock_); + DCHECK(workers_.empty()) + << "New worker(s) unexpectedly registered during join."; + workers_ = std::move(local_workers); + } +} + +SchedulerWorker* +SchedulerSingleThreadTaskRunnerManager::CreateAndRegisterSchedulerWorker( + const SchedulerWorkerPoolParams& params) { + AutoSchedulerLock auto_lock(workers_lock_); + int id = next_worker_id_++; + auto delegate = MakeUnique<SchedulerWorkerDelegate>(base::StringPrintf( + "TaskSchedulerSingleThreadWorker%d%s", id, params.name().c_str())); + workers_.emplace_back(SchedulerWorker::Create( + params.priority_hint(), std::move(delegate), task_tracker_, + SchedulerWorker::InitialState::DETACHED)); + return workers_.back().get(); +} + +void SchedulerSingleThreadTaskRunnerManager::UnregisterSchedulerWorker( + SchedulerWorker* worker) { + // Cleanup uses a SchedulerLock, so call Cleanup() after releasing + // |workers_lock_|. + scoped_refptr<SchedulerWorker> worker_to_destroy; + { + AutoSchedulerLock auto_lock(workers_lock_); + + // We might be joining, so no-op this if |workers_| is empty. + if (workers_.empty()) + return; + + auto worker_iter = + std::find_if(workers_.begin(), workers_.end(), + [worker](const scoped_refptr<SchedulerWorker>& candidate) { + return candidate.get() == worker; + }); + DCHECK(worker_iter != workers_.end()); + worker_to_destroy = std::move(*worker_iter); + workers_.erase(worker_iter); + } + worker_to_destroy->Cleanup(); +} + +} // namespace internal +} // namespace base
diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager.h b/base/task_scheduler/scheduler_single_thread_task_runner_manager.h new file mode 100644 index 0000000..3b0ffd4f --- /dev/null +++ b/base/task_scheduler/scheduler_single_thread_task_runner_manager.h
@@ -0,0 +1,68 @@ +// Copyright 2017 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 BASE_TASK_SCHEDULER_SCHEDULER_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_ +#define BASE_TASK_SCHEDULER_SCHEDULER_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_ + +#include <vector> + +#include "base/base_export.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/task_scheduler/scheduler_lock.h" +#include "base/task_scheduler/scheduler_worker_pool_params.h" +#include "base/task_scheduler/task_scheduler.h" + +namespace base { + +class TaskTraits; +class SingleThreadTaskRunner; + +namespace internal { + +class DelayedTaskManager; +class SchedulerWorker; +class TaskTracker; + +class BASE_EXPORT SchedulerSingleThreadTaskRunnerManager final { + public: + SchedulerSingleThreadTaskRunnerManager( + const std::vector<SchedulerWorkerPoolParams>& worker_pool_params_vector, + const TaskScheduler::WorkerPoolIndexForTraitsCallback& + worker_pool_index_for_traits_callback, + TaskTracker* task_tracker, + DelayedTaskManager* delayed_task_manager); + ~SchedulerSingleThreadTaskRunnerManager(); + + scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunnerWithTraits( + const TaskTraits& traits); + + void JoinForTesting(); + + private: + class SchedulerSingleThreadTaskRunner; + + SchedulerWorker* CreateAndRegisterSchedulerWorker( + const SchedulerWorkerPoolParams& params); + + void UnregisterSchedulerWorker(SchedulerWorker* worker); + + const std::vector<SchedulerWorkerPoolParams> worker_pool_params_vector_; + const TaskScheduler::WorkerPoolIndexForTraitsCallback + worker_pool_index_for_traits_callback_; + TaskTracker* const task_tracker_; + DelayedTaskManager* const delayed_task_manager_; + + // Synchronizes access to |workers_| and |worker_id_|. + SchedulerLock workers_lock_; + std::vector<scoped_refptr<SchedulerWorker>> workers_; + int next_worker_id_ = 0; + + DISALLOW_COPY_AND_ASSIGN(SchedulerSingleThreadTaskRunnerManager); +}; + +} // namespace internal +} // namespace base + +#endif // BASE_TASK_SCHEDULER_SCHEDULER_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_
diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc b/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc new file mode 100644 index 0000000..6db240a7 --- /dev/null +++ b/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
@@ -0,0 +1,254 @@ +// Copyright 2017 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 "base/task_scheduler/scheduler_single_thread_task_runner_manager.h" + +#include "base/bind.h" +#include "base/memory/ptr_util.h" +#include "base/synchronization/lock.h" +#include "base/synchronization/waitable_event.h" +#include "base/task_scheduler/delayed_task_manager.h" +#include "base/task_scheduler/post_task.h" +#include "base/task_scheduler/scheduler_worker_pool_params.h" +#include "base/task_scheduler/task_tracker.h" +#include "base/task_scheduler/task_traits.h" +#include "base/test/test_timeouts.h" +#include "base/threading/thread.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +namespace internal { + +namespace { + +enum WorkerPoolType { + BACKGROUND_WORKER_POOL = 0, + FOREGROUND_WORKER_POOL, +}; + +static size_t GetThreadPoolIndexForTraits(const TaskTraits& traits) { + return traits.priority() == TaskPriority::BACKGROUND ? BACKGROUND_WORKER_POOL + : FOREGROUND_WORKER_POOL; +} + +class TaskSchedulerSingleThreadTaskRunnerManagerTest : public testing::Test { + public: + TaskSchedulerSingleThreadTaskRunnerManagerTest() + : service_thread_("TaskSchedulerServiceThread") {} + + void SetUp() override { + service_thread_.Start(); + + using StandbyThreadPolicy = SchedulerWorkerPoolParams::StandbyThreadPolicy; + + std::vector<SchedulerWorkerPoolParams> params_vector; + + ASSERT_EQ(BACKGROUND_WORKER_POOL, params_vector.size()); + params_vector.emplace_back("Background", ThreadPriority::BACKGROUND, + StandbyThreadPolicy::LAZY, 1U, TimeDelta::Max()); + + ASSERT_EQ(FOREGROUND_WORKER_POOL, params_vector.size()); + params_vector.emplace_back("Foreground", ThreadPriority::NORMAL, + StandbyThreadPolicy::LAZY, 1U, TimeDelta::Max()); + + delayed_task_manager_ = + MakeUnique<DelayedTaskManager>(service_thread_.task_runner()); + single_thread_task_runner_manager_ = + MakeUnique<SchedulerSingleThreadTaskRunnerManager>( + params_vector, Bind(&GetThreadPoolIndexForTraits), &task_tracker_, + delayed_task_manager_.get()); + } + + void TearDown() override { + single_thread_task_runner_manager_->JoinForTesting(); + single_thread_task_runner_manager_.reset(); + delayed_task_manager_.reset(); + service_thread_.Stop(); + } + + protected: + std::unique_ptr<SchedulerSingleThreadTaskRunnerManager> + single_thread_task_runner_manager_; + TaskTracker task_tracker_; + + private: + Thread service_thread_; + std::unique_ptr<DelayedTaskManager> delayed_task_manager_; + + DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTest); +}; + +void CaptureThreadRef(PlatformThreadRef* thread_ref) { + ASSERT_TRUE(thread_ref); + *thread_ref = PlatformThread::CurrentRef(); +} + +void CaptureThreadPriority(ThreadPriority* thread_priority) { + ASSERT_TRUE(thread_priority); + *thread_priority = PlatformThread::GetCurrentThreadPriority(); +} + +void ShouldNotRun() { + ADD_FAILURE() << "Ran a task that shouldn't run."; +} + +} // namespace + +TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, DifferentThreadsUsed) { + scoped_refptr<SingleThreadTaskRunner> task_runner_1 = + single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits( + TaskTraits().WithShutdownBehavior( + TaskShutdownBehavior::BLOCK_SHUTDOWN)); + scoped_refptr<SingleThreadTaskRunner> task_runner_2 = + single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits( + TaskTraits().WithShutdownBehavior( + TaskShutdownBehavior::BLOCK_SHUTDOWN)); + + PlatformThreadRef thread_ref_1; + task_runner_1->PostTask(FROM_HERE, Bind(&CaptureThreadRef, &thread_ref_1)); + PlatformThreadRef thread_ref_2; + task_runner_2->PostTask(FROM_HERE, Bind(&CaptureThreadRef, &thread_ref_2)); + + task_tracker_.Shutdown(); + + ASSERT_FALSE(thread_ref_1.is_null()); + ASSERT_FALSE(thread_ref_2.is_null()); + EXPECT_NE(thread_ref_1, thread_ref_2); +} + +TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PrioritySetCorrectly) { + // Why are events used here instead of the task tracker? + // Shutting down can cause priorities to get raised. This means we have to use + // events to determine when a task is run. + scoped_refptr<SingleThreadTaskRunner> task_runner_background = + single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits( + TaskTraits().WithPriority(TaskPriority::BACKGROUND)); + scoped_refptr<SingleThreadTaskRunner> task_runner_user_visible = + single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits( + TaskTraits().WithPriority(TaskPriority::USER_VISIBLE)); + scoped_refptr<SingleThreadTaskRunner> task_runner_user_blocking = + single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits( + TaskTraits() + .WithPriority(TaskPriority::USER_BLOCKING) + .WithShutdownBehavior(TaskShutdownBehavior::BLOCK_SHUTDOWN)); + + ThreadPriority thread_priority_background; + task_runner_background->PostTask( + FROM_HERE, Bind(&CaptureThreadPriority, &thread_priority_background)); + WaitableEvent waitable_event_background( + WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + task_runner_background->PostTask( + FROM_HERE, + Bind(&WaitableEvent::Signal, Unretained(&waitable_event_background))); + + ThreadPriority thread_priority_user_visible; + task_runner_user_visible->PostTask( + FROM_HERE, Bind(&CaptureThreadPriority, &thread_priority_user_visible)); + WaitableEvent waitable_event_user_visible( + WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + task_runner_user_visible->PostTask( + FROM_HERE, + Bind(&WaitableEvent::Signal, Unretained(&waitable_event_user_visible))); + + ThreadPriority thread_priority_user_blocking; + task_runner_user_blocking->PostTask( + FROM_HERE, Bind(&CaptureThreadPriority, &thread_priority_user_blocking)); + WaitableEvent waitable_event_user_blocking( + WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + task_runner_user_blocking->PostTask( + FROM_HERE, + Bind(&WaitableEvent::Signal, Unretained(&waitable_event_user_blocking))); + + waitable_event_background.Wait(); + waitable_event_user_visible.Wait(); + waitable_event_user_blocking.Wait(); + + if (Lock::HandlesMultipleThreadPriorities()) + EXPECT_EQ(ThreadPriority::BACKGROUND, thread_priority_background); + else + EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_background); + EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_user_visible); + EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_user_blocking); +} + +TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostTaskAfterShutdown) { + auto task_runner = single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); + task_tracker_.Shutdown(); + EXPECT_FALSE(task_runner->PostTask(FROM_HERE, Bind(&ShouldNotRun))); +} + +// Verify that a Task runs shortly after its delay expires. +TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostDelayedTask) { + TimeTicks start_time = TimeTicks::Now(); + + // Post a task with a short delay. + WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + auto task_runner = single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); + EXPECT_TRUE(task_runner->PostDelayedTask( + FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_ran)), + TestTimeouts::tiny_timeout())); + + // Wait until the task runs. + task_ran.Wait(); + + // Expect the task to run after its delay expires, but not more than 250 ms + // after that. + const TimeDelta actual_delay = TimeTicks::Now() - start_time; + EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout()); + EXPECT_LT(actual_delay, + TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout()); +} + +TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, + RunsTasksOnCurrentThread) { + scoped_refptr<SingleThreadTaskRunner> task_runner_1 = + single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits( + TaskTraits().WithShutdownBehavior( + TaskShutdownBehavior::BLOCK_SHUTDOWN)); + scoped_refptr<SingleThreadTaskRunner> task_runner_2 = + single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits( + TaskTraits().WithShutdownBehavior( + TaskShutdownBehavior::BLOCK_SHUTDOWN)); + + EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread()); + EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread()); + + task_runner_1->PostTask( + FROM_HERE, + Bind( + [](scoped_refptr<SingleThreadTaskRunner> task_runner_1, + scoped_refptr<SingleThreadTaskRunner> task_runner_2) { + EXPECT_TRUE(task_runner_1->RunsTasksOnCurrentThread()); + EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread()); + }, + task_runner_1, task_runner_2)); + + task_runner_2->PostTask( + FROM_HERE, + Bind( + [](scoped_refptr<SingleThreadTaskRunner> task_runner_1, + scoped_refptr<SingleThreadTaskRunner> task_runner_2) { + EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread()); + EXPECT_TRUE(task_runner_2->RunsTasksOnCurrentThread()); + }, + task_runner_1, task_runner_2)); + + task_tracker_.Shutdown(); +} + +} // namespace internal +} // namespace base
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.cc b/base/task_scheduler/scheduler_worker_pool_impl.cc index 22aa2c65..9a6a20b 100644 --- a/base/task_scheduler/scheduler_worker_pool_impl.cc +++ b/base/task_scheduler/scheduler_worker_pool_impl.cc
@@ -141,6 +141,7 @@ } // namespace +// TODO(http://crbug.com/694823): Remove this and supporting framework. // A task runner that runs tasks with the SINGLE_THREADED ExecutionMode. class SchedulerWorkerPoolImpl::SchedulerSingleThreadTaskRunner : public SingleThreadTaskRunner {
diff --git a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc index dfaa9c7f..d8aa212 100644 --- a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc +++ b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
@@ -719,6 +719,104 @@ worker_pool_->DisallowWorkerDetachmentForTesting(); } +TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeDetach) { + InitializeWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); + + auto histogrammed_thread_task_runner = + worker_pool_->CreateSequencedTaskRunnerWithTraits( + TaskTraits().WithBaseSyncPrimitives()); + + // Post 3 tasks and hold the thread for idle thread stack ordering. + // This test assumes |histogrammed_thread_task_runner| gets assigned the same + // thread for each of its tasks. + PlatformThreadRef thread_ref; + histogrammed_thread_task_runner->PostTask( + FROM_HERE, Bind( + [](PlatformThreadRef* thread_ref) { + ASSERT_TRUE(thread_ref); + *thread_ref = PlatformThread::CurrentRef(); + }, + Unretained(&thread_ref))); + histogrammed_thread_task_runner->PostTask( + FROM_HERE, Bind( + [](PlatformThreadRef thread_ref) { + EXPECT_EQ(thread_ref, PlatformThreadRef()); + }, + thread_ref)); + WaitableEvent detach_thread_running( + WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + WaitableEvent detach_thread_continue( + WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + histogrammed_thread_task_runner->PostTask( + FROM_HERE, + Bind( + [](PlatformThreadRef thread_ref, WaitableEvent* detach_thread_running, + WaitableEvent* detach_thread_continue) { + EXPECT_EQ(thread_ref, PlatformThreadRef()); + detach_thread_running->Signal(); + detach_thread_continue->Wait(); + }, + thread_ref, Unretained(&detach_thread_running), + Unretained(&detach_thread_continue))); + + detach_thread_running.Wait(); + + // To allow the SchedulerWorker associated with + // |histogrammed_thread_task_runner| to detach, make sure it isn't on top of + // the idle stack by waking up another SchedulerWorker via + // |task_runner_for_top_idle|. |histogrammed_thread_task_runner| should + // release and go idle first and then |task_runner_for_top_idle| should + // release and go idle. This allows the SchedulerWorker associated with + // |histogrammed_thread_task_runner| to detach. + WaitableEvent top_idle_thread_running( + WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + WaitableEvent top_idle_thread_continue( + WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + auto task_runner_for_top_idle = + worker_pool_->CreateSequencedTaskRunnerWithTraits( + TaskTraits().WithBaseSyncPrimitives()); + task_runner_for_top_idle->PostTask( + FROM_HERE, Bind( + [](PlatformThreadRef thread_ref, + WaitableEvent* top_idle_thread_running, + WaitableEvent* top_idle_thread_continue) { + EXPECT_NE(thread_ref, PlatformThread::CurrentRef()) + << "Worker reused. Thread will not detach and the " + "histogram value will be wrong."; + top_idle_thread_running->Signal(); + top_idle_thread_continue->Wait(); + }, + thread_ref, Unretained(&top_idle_thread_running), + Unretained(&top_idle_thread_continue))); + top_idle_thread_running.Wait(); + detach_thread_continue.Signal(); + // Wait for the thread processing the |histogrammed_thread_task_runner| work + // to go to the idle stack. + PlatformThread::Sleep(TestTimeouts::tiny_timeout()); + top_idle_thread_continue.Signal(); + // Allow the thread processing the |histogrammed_thread_task_runner| work to + // detach. + PlatformThread::Sleep(kReclaimTimeForDetachTests + + kReclaimTimeForDetachTests); + worker_pool_->WaitForAllWorkersIdleForTesting(); + worker_pool_->DisallowWorkerDetachmentForTesting(); + + // Verify that counts were recorded to the histogram as expected. + const auto* histogram = worker_pool_->num_tasks_before_detach_histogram(); + EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0)); + EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(1)); + EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(2)); + EXPECT_EQ(1, histogram->SnapshotSamples()->GetCount(3)); + EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(4)); + EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(5)); + EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(6)); + EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10)); +} + namespace { void NotReachedReEnqueueSequenceCallback(scoped_refptr<Sequence> sequence) { @@ -726,53 +824,8 @@ << "Unexpected invocation of NotReachedReEnqueueSequenceCallback."; } -void CaptureThreadId(PlatformThreadId* thread_id) { - ASSERT_TRUE(thread_id); - *thread_id = PlatformThread::CurrentId(); -} - -void VerifyThreadIdIsNot(PlatformThreadId thread_id) { - EXPECT_NE(thread_id, PlatformThread::CurrentId()); -} - } // namespace -TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeDetach) { - InitializeWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); - - // This test assumes that the TaskRunners aren't assigned to the same worker. - auto task_runner = - worker_pool_->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); - auto other_task_runner = - worker_pool_->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); - - // Post 3 tasks and wait until they run. - PlatformThreadId thread_id; - task_runner->PostTask(FROM_HERE, - Bind(&CaptureThreadId, Unretained(&thread_id))); - task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); - task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); - worker_pool_->WaitForAllWorkersIdleForTesting(); - - // To allow the SchedulerWorker associated with |task_runner| to detach: - // - Make sure it isn't on top of the idle stack by waking up another - // SchedulerWorker and waiting until it goes back to sleep. - // - Release |task_runner|. - other_task_runner->PostTask(FROM_HERE, Bind(&VerifyThreadIdIsNot, thread_id)); - worker_pool_->WaitForAllWorkersIdleForTesting(); - task_runner = nullptr; - - // Allow the SchedulerWorker that was associated with |task_runner| to detach. - PlatformThread::Sleep(kReclaimTimeForDetachTests + kExtraTimeToWaitForDetach); - worker_pool_->DisallowWorkerDetachmentForTesting(); - - // Verify that counts were recorded to the histogram as expected. - const auto* histogram = worker_pool_->num_tasks_before_detach_histogram(); - EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0)); - EXPECT_EQ(1, histogram->SnapshotSamples()->GetCount(3)); - EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10)); -} - TEST(TaskSchedulerWorkerPoolStandbyPolicyTest, InitLazy) { TaskTracker task_tracker; DelayedTaskManager delayed_task_manager(
diff --git a/base/task_scheduler/scheduler_worker_pool_params.cc b/base/task_scheduler/scheduler_worker_pool_params.cc index 0747c2e..43a66d0 100644 --- a/base/task_scheduler/scheduler_worker_pool_params.cc +++ b/base/task_scheduler/scheduler_worker_pool_params.cc
@@ -21,9 +21,9 @@ backward_compatibility_(backward_compatibility) {} SchedulerWorkerPoolParams::SchedulerWorkerPoolParams( - SchedulerWorkerPoolParams&& other) = default; + const SchedulerWorkerPoolParams& other) = default; SchedulerWorkerPoolParams& SchedulerWorkerPoolParams::operator=( - SchedulerWorkerPoolParams&& other) = default; + const SchedulerWorkerPoolParams& other) = default; } // namespace base
diff --git a/base/task_scheduler/scheduler_worker_pool_params.h b/base/task_scheduler/scheduler_worker_pool_params.h index 5f90fd4..4c0548c5 100644 --- a/base/task_scheduler/scheduler_worker_pool_params.h +++ b/base/task_scheduler/scheduler_worker_pool_params.h
@@ -7,7 +7,6 @@ #include <string> -#include "base/macros.h" #include "base/task_scheduler/scheduler_worker_params.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" @@ -42,8 +41,8 @@ TimeDelta suggested_reclaim_time, SchedulerBackwardCompatibility backward_compatibility = SchedulerBackwardCompatibility::DISABLED); - SchedulerWorkerPoolParams(SchedulerWorkerPoolParams&& other); - SchedulerWorkerPoolParams& operator=(SchedulerWorkerPoolParams&& other); + SchedulerWorkerPoolParams(const SchedulerWorkerPoolParams& other); + SchedulerWorkerPoolParams& operator=(const SchedulerWorkerPoolParams& other); const std::string& name() const { return name_; } ThreadPriority priority_hint() const { return priority_hint_; } @@ -63,8 +62,6 @@ size_t max_threads_; TimeDelta suggested_reclaim_time_; SchedulerBackwardCompatibility backward_compatibility_; - - DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerPoolParams); }; } // namespace base
diff --git a/base/task_scheduler/task_scheduler_impl_unittest.cc b/base/task_scheduler/task_scheduler_impl_unittest.cc index 6aaf4af..bacedb7 100644 --- a/base/task_scheduler/task_scheduler_impl_unittest.cc +++ b/base/task_scheduler/task_scheduler_impl_unittest.cc
@@ -322,5 +322,49 @@ TaskTraits().WithPriority(TaskPriority::USER_BLOCKING).MayBlock())); } +// Verify that the RunsTasksOnCurrentThread() method of a SequencedTaskRunner +// returns false when called from a task that isn't part of the sequence. +TEST_F(TaskSchedulerImplTest, SequencedRunsTasksOnCurrentThread) { + auto single_thread_task_runner = + scheduler_->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); + auto sequenced_task_runner = + scheduler_->CreateSequencedTaskRunnerWithTraits(TaskTraits()); + + WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + single_thread_task_runner->PostTask( + FROM_HERE, + Bind( + [](scoped_refptr<TaskRunner> sequenced_task_runner, + WaitableEvent* task_ran) { + EXPECT_FALSE(sequenced_task_runner->RunsTasksOnCurrentThread()); + task_ran->Signal(); + }, + sequenced_task_runner, Unretained(&task_ran))); + task_ran.Wait(); +} + +// Verify that the RunsTasksOnCurrentThread() method of a SingleThreadTaskRunner +// returns false when called from a task that isn't part of the sequence. +TEST_F(TaskSchedulerImplTest, SingleThreadRunsTasksOnCurrentThread) { + auto sequenced_task_runner = + scheduler_->CreateSequencedTaskRunnerWithTraits(TaskTraits()); + auto single_thread_task_runner = + scheduler_->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); + + WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + sequenced_task_runner->PostTask( + FROM_HERE, + Bind( + [](scoped_refptr<TaskRunner> single_thread_task_runner, + WaitableEvent* task_ran) { + EXPECT_FALSE(single_thread_task_runner->RunsTasksOnCurrentThread()); + task_ran->Signal(); + }, + single_thread_task_runner, Unretained(&task_ran))); + task_ran.Wait(); +} + } // namespace internal } // namespace base
diff --git a/base/threading/platform_thread.h b/base/threading/platform_thread.h index f886904..8c0d8e4 100644 --- a/base/threading/platform_thread.h +++ b/base/threading/platform_thread.h
@@ -63,6 +63,8 @@ return id_ == other.id_; } + bool operator!=(PlatformThreadRef other) const { return id_ != other.id_; } + bool is_null() const { return id_ == 0; }
diff --git a/chrome/VERSION b/chrome/VERSION index 03c5666..8300881 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=58 MINOR=0 -BUILD=3025 +BUILD=3026 PATCH=0
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc b/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc index 9db262e..8e15742 100644 --- a/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc +++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
@@ -324,8 +324,9 @@ extensions::SOURCE_NETWORK); file_manager::VolumeManager::Get(browser()->profile()) - ->AddVolumeForTesting(file_manager::Volume::CreateForProvidedFileSystem( - info, file_manager::MOUNT_CONTEXT_AUTO)); + ->AddVolumeForTesting( + make_linked_ptr(file_manager::Volume::CreateForProvidedFileSystem( + info, file_manager::MOUNT_CONTEXT_AUTO))); // We will call fileManagerPrivate.unmountVolume once. To test that method, we // check that UnmountPath is really called with the same value.
diff --git a/chrome/browser/chromeos/extensions/file_manager/job_event_router.cc b/chrome/browser/chromeos/extensions/file_manager/job_event_router.cc index 529bc17..daf2fb3 100644 --- a/chrome/browser/chromeos/extensions/file_manager/job_event_router.cc +++ b/chrome/browser/chromeos/extensions/file_manager/job_event_router.cc
@@ -48,7 +48,7 @@ // Add new job info. UpdateBytes(job_info); - drive_jobs_[job_info.job_id] = base::MakeUnique<drive::JobInfo>(job_info); + drive_jobs_[job_info.job_id] = make_linked_ptr(new drive::JobInfo(job_info)); ScheduleDriveFileTransferEvent( job_info, file_manager_private::TRANSFER_STATE_IN_PROGRESS,
diff --git a/chrome/browser/chromeos/extensions/file_manager/job_event_router.h b/chrome/browser/chromeos/extensions/file_manager/job_event_router.h index ea787a67..85e4dc5 100644 --- a/chrome/browser/chromeos/extensions/file_manager/job_event_router.h +++ b/chrome/browser/chromeos/extensions/file_manager/job_event_router.h
@@ -13,6 +13,7 @@ #include <string> #include "base/macros.h" +#include "base/memory/linked_ptr.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" @@ -81,7 +82,7 @@ base::TimeDelta event_delay_; // Set of job that are in the job schedular. - std::map<drive::JobID, std::unique_ptr<drive::JobInfo>> drive_jobs_; + std::map<drive::JobID, linked_ptr<drive::JobInfo>> drive_jobs_; // Job info of pending event. |ScheduleDriveFileTransferEvent| registers // timeout callback to dispatch this.
diff --git a/chrome/browser/chromeos/extensions/file_manager/job_event_router_unittest.cc b/chrome/browser/chromeos/extensions/file_manager/job_event_router_unittest.cc index 13f220e..8b84ea50 100644 --- a/chrome/browser/chromeos/extensions/file_manager/job_event_router_unittest.cc +++ b/chrome/browser/chromeos/extensions/file_manager/job_event_router_unittest.cc
@@ -8,7 +8,6 @@ #include <stdint.h> #include "base/macros.h" -#include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "testing/gtest/include/gtest/gtest.h" @@ -21,7 +20,7 @@ JobEventRouterImpl() : JobEventRouter(base::TimeDelta::FromMilliseconds(0)) { listener_extension_ids_.insert("extension_a"); } - std::vector<std::unique_ptr<base::DictionaryValue>> events; + std::vector<linked_ptr<base::DictionaryValue>> events; void SetListenerExtensionIds(std::set<std::string> extension_ids) { listener_extension_ids_ = extension_ids; @@ -50,7 +49,7 @@ std::unique_ptr<base::ListValue> event_args) override { const base::DictionaryValue* event; event_args->GetDictionary(0, &event); - events.push_back(base::WrapUnique(event->DeepCopy())); + events.push_back(make_linked_ptr(event->DeepCopy())); } private:
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.cc b/chrome/browser/chromeos/file_manager/volume_manager.cc index b8aef48..8d592b6 100644 --- a/chrome/browser/chromeos/file_manager/volume_manager.cc +++ b/chrome/browser/chromeos/file_manager/volume_manager.cc
@@ -168,10 +168,10 @@ } // static -std::unique_ptr<Volume> Volume::CreateForDrive(Profile* profile) { +Volume* Volume::CreateForDrive(Profile* profile) { const base::FilePath& drive_path = drive::util::GetDriveMountPointPath(profile); - std::unique_ptr<Volume> volume(new Volume()); + Volume* const volume = new Volume; volume->type_ = VOLUME_TYPE_GOOGLE_DRIVE; volume->device_type_ = chromeos::DEVICE_TYPE_UNKNOWN; volume->source_path_ = drive_path; @@ -184,9 +184,8 @@ } // static -std::unique_ptr<Volume> Volume::CreateForDownloads( - const base::FilePath& downloads_path) { - std::unique_ptr<Volume> volume(new Volume()); +Volume* Volume::CreateForDownloads(const base::FilePath& downloads_path) { + Volume* const volume = new Volume; volume->type_ = VOLUME_TYPE_DOWNLOADS_DIRECTORY; volume->device_type_ = chromeos::DEVICE_TYPE_UNKNOWN; // Keep source_path empty. @@ -199,10 +198,10 @@ } // static -std::unique_ptr<Volume> Volume::CreateForRemovable( +Volume* Volume::CreateForRemovable( const chromeos::disks::DiskMountManager::MountPointInfo& mount_point, const chromeos::disks::DiskMountManager::Disk* disk) { - std::unique_ptr<Volume> volume(new Volume()); + Volume* const volume = new Volume; volume->type_ = MountTypeToVolumeType(mount_point.mount_type); volume->source_path_ = base::FilePath(mount_point.source_path); volume->source_ = mount_point.mount_type == chromeos::MOUNT_TYPE_ARCHIVE @@ -229,11 +228,11 @@ } // static -std::unique_ptr<Volume> Volume::CreateForProvidedFileSystem( +Volume* Volume::CreateForProvidedFileSystem( const chromeos::file_system_provider::ProvidedFileSystemInfo& file_system_info, MountContext mount_context) { - std::unique_ptr<Volume> volume(new Volume()); + Volume* const volume = new Volume; volume->file_system_id_ = file_system_info.file_system_id(); volume->extension_id_ = file_system_info.extension_id(); switch (file_system_info.source()) { @@ -261,10 +260,10 @@ } // static -std::unique_ptr<Volume> Volume::CreateForMTP(const base::FilePath& mount_path, - const std::string& label, - bool read_only) { - std::unique_ptr<Volume> volume(new Volume()); +Volume* Volume::CreateForMTP(const base::FilePath& mount_path, + const std::string& label, + bool read_only) { + Volume* const volume = new Volume; volume->type_ = VOLUME_TYPE_MTP; volume->mount_path_ = mount_path; volume->mount_condition_ = chromeos::disks::MOUNT_CONDITION_NONE; @@ -279,9 +278,8 @@ } // static -std::unique_ptr<Volume> Volume::CreateForMediaView( - const std::string& root_document_id) { - std::unique_ptr<Volume> volume(new Volume()); +Volume* Volume::CreateForMediaView(const std::string& root_document_id) { + Volume* const volume = new Volume; volume->type_ = VOLUME_TYPE_MEDIA_VIEW; volume->device_type_ = chromeos::DEVICE_TYPE_UNKNOWN; volume->source_ = SOURCE_SYSTEM; @@ -296,12 +294,11 @@ } // static -std::unique_ptr<Volume> Volume::CreateForTesting( - const base::FilePath& path, - VolumeType volume_type, - chromeos::DeviceType device_type, - bool read_only) { - std::unique_ptr<Volume> volume(new Volume()); +Volume* Volume::CreateForTesting(const base::FilePath& path, + VolumeType volume_type, + chromeos::DeviceType device_type, + bool read_only) { + Volume* const volume = new Volume; volume->type_ = volume_type; volume->device_type_ = device_type; // Keep source_path empty. @@ -314,10 +311,9 @@ } // static -std::unique_ptr<Volume> Volume::CreateForTesting( - const base::FilePath& device_path, - const base::FilePath& mount_path) { - std::unique_ptr<Volume> volume(new Volume()); +Volume* Volume::CreateForTesting(const base::FilePath& device_path, + const base::FilePath& mount_path) { + Volume* const volume = new Volume; volume->system_path_prefix_ = device_path; volume->mount_path_ = mount_path; return volume; @@ -359,14 +355,14 @@ DCHECK(success); DoMountEvent(chromeos::MOUNT_ERROR_NONE, - Volume::CreateForDownloads(downloads)); + make_linked_ptr(Volume::CreateForDownloads(downloads))); // Subscribe to DriveIntegrationService. if (drive_integration_service_) { drive_integration_service_->AddObserver(this); if (drive_integration_service_->IsMounted()) { DoMountEvent(chromeos::MOUNT_ERROR_NONE, - Volume::CreateForDrive(profile_)); + make_linked_ptr(Volume::CreateForDrive(profile_))); } } @@ -386,9 +382,9 @@ std::vector<ProvidedFileSystemInfo> file_system_info_list = file_system_provider_service_->GetProvidedFileSystemInfoList(); for (size_t i = 0; i < file_system_info_list.size(); ++i) { - std::unique_ptr<Volume> volume = Volume::CreateForProvidedFileSystem( - file_system_info_list[i], MOUNT_CONTEXT_AUTO); - DoMountEvent(chromeos::MOUNT_ERROR_NONE, std::move(volume)); + linked_ptr<Volume> volume(Volume::CreateForProvidedFileSystem( + file_system_info_list[i], MOUNT_CONTEXT_AUTO)); + DoMountEvent(chromeos::MOUNT_ERROR_NONE, volume); } } @@ -461,7 +457,6 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); std::vector<base::WeakPtr<Volume>> result; - result.reserve(mounted_volumes_.size()); for (const auto& pair : mounted_volumes_) { result.push_back(pair.second->AsWeakPtr()); } @@ -485,13 +480,13 @@ base::FilePath old_path; if (FindDownloadsMountPointPath(profile_, &old_path)) { DoUnmountEvent(chromeos::MOUNT_ERROR_NONE, - *Volume::CreateForDownloads(old_path)); + make_linked_ptr(Volume::CreateForDownloads(old_path))); } bool success = RegisterDownloadsMountPoint(profile_, path); DoMountEvent( success ? chromeos::MOUNT_ERROR_NONE : chromeos::MOUNT_ERROR_INVALID_PATH, - Volume::CreateForDownloads(path)); + make_linked_ptr(Volume::CreateForDownloads(path))); return success; } @@ -500,14 +495,14 @@ chromeos::DeviceType device_type, bool read_only) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DoMountEvent( - chromeos::MOUNT_ERROR_NONE, - Volume::CreateForTesting(path, volume_type, device_type, read_only)); + DoMountEvent(chromeos::MOUNT_ERROR_NONE, + make_linked_ptr(Volume::CreateForTesting( + path, volume_type, device_type, read_only))); } -void VolumeManager::AddVolumeForTesting(std::unique_ptr<Volume> volume) { +void VolumeManager::AddVolumeForTesting(const linked_ptr<Volume>& volume) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DoMountEvent(chromeos::MOUNT_ERROR_NONE, std::move(volume)); + DoMountEvent(chromeos::MOUNT_ERROR_NONE, volume); } void VolumeManager::OnFileSystemMounted() { @@ -516,13 +511,15 @@ // Raise mount event. // We can pass chromeos::MOUNT_ERROR_NONE even when authentication is failed // or network is unreachable. These two errors will be handled later. - DoMountEvent(chromeos::MOUNT_ERROR_NONE, Volume::CreateForDrive(profile_)); + linked_ptr<Volume> volume(Volume::CreateForDrive(profile_)); + DoMountEvent(chromeos::MOUNT_ERROR_NONE, volume); } void VolumeManager::OnFileSystemBeingUnmounted() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DoUnmountEvent(chromeos::MOUNT_ERROR_NONE, *Volume::CreateForDrive(profile_)); + linked_ptr<Volume> volume(Volume::CreateForDrive(profile_)); + DoUnmountEvent(chromeos::MOUNT_ERROR_NONE, volume); } void VolumeManager::OnDiskEvent( @@ -632,14 +629,14 @@ // Notify a mounting/unmounting event to observers. const chromeos::disks::DiskMountManager::Disk* const disk = disk_mount_manager_->FindDiskBySourcePath(mount_info.source_path); - std::unique_ptr<Volume> volume = Volume::CreateForRemovable(mount_info, disk); + linked_ptr<Volume> volume(Volume::CreateForRemovable(mount_info, disk)); switch (event) { case chromeos::disks::DiskMountManager::MOUNTING: { - DoMountEvent(error_code, std::move(volume)); + DoMountEvent(error_code, volume); return; } case chromeos::disks::DiskMountManager::UNMOUNTING: - DoUnmountEvent(error_code, *volume); + DoUnmountEvent(error_code, volume); return; } NOTREACHED(); @@ -697,8 +694,8 @@ break; } - std::unique_ptr<Volume> volume = - Volume::CreateForProvidedFileSystem(file_system_info, volume_context); + linked_ptr<Volume> volume( + Volume::CreateForProvidedFileSystem(file_system_info, volume_context)); // TODO(mtomasz): Introduce own type, and avoid using MountError internally, // since it is related to cros disks only. @@ -715,7 +712,7 @@ break; } - DoMountEvent(mount_error, std::move(volume)); + DoMountEvent(mount_error, volume); } void VolumeManager::OnProvidedFileSystemUnmount( @@ -727,9 +724,9 @@ const chromeos::MountError mount_error = error == base::File::FILE_OK ? chromeos::MOUNT_ERROR_NONE : chromeos::MOUNT_ERROR_UNKNOWN; - std::unique_ptr<Volume> volume = Volume::CreateForProvidedFileSystem( - file_system_info, MOUNT_CONTEXT_UNKNOWN); - DoUnmountEvent(mount_error, *volume); + linked_ptr<Volume> volume(Volume::CreateForProvidedFileSystem( + file_system_info, MOUNT_CONTEXT_UNKNOWN)); + DoUnmountEvent(mount_error, volume); } void VolumeManager::OnExternalStorageDisabledChangedUnmountCallback( @@ -756,18 +753,24 @@ if (enabled) { DoMountEvent(chromeos::MOUNT_ERROR_NONE, - Volume::CreateForMediaView(arc::kImagesRootDocumentId)); + linked_ptr<Volume>( + Volume::CreateForMediaView(arc::kImagesRootDocumentId))); DoMountEvent(chromeos::MOUNT_ERROR_NONE, - Volume::CreateForMediaView(arc::kVideosRootDocumentId)); + linked_ptr<Volume>( + Volume::CreateForMediaView(arc::kVideosRootDocumentId))); DoMountEvent(chromeos::MOUNT_ERROR_NONE, - Volume::CreateForMediaView(arc::kAudioRootDocumentId)); + linked_ptr<Volume>( + Volume::CreateForMediaView(arc::kAudioRootDocumentId))); } else { DoUnmountEvent(chromeos::MOUNT_ERROR_NONE, - *Volume::CreateForMediaView(arc::kImagesRootDocumentId)); + linked_ptr<Volume>( + Volume::CreateForMediaView(arc::kImagesRootDocumentId))); DoUnmountEvent(chromeos::MOUNT_ERROR_NONE, - *Volume::CreateForMediaView(arc::kVideosRootDocumentId)); + linked_ptr<Volume>( + Volume::CreateForMediaView(arc::kVideosRootDocumentId))); DoUnmountEvent(chromeos::MOUNT_ERROR_NONE, - *Volume::CreateForMediaView(arc::kAudioRootDocumentId)); + linked_ptr<Volume>( + Volume::CreateForMediaView(arc::kAudioRootDocumentId))); } arc_volumes_mounted_ = enabled; @@ -855,8 +858,8 @@ base::Unretained(MTPDeviceMapService::GetInstance()), info.location(), fsid, read_only)); - std::unique_ptr<Volume> volume = Volume::CreateForMTP(path, label, read_only); - DoMountEvent(chromeos::MOUNT_ERROR_NONE, std::move(volume)); + linked_ptr<Volume> volume(Volume::CreateForMTP(path, label, read_only)); + DoMountEvent(chromeos::MOUNT_ERROR_NONE, volume); } void VolumeManager::OnRemovableStorageDetached( @@ -864,9 +867,9 @@ if (!storage_monitor::StorageInfo::IsMTPDevice(info.device_id())) return; - for (const auto& mounted_volume : mounted_volumes_) { + for (const auto mounted_volume : mounted_volumes_) { if (mounted_volume.second->source_path().value() == info.location()) { - DoUnmountEvent(chromeos::MOUNT_ERROR_NONE, *mounted_volume.second.get()); + DoUnmountEvent(chromeos::MOUNT_ERROR_NONE, mounted_volume.second); const std::string fsid = GetMountPointNameForMediaStorage(info); storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fsid); @@ -886,7 +889,7 @@ return; } - std::vector<std::unique_ptr<Volume>> archives; + std::vector<linked_ptr<Volume>> archives; const chromeos::disks::DiskMountManager::MountPointMap& mount_points = disk_mount_manager_->mount_points(); @@ -896,14 +899,14 @@ ++it) { if (it->second.mount_type == chromeos::MOUNT_TYPE_ARCHIVE) { // Archives are mounted after other types of volume. See below. - archives.push_back(Volume::CreateForRemovable(it->second, nullptr)); + archives.push_back( + make_linked_ptr(Volume::CreateForRemovable(it->second, NULL))); continue; } - DoMountEvent( - chromeos::MOUNT_ERROR_NONE, - Volume::CreateForRemovable( - it->second, - disk_mount_manager_->FindDiskBySourcePath(it->second.source_path))); + DoMountEvent(chromeos::MOUNT_ERROR_NONE, + make_linked_ptr(Volume::CreateForRemovable( + it->second, disk_mount_manager_->FindDiskBySourcePath( + it->second.source_path)))); } // We mount archives only if they are opened from currently mounted volumes. @@ -913,26 +916,24 @@ if (done[i]) continue; - std::vector<std::unique_ptr<Volume>> chain; - // done[x] = true means archives[x] is null and that volume is in |chain|. + std::vector<linked_ptr<Volume>> chain; done[i] = true; - chain.push_back(std::move(archives[i])); + chain.push_back(archives[i]); // If archives[i]'s source_path is in another archive, mount it first. for (size_t parent = i + 1; parent < archives.size(); ++parent) { if (!done[parent] && archives[parent]->mount_path().IsParent( chain.back()->source_path())) { - // done[parent] started false, so archives[parent] is non-null. done[parent] = true; - chain.push_back(std::move(archives[parent])); + chain.push_back(archives[parent]); parent = i + 1; // Search archives[parent]'s parent from the beginning. } } // Mount from the tail of chain. for (size_t i = chain.size(); i > 0; --i) { - DoMountEvent(chromeos::MOUNT_ERROR_NONE, std::move(chain[i - 1])); + DoMountEvent(chromeos::MOUNT_ERROR_NONE, chain[i - 1]); } } } @@ -946,7 +947,7 @@ } void VolumeManager::DoMountEvent(chromeos::MountError error_code, - std::unique_ptr<Volume> volume) { + const linked_ptr<Volume>& volume) { // Archive files are mounted globally in system. We however don't want to show // archives from profile-specific folders (Drive/Downloads) of other users in // multi-profile session. To this end, we filter out archives not on the @@ -971,27 +972,25 @@ return; } - Volume* raw_volume = volume.get(); if (error_code == chromeos::MOUNT_ERROR_NONE || volume->mount_condition()) { - mounted_volumes_[volume->volume_id()] = std::move(volume); - UMA_HISTOGRAM_ENUMERATION("FileBrowser.VolumeType", raw_volume->type(), + mounted_volumes_[volume->volume_id()] = volume; + UMA_HISTOGRAM_ENUMERATION("FileBrowser.VolumeType", volume->type(), NUM_VOLUME_TYPE); } for (auto& observer : observers_) - observer.OnVolumeMounted(error_code, *raw_volume); + observer.OnVolumeMounted(error_code, *volume); } void VolumeManager::DoUnmountEvent(chromeos::MountError error_code, - const Volume& volume) { - auto iter = mounted_volumes_.find(volume.volume_id()); - if (iter == mounted_volumes_.end()) + const linked_ptr<Volume>& volume) { + if (mounted_volumes_.find(volume->volume_id()) == mounted_volumes_.end()) return; if (error_code == chromeos::MOUNT_ERROR_NONE) - mounted_volumes_.erase(iter); + mounted_volumes_.erase(volume->volume_id()); for (auto& observer : observers_) - observer.OnVolumeUnmounted(error_code, volume); + observer.OnVolumeUnmounted(error_code, *volume.get()); } } // namespace file_manager
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.h b/chrome/browser/chromeos/file_manager/volume_manager.h index 1658d149..46014daf 100644 --- a/chrome/browser/chromeos/file_manager/volume_manager.h +++ b/chrome/browser/chromeos/file_manager/volume_manager.h
@@ -14,6 +14,7 @@ #include "base/files/file.h" #include "base/files/file_path.h" #include "base/macros.h" +#include "base/memory/linked_ptr.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "chrome/browser/chromeos/arc/arc_session_manager.h" @@ -79,29 +80,25 @@ ~Volume(); // Factory static methods for different volume types. - static std::unique_ptr<Volume> CreateForDrive(Profile* profile); - static std::unique_ptr<Volume> CreateForDownloads( - const base::FilePath& downloads_path); - static std::unique_ptr<Volume> CreateForRemovable( + static Volume* CreateForDrive(Profile* profile); + static Volume* CreateForDownloads(const base::FilePath& downloads_path); + static Volume* CreateForRemovable( const chromeos::disks::DiskMountManager::MountPointInfo& mount_point, const chromeos::disks::DiskMountManager::Disk* disk); - static std::unique_ptr<Volume> CreateForProvidedFileSystem( + static Volume* CreateForProvidedFileSystem( const chromeos::file_system_provider::ProvidedFileSystemInfo& file_system_info, MountContext mount_context); - static std::unique_ptr<Volume> CreateForMTP(const base::FilePath& mount_path, - const std::string& label, - bool read_only); - static std::unique_ptr<Volume> CreateForMediaView( - const std::string& root_document_id); - static std::unique_ptr<Volume> CreateForTesting( - const base::FilePath& path, - VolumeType volume_type, - chromeos::DeviceType device_type, - bool read_only); - static std::unique_ptr<Volume> CreateForTesting( - const base::FilePath& device_path, - const base::FilePath& mount_path); + static Volume* CreateForMTP(const base::FilePath& mount_path, + const std::string& label, + bool read_only); + static Volume* CreateForMediaView(const std::string& root_document_id); + static Volume* CreateForTesting(const base::FilePath& path, + VolumeType volume_type, + chromeos::DeviceType device_type, + bool read_only); + static Volume* CreateForTesting(const base::FilePath& device_path, + const base::FilePath& mount_path); // Getters for all members. See below for details. const std::string& volume_id() const { return volume_id_; } @@ -273,7 +270,7 @@ bool read_only); // For testing purpose, adds the volume info to the volume manager. - void AddVolumeForTesting(std::unique_ptr<Volume> volume); + void AddVolumeForTesting(const linked_ptr<Volume>& volume); // drive::DriveIntegrationServiceObserver overrides. void OnFileSystemMounted() override; @@ -325,8 +322,9 @@ void OnDiskMountManagerRefreshed(bool success); void OnStorageMonitorInitialized(); void DoMountEvent(chromeos::MountError error_code, - std::unique_ptr<Volume> volume); - void DoUnmountEvent(chromeos::MountError error_code, const Volume& volume); + const linked_ptr<Volume>& volume); + void DoUnmountEvent(chromeos::MountError error_code, + const linked_ptr<Volume>& volume); void OnExternalStorageDisabledChangedUnmountCallback( chromeos::MountError error_code); @@ -338,7 +336,7 @@ chromeos::file_system_provider::Service* file_system_provider_service_; // Not owned by this class. GetMtpStorageInfoCallback get_mtp_storage_info_callback_; - std::map<std::string, std::unique_ptr<Volume>> mounted_volumes_; + std::map<std::string, linked_ptr<Volume>> mounted_volumes_; std::unique_ptr<SnapshotManager> snapshot_manager_; bool arc_volumes_mounted_ = false;
diff --git a/chrome/test/data/webui/md_history/md_history_browsertest.js b/chrome/test/data/webui/md_history/md_history_browsertest.js index 754d587..22d988a 100644 --- a/chrome/test/data/webui/md_history/md_history_browsertest.js +++ b/chrome/test/data/webui/md_history/md_history_browsertest.js
@@ -107,7 +107,16 @@ ]), }; -TEST_F('MaterialHistoryListTest', 'All', function() { +// Times out on debug builders and may time out on memory bots because +// the History page can take several seconds to load in a Debug build. See +// https://crbug.com/669227. +GEN('#if defined(MEMORY_SANITIZER) || !defined(NDEBUG)'); +GEN('#define MAYBE_All DISABLED_All'); +GEN('#else'); +GEN('#define MAYBE_All All'); +GEN('#endif'); + +TEST_F('MaterialHistoryListTest', 'MAYBE_All', function() { mocha.run(); });
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index b2d2315..5b5af15 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1037,6 +1037,8 @@ "renderer_host/input/mouse_wheel_event_queue.h", "renderer_host/input/mouse_wheel_rails_filter_mac.cc", "renderer_host/input/mouse_wheel_rails_filter_mac.h", + "renderer_host/input/passthrough_touch_event_queue.cc", + "renderer_host/input/passthrough_touch_event_queue.h", "renderer_host/input/render_widget_host_latency_tracker.cc", "renderer_host/input/render_widget_host_latency_tracker.h", "renderer_host/input/stylus_text_selector.cc",
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc index 86ed1c67..2de801a 100644 --- a/content/browser/renderer_host/input/input_router_impl.cc +++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -17,6 +17,7 @@ #include "content/browser/renderer_host/input/input_ack_handler.h" #include "content/browser/renderer_host/input/input_router_client.h" #include "content/browser/renderer_host/input/legacy_touch_event_queue.h" +#include "content/browser/renderer_host/input/passthrough_touch_event_queue.h" #include "content/browser/renderer_host/input/touch_event_queue.h" #include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h" #include "content/common/content_constants_internal.h" @@ -91,9 +92,15 @@ wheel_event_queue_(this, base::FeatureList::IsEnabled( features::kTouchpadAndWheelScrollLatching)), - touch_event_queue_(new LegacyTouchEventQueue(this, config.touch_config)), gesture_event_queue_(this, this, config.gesture_config), device_scale_factor_(1.f) { + if (base::FeatureList::IsEnabled(features::kRafAlignedTouchInputEvents)) + touch_event_queue_.reset( + new PassthroughTouchEventQueue(this, config.touch_config)); + else + touch_event_queue_.reset( + new LegacyTouchEventQueue(this, config.touch_config)); + DCHECK(sender); DCHECK(client); DCHECK(ack_handler);
diff --git a/content/browser/renderer_host/input/legacy_touch_event_queue.h b/content/browser/renderer_host/input/legacy_touch_event_queue.h index 8468cde1..742301a 100644 --- a/content/browser/renderer_host/input/legacy_touch_event_queue.h +++ b/content/browser/renderer_host/input/legacy_touch_event_queue.h
@@ -96,7 +96,7 @@ } private: - friend class TouchEventQueueTest; + friend class LegacyTouchEventQueueTest; bool HasPendingAsyncTouchMoveForTesting() const; bool IsTimeoutRunningForTesting() const;
diff --git a/content/browser/renderer_host/input/touch_event_queue_unittest.cc b/content/browser/renderer_host/input/legacy_touch_event_queue_unittest.cc similarity index 95% rename from content/browser/renderer_host/input/touch_event_queue_unittest.cc rename to content/browser/renderer_host/input/legacy_touch_event_queue_unittest.cc index b20f6921..7f391d2b 100644 --- a/content/browser/renderer_host/input/touch_event_queue_unittest.cc +++ b/content/browser/renderer_host/input/legacy_touch_event_queue_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/input/touch_event_queue.h" +#include "content/browser/renderer_host/input/legacy_touch_event_queue.h" #include <stddef.h> @@ -15,7 +15,6 @@ #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" -#include "content/browser/renderer_host/input/legacy_touch_event_queue.h" #include "content/browser/renderer_host/input/timeout_monitor.h" #include "content/common/input/synthetic_web_input_event_builders.h" #include "content/common/input/web_touch_event_traits.h" @@ -40,15 +39,15 @@ } } // namespace -class TouchEventQueueTest : public testing::Test, - public TouchEventQueueClient { +class LegacyTouchEventQueueTest : public testing::Test, + public TouchEventQueueClient { public: - TouchEventQueueTest() + LegacyTouchEventQueueTest() : acked_event_count_(0), last_acked_event_state_(INPUT_EVENT_ACK_STATE_UNKNOWN), slop_length_dips_(0) {} - ~TouchEventQueueTest() override {} + ~LegacyTouchEventQueueTest() override {} // testing::Test void SetUp() override { @@ -82,9 +81,8 @@ if (followup_gesture_event_) { std::unique_ptr<WebGestureEvent> followup_gesture_event = std::move(followup_gesture_event_); - queue_->OnGestureScrollEvent( - GestureEventWithLatencyInfo(*followup_gesture_event, - ui::LatencyInfo())); + queue_->OnGestureScrollEvent(GestureEventWithLatencyInfo( + *followup_gesture_event, ui::LatencyInfo())); } } @@ -247,9 +245,7 @@ touch_event_.setTimeStampSeconds(touch_event_.timeStampSeconds() + seconds); } - void ResetTouchEvent() { - touch_event_ = SyntheticWebTouchEvent(); - } + void ResetTouchEvent() { touch_event_ = SyntheticWebTouchEvent(); } size_t GetAndResetAckedEventCount() { size_t count = acked_event_count_; @@ -283,17 +279,13 @@ return queue_->HasPendingAsyncTouchMoveForTesting(); } - size_t queued_event_count() const { - return queue_->size(); - } + size_t queued_event_count() const { return queue_->size(); } const WebTouchEvent& latest_event() const { return queue_->GetLatestEventForTesting().event; } - const WebTouchEvent& acked_event() const { - return last_acked_event_; - } + const WebTouchEvent& acked_event() const { return last_acked_event_; } const WebTouchEvent& sent_event() const { DCHECK(!sent_events_.empty()); @@ -346,9 +338,8 @@ std::deque<int> sent_events_ids_; }; - // Tests that touch-events are queued properly. -TEST_F(TouchEventQueueTest, Basic) { +TEST_F(LegacyTouchEventQueueTest, Basic) { PressTouchPoint(1, 1); EXPECT_EQ(1U, queued_event_count()); EXPECT_EQ(1U, GetAndResetSentEventCount()); @@ -376,7 +367,7 @@ } // Tests that touch-events with multiple points are queued properly. -TEST_F(TouchEventQueueTest, BasicMultiTouch) { +TEST_F(LegacyTouchEventQueueTest, BasicMultiTouch) { const size_t kPointerCount = 10; for (float i = 0; i < kPointerCount; ++i) PressTouchPoint(i, i); @@ -422,7 +413,8 @@ // Tests that the touch-queue continues delivering events for an active touch // sequence after all handlers are removed. -TEST_F(TouchEventQueueTest, TouchesForwardedIfHandlerRemovedDuringSequence) { +TEST_F(LegacyTouchEventQueueTest, + TouchesForwardedIfHandlerRemovedDuringSequence) { OnHasTouchEventHandlers(true); EXPECT_EQ(0U, queued_event_count()); EXPECT_EQ(0U, GetAndResetSentEventCount()); @@ -485,7 +477,7 @@ // Tests that addition of a touch handler during a touch sequence will not cause // the remaining sequence to be forwarded. -TEST_F(TouchEventQueueTest, ActiveSequenceNotForwardedWhenHandlersAdded) { +TEST_F(LegacyTouchEventQueueTest, ActiveSequenceNotForwardedWhenHandlersAdded) { OnHasTouchEventHandlers(false); // Send a touch-press event while there is no handler. @@ -512,7 +504,7 @@ // Tests that removal of a touch handler during a touch sequence will prevent // the remaining sequence from being forwarded, even if another touch handler is // registered during the same touch sequence. -TEST_F(TouchEventQueueTest, ActiveSequenceDroppedWhenHandlersRemoved) { +TEST_F(LegacyTouchEventQueueTest, ActiveSequenceDroppedWhenHandlersRemoved) { // Send a touch-press event. PressTouchPoint(1, 1); EXPECT_EQ(1U, GetAndResetSentEventCount()); @@ -566,7 +558,7 @@ // Tests that removal/addition of a touch handler without any intervening // touch activity has no affect on touch forwarding. -TEST_F(TouchEventQueueTest, +TEST_F(LegacyTouchEventQueueTest, ActiveSequenceUnaffectedByRepeatedHandlerRemovalAndAddition) { // Send a touch-press event. PressTouchPoint(1, 1); @@ -593,7 +585,7 @@ } // Tests that touch-events are coalesced properly in the queue. -TEST_F(TouchEventQueueTest, Coalesce) { +TEST_F(LegacyTouchEventQueueTest, Coalesce) { // Send a touch-press event. PressTouchPoint(1, 1); EXPECT_EQ(1U, GetAndResetSentEventCount()); @@ -633,7 +625,7 @@ // Tests that an event that has already been sent but hasn't been ack'ed yet // doesn't get coalesced with newer events. -TEST_F(TouchEventQueueTest, SentTouchEventDoesNotCoalesce) { +TEST_F(LegacyTouchEventQueueTest, SentTouchEventDoesNotCoalesce) { // Send a touch-press event. PressTouchPoint(1, 1); EXPECT_EQ(1U, GetAndResetSentEventCount()); @@ -660,7 +652,7 @@ } // Tests that coalescing works correctly for multi-touch events. -TEST_F(TouchEventQueueTest, MultiTouch) { +TEST_F(LegacyTouchEventQueueTest, MultiTouch) { // Press the first finger. PressTouchPoint(1, 1); EXPECT_EQ(1U, GetAndResetSentEventCount()); @@ -694,7 +686,7 @@ } // Tests that the touch-event queue is robust to redundant acks. -TEST_F(TouchEventQueueTest, SpuriousAcksIgnored) { +TEST_F(LegacyTouchEventQueueTest, SpuriousAcksIgnored) { // Trigger a spurious ack. SendTouchEventAckWithID(INPUT_EVENT_ACK_STATE_CONSUMED, 0); EXPECT_EQ(0U, GetAndResetAckedEventCount()); @@ -717,7 +709,7 @@ // main thread in the renderer). Also tests that all queued/coalesced touch // events are flushed immediately when the ACK for the touch-press comes back // with NO_CONSUMER status. -TEST_F(TouchEventQueueTest, NoConsumer) { +TEST_F(LegacyTouchEventQueueTest, NoConsumer) { // The first touch-press should reach the renderer. PressTouchPoint(1, 1); EXPECT_EQ(1U, GetAndResetSentEventCount()); @@ -781,7 +773,7 @@ EXPECT_EQ(1U, GetAndResetAckedEventCount()); } -TEST_F(TouchEventQueueTest, ConsumerIgnoreMultiFinger) { +TEST_F(LegacyTouchEventQueueTest, ConsumerIgnoreMultiFinger) { // Interleave three pointer press, move and release events. PressTouchPoint(1, 1); MoveTouchPoint(0, 5, 5); @@ -835,7 +827,7 @@ } // Tests that touch-event's enqueued via a touch ack are properly handled. -TEST_F(TouchEventQueueTest, AckWithFollowupEvents) { +TEST_F(LegacyTouchEventQueueTest, AckWithFollowupEvents) { // Queue a touch down. PressTouchPoint(1, 1); EXPECT_EQ(1U, queued_event_count()); @@ -874,7 +866,7 @@ } // Tests that touch-events can be synchronously ack'ed. -TEST_F(TouchEventQueueTest, SynchronousAcks) { +TEST_F(LegacyTouchEventQueueTest, SynchronousAcks) { // TouchStart SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED); PressTouchPoint(1, 1); @@ -912,7 +904,7 @@ // Tests that followup events triggered by an immediate ack from // TouchEventQueue::QueueEvent() are properly handled. -TEST_F(TouchEventQueueTest, ImmediateAckWithFollowupEvents) { +TEST_F(LegacyTouchEventQueueTest, ImmediateAckWithFollowupEvents) { // Create a touch event that will be queued synchronously by a touch ack. WebTouchEvent followup_event( WebInputEvent::TouchStart, WebInputEvent::NoModifiers, @@ -942,7 +934,7 @@ } // Tests basic TouchEvent forwarding suppression. -TEST_F(TouchEventQueueTest, NoTouchBasic) { +TEST_F(LegacyTouchEventQueueTest, NoTouchBasic) { // Disable TouchEvent forwarding. OnHasTouchEventHandlers(false); PressTouchPoint(30, 5); @@ -979,8 +971,7 @@ } // Tests that IsTouchStartPendingAck works correctly. -TEST_F(TouchEventQueueTest, PendingStart) { - +TEST_F(LegacyTouchEventQueueTest, PendingStart) { EXPECT_FALSE(IsPendingAckTouchStart()); // Send the touchstart for one point (#1). @@ -1025,7 +1016,7 @@ } // Tests that the touch timeout is started when sending certain touch types. -TEST_F(TouchEventQueueTest, TouchTimeoutTypes) { +TEST_F(LegacyTouchEventQueueTest, TouchTimeoutTypes) { SetUpForTimeoutTesting(); // Sending a TouchStart will start the timeout. @@ -1059,7 +1050,7 @@ // Tests that a delayed TouchEvent ack will trigger a TouchCancel timeout, // disabling touch forwarding until the next TouchStart is received after // the timeout events are ack'ed. -TEST_F(TouchEventQueueTest, TouchTimeoutBasic) { +TEST_F(LegacyTouchEventQueueTest, TouchTimeoutBasic) { SetUpForTimeoutTesting(); // Queue a TouchStart. @@ -1113,7 +1104,7 @@ // Tests that the timeout is never started if the renderer consumes // a TouchEvent from the current touch sequence. -TEST_F(TouchEventQueueTest, NoTouchTimeoutIfRendererIsConsumingGesture) { +TEST_F(LegacyTouchEventQueueTest, NoTouchTimeoutIfRendererIsConsumingGesture) { SetUpForTimeoutTesting(); // Queue a TouchStart. @@ -1147,7 +1138,7 @@ // Tests that the timeout is never started if the renderer consumes // a TouchEvent from the current touch sequence. -TEST_F(TouchEventQueueTest, NoTouchTimeoutIfDisabledAfterTouchStart) { +TEST_F(LegacyTouchEventQueueTest, NoTouchTimeoutIfDisabledAfterTouchStart) { SetUpForTimeoutTesting(); // Queue a TouchStart. @@ -1173,7 +1164,7 @@ } // Tests that the timeout is never started if the ack is synchronous. -TEST_F(TouchEventQueueTest, NoTouchTimeoutIfAckIsSynchronous) { +TEST_F(LegacyTouchEventQueueTest, NoTouchTimeoutIfAckIsSynchronous) { SetUpForTimeoutTesting(); // Queue a TouchStart. @@ -1185,7 +1176,7 @@ // Tests that the timeout does not fire if explicitly disabled while an event // is in-flight. -TEST_F(TouchEventQueueTest, NoTouchTimeoutIfDisabledWhileTimerIsActive) { +TEST_F(LegacyTouchEventQueueTest, NoTouchTimeoutIfDisabledWhileTimerIsActive) { SetUpForTimeoutTesting(); // Queue a TouchStart. @@ -1200,7 +1191,7 @@ } // Tests that the timeout does not fire if the delay is zero. -TEST_F(TouchEventQueueTest, NoTouchTimeoutIfTimeoutDelayIsZero) { +TEST_F(LegacyTouchEventQueueTest, NoTouchTimeoutIfTimeoutDelayIsZero) { SetUpForTimeoutTesting(base::TimeDelta(), base::TimeDelta()); // As the delay is zero, timeout behavior should be disabled. @@ -1211,7 +1202,7 @@ } // Tests that timeout delays for mobile sites take effect when appropriate. -TEST_F(TouchEventQueueTest, TouchTimeoutConfiguredForMobile) { +TEST_F(LegacyTouchEventQueueTest, TouchTimeoutConfiguredForMobile) { base::TimeDelta desktop_delay = DefaultTouchTimeoutDelay(); base::TimeDelta mobile_delay = base::TimeDelta(); SetUpForTimeoutTesting(desktop_delay, mobile_delay); @@ -1238,7 +1229,7 @@ // Tests that a TouchCancel timeout plays nice when the timed out touch stream // turns into a scroll gesture sequence. -TEST_F(TouchEventQueueTest, TouchTimeoutWithFollowupGesture) { +TEST_F(LegacyTouchEventQueueTest, TouchTimeoutWithFollowupGesture) { SetUpForTimeoutTesting(); // Queue a TouchStart. @@ -1294,7 +1285,8 @@ // Tests that a TouchCancel timeout plays nice when the timed out touch stream // turns into a scroll gesture sequence, but the original event acks are // significantly delayed. -TEST_F(TouchEventQueueTest, TouchTimeoutWithFollowupGestureAndDelayedAck) { +TEST_F(LegacyTouchEventQueueTest, + TouchTimeoutWithFollowupGestureAndDelayedAck) { SetUpForTimeoutTesting(); // Queue a TouchStart. @@ -1351,7 +1343,7 @@ // Tests that a delayed TouchEvent ack will not trigger a TouchCancel timeout if // the timed-out event had no consumer. -TEST_F(TouchEventQueueTest, NoCancelOnTouchTimeoutWithoutConsumer) { +TEST_F(LegacyTouchEventQueueTest, NoCancelOnTouchTimeoutWithoutConsumer) { SetUpForTimeoutTesting(); // Queue a TouchStart. @@ -1390,7 +1382,7 @@ // Tests that TouchMove's movedBeyondSlopRegion is set to false if within the // boundary-inclusive slop region for an unconsumed TouchStart. -TEST_F(TouchEventQueueTest, TouchMovedBeyondSlopRegionCheck) { +TEST_F(LegacyTouchEventQueueTest, TouchMovedBeyondSlopRegionCheck) { SetUpForTouchMoveSlopTesting(kSlopLengthDips); // Queue a TouchStart. @@ -1440,7 +1432,7 @@ const float kFortyFiveDegreeSlopLengthXY = kSlopLengthDips * std::sqrt(2.f) / 2; MoveTouchPoint(0, kFortyFiveDegreeSlopLengthXY + .2f, - kFortyFiveDegreeSlopLengthXY + .2f); + kFortyFiveDegreeSlopLengthXY + .2f); EXPECT_EQ(1U, queued_event_count()); EXPECT_EQ(1U, GetAndResetSentEventCount()); EXPECT_EQ(0U, GetAndResetAckedEventCount()); @@ -1451,7 +1443,8 @@ // Tests that even very small TouchMove's movedBeyondSlopRegion is set to true // when the slop region's dimension is 0. -TEST_F(TouchEventQueueTest, MovedBeyondSlopRegionAlwaysTrueIfDimensionZero) { +TEST_F(LegacyTouchEventQueueTest, + MovedBeyondSlopRegionAlwaysTrueIfDimensionZero) { // Queue a TouchStart. PressTouchPoint(0, 0); SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); @@ -1470,7 +1463,8 @@ // Tests that secondary touch points can be forwarded even if the primary touch // point had no consumer. -TEST_F(TouchEventQueueTest, SecondaryTouchForwardedAfterPrimaryHadNoConsumer) { +TEST_F(LegacyTouchEventQueueTest, + SecondaryTouchForwardedAfterPrimaryHadNoConsumer) { // Queue a TouchStart. PressTouchPoint(0, 0); SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); @@ -1499,7 +1493,7 @@ // Tests that secondary touch points can be forwarded after scrolling begins // while first touch point has no consumer. -TEST_F(TouchEventQueueTest, NoForwardingAfterScrollWithNoTouchConsumers) { +TEST_F(LegacyTouchEventQueueTest, NoForwardingAfterScrollWithNoTouchConsumers) { // Queue a TouchStart. PressTouchPoint(0, 0); SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); @@ -1529,7 +1523,7 @@ EXPECT_EQ(1U, GetAndResetAckedEventCount()); } -TEST_F(TouchEventQueueTest, AsyncTouch) { +TEST_F(LegacyTouchEventQueueTest, AsyncTouch) { // Queue a TouchStart. PressTouchPoint(0, 1); EXPECT_EQ(1U, GetAndResetSentEventCount()); @@ -1537,29 +1531,29 @@ EXPECT_EQ(1U, GetAndResetAckedEventCount()); for (int i = 0; i < 3; ++i) { - SendGestureEventAck(WebInputEvent::GestureScrollUpdate, - INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + SendGestureEventAck(WebInputEvent::GestureScrollUpdate, + INPUT_EVENT_ACK_STATE_NOT_CONSUMED); - MoveTouchPoint(0, 10, 5+i); - SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); - EXPECT_FALSE(HasPendingAsyncTouchMove()); - EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType); - EXPECT_EQ(0U, queued_event_count()); - EXPECT_EQ(1U, GetAndResetSentEventCount()); + MoveTouchPoint(0, 10, 5 + i); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_FALSE(HasPendingAsyncTouchMove()); + EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); - // Consuming a scroll event will throttle subsequent touchmoves. - SendGestureEventAck(WebInputEvent::GestureScrollUpdate, - INPUT_EVENT_ACK_STATE_CONSUMED); - MoveTouchPoint(0, 10, 7+i); - EXPECT_TRUE(HasPendingAsyncTouchMove()); - EXPECT_EQ(0U, queued_event_count()); - EXPECT_EQ(0U, GetAndResetSentEventCount()); + // Consuming a scroll event will throttle subsequent touchmoves. + SendGestureEventAck(WebInputEvent::GestureScrollUpdate, + INPUT_EVENT_ACK_STATE_CONSUMED); + MoveTouchPoint(0, 10, 7 + i); + EXPECT_TRUE(HasPendingAsyncTouchMove()); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); } } // Ensure that touchmove's are appropriately throttled during a typical // scroll sequences that transitions between scrolls consumed and unconsumed. -TEST_F(TouchEventQueueTest, AsyncTouchThrottledAfterScroll) { +TEST_F(LegacyTouchEventQueueTest, AsyncTouchThrottledAfterScroll) { // Process a TouchStart PressTouchPoint(0, 1); EXPECT_EQ(1U, GetAndResetSentEventCount()); @@ -1746,7 +1740,7 @@ EXPECT_EQ(1U, GetAndResetAckedEventCount()); } -TEST_F(TouchEventQueueTest, AsyncTouchFlushedByTouchEnd) { +TEST_F(LegacyTouchEventQueueTest, AsyncTouchFlushedByTouchEnd) { PressTouchPoint(0, 0); SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); EXPECT_EQ(1U, GetAndResetSentEventCount()); @@ -1802,7 +1796,7 @@ // Ensure that async touch dispatch and touch ack timeout interactions work // appropriately. -TEST_F(TouchEventQueueTest, AsyncTouchWithAckTimeout) { +TEST_F(LegacyTouchEventQueueTest, AsyncTouchWithAckTimeout) { SetUpForTimeoutTesting(); // The touchstart should start the timeout. @@ -1884,7 +1878,7 @@ // Ensure that if the touch ack for an async touchmove triggers a follow-up // touch event, that follow-up touch will be forwarded appropriately. -TEST_F(TouchEventQueueTest, AsyncTouchWithTouchCancelAfterAck) { +TEST_F(LegacyTouchEventQueueTest, AsyncTouchWithTouchCancelAfterAck) { PressTouchPoint(0, 0); EXPECT_EQ(1U, GetAndResetSentEventCount()); SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); @@ -1935,7 +1929,7 @@ // Ensure that the async touch is fully reset if the touch sequence restarts // without properly terminating. -TEST_F(TouchEventQueueTest, AsyncTouchWithHardTouchStartReset) { +TEST_F(LegacyTouchEventQueueTest, AsyncTouchWithHardTouchStartReset) { PressTouchPoint(0, 0); EXPECT_EQ(1U, GetAndResetSentEventCount()); SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); @@ -1976,7 +1970,7 @@ // Ensure that even when the interval expires, we still need to wait for the // ack sent back from render to send the next async touchmove once the scroll // starts. -TEST_F(TouchEventQueueTest, SendNextThrottledAsyncTouchMoveAfterAck) { +TEST_F(LegacyTouchEventQueueTest, SendNextThrottledAsyncTouchMoveAfterAck) { // Process a TouchStart PressTouchPoint(0, 1); EXPECT_EQ(1U, GetAndResetSentEventCount()); @@ -2038,7 +2032,7 @@ // Ensure that even when we receive the ack from render, we still need to wait // for the interval expires to send the next async touchmove once the scroll // starts. -TEST_F(TouchEventQueueTest, SendNextAsyncTouchMoveAfterAckAndTimeExpire) { +TEST_F(LegacyTouchEventQueueTest, SendNextAsyncTouchMoveAfterAckAndTimeExpire) { // Process a TouchStart PressTouchPoint(0, 1); EXPECT_EQ(1U, GetAndResetSentEventCount()); @@ -2097,7 +2091,7 @@ EXPECT_EQ(1U, uncancelable_touch_moves_pending_ack_count()); } -TEST_F(TouchEventQueueTest, AsyncTouchFlushedByNonTouchMove) { +TEST_F(LegacyTouchEventQueueTest, AsyncTouchFlushedByNonTouchMove) { // Process a TouchStart PressTouchPoint(0, 1); EXPECT_EQ(1U, GetAndResetSentEventCount()); @@ -2212,7 +2206,7 @@ // Ensure that even when we receive the ack from render, we still need to wait // for the interval expires to send the next async touchmove once the scroll // starts. -TEST_F(TouchEventQueueTest, DoNotIncreaseIfClientConsumeAsyncTouchMove) { +TEST_F(LegacyTouchEventQueueTest, DoNotIncreaseIfClientConsumeAsyncTouchMove) { // Process a TouchStart PressTouchPoint(0, 1); EXPECT_EQ(1U, GetAndResetSentEventCount()); @@ -2274,7 +2268,7 @@ EXPECT_EQ(0U, uncancelable_touch_moves_pending_ack_count()); } -TEST_F(TouchEventQueueTest, TouchAbsorptionWithConsumedFirstMove) { +TEST_F(LegacyTouchEventQueueTest, TouchAbsorptionWithConsumedFirstMove) { // Queue a TouchStart. PressTouchPoint(0, 1); SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); @@ -2313,7 +2307,7 @@ EXPECT_EQ(0U, GetAndResetSentEventCount()); } -TEST_F(TouchEventQueueTest, TouchStartCancelableDuringScroll) { +TEST_F(LegacyTouchEventQueueTest, TouchStartCancelableDuringScroll) { // Queue a touchstart and touchmove that go unconsumed, transitioning to an // active scroll sequence. PressTouchPoint(0, 1); @@ -2372,7 +2366,7 @@ ASSERT_EQ(1U, GetAndResetSentEventCount()); } -TEST_F(TouchEventQueueTest, UnseenTouchPointerIdsNotForwarded) { +TEST_F(LegacyTouchEventQueueTest, UnseenTouchPointerIdsNotForwarded) { SyntheticWebTouchEvent event; event.PressPoint(0, 0); SendTouchEvent(event); @@ -2411,7 +2405,7 @@ } // Tests that touch points states are correct in TouchMove events. -TEST_F(TouchEventQueueTest, PointerStatesInTouchMove) { +TEST_F(LegacyTouchEventQueueTest, PointerStatesInTouchMove) { PressTouchPoint(1, 1); PressTouchPoint(2, 2); PressTouchPoint(3, 3); @@ -2468,7 +2462,7 @@ // Tests that touch point state is correct in TouchMove events // when point properties other than position changed. -TEST_F(TouchEventQueueTest, PointerStatesWhenOtherThanPositionChanged) { +TEST_F(LegacyTouchEventQueueTest, PointerStatesWhenOtherThanPositionChanged) { PressTouchPoint(1, 1); SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); @@ -2509,7 +2503,7 @@ } // Tests that TouchMoves are filtered when none of the points are changed. -TEST_F(TouchEventQueueTest, FilterTouchMovesWhenNoPointerChanged) { +TEST_F(LegacyTouchEventQueueTest, FilterTouchMovesWhenNoPointerChanged) { PressTouchPoint(1, 1); PressTouchPoint(2, 2); SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); @@ -2562,7 +2556,7 @@ } // Tests that touch-scroll-notification is not pushed into an empty queue. -TEST_F(TouchEventQueueTest, TouchScrollNotificationOrder_EmptyQueue) { +TEST_F(LegacyTouchEventQueueTest, TouchScrollNotificationOrder_EmptyQueue) { PrependTouchScrollNotification(); EXPECT_EQ(0U, GetAndResetAckedEventCount()); @@ -2572,7 +2566,7 @@ // Tests touch-scroll-notification firing order when the event is placed at the // end of touch queue because of a pending ack for the head of the queue. -TEST_F(TouchEventQueueTest, TouchScrollNotificationOrder_EndOfQueue) { +TEST_F(LegacyTouchEventQueueTest, TouchScrollNotificationOrder_EndOfQueue) { PressTouchPoint(1, 1); EXPECT_EQ(0U, GetAndResetAckedEventCount()); @@ -2604,7 +2598,7 @@ // Tests touch-scroll-notification firing order when the event is placed in the // 2nd position in the touch queue between two events. -TEST_F(TouchEventQueueTest, TouchScrollNotificationOrder_SecondPosition) { +TEST_F(LegacyTouchEventQueueTest, TouchScrollNotificationOrder_SecondPosition) { PressTouchPoint(1, 1); MoveTouchPoint(0, 5, 5); ReleaseTouchPoint(0); @@ -2654,7 +2648,7 @@ // Tests that if touchStartOrFirstTouchMove is correctly set up for touch // events. -TEST_F(TouchEventQueueTest, TouchStartOrFirstTouchMove) { +TEST_F(LegacyTouchEventQueueTest, TouchStartOrFirstTouchMove) { PressTouchPoint(1, 1); SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); EXPECT_EQ(WebInputEvent::TouchStart, sent_event().type());
diff --git a/content/browser/renderer_host/input/passthrough_touch_event_queue.cc b/content/browser/renderer_host/input/passthrough_touch_event_queue.cc new file mode 100644 index 0000000..fb5a0f4 --- /dev/null +++ b/content/browser/renderer_host/input/passthrough_touch_event_queue.cc
@@ -0,0 +1,382 @@ +// Copyright 2017 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 "content/browser/renderer_host/input/passthrough_touch_event_queue.h" + +#include <utility> + +#include "base/auto_reset.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" +#include "base/trace_event/trace_event.h" +#include "content/browser/renderer_host/input/touch_timeout_handler.h" +#include "content/common/input/web_touch_event_traits.h" +#include "ui/events/base_event_utils.h" +#include "ui/gfx/geometry/point_f.h" + +using blink::WebInputEvent; +using blink::WebTouchEvent; +using blink::WebTouchPoint; +using ui::LatencyInfo; + +namespace content { +namespace { + +// Compare all properties of touch points to determine the state. +bool HasPointChanged(const WebTouchPoint& point_1, + const WebTouchPoint& point_2) { + DCHECK_EQ(point_1.id, point_2.id); + if (point_1.screenPosition != point_2.screenPosition || + point_1.position != point_2.position || + point_1.radiusX != point_2.radiusX || + point_1.radiusY != point_2.radiusY || + point_1.rotationAngle != point_2.rotationAngle || + point_1.force != point_2.force || point_1.tiltX != point_2.tiltX || + point_1.tiltY != point_2.tiltY) { + return true; + } + return false; +} + +} // namespace + +PassthroughTouchEventQueue::TouchEventWithLatencyInfoAndAckState:: + TouchEventWithLatencyInfoAndAckState(const TouchEventWithLatencyInfo& event) + : TouchEventWithLatencyInfo(event), + ack_state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {} + +bool PassthroughTouchEventQueue::TouchEventWithLatencyInfoAndAckState:: +operator<(const TouchEventWithLatencyInfoAndAckState& other) const { + return event.uniqueTouchEventId < other.event.uniqueTouchEventId; +} + +PassthroughTouchEventQueue::PassthroughTouchEventQueue( + TouchEventQueueClient* client, + const Config& config) + : client_(client), + has_handlers_(true), + maybe_has_handler_for_current_sequence_(false), + drop_remaining_touches_in_sequence_(false), + send_touch_events_async_(false) { + if (config.touch_ack_timeout_supported) { + timeout_handler_.reset( + new TouchTimeoutHandler(this, config.desktop_touch_ack_timeout_delay, + config.mobile_touch_ack_timeout_delay)); + } +} + +PassthroughTouchEventQueue::~PassthroughTouchEventQueue() {} + +void PassthroughTouchEventQueue::SendTouchCancelEventForTouchEvent( + const TouchEventWithLatencyInfo& event_to_cancel) { + TouchEventWithLatencyInfo event = event_to_cancel; + WebTouchEventTraits::ResetTypeAndTouchStates( + WebInputEvent::TouchCancel, + // TODO(rbyers): Shouldn't we use a fresh timestamp? + event.event.timeStampSeconds(), &event.event); + SendTouchEventImmediately(&event, false); +} + +void PassthroughTouchEventQueue::QueueEvent( + const TouchEventWithLatencyInfo& event) { + TRACE_EVENT0("input", "PassthroughTouchEventQueue::QueueEvent"); + PreFilterResult filter_result = FilterBeforeForwarding(event.event); + if (filter_result != FORWARD_TO_RENDERER) { + client_->OnFilteringTouchEvent(event.event); + + InputEventAckState ack_state = + filter_result == ACK_WITH_NO_CONSUMER_EXISTS + ? INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS + : INPUT_EVENT_ACK_STATE_NOT_CONSUMED; + TouchEventWithLatencyInfoAndAckState event_with_ack_state = event; + event_with_ack_state.set_ack_state(ack_state); + outstanding_touches_.insert(event_with_ack_state); + AckCompletedEvents(); + return; + } + TouchEventWithLatencyInfo cloned_event(event); + SendTouchEventImmediately(&cloned_event, true); +} + +void PassthroughTouchEventQueue::PrependTouchScrollNotification() { + TRACE_EVENT0("input", + "PassthroughTouchEventQueue::PrependTouchScrollNotification"); + + TouchEventWithLatencyInfo touch( + WebInputEvent::TouchScrollStarted, WebInputEvent::NoModifiers, + ui::EventTimeStampToSeconds(ui::EventTimeForNow()), LatencyInfo()); + touch.event.dispatchType = WebInputEvent::EventNonBlocking; + SendTouchEventImmediately(&touch, true); +} + +void PassthroughTouchEventQueue::ProcessTouchAck( + InputEventAckState ack_result, + const LatencyInfo& latency_info, + const uint32_t unique_touch_event_id) { + TRACE_EVENT0("input", "PassthroughTouchEventQueue::ProcessTouchAck"); + if (timeout_handler_ && + timeout_handler_->ConfirmTouchEvent(unique_touch_event_id, ack_result)) + return; + + auto touch_event_iter = outstanding_touches_.begin(); + while (touch_event_iter != outstanding_touches_.end()) { + if (unique_touch_event_id == touch_event_iter->event.uniqueTouchEventId) + break; + ++touch_event_iter; + } + + if (touch_event_iter == outstanding_touches_.end()) + return; + + TouchEventWithLatencyInfoAndAckState event = *touch_event_iter; + touch_event_iter = outstanding_touches_.erase(touch_event_iter); + event.latency.AddNewLatencyFrom(latency_info); + event.set_ack_state(ack_result); + outstanding_touches_.insert(touch_event_iter, event); + + AckCompletedEvents(); +} + +void PassthroughTouchEventQueue::OnGestureScrollEvent( + const GestureEventWithLatencyInfo& gesture_event) { + if (gesture_event.event.type() == blink::WebInputEvent::GestureScrollUpdate && + gesture_event.event.resendingPluginId == -1) { + send_touch_events_async_ = true; + } +} + +void PassthroughTouchEventQueue::OnGestureEventAck( + const GestureEventWithLatencyInfo& event, + InputEventAckState ack_result) { + // Turn events sent during gesture scrolls to be async. + if (event.event.type() == blink::WebInputEvent::GestureScrollUpdate && + event.event.resendingPluginId == -1) { + send_touch_events_async_ = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED); + } +} + +void PassthroughTouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) { + has_handlers_ = has_handlers; +} + +bool PassthroughTouchEventQueue::IsPendingAckTouchStart() const { + if (outstanding_touches_.empty()) + return false; + + for (auto& iter : outstanding_touches_) { + if (iter.event.type() == WebInputEvent::TouchStart) + return true; + } + return false; +} + +void PassthroughTouchEventQueue::SetAckTimeoutEnabled(bool enabled) { + if (timeout_handler_) + timeout_handler_->SetEnabled(enabled); +} + +void PassthroughTouchEventQueue::SetIsMobileOptimizedSite( + bool mobile_optimized_site) { + if (timeout_handler_) + timeout_handler_->SetUseMobileTimeout(mobile_optimized_site); +} + +bool PassthroughTouchEventQueue::IsAckTimeoutEnabled() const { + return timeout_handler_ && timeout_handler_->IsEnabled(); +} + +bool PassthroughTouchEventQueue::Empty() const { + return outstanding_touches_.empty(); +} + +void PassthroughTouchEventQueue::FlushQueue() { + drop_remaining_touches_in_sequence_ = true; + while (!outstanding_touches_.empty()) { + auto iter = outstanding_touches_.begin(); + TouchEventWithLatencyInfoAndAckState event = *iter; + outstanding_touches_.erase(iter); + if (event.ack_state() == INPUT_EVENT_ACK_STATE_UNKNOWN) + event.set_ack_state(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); + AckTouchEventToClient(event, event.ack_state()); + } +} + +void PassthroughTouchEventQueue::AckCompletedEvents() { + while (!outstanding_touches_.empty()) { + auto iter = outstanding_touches_.begin(); + if (iter->ack_state() == INPUT_EVENT_ACK_STATE_UNKNOWN) + break; + TouchEventWithLatencyInfoAndAckState event = *iter; + outstanding_touches_.erase(iter); + AckTouchEventToClient(event, event.ack_state()); + } +} + +void PassthroughTouchEventQueue::AckTouchEventToClient( + const TouchEventWithLatencyInfo& acked_event, + InputEventAckState ack_result) { + UpdateTouchConsumerStates(acked_event.event, ack_result); + + // Skip ack for TouchScrollStarted since it was synthesized within the queue. + if (acked_event.event.type() != WebInputEvent::TouchScrollStarted) { + client_->OnTouchEventAck(acked_event, ack_result); + } +} + +void PassthroughTouchEventQueue::SendTouchEventImmediately( + TouchEventWithLatencyInfo* touch, + bool wait_for_ack) { + // Note: Touchstart events are marked cancelable to allow transitions between + // platform scrolling and JS pinching. Touchend events, however, remain + // uncancelable, mitigating the risk of jank when transitioning to a fling. + if (send_touch_events_async_ && + touch->event.type() != WebInputEvent::TouchStart) + touch->event.dispatchType = WebInputEvent::EventNonBlocking; + + if (touch->event.type() == WebInputEvent::TouchStart) + touch->event.touchStartOrFirstTouchMove = true; + + // For touchmove events, compare touch points position from current event + // to last sent event and update touch points state. + if (touch->event.type() == WebInputEvent::TouchMove) { + CHECK(last_sent_touchevent_); + if (last_sent_touchevent_->type() == WebInputEvent::TouchStart) + touch->event.touchStartOrFirstTouchMove = true; + for (unsigned int i = 0; i < last_sent_touchevent_->touchesLength; ++i) { + const WebTouchPoint& last_touch_point = last_sent_touchevent_->touches[i]; + // Touches with same id may not have same index in Touches array. + for (unsigned int j = 0; j < touch->event.touchesLength; ++j) { + const WebTouchPoint& current_touchmove_point = touch->event.touches[j]; + if (current_touchmove_point.id != last_touch_point.id) + continue; + + if (!HasPointChanged(last_touch_point, current_touchmove_point)) + touch->event.touches[j].state = WebTouchPoint::StateStationary; + + break; + } + } + } + + if (touch->event.type() != WebInputEvent::TouchScrollStarted) { + if (last_sent_touchevent_) + *last_sent_touchevent_ = touch->event; + else + last_sent_touchevent_.reset(new WebTouchEvent(touch->event)); + } + + if (timeout_handler_) + timeout_handler_->StartIfNecessary(*touch); + if (wait_for_ack) + outstanding_touches_.insert(*touch); + client_->SendTouchEventImmediately(*touch); +} + +PassthroughTouchEventQueue::PreFilterResult +PassthroughTouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) { + if (event.type() == WebInputEvent::TouchScrollStarted) + return FORWARD_TO_RENDERER; + + if (WebTouchEventTraits::IsTouchSequenceStart(event)) { + // We don't know if we have a handler until we get the ACK back so + // assume it is true. + maybe_has_handler_for_current_sequence_ = true; + send_touch_events_async_ = false; + last_sent_touchevent_.reset(); + + drop_remaining_touches_in_sequence_ = false; + if (!has_handlers_) { + drop_remaining_touches_in_sequence_ = true; + return ACK_WITH_NO_CONSUMER_EXISTS; + } + } + + if (timeout_handler_ && timeout_handler_->FilterEvent(event)) + return ACK_WITH_NO_CONSUMER_EXISTS; + + if (drop_remaining_touches_in_sequence_ && + event.type() != WebInputEvent::TouchCancel) { + return ACK_WITH_NO_CONSUMER_EXISTS; + } + + if (event.type() == WebInputEvent::TouchStart) { + return (has_handlers_ || maybe_has_handler_for_current_sequence_) + ? FORWARD_TO_RENDERER + : ACK_WITH_NO_CONSUMER_EXISTS; + } + + if (maybe_has_handler_for_current_sequence_) { + // Only forward a touch if it has a non-stationary pointer that is active + // in the current touch sequence. + for (size_t i = 0; i < event.touchesLength; ++i) { + const WebTouchPoint& point = event.touches[i]; + if (point.state == WebTouchPoint::StateStationary) + continue; + + // |last_sent_touchevent_| will be non-null as long as there is an + // active touch sequence being forwarded to the renderer. + if (!last_sent_touchevent_) + continue; + + for (size_t j = 0; j < last_sent_touchevent_->touchesLength; ++j) { + if (point.id != last_sent_touchevent_->touches[j].id) + continue; + + if (event.type() != WebInputEvent::TouchMove) + return FORWARD_TO_RENDERER; + + // All pointers in TouchMove events may have state as StateMoved, + // even though none of the pointers have not changed in real. + // Forward these events when at least one pointer has changed. + if (HasPointChanged(last_sent_touchevent_->touches[j], point)) + return FORWARD_TO_RENDERER; + + // This is a TouchMove event for which we have yet to find a + // non-stationary pointer. Continue checking the next pointers + // in the |event|. + break; + } + } + } + + return ACK_WITH_NO_CONSUMER_EXISTS; +} + +void PassthroughTouchEventQueue::UpdateTouchConsumerStates( + const WebTouchEvent& event, + InputEventAckState ack_result) { + if (event.type() == WebInputEvent::TouchStart) { + if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) + send_touch_events_async_ = false; + + // Once we have the ack back for the sequence we know if there + // is a handler or not. Other touch-starts sent can upgrade + // whether we have a handler or not as well. + if (WebTouchEventTraits::IsTouchSequenceStart(event)) { + maybe_has_handler_for_current_sequence_ = + ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; + } else { + maybe_has_handler_for_current_sequence_ |= + ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; + } + } else if (WebTouchEventTraits::IsTouchSequenceEnd(event)) { + maybe_has_handler_for_current_sequence_ = false; + } +} + +size_t PassthroughTouchEventQueue::SizeForTesting() const { + return outstanding_touches_.size(); +} + +bool PassthroughTouchEventQueue::IsTimeoutRunningForTesting() const { + return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning(); +} + +const TouchEventWithLatencyInfo& +PassthroughTouchEventQueue::GetLatestEventForTesting() const { + return *outstanding_touches_.rbegin(); +} + +} // namespace content
diff --git a/content/browser/renderer_host/input/passthrough_touch_event_queue.h b/content/browser/renderer_host/input/passthrough_touch_event_queue.h new file mode 100644 index 0000000..598e9b8 --- /dev/null +++ b/content/browser/renderer_host/input/passthrough_touch_event_queue.h
@@ -0,0 +1,137 @@ +// Copyright 2017 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 CONTENT_BROWSER_RENDERER_HOST_INPUT_PASSTHROUGH_TOUCH_EVENT_QUEUE_H_ +#define CONTENT_BROWSER_RENDERER_HOST_INPUT_PASSTHROUGH_TOUCH_EVENT_QUEUE_H_ + +#include "content/browser/renderer_host/input/touch_event_queue.h" + +#include <set> + +namespace content { + +class TouchTimeoutHandler; + +// A queue that processes a touch-event and forwards it on to the +// renderer process immediately. This class assumes that queueing will +// happen inside the renderer process. This class will hold onto the pending +// events so that it can re-order the acks so that they appear in a +// logical order to the rest of the browser process. Due to the threaded +// model of the renderer it is possible that an ack for a touchend can +// be sent before the corresponding ack for the touchstart. This class +// corrects that state. +class CONTENT_EXPORT PassthroughTouchEventQueue : public TouchEventQueue { + public: + PassthroughTouchEventQueue(TouchEventQueueClient* client, + const Config& config); + + ~PassthroughTouchEventQueue() override; + + // TouchEventQueue overrides. + void QueueEvent(const TouchEventWithLatencyInfo& event) override; + + void PrependTouchScrollNotification() override; + + void ProcessTouchAck(InputEventAckState ack_result, + const ui::LatencyInfo& latency_info, + const uint32_t unique_touch_event_id) override; + void OnGestureScrollEvent( + const GestureEventWithLatencyInfo& gesture_event) override; + + void OnGestureEventAck(const GestureEventWithLatencyInfo& event, + InputEventAckState ack_result) override; + + void OnHasTouchEventHandlers(bool has_handlers) override; + + bool IsPendingAckTouchStart() const override; + + void SetAckTimeoutEnabled(bool enabled) override; + + void SetIsMobileOptimizedSite(bool mobile_optimized_site) override; + + bool IsAckTimeoutEnabled() const override; + + bool Empty() const override; + + protected: + void SendTouchCancelEventForTouchEvent( + const TouchEventWithLatencyInfo& event_to_cancel) override; + void UpdateTouchConsumerStates(const blink::WebTouchEvent& event, + InputEventAckState ack_result) override; + // Empties the queue of touch events. This may result in any number of gesture + // events being sent to the renderer. + void FlushQueue() override; + + private: + friend class PassthroughTouchEventQueueTest; + + class TouchEventWithLatencyInfoAndAckState + : public TouchEventWithLatencyInfo { + public: + TouchEventWithLatencyInfoAndAckState(const TouchEventWithLatencyInfo&); + bool operator<(const TouchEventWithLatencyInfoAndAckState&) const; + InputEventAckState ack_state() const { return ack_state_; } + void set_ack_state(InputEventAckState state) { ack_state_ = state; } + + private: + InputEventAckState ack_state_; + }; + + enum PreFilterResult { + ACK_WITH_NO_CONSUMER_EXISTS, + ACK_WITH_NOT_CONSUMED, + FORWARD_TO_RENDERER, + }; + // Filter touches prior to forwarding to the renderer, e.g., if the renderer + // has no touch handler. + PreFilterResult FilterBeforeForwarding(const blink::WebTouchEvent& event); + + void AckTouchEventToClient(const TouchEventWithLatencyInfo& acked_event, + InputEventAckState ack_result); + + void SendTouchEventImmediately(TouchEventWithLatencyInfo* touch, + bool wait_for_ack); + + void AckCompletedEvents(); + + bool IsTimeoutRunningForTesting() const; + const TouchEventWithLatencyInfo& GetLatestEventForTesting() const; + size_t SizeForTesting() const; + + // Handles touch event forwarding and ack'ed event dispatch. + TouchEventQueueClient* client_; + + // Whether the renderer has at least one touch handler. + bool has_handlers_; + + // Whether any pointer in the touch sequence may have having a consumer. + bool maybe_has_handler_for_current_sequence_; + + // Whether to allow any remaining touches for the current sequence. Note that + // this is a stricter condition than an empty |touch_consumer_states_|, as it + // also prevents forwarding of touchstart events for new pointers in the + // current sequence. This is only used when the event is synthetically + // cancelled after a touch timeout. + bool drop_remaining_touches_in_sequence_; + + // Optional handler for timed-out touch event acks. + std::unique_ptr<TouchTimeoutHandler> timeout_handler_; + + // Whether touch events should be sent as uncancelable or not. + bool send_touch_events_async_; + + // Event is saved to compare pointer positions for new touchmove events. + std::unique_ptr<blink::WebTouchEvent> last_sent_touchevent_; + + // Stores outstanding touches that have been sent to the renderer but have + // not yet been ack'd by the renderer. The set is explicitly ordered based + // on the unique touch event id. + std::set<TouchEventWithLatencyInfoAndAckState> outstanding_touches_; + + DISALLOW_COPY_AND_ASSIGN(PassthroughTouchEventQueue); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_PASSTHROUGH_TOUCH_EVENT_QUEUE_H_
diff --git a/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc b/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc new file mode 100644 index 0000000..6b708cc --- /dev/null +++ b/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
@@ -0,0 +1,1733 @@ +// Copyright 2017 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 "content/browser/renderer_host/input/passthrough_touch_event_queue.h" + +#include <stddef.h> + +#include <memory> +#include <utility> + +#include "base/location.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "content/browser/renderer_host/input/timeout_monitor.h" +#include "content/common/input/synthetic_web_input_event_builders.h" +#include "content/common/input/web_touch_event_traits.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/public/platform/WebInputEvent.h" +#include "ui/events/base_event_utils.h" + +using blink::WebGestureEvent; +using blink::WebInputEvent; +using blink::WebTouchEvent; +using blink::WebTouchPoint; + +namespace content { +namespace { + +const double kMinSecondsBetweenThrottledTouchmoves = 0.2; +const float kSlopLengthDips = 10; +const float kHalfSlopLengthDips = kSlopLengthDips / 2; + +base::TimeDelta DefaultTouchTimeoutDelay() { + return base::TimeDelta::FromMilliseconds(1); +} +} // namespace + +class PassthroughTouchEventQueueTest : public testing::Test, + public TouchEventQueueClient { + public: + PassthroughTouchEventQueueTest() + : acked_event_count_(0), + last_acked_event_state_(INPUT_EVENT_ACK_STATE_UNKNOWN), + slop_length_dips_(0) {} + + ~PassthroughTouchEventQueueTest() override {} + + // testing::Test + void SetUp() override { + ResetQueueWithConfig(TouchEventQueue::Config()); + sent_events_ids_.clear(); + } + + void TearDown() override { queue_.reset(); } + + // TouchEventQueueClient + void SendTouchEventImmediately( + const TouchEventWithLatencyInfo& event) override { + sent_events_.push_back(event.event); + sent_events_ids_.push_back(event.event.uniqueTouchEventId); + if (sync_ack_result_) { + auto sync_ack_result = std::move(sync_ack_result_); + SendTouchEventAck(*sync_ack_result); + } + } + + void OnTouchEventAck(const TouchEventWithLatencyInfo& event, + InputEventAckState ack_result) override { + ++acked_event_count_; + last_acked_event_ = event.event; + last_acked_event_state_ = ack_result; + if (followup_touch_event_) { + std::unique_ptr<WebTouchEvent> followup_touch_event = + std::move(followup_touch_event_); + SendTouchEvent(*followup_touch_event); + } + if (followup_gesture_event_) { + std::unique_ptr<WebGestureEvent> followup_gesture_event = + std::move(followup_gesture_event_); + queue_->OnGestureScrollEvent(GestureEventWithLatencyInfo( + *followup_gesture_event, ui::LatencyInfo())); + } + } + + void OnFilteringTouchEvent(const blink::WebTouchEvent& touch_event) override { + } + + protected: + void SetUpForTouchMoveSlopTesting(double slop_length_dips) { + slop_length_dips_ = slop_length_dips; + } + + void SetUpForTimeoutTesting(base::TimeDelta desktop_timeout_delay, + base::TimeDelta mobile_timeout_delay) { + TouchEventQueue::Config config; + config.desktop_touch_ack_timeout_delay = desktop_timeout_delay; + config.mobile_touch_ack_timeout_delay = mobile_timeout_delay; + config.touch_ack_timeout_supported = true; + ResetQueueWithConfig(config); + } + + void SetUpForTimeoutTesting() { + SetUpForTimeoutTesting(DefaultTouchTimeoutDelay(), + DefaultTouchTimeoutDelay()); + } + + void SendTouchEvent(WebTouchEvent event) { + if (slop_length_dips_) { + event.movedBeyondSlopRegion = false; + if (WebTouchEventTraits::IsTouchSequenceStart(event)) + anchor_ = event.touches[0].position; + if (event.type() == WebInputEvent::TouchMove) { + gfx::Vector2dF delta = anchor_ - event.touches[0].position; + if (delta.LengthSquared() > slop_length_dips_ * slop_length_dips_) + event.movedBeyondSlopRegion = true; + } + } else { + event.movedBeyondSlopRegion = event.type() == WebInputEvent::TouchMove; + } + queue_->QueueEvent(TouchEventWithLatencyInfo(event, ui::LatencyInfo())); + } + + void SendGestureEvent(WebInputEvent::Type type) { + WebGestureEvent event(type, WebInputEvent::NoModifiers, + ui::EventTimeStampToSeconds(ui::EventTimeForNow())); + queue_->OnGestureScrollEvent( + GestureEventWithLatencyInfo(event, ui::LatencyInfo())); + } + + void SendTouchEventAck(InputEventAckState ack_result) { + DCHECK(!sent_events_ids_.empty()); + queue_->ProcessTouchAck(ack_result, ui::LatencyInfo(), + sent_events_ids_.front()); + sent_events_ids_.pop_front(); + } + + void SendTouchEventAckLast(InputEventAckState ack_result) { + DCHECK(!sent_events_ids_.empty()); + queue_->ProcessTouchAck(ack_result, ui::LatencyInfo(), + sent_events_ids_.back()); + sent_events_ids_.pop_back(); + } + + void SendTouchEventAckWithID(InputEventAckState ack_result, + int unique_event_id) { + queue_->ProcessTouchAck(ack_result, ui::LatencyInfo(), unique_event_id); + sent_events_ids_.erase(std::remove(sent_events_ids_.begin(), + sent_events_ids_.end(), unique_event_id), + sent_events_ids_.end()); + } + + void SendGestureEventAck(WebInputEvent::Type type, + InputEventAckState ack_result) { + GestureEventWithLatencyInfo event( + type, blink::WebInputEvent::NoModifiers, + ui::EventTimeStampToSeconds(ui::EventTimeForNow()), ui::LatencyInfo()); + queue_->OnGestureEventAck(event, ack_result); + } + + void SetFollowupEvent(const WebTouchEvent& event) { + followup_touch_event_.reset(new WebTouchEvent(event)); + } + + void SetFollowupEvent(const WebGestureEvent& event) { + followup_gesture_event_.reset(new WebGestureEvent(event)); + } + + void SetSyncAckResult(InputEventAckState sync_ack_result) { + sync_ack_result_.reset(new InputEventAckState(sync_ack_result)); + } + + void PressTouchPoint(float x, float y) { + touch_event_.PressPoint(x, y); + SendTouchEvent(); + } + + void MoveTouchPoint(int index, float x, float y) { + touch_event_.MovePoint(index, x, y); + SendTouchEvent(); + } + + void MoveTouchPoints(int index0, + float x0, + float y0, + int index1, + float x1, + float y1) { + touch_event_.MovePoint(index0, x0, y0); + touch_event_.MovePoint(index1, x1, y1); + SendTouchEvent(); + } + + void ChangeTouchPointRadius(int index, float radius_x, float radius_y) { + CHECK_GE(index, 0); + CHECK_LT(index, touch_event_.kTouchesLengthCap); + WebTouchPoint& point = touch_event_.touches[index]; + point.radiusX = radius_x; + point.radiusY = radius_y; + touch_event_.touches[index].state = WebTouchPoint::StateMoved; + touch_event_.movedBeyondSlopRegion = true; + WebTouchEventTraits::ResetType(WebInputEvent::TouchMove, + touch_event_.timeStampSeconds(), + &touch_event_); + SendTouchEvent(); + } + + void ChangeTouchPointRotationAngle(int index, float rotation_angle) { + CHECK_GE(index, 0); + CHECK_LT(index, touch_event_.kTouchesLengthCap); + WebTouchPoint& point = touch_event_.touches[index]; + point.rotationAngle = rotation_angle; + touch_event_.touches[index].state = WebTouchPoint::StateMoved; + touch_event_.movedBeyondSlopRegion = true; + WebTouchEventTraits::ResetType(WebInputEvent::TouchMove, + touch_event_.timeStampSeconds(), + &touch_event_); + SendTouchEvent(); + } + + void ChangeTouchPointForce(int index, float force) { + CHECK_GE(index, 0); + CHECK_LT(index, touch_event_.kTouchesLengthCap); + WebTouchPoint& point = touch_event_.touches[index]; + point.force = force; + touch_event_.touches[index].state = WebTouchPoint::StateMoved; + touch_event_.movedBeyondSlopRegion = true; + WebTouchEventTraits::ResetType(WebInputEvent::TouchMove, + touch_event_.timeStampSeconds(), + &touch_event_); + SendTouchEvent(); + } + + void ReleaseTouchPoint(int index) { + touch_event_.ReleasePoint(index); + SendTouchEvent(); + } + + void CancelTouchPoint(int index) { + touch_event_.CancelPoint(index); + SendTouchEvent(); + } + + void PrependTouchScrollNotification() { + queue_->PrependTouchScrollNotification(); + } + + void AdvanceTouchTime(double seconds) { + touch_event_.setTimeStampSeconds(touch_event_.timeStampSeconds() + seconds); + } + + void ResetTouchEvent() { touch_event_ = SyntheticWebTouchEvent(); } + + size_t GetAndResetAckedEventCount() { + size_t count = acked_event_count_; + acked_event_count_ = 0; + return count; + } + + size_t GetAndResetSentEventCount() { + size_t count = sent_events_.size(); + sent_events_.clear(); + return count; + } + + bool IsPendingAckTouchStart() const { + return queue_->IsPendingAckTouchStart(); + } + + void OnHasTouchEventHandlers(bool has_handlers) { + queue_->OnHasTouchEventHandlers(has_handlers); + } + + void SetAckTimeoutDisabled() { queue_->SetAckTimeoutEnabled(false); } + + void SetIsMobileOptimizedSite(bool is_mobile_optimized) { + queue_->SetIsMobileOptimizedSite(is_mobile_optimized); + } + + bool IsTimeoutRunning() const { return queue_->IsTimeoutRunningForTesting(); } + + size_t queued_event_count() const { return queue_->SizeForTesting(); } + + const WebTouchEvent& latest_event() const { + return queue_->GetLatestEventForTesting().event; + } + + const WebTouchEvent& acked_event() const { return last_acked_event_; } + + const WebTouchEvent& sent_event() const { + DCHECK(!sent_events_.empty()); + return sent_events_.back(); + } + + const std::vector<WebTouchEvent>& all_sent_events() const { + return sent_events_; + } + + InputEventAckState acked_event_state() const { + return last_acked_event_state_; + } + + static void RunTasksAndWait(base::TimeDelta delay) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), delay); + base::RunLoop().Run(); + } + + int GetUniqueTouchEventID() { return sent_events_ids_.back(); } + + private: + void SendTouchEvent() { + SendTouchEvent(touch_event_); + touch_event_.ResetPoints(); + } + + void ResetQueueWithConfig(const TouchEventQueue::Config& config) { + queue_.reset(new PassthroughTouchEventQueue(this, config)); + queue_->OnHasTouchEventHandlers(true); + } + + std::unique_ptr<PassthroughTouchEventQueue> queue_; + size_t acked_event_count_; + WebTouchEvent last_acked_event_; + std::vector<WebTouchEvent> sent_events_; + InputEventAckState last_acked_event_state_; + SyntheticWebTouchEvent touch_event_; + std::unique_ptr<WebTouchEvent> followup_touch_event_; + std::unique_ptr<WebGestureEvent> followup_gesture_event_; + std::unique_ptr<InputEventAckState> sync_ack_result_; + double slop_length_dips_; + gfx::PointF anchor_; + base::MessageLoopForUI message_loop_; + std::deque<int> sent_events_ids_; +}; + +// Tests that touch-events are queued properly. +TEST_F(PassthroughTouchEventQueueTest, Basic) { + PressTouchPoint(1, 1); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + + // The second touch should be sent right away even though + // we haven't received an ack for the touch start. + MoveTouchPoint(0, 5, 5); + EXPECT_EQ(2U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + + // Receive an ACK for the first touch-event. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(WebInputEvent::TouchStart, acked_event().type()); + EXPECT_EQ(WebInputEvent::Blocking, acked_event().dispatchType); + + // Receive an ACK for the second touch-event. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(WebInputEvent::TouchMove, acked_event().type()); + EXPECT_EQ(WebInputEvent::Blocking, acked_event().dispatchType); +} + +// Tests that touch-events with multiple points are queued properly. +TEST_F(PassthroughTouchEventQueueTest, BasicMultiTouch) { + const size_t kPointerCount = 10; + for (float i = 0; i < kPointerCount; ++i) + PressTouchPoint(i, i); + + EXPECT_EQ(kPointerCount, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(kPointerCount, queued_event_count()); + + for (int i = 0; i < static_cast<int>(kPointerCount); ++i) + MoveTouchPoint(i, 1.f + i, 2.f + i); + + EXPECT_EQ(kPointerCount, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + // No coalescing happens in the queue since they are all sent immediately. + EXPECT_EQ(2 * kPointerCount, queued_event_count()); + + for (int i = 0; i < static_cast<int>(kPointerCount); ++i) + ReleaseTouchPoint(kPointerCount - 1 - i); + + EXPECT_EQ(kPointerCount, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(kPointerCount * 3, queued_event_count()); + + // Ack all presses. + for (size_t i = 0; i < kPointerCount; ++i) + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + + EXPECT_EQ(kPointerCount, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + + // Ack the touch moves. + for (size_t i = 0; i < kPointerCount; ++i) + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(kPointerCount, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + + // Ack all releases. + for (size_t i = 0; i < kPointerCount; ++i) + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + + EXPECT_EQ(kPointerCount, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); +} + +// Tests that the touch-queue continues delivering events for an active touch +// sequence after all handlers are removed. +TEST_F(PassthroughTouchEventQueueTest, + TouchesForwardedIfHandlerRemovedDuringSequence) { + OnHasTouchEventHandlers(true); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + + // Send a touch-press event. + PressTouchPoint(1, 1); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, queued_event_count()); + + // Signal that all touch handlers have been removed. + OnHasTouchEventHandlers(false); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(1U, queued_event_count()); + + // Process the ack for the sent touch, ensuring that it is honored (despite + // the touch handler having been removed). + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, acked_event_state()); + + // Try forwarding a new pointer. It should be forwarded as usual. + PressTouchPoint(2, 2); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, queued_event_count()); + + // Further events for any pointer should be forwarded, even for pointers that + // reported no consumer. + MoveTouchPoint(1, 3, 3); + ReleaseTouchPoint(1); + EXPECT_EQ(2U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Events for the first pointer, that had a handler, should be forwarded. + MoveTouchPoint(0, 4, 4); + ReleaseTouchPoint(0); + EXPECT_EQ(2U, GetAndResetSentEventCount()); + EXPECT_EQ(2U, queued_event_count()); + + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, acked_event_state()); + + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, acked_event_state()); +} + +// Tests that addition of a touch handler during a touch sequence will not cause +// the remaining sequence to be forwarded. +TEST_F(PassthroughTouchEventQueueTest, + ActiveSequenceNotForwardedWhenHandlersAdded) { + OnHasTouchEventHandlers(false); + + // Send a touch-press event while there is no handler. + PressTouchPoint(1, 1); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, queued_event_count()); + + OnHasTouchEventHandlers(true); + + // The remaining touch sequence should not be forwarded. + MoveTouchPoint(0, 5, 5); + ReleaseTouchPoint(0); + EXPECT_EQ(2U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, queued_event_count()); + + // A new touch sequence should resume forwarding. + PressTouchPoint(1, 1); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); +} + +// Tests that removal of a touch handler during a touch sequence will prevent +// the remaining sequence from being forwarded, even if another touch handler is +// registered during the same touch sequence. +TEST_F(PassthroughTouchEventQueueTest, + ActiveSequenceDroppedWhenHandlersRemoved) { + // Send a touch-press event. + PressTouchPoint(1, 1); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, queued_event_count()); + + // Queue a touch-move event. + MoveTouchPoint(0, 5, 5); + EXPECT_EQ(2U, queued_event_count()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + + // Unregister all touch handlers. + OnHasTouchEventHandlers(false); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(2U, queued_event_count()); + + // Repeated registration/unregstration of handlers should have no effect as + // we're still awaiting the ack arrival. + OnHasTouchEventHandlers(true); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(2U, queued_event_count()); + OnHasTouchEventHandlers(false); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(2U, queued_event_count()); + + // clear the queue . + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); + EXPECT_EQ(2U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, queued_event_count()); + + // Events should be dropped while there is no touch handler. + MoveTouchPoint(0, 10, 10); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + + // Simulate touch handler registration in the middle of a touch sequence. + OnHasTouchEventHandlers(true); + + // The touch end for the interrupted sequence should be dropped. + ReleaseTouchPoint(0); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + + // A new touch sequence should be forwarded properly. + PressTouchPoint(1, 1); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); +} + +// Tests that removal/addition of a touch handler without any intervening +// touch activity has no affect on touch forwarding. +TEST_F(PassthroughTouchEventQueueTest, + ActiveSequenceUnaffectedByRepeatedHandlerRemovalAndAddition) { + // Send a touch-press event. + PressTouchPoint(1, 1); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, queued_event_count()); + + // Simulate the case where the touchstart handler removes itself, and adds a + // touchmove handler. + OnHasTouchEventHandlers(false); + OnHasTouchEventHandlers(true); + + // Queue a touch-move event, should be sent right away. + MoveTouchPoint(0, 5, 5); + EXPECT_EQ(2U, queued_event_count()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + + // The ack should trigger forwarding of the touchmove, as if no touch + // handler registration changes have occurred. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, queued_event_count()); +} + +// Tests that the touch-event queue is robust to redundant acks. +TEST_F(PassthroughTouchEventQueueTest, SpuriousAcksIgnored) { + // Trigger a spurious ack. + SendTouchEventAckWithID(INPUT_EVENT_ACK_STATE_CONSUMED, 0); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + + // Send and ack a touch press. + PressTouchPoint(1, 1); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, queued_event_count()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, queued_event_count()); + + // Trigger a spurious ack. + SendTouchEventAckWithID(INPUT_EVENT_ACK_STATE_CONSUMED, 3); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); +} + +// Tests that touch-move events are not sent to the renderer if the preceding +// touch-press event did not have a consumer (and consequently, did not hit the +// main thread in the renderer). +TEST_F(PassthroughTouchEventQueueTest, NoConsumer) { + // The first touch-press should reach the renderer. + PressTouchPoint(1, 1); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + + // The second touch should be sent since we don't know if there is + // a consumer or not. + MoveTouchPoint(0, 5, 5); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(2U, queued_event_count()); + + // Receive an ACK for the first touch-event and the first touch-move + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(2U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + + // Send a release event. This should not reach the renderer. + ReleaseTouchPoint(0); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(WebInputEvent::TouchEnd, acked_event().type()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Send a press-event, followed by move a following move should not + // be sent but held in the queue. + PressTouchPoint(10, 10); + MoveTouchPoint(0, 5, 5); + + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); + EXPECT_EQ(2U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + MoveTouchPoint(0, 6, 5); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(2U, queued_event_count()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(2U, GetAndResetAckedEventCount()); +} + +TEST_F(PassthroughTouchEventQueueTest, AckTouchEventInReverse) { + PressTouchPoint(1, 1); + MoveTouchPoint(0, 5, 5); + MoveTouchPoint(0, 15, 15); + ReleaseTouchPoint(0); + + EXPECT_EQ(4U, GetAndResetSentEventCount()); + EXPECT_EQ(4U, queued_event_count()); + + SendTouchEventAckLast(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(4U, queued_event_count()); + + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(WebInputEvent::TouchStart, acked_event().type()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(3U, queued_event_count()); + + SendTouchEventAckLast(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(3U, queued_event_count()); + + SendTouchEventAckLast(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(WebInputEvent::TouchEnd, acked_event().type()); + EXPECT_EQ(3U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, queued_event_count()); +} + +// Tests that touch-event's enqueued via a touch ack are properly handled. +TEST_F(PassthroughTouchEventQueueTest, AckWithFollowupEvents) { + // Queue a touch down. + PressTouchPoint(1, 1); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + + // Create a touch event that will be queued synchronously by a touch ack. + // Note, this will be triggered by all subsequent touch acks. + WebTouchEvent followup_event( + WebInputEvent::TouchMove, WebInputEvent::NoModifiers, + ui::EventTimeStampToSeconds(ui::EventTimeForNow())); + followup_event.touchesLength = 1; + followup_event.touches[0].id = 0; + followup_event.touches[0].state = WebTouchPoint::StateMoved; + SetFollowupEvent(followup_event); + + // Receive an ACK for the press. This should cause the followup touch-move to + // be sent to the renderer. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, acked_event_state()); + EXPECT_EQ(WebInputEvent::TouchStart, acked_event().type()); + + // Queue another event. + MoveTouchPoint(0, 2, 2); + EXPECT_EQ(2U, queued_event_count()); + + // Receive an ACK for the touch-move followup event. This should cause the + // subsequent touch move event be sent to the renderer. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); +} + +// Tests that touch-events can be synchronously ack'ed. +TEST_F(PassthroughTouchEventQueueTest, SynchronousAcks) { + // TouchStart + SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED); + PressTouchPoint(1, 1); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // TouchMove + SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED); + MoveTouchPoint(0, 2, 2); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // TouchEnd + SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED); + ReleaseTouchPoint(0); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // TouchCancel (first inserting a TouchStart so the TouchCancel will be sent) + PressTouchPoint(1, 1); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED); + CancelTouchPoint(0); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); +} + +// Tests that followup events triggered by an immediate ack from +// TouchEventQueue::QueueEvent() are properly handled. +TEST_F(PassthroughTouchEventQueueTest, ImmediateAckWithFollowupEvents) { + // Create a touch event that will be queued synchronously by a touch ack. + WebTouchEvent followup_event( + WebInputEvent::TouchStart, WebInputEvent::NoModifiers, + ui::EventTimeStampToSeconds(ui::EventTimeForNow())); + followup_event.touchesLength = 1; + followup_event.touches[0].id = 1; + followup_event.touches[0].state = WebTouchPoint::StatePressed; + SetFollowupEvent(followup_event); + + // Now, enqueue a stationary touch that will not be forwarded. This should be + // immediately ack'ed with "NO_CONSUMER_EXISTS". The followup event should + // then be enqueued and immediately sent to the renderer. + WebTouchEvent stationary_event( + WebInputEvent::TouchMove, WebInputEvent::NoModifiers, + ui::EventTimeStampToSeconds(ui::EventTimeForNow())); + ; + stationary_event.touchesLength = 1; + stationary_event.touches[0].id = 1; + stationary_event.touches[0].state = WebTouchPoint::StateStationary; + SendTouchEvent(stationary_event); + + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, acked_event_state()); + EXPECT_EQ(WebInputEvent::TouchMove, acked_event().type()); +} + +// Tests basic TouchEvent forwarding suppression. +TEST_F(PassthroughTouchEventQueueTest, NoTouchBasic) { + // Disable TouchEvent forwarding. + OnHasTouchEventHandlers(false); + PressTouchPoint(30, 5); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // TouchMove should not be sent to renderer. + MoveTouchPoint(0, 65, 10); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // TouchEnd should not be sent to renderer. + ReleaseTouchPoint(0); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Enable TouchEvent forwarding. + OnHasTouchEventHandlers(true); + + PressTouchPoint(80, 10); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + MoveTouchPoint(0, 80, 20); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + ReleaseTouchPoint(0); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); +} + +// Tests that IsTouchStartPendingAck works correctly. +TEST_F(PassthroughTouchEventQueueTest, PendingStart) { + EXPECT_FALSE(IsPendingAckTouchStart()); + + // Send the touchstart for one point (#1). + PressTouchPoint(1, 1); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_TRUE(IsPendingAckTouchStart()); + + // Send a touchmove for that point (#2). + MoveTouchPoint(0, 5, 5); + EXPECT_EQ(2U, queued_event_count()); + EXPECT_TRUE(IsPendingAckTouchStart()); + + // Ack the touchstart (#1). + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_FALSE(IsPendingAckTouchStart()); + + // Send a touchstart for another point (#3). + PressTouchPoint(10, 10); + EXPECT_EQ(2U, queued_event_count()); + EXPECT_TRUE(IsPendingAckTouchStart()); + + // Ack the touchmove (#2). + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_TRUE(IsPendingAckTouchStart()); + + // Send a touchstart for a third point (#4). + PressTouchPoint(15, 15); + EXPECT_EQ(2U, queued_event_count()); + EXPECT_TRUE(IsPendingAckTouchStart()); + + // Ack the touchstart for the second point (#3). + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_TRUE(IsPendingAckTouchStart()); + + // Ack the touchstart for the third point (#4). + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_FALSE(IsPendingAckTouchStart()); +} + +// Tests that the touch timeout is started when sending certain touch types. +TEST_F(PassthroughTouchEventQueueTest, TouchTimeoutTypes) { + SetUpForTimeoutTesting(); + + // Sending a TouchStart will start the timeout. + PressTouchPoint(0, 1); + EXPECT_TRUE(IsTimeoutRunning()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + + // A TouchMove should start the timeout. + MoveTouchPoint(0, 5, 5); + EXPECT_TRUE(IsTimeoutRunning()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + + // A TouchEnd should not start the timeout. + ReleaseTouchPoint(0); + EXPECT_FALSE(IsTimeoutRunning()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + + // A TouchCancel should not start the timeout. + PressTouchPoint(0, 1); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + ASSERT_FALSE(IsTimeoutRunning()); + CancelTouchPoint(0); + EXPECT_FALSE(IsTimeoutRunning()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); +} + +// Tests that a delayed TouchEvent ack will trigger a TouchCancel timeout, +// disabling touch forwarding until the next TouchStart is received after +// the timeout events are ack'ed. +TEST_F(PassthroughTouchEventQueueTest, TouchTimeoutBasic) { + SetUpForTimeoutTesting(); + + // Queue a TouchStart. + GetAndResetSentEventCount(); + GetAndResetAckedEventCount(); + PressTouchPoint(0, 1); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + ASSERT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_TRUE(IsTimeoutRunning()); + + // Delay the ack. + RunTasksAndWait(DefaultTouchTimeoutDelay() * 2); + + // The timeout should have fired, synthetically ack'ing the timed-out event. + // TouchEvent forwarding is disabled until the ack is received for the + // timed-out event and the future cancel event. + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Ack'ing the original event should trigger a cancel event. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(WebInputEvent::TouchCancel, sent_event().type()); + EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + + // Touch events should not be forwarded until we receive the cancel acks. + MoveTouchPoint(0, 1, 1); + ASSERT_EQ(0U, GetAndResetSentEventCount()); + ASSERT_EQ(1U, GetAndResetAckedEventCount()); + + ReleaseTouchPoint(0); + ASSERT_EQ(0U, GetAndResetSentEventCount()); + ASSERT_EQ(1U, GetAndResetAckedEventCount()); + + // The synthetic TouchCancel ack should not reach the client, but should + // resume touch forwarding. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + + // Subsequent events should be handled normally. + PressTouchPoint(0, 1); + EXPECT_EQ(WebInputEvent::TouchStart, sent_event().type()); + EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); +} + +// Tests that the timeout is never started if the renderer consumes +// a TouchEvent from the current touch sequence. +TEST_F(PassthroughTouchEventQueueTest, + NoTouchTimeoutIfRendererIsConsumingGesture) { + SetUpForTimeoutTesting(); + + // Queue a TouchStart. + PressTouchPoint(0, 1); + ASSERT_TRUE(IsTimeoutRunning()); + + // Mark the event as consumed. This should prevent the timeout from + // being activated on subsequent TouchEvents in this gesture. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + + // A TouchMove should not start the timeout. + MoveTouchPoint(0, 5, 5); + EXPECT_FALSE(IsTimeoutRunning()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + + // A secondary TouchStart should not start the timeout. + PressTouchPoint(1, 0); + EXPECT_FALSE(IsTimeoutRunning()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + + // A TouchEnd should not start the timeout. + ReleaseTouchPoint(1); + EXPECT_FALSE(IsTimeoutRunning()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + + // A TouchCancel should not start the timeout. + CancelTouchPoint(0); + EXPECT_FALSE(IsTimeoutRunning()); +} + +// Tests that the timeout is never started if the renderer consumes +// a TouchEvent from the current touch sequence. +TEST_F(PassthroughTouchEventQueueTest, + NoTouchTimeoutIfDisabledAfterTouchStart) { + SetUpForTimeoutTesting(); + + // Queue a TouchStart. + PressTouchPoint(0, 1); + ASSERT_TRUE(IsTimeoutRunning()); + + // Send the ack immediately. The timeout should not have fired. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Now explicitly disable the timeout. + SetAckTimeoutDisabled(); + EXPECT_FALSE(IsTimeoutRunning()); + + // A TouchMove should not start or trigger the timeout. + MoveTouchPoint(0, 5, 5); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + RunTasksAndWait(DefaultTouchTimeoutDelay() * 2); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); +} + +// Tests that the timeout is never started if the ack is synchronous. +TEST_F(PassthroughTouchEventQueueTest, NoTouchTimeoutIfAckIsSynchronous) { + SetUpForTimeoutTesting(); + + // Queue a TouchStart. + SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED); + ASSERT_FALSE(IsTimeoutRunning()); + PressTouchPoint(0, 1); + EXPECT_FALSE(IsTimeoutRunning()); +} + +// Tests that the timeout does not fire if explicitly disabled while an event +// is in-flight. +TEST_F(PassthroughTouchEventQueueTest, + NoTouchTimeoutIfDisabledWhileTimerIsActive) { + SetUpForTimeoutTesting(); + + // Queue a TouchStart. + PressTouchPoint(0, 1); + ASSERT_TRUE(IsTimeoutRunning()); + + // Verify that disabling the timeout also turns off the timer. + SetAckTimeoutDisabled(); + EXPECT_FALSE(IsTimeoutRunning()); + RunTasksAndWait(DefaultTouchTimeoutDelay() * 2); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); +} + +// Tests that the timeout does not fire if the delay is zero. +TEST_F(PassthroughTouchEventQueueTest, NoTouchTimeoutIfTimeoutDelayIsZero) { + SetUpForTimeoutTesting(base::TimeDelta(), base::TimeDelta()); + + // As the delay is zero, timeout behavior should be disabled. + PressTouchPoint(0, 1); + EXPECT_FALSE(IsTimeoutRunning()); + RunTasksAndWait(DefaultTouchTimeoutDelay() * 2); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); +} + +// Tests that timeout delays for mobile sites take effect when appropriate. +TEST_F(PassthroughTouchEventQueueTest, TouchTimeoutConfiguredForMobile) { + base::TimeDelta desktop_delay = DefaultTouchTimeoutDelay(); + base::TimeDelta mobile_delay = base::TimeDelta(); + SetUpForTimeoutTesting(desktop_delay, mobile_delay); + + // The desktop delay is non-zero, allowing timeout behavior. + SetIsMobileOptimizedSite(false); + + PressTouchPoint(0, 1); + ASSERT_TRUE(IsTimeoutRunning()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + ReleaseTouchPoint(0); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(2U, GetAndResetAckedEventCount()); + ASSERT_FALSE(IsTimeoutRunning()); + + // The mobile delay is zero, preventing timeout behavior. + SetIsMobileOptimizedSite(true); + + PressTouchPoint(0, 1); + EXPECT_FALSE(IsTimeoutRunning()); + RunTasksAndWait(DefaultTouchTimeoutDelay() * 2); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); +} + +// Tests that a TouchCancel timeout plays nice when the timed out touch stream +// turns into a scroll gesture sequence. +TEST_F(PassthroughTouchEventQueueTest, TouchTimeoutWithFollowupGesture) { + SetUpForTimeoutTesting(); + + // Queue a TouchStart. + PressTouchPoint(0, 1); + EXPECT_TRUE(IsTimeoutRunning()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + + // The cancelled sequence may turn into a scroll gesture. + WebGestureEvent followup_scroll( + WebInputEvent::GestureScrollBegin, WebInputEvent::NoModifiers, + ui::EventTimeStampToSeconds(ui::EventTimeForNow())); + SetFollowupEvent(followup_scroll); + + // Delay the ack. + RunTasksAndWait(DefaultTouchTimeoutDelay() * 2); + + // The timeout should have fired, disabling touch forwarding until both acks + // are received, acking the timed out event. + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Ack the original event, triggering a TouchCancel. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + + // Ack the cancel event. Normally, this would resume touch forwarding, + // but we're still within a scroll gesture so it remains disabled. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + + // Try to forward touch events for the current sequence. + GetAndResetSentEventCount(); + GetAndResetAckedEventCount(); + MoveTouchPoint(0, 1, 1); + ReleaseTouchPoint(0); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(2U, GetAndResetAckedEventCount()); + + // Now end the scroll sequence, resuming touch handling. + SendGestureEvent(blink::WebInputEvent::GestureScrollEnd); + PressTouchPoint(0, 1); + EXPECT_TRUE(IsTimeoutRunning()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); +} + +// Tests that a TouchCancel timeout plays nice when the timed out touch stream +// turns into a scroll gesture sequence, but the original event acks are +// significantly delayed. +TEST_F(PassthroughTouchEventQueueTest, + TouchTimeoutWithFollowupGestureAndDelayedAck) { + SetUpForTimeoutTesting(); + + // Queue a TouchStart. + PressTouchPoint(0, 1); + EXPECT_TRUE(IsTimeoutRunning()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + + // The cancelled sequence may turn into a scroll gesture. + WebGestureEvent followup_scroll( + WebInputEvent::GestureScrollBegin, WebInputEvent::NoModifiers, + ui::EventTimeStampToSeconds(ui::EventTimeForNow())); + SetFollowupEvent(followup_scroll); + + // Delay the ack. + RunTasksAndWait(DefaultTouchTimeoutDelay() * 2); + + // The timeout should have fired, disabling touch forwarding until both acks + // are received and acking the timed out event. + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Try to forward a touch event. + GetAndResetSentEventCount(); + GetAndResetAckedEventCount(); + MoveTouchPoint(0, 1, 1); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Now end the scroll sequence. Events will not be forwarded until the two + // outstanding touch acks are received. + SendGestureEvent(blink::WebInputEvent::GestureScrollEnd); + MoveTouchPoint(0, 2, 2); + ReleaseTouchPoint(0); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(2U, GetAndResetAckedEventCount()); + + // Ack the original event, triggering a cancel. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + + // Ack the cancel event, resuming touch forwarding. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + + PressTouchPoint(0, 1); + EXPECT_TRUE(IsTimeoutRunning()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); +} + +// Tests that a delayed TouchEvent ack will not trigger a TouchCancel timeout if +// the timed-out event had no consumer. +TEST_F(PassthroughTouchEventQueueTest, NoCancelOnTouchTimeoutWithoutConsumer) { + SetUpForTimeoutTesting(); + + // Queue a TouchStart. + PressTouchPoint(0, 1); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + ASSERT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_TRUE(IsTimeoutRunning()); + + // Delay the ack. + RunTasksAndWait(DefaultTouchTimeoutDelay() * 2); + + // The timeout should have fired, synthetically ack'ing the timed out event. + // TouchEvent forwarding is disabled until the original ack is received. + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Touch events should not be forwarded until we receive the original ack. + MoveTouchPoint(0, 1, 1); + ReleaseTouchPoint(0); + ASSERT_EQ(0U, GetAndResetSentEventCount()); + ASSERT_EQ(2U, GetAndResetAckedEventCount()); + + // Ack'ing the original event should not trigger a cancel event, as the + // TouchStart had no consumer. However, it should re-enable touch forwarding. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + + // Subsequent events should be handled normally. + PressTouchPoint(0, 1); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); +} + +// Tests that TouchMove's movedBeyondSlopRegion is set to false if within the +// boundary-inclusive slop region for an unconsumed TouchStart. +TEST_F(PassthroughTouchEventQueueTest, TouchMovedBeyondSlopRegionCheck) { + SetUpForTouchMoveSlopTesting(kSlopLengthDips); + + // Queue a TouchStart. + PressTouchPoint(0, 0); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + ASSERT_EQ(1U, GetAndResetAckedEventCount()); + + // TouchMove's movedBeyondSlopRegion within the slop region is set to false. + MoveTouchPoint(0, 0, kHalfSlopLengthDips); + EXPECT_EQ(1U, queued_event_count()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_FALSE(acked_event().movedBeyondSlopRegion); + + MoveTouchPoint(0, kHalfSlopLengthDips, 0); + EXPECT_EQ(1U, queued_event_count()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_FALSE(acked_event().movedBeyondSlopRegion); + + MoveTouchPoint(0, -kHalfSlopLengthDips, 0); + EXPECT_EQ(1U, queued_event_count()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_FALSE(acked_event().movedBeyondSlopRegion); + + MoveTouchPoint(0, -kSlopLengthDips, 0); + EXPECT_EQ(1U, queued_event_count()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_FALSE(acked_event().movedBeyondSlopRegion); + + MoveTouchPoint(0, 0, kSlopLengthDips); + EXPECT_EQ(1U, queued_event_count()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_FALSE(acked_event().movedBeyondSlopRegion); + + // When a TouchMove exceeds the (Euclidean) distance, the TouchMove's + // movedBeyondSlopRegion is set to true. + const float kFortyFiveDegreeSlopLengthXY = + kSlopLengthDips * std::sqrt(2.f) / 2; + MoveTouchPoint(0, kFortyFiveDegreeSlopLengthXY + .2f, + kFortyFiveDegreeSlopLengthXY + .2f); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_TRUE(acked_event().movedBeyondSlopRegion); +} + +// Tests that even very small TouchMove's movedBeyondSlopRegion is set to true +// when the slop region's dimension is 0. +TEST_F(PassthroughTouchEventQueueTest, + MovedBeyondSlopRegionAlwaysTrueIfDimensionZero) { + // Queue a TouchStart. + PressTouchPoint(0, 0); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + ASSERT_EQ(1U, GetAndResetAckedEventCount()); + + // Small TouchMove's movedBeyondSlopRegion is set to true. + MoveTouchPoint(0, 0.001f, 0.001f); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_TRUE(acked_event().movedBeyondSlopRegion); +} + +// Tests that secondary touch points can be forwarded even if the primary touch +// point had no consumer. +TEST_F(PassthroughTouchEventQueueTest, + SecondaryTouchForwardedAfterPrimaryHadNoConsumer) { + // Queue a TouchStart. + PressTouchPoint(0, 0); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + ASSERT_EQ(1U, GetAndResetAckedEventCount()); + + // Events should not be forwarded, as the point had no consumer. + MoveTouchPoint(0, 0, 15); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Simulate a secondary pointer press. + PressTouchPoint(20, 0); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // TouchMove with a secondary pointer should not be suppressed. + MoveTouchPoint(1, 25, 0); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); +} + +// Tests that secondary touch points can be forwarded after scrolling begins +// while first touch point has no consumer. +TEST_F(PassthroughTouchEventQueueTest, + NoForwardingAfterScrollWithNoTouchConsumers) { + // Queue a TouchStart. + PressTouchPoint(0, 0); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + ASSERT_EQ(1U, GetAndResetAckedEventCount()); + + WebGestureEvent followup_scroll(WebInputEvent::GestureScrollBegin, + WebInputEvent::NoModifiers, + WebInputEvent::TimeStampForTesting); + SetFollowupEvent(followup_scroll); + MoveTouchPoint(0, 20, 5); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, acked_event_state()); + + // The secondary pointer press should be forwarded. + PressTouchPoint(20, 0); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // TouchMove with a secondary pointer should also be forwarded. + MoveTouchPoint(1, 25, 0); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); +} + +TEST_F(PassthroughTouchEventQueueTest, TouchAbsorptionWithConsumedFirstMove) { + // Queue a TouchStart. + PressTouchPoint(0, 1); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + MoveTouchPoint(0, 20, 5); + SendGestureEvent(blink::WebInputEvent::GestureScrollBegin); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(2U, GetAndResetSentEventCount()); + + // Even if the first touchmove event was consumed, subsequent unconsumed + // touchmove events should trigger scrolling. + MoveTouchPoint(0, 60, 5); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + + MoveTouchPoint(0, 20, 5); + WebGestureEvent followup_scroll(WebInputEvent::GestureScrollUpdate, + WebInputEvent::NoModifiers, + WebInputEvent::TimeStampForTesting); + SetFollowupEvent(followup_scroll); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + SendGestureEventAck(WebInputEvent::GestureScrollUpdate, + INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + + // Touch moves are sent right away. + MoveTouchPoint(0, 60, 5); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); +} + +TEST_F(PassthroughTouchEventQueueTest, TouchStartCancelableDuringScroll) { + // Queue a touchstart and touchmove that go unconsumed, transitioning to an + // active scroll sequence. + PressTouchPoint(0, 1); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + + MoveTouchPoint(0, 20, 5); + EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType); + SendGestureEvent(blink::WebInputEvent::GestureScrollBegin); + SendGestureEvent(blink::WebInputEvent::GestureScrollUpdate); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + + // Even though scrolling has begun, touchstart events should be cancelable, + // allowing, for example, customized pinch processing. + PressTouchPoint(10, 11); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + + // As the touch start was consumed, touchmoves should no longer be throttled. + MoveTouchPoint(1, 11, 11); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + + // With throttling disabled, touchend and touchmove events should also be + // cancelable. + MoveTouchPoint(1, 12, 12); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + ReleaseTouchPoint(1); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + + // If subsequent touchmoves aren't consumed, the generated scroll events + // will restore async touch dispatch. + MoveTouchPoint(0, 25, 5); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + SendGestureEvent(blink::WebInputEvent::GestureScrollUpdate); + EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + AdvanceTouchTime(kMinSecondsBetweenThrottledTouchmoves + 0.1); + MoveTouchPoint(0, 30, 5); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + + // The touchend will be uncancelable during an active scroll sequence. + ReleaseTouchPoint(0); + EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType); + ASSERT_EQ(1U, GetAndResetSentEventCount()); +} + +TEST_F(PassthroughTouchEventQueueTest, UnseenTouchPointerIdsNotForwarded) { + SyntheticWebTouchEvent event; + event.PressPoint(0, 0); + SendTouchEvent(event); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Give the touchmove a previously unseen pointer id; it should not be sent. + int press_id = event.touches[0].id; + event.MovePoint(0, 1, 1); + event.touches[0].id = 7; + SendTouchEvent(event); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Give the touchmove a valid id; it should be sent. + event.touches[0].id = press_id; + SendTouchEvent(event); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Do the same for release. + event.ReleasePoint(0); + event.touches[0].id = 11; + SendTouchEvent(event); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Give the touchmove a valid id after release it shouldn't be sent. + event.touches[0].id = press_id; + SendTouchEvent(event); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); +} + +// Tests that touch points states are correct in TouchMove events. +TEST_F(PassthroughTouchEventQueueTest, PointerStatesInTouchMove) { + PressTouchPoint(1, 1); + PressTouchPoint(2, 2); + PressTouchPoint(3, 3); + EXPECT_EQ(3U, queued_event_count()); + EXPECT_EQ(3U, GetAndResetSentEventCount()); + PressTouchPoint(4, 4); + + // Receive ACK for the first three touch-events. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(1U, queued_event_count()); + + // Test current touches state before sending TouchMoves. + const WebTouchEvent& event1 = sent_event(); + EXPECT_EQ(WebInputEvent::TouchStart, event1.type()); + EXPECT_EQ(WebTouchPoint::StateStationary, event1.touches[0].state); + EXPECT_EQ(WebTouchPoint::StateStationary, event1.touches[1].state); + EXPECT_EQ(WebTouchPoint::StateStationary, event1.touches[2].state); + EXPECT_EQ(WebTouchPoint::StatePressed, event1.touches[3].state); + + // Move x-position for 1st touch, y-position for 2nd touch + // and do not move other touches. + MoveTouchPoints(0, 1.1f, 1.f, 1, 2.f, 20.001f); + MoveTouchPoints(2, 3.f, 3.f, 3, 4.f, 4.f); + EXPECT_EQ(3U, queued_event_count()); + + // Receive an ACK for the last TouchPress event. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + + // 1st TouchMove is sent. Test for touches state. + const WebTouchEvent& event2 = sent_event(); + EXPECT_EQ(WebInputEvent::TouchMove, event2.type()); + EXPECT_EQ(WebTouchPoint::StateMoved, event2.touches[0].state); + EXPECT_EQ(WebTouchPoint::StateMoved, event2.touches[1].state); + EXPECT_EQ(WebTouchPoint::StateStationary, event2.touches[2].state); + EXPECT_EQ(WebTouchPoint::StateStationary, event2.touches[3].state); + + // Move only 4th touch but not others. + MoveTouchPoints(0, 1.1f, 1.f, 1, 2.f, 20.001f); + MoveTouchPoints(2, 3.f, 3.f, 3, 4.1f, 4.1f); + + // Receive an ACK for previous (1st) TouchMove. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + + // 2nd TouchMove is sent. Test for touches state. + const WebTouchEvent& event3 = sent_event(); + EXPECT_EQ(WebInputEvent::TouchMove, event3.type()); + EXPECT_EQ(WebTouchPoint::StateStationary, event3.touches[0].state); + EXPECT_EQ(WebTouchPoint::StateStationary, event3.touches[1].state); + EXPECT_EQ(WebTouchPoint::StateStationary, event3.touches[2].state); + EXPECT_EQ(WebTouchPoint::StateMoved, event3.touches[3].state); +} + +// Tests that touch point state is correct in TouchMove events +// when point properties other than position changed. +TEST_F(PassthroughTouchEventQueueTest, + PointerStatesWhenOtherThanPositionChanged) { + PressTouchPoint(1, 1); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + + // Default initial radiusX/Y is (1.f, 1.f). + // Default initial rotationAngle is 1.f. + // Default initial force is 1.f. + + // Change touch point radius only. + ChangeTouchPointRadius(0, 1.5f, 1.f); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + + // TouchMove is sent. Test for pointer state. + const WebTouchEvent& event1 = sent_event(); + EXPECT_EQ(WebInputEvent::TouchMove, event1.type()); + EXPECT_EQ(WebTouchPoint::StateMoved, event1.touches[0].state); + + // Change touch point force. + ChangeTouchPointForce(0, 0.9f); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + + // TouchMove is sent. Test for pointer state. + const WebTouchEvent& event2 = sent_event(); + EXPECT_EQ(WebInputEvent::TouchMove, event2.type()); + EXPECT_EQ(WebTouchPoint::StateMoved, event2.touches[0].state); + + // Change touch point rotationAngle. + ChangeTouchPointRotationAngle(0, 1.1f); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + + // TouchMove is sent. Test for pointer state. + const WebTouchEvent& event3 = sent_event(); + EXPECT_EQ(WebInputEvent::TouchMove, event3.type()); + EXPECT_EQ(WebTouchPoint::StateMoved, event3.touches[0].state); + + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(4U, GetAndResetSentEventCount()); + EXPECT_EQ(4U, GetAndResetAckedEventCount()); +} + +// Tests that TouchMoves are filtered when none of the points are changed. +TEST_F(PassthroughTouchEventQueueTest, FilterTouchMovesWhenNoPointerChanged) { + PressTouchPoint(1, 1); + PressTouchPoint(2, 2); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(2U, GetAndResetSentEventCount()); + EXPECT_EQ(2U, GetAndResetAckedEventCount()); + + // Move 1st touch point. + MoveTouchPoint(0, 10, 10); + EXPECT_EQ(1U, queued_event_count()); + + // TouchMove should be allowed and test for touches state. + const WebTouchEvent& event1 = sent_event(); + EXPECT_EQ(WebInputEvent::TouchMove, event1.type()); + EXPECT_EQ(WebTouchPoint::StateMoved, event1.touches[0].state); + EXPECT_EQ(WebTouchPoint::StateStationary, event1.touches[1].state); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + + // Do not really move any touch points, but use previous values. + MoveTouchPoint(0, 10, 10); + ChangeTouchPointRadius(1, 1, 1); + MoveTouchPoint(1, 2, 2); + EXPECT_EQ(4U, queued_event_count()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + // The TouchMove but should be filtered when none of the touch points have + // changed but don't get acked right away. + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + + // Receive an ACK for 1st TouchMove. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + + EXPECT_EQ(0U, queued_event_count()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(4U, GetAndResetAckedEventCount()); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, acked_event_state()); + + // Move 2nd touch point. + MoveTouchPoint(1, 3, 3); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(0U, queued_event_count()); + + // TouchMove should be allowed and test for touches state. + const WebTouchEvent& event2 = sent_event(); + EXPECT_EQ(WebInputEvent::TouchMove, event2.type()); + EXPECT_EQ(WebTouchPoint::StateStationary, event2.touches[0].state); + EXPECT_EQ(WebTouchPoint::StateMoved, event2.touches[1].state); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); +} + +// Tests that touch-scroll-notification is queued normally. +TEST_F(PassthroughTouchEventQueueTest, + TouchScrollNotificationOrder_EmptyQueue) { + PrependTouchScrollNotification(); + + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); +} + +// Tests touch-scroll-notification firing is appended to the tail of sent +// events since all events are sent right away. +TEST_F(PassthroughTouchEventQueueTest, + TouchScrollNotificationOrder_EndOfQueue) { + PressTouchPoint(1, 1); + + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(1U, queued_event_count()); + + // Send the touch-scroll-notification when 3 events are in the queue. + PrependTouchScrollNotification(); + + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(2U, queued_event_count()); + + // Send ACKs. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_IGNORED); + + // Touch-scroll-start Ack is not reported to client. + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, queued_event_count()); + + EXPECT_EQ(WebInputEvent::TouchStart, all_sent_events()[0].type()); + EXPECT_EQ(WebInputEvent::TouchScrollStarted, all_sent_events()[1].type()); + EXPECT_EQ(2U, GetAndResetSentEventCount()); +} + +// Tests that if touchStartOrFirstTouchMove is correctly set up for touch +// events. +TEST_F(PassthroughTouchEventQueueTest, TouchStartOrFirstTouchMove) { + PressTouchPoint(1, 1); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(WebInputEvent::TouchStart, sent_event().type()); + EXPECT_TRUE(sent_event().touchStartOrFirstTouchMove); + + MoveTouchPoint(0, 5, 5); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(WebInputEvent::TouchMove, sent_event().type()); + EXPECT_TRUE(sent_event().touchStartOrFirstTouchMove); + + MoveTouchPoint(0, 15, 15); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(WebInputEvent::TouchMove, sent_event().type()); + EXPECT_FALSE(sent_event().touchStartOrFirstTouchMove); + + ReleaseTouchPoint(0); + SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(WebInputEvent::TouchEnd, sent_event().type()); + EXPECT_FALSE(sent_event().touchStartOrFirstTouchMove); +} + +} // namespace content
diff --git a/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc b/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc index 932393d..15dded6 100644 --- a/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc +++ b/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
@@ -202,7 +202,7 @@ } std::vector<HANDLE> handles; - file_handles.reserve(file_names.size() + file_handles.size()); + handles.reserve(file_names.size() + file_handles.size()); for (const base::string16& file_name : file_names) { // This leaks the handles, since they are used as the reference key to // CreateStreamFromKey, and DirectWrite requires the reference keys to
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 0fdae4b..9d993b3 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1196,6 +1196,7 @@ "../browser/renderer_host/dwrite_font_proxy_message_filter_win_unittest.cc", "../browser/renderer_host/input/gesture_event_queue_unittest.cc", "../browser/renderer_host/input/input_router_impl_unittest.cc", + "../browser/renderer_host/input/legacy_touch_event_queue_unittest.cc", "../browser/renderer_host/input/mock_input_ack_handler.cc", "../browser/renderer_host/input/mock_input_ack_handler.h", "../browser/renderer_host/input/mock_input_router_client.cc", @@ -1203,6 +1204,7 @@ "../browser/renderer_host/input/motion_event_web_unittest.cc", "../browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc", "../browser/renderer_host/input/mouse_wheel_rails_filter_unittest_mac.cc", + "../browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc", "../browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc", "../browser/renderer_host/input/stylus_text_selector_unittest.cc", "../browser/renderer_host/input/synthetic_gesture_controller_unittest.cc", @@ -1210,7 +1212,6 @@ "../browser/renderer_host/input/tap_suppression_controller_unittest.cc", "../browser/renderer_host/input/touch_action_filter_unittest.cc", "../browser/renderer_host/input/touch_emulator_unittest.cc", - "../browser/renderer_host/input/touch_event_queue_unittest.cc", "../browser/renderer_host/input/web_input_event_builders_android_unittest.cc", "../browser/renderer_host/input/web_input_event_builders_mac_unittest.mm", "../browser/renderer_host/input/web_input_event_util_unittest.cc",
diff --git a/headless/BUILD.gn b/headless/BUILD.gn index fc234f7..8b8c6a9 100644 --- a/headless/BUILD.gn +++ b/headless/BUILD.gn
@@ -196,6 +196,7 @@ "lib/browser/headless_browser_context_options.h", "lib/browser/headless_browser_impl.cc", "lib/browser/headless_browser_impl.h", + "lib/browser/headless_browser_impl_mac.mm", "lib/browser/headless_browser_main_parts.cc", "lib/browser/headless_browser_main_parts.h", "lib/browser/headless_content_browser_client.cc", @@ -289,7 +290,6 @@ "//net", "//services/service_manager/public/cpp", "//third_party/mesa:osmesa", - "//ui/aura", "//ui/base", "//ui/compositor", "//ui/display", @@ -305,6 +305,10 @@ ] } + if (!is_mac) { + deps += [ "//ui/aura" ] + } + if (headless_use_embedded_resources) { deps += [ ":embed_resources" ] sources += [
diff --git a/headless/lib/browser/headless_browser_impl_mac.mm b/headless/lib/browser/headless_browser_impl_mac.mm new file mode 100644 index 0000000..e1911162 --- /dev/null +++ b/headless/lib/browser/headless_browser_impl_mac.mm
@@ -0,0 +1,27 @@ +// Copyright 2017 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 "headless/lib/browser/headless_browser_impl.h" + +#include "content/public/browser/web_contents.h" +#include "ui/base/cocoa/base_view.h" + +namespace headless { + +void HeadlessBrowserImpl::PlatformInitialize() {} + +void HeadlessBrowserImpl::PlatformCreateWindow() {} + +void HeadlessBrowserImpl::PlatformInitializeWebContents( + const gfx::Size& initial_size, + content::WebContents* web_contents) { + NSView* web_view = web_contents->GetNativeView(); + [web_view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; + + NSRect frame = NSMakeRect(0, 0, initial_size.width(), initial_size.height()); + [web_view setFrame:frame]; + return; +} + +} // namespace headless
diff --git a/headless/lib/browser/headless_content_browser_client.cc b/headless/lib/browser/headless_content_browser_client.cc index e993fc1..ade0c60f 100644 --- a/headless/lib/browser/headless_content_browser_client.cc +++ b/headless/lib/browser/headless_content_browser_client.cc
@@ -170,6 +170,7 @@ callback); } +#if defined(OS_POSIX) && !defined(OS_MACOSX) void HeadlessContentBrowserClient::GetAdditionalMappedFilesForChildProcess( const base::CommandLine& command_line, int child_process_id, @@ -180,6 +181,7 @@ mappings->Share(kCrashDumpSignal, crash_signal_fd); #endif // defined(HEADLESS_USE_BREAKPAD) } +#endif // defined(OS_POSIX) && !defined(OS_MACOSX) void HeadlessContentBrowserClient::AppendExtraCommandLineSwitches( base::CommandLine* command_line,
diff --git a/headless/lib/browser/headless_content_browser_client.h b/headless/lib/browser/headless_content_browser_client.h index aa188832..53a95040 100644 --- a/headless/lib/browser/headless_content_browser_client.h +++ b/headless/lib/browser/headless_content_browser_client.h
@@ -28,10 +28,12 @@ content::BrowserContext* context, content::StoragePartition* partition, const storage::OptionalQuotaSettingsCallback& callback) override; +#if defined(OS_POSIX) && !defined(OS_MACOSX) void GetAdditionalMappedFilesForChildProcess( const base::CommandLine& command_line, int child_process_id, content::FileDescriptorInfo* mappings) override; +#endif void AppendExtraCommandLineSwitches(base::CommandLine* command_line, int child_process_id) override;
diff --git a/headless/lib/headless_content_main_delegate.cc b/headless/lib/headless_content_main_delegate.cc index 1aa61b4..72df5a2 100644 --- a/headless/lib/headless_content_main_delegate.cc +++ b/headless/lib/headless_content_main_delegate.cc
@@ -147,6 +147,7 @@ g_headless_crash_client.Pointer()->set_crash_dumps_dir( browser_->options()->crash_dumps_dir); +#if !defined(OS_MACOSX) if (!browser_->options()->enable_crash_reporter) { DCHECK(!breakpad::IsCrashReporterEnabled()); return; @@ -155,6 +156,7 @@ if (process_type != switches::kZygoteProcess) breakpad::InitCrashReporter(process_type); #endif // defined(HEADLESS_USE_BREAKPAD) +#endif // !defined(OS_MACOSX) } void HeadlessContentMainDelegate::PreSandboxStartup() { @@ -168,7 +170,9 @@ if (command_line.HasSwitch(switches::kEnableLogging)) InitLogging(command_line); #endif +#if !defined(OS_MACOSX) InitCrashReporter(command_line); +#endif InitializeResourceBundle(); } @@ -198,6 +202,7 @@ return 0; } +#if !defined(OS_MACOSX) && defined(OS_POSIX) && !defined(OS_ANDROID) void HeadlessContentMainDelegate::ZygoteForked() { const base::CommandLine& command_line( *base::CommandLine::ForCurrentProcess()); @@ -208,6 +213,7 @@ // bail out gracefully if the browser process hasn't enabled crash reporting. breakpad::InitCrashReporter(process_type); } +#endif // static HeadlessContentMainDelegate* HeadlessContentMainDelegate::GetInstance() {
diff --git a/headless/lib/headless_content_main_delegate.h b/headless/lib/headless_content_main_delegate.h index 35eff70c..cb33f22 100644 --- a/headless/lib/headless_content_main_delegate.h +++ b/headless/lib/headless_content_main_delegate.h
@@ -35,11 +35,14 @@ int RunProcess( const std::string& process_type, const content::MainFunctionParams& main_function_params) override; - void ZygoteForked() override; content::ContentBrowserClient* CreateContentBrowserClient() override; HeadlessBrowserImpl* browser() const { return browser_.get(); } +#if !defined(OS_MACOSX) && defined(OS_POSIX) && !defined(OS_ANDROID) + void ZygoteForked() override; +#endif + private: friend class HeadlessBrowserTest;
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 37796ba42..f2107f4 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2561,3 +2561,6 @@ # Sheriff failures 2017-02-23 crbug.com/695352 [ Mac ] virtual/threaded/compositing/visibility/overlays-persist-on-navigation.html [ Pass Crash ] +# Sheriff failures 2017-02-27 +crbug.com/696398 [ Win7 ] virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem.html [ Failure ] +crbug.com/696407 [ Linux ] external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-with-colon.sub.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt index a3dec7a..e6a549c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
@@ -39,7 +39,7 @@ CONSOLE MESSAGE: line 138: method divide CONSOLE MESSAGE: line 138: method multiply CONSOLE MESSAGE: line 138: method subtract -CONSOLE MESSAGE: line 138: interface CSSMatrixTransformComponent : CSSTransformComponent +CONSOLE MESSAGE: line 138: interface CSSMatrixComponent : CSSTransformComponent CONSOLE MESSAGE: line 138: getter a CONSOLE MESSAGE: line 138: getter b CONSOLE MESSAGE: line 138: getter c
diff --git a/third_party/WebKit/LayoutTests/typedcssom/cssMatrixTransformComponent.html b/third_party/WebKit/LayoutTests/typedcssom/cssMatrixComponent.html similarity index 66% rename from third_party/WebKit/LayoutTests/typedcssom/cssMatrixTransformComponent.html rename to third_party/WebKit/LayoutTests/typedcssom/cssMatrixComponent.html index 731013d..bb84910 100644 --- a/third_party/WebKit/LayoutTests/typedcssom/cssMatrixTransformComponent.html +++ b/third_party/WebKit/LayoutTests/typedcssom/cssMatrixComponent.html
@@ -4,27 +4,27 @@ <script> var values = [ - {input: new CSSMatrixTransformComponent(0, 0, 0, 0, 0, 0), + {input: new CSSMatrixComponent(0, 0, 0, 0, 0, 0), a: 0, b: 0, c: 0, d: 0, e: 0, f: 0, is2D: true, cssText: "matrix(0, 0, 0, 0, 0, 0)"}, - {input: new CSSMatrixTransformComponent(2, 4, 6, 8, 10, 12), + {input: new CSSMatrixComponent(2, 4, 6, 8, 10, 12), a: 2, b: 4, c: 6, d: 8, e: 10, f: 12, is2D: true, cssText: "matrix(2, 4, 6, 8, 10, 12)"}, - {input: new CSSMatrixTransformComponent(-2, -4, -6, -8, -10, -12), + {input: new CSSMatrixComponent(-2, -4, -6, -8, -10, -12), a: -2, b: -4, c: -6, d: -8, e: -10, f: -12, is2D: true, cssText: "matrix(-2, -4, -6, -8, -10, -12)"}, - {input: new CSSMatrixTransformComponent(1.1, -2.2, 3.3, -4.4, 5.5, 0.6), + {input: new CSSMatrixComponent(1.1, -2.2, 3.3, -4.4, 5.5, 0.6), a: 1.1, b: -2.2, c: 3.3, d: -4.4, e: 5.5, f: 0.6, is2D: true, cssText: "matrix(1.1, -2.2, 3.3, -4.4, 5.5, 0.6)"}, - {input: new CSSMatrixTransformComponent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + {input: new CSSMatrixComponent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), m11: 0, m12: 0, m13: 0, m14: 0, m21: 0, m22: 0, m23: 0, m24: 0, m31: 0, m32: 0, m33: 0, m34: 0, m41: 0, m42: 0, m43: 0, m44: 0, is2D: false, cssText: "matrix3d(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)"}, - {input: new CSSMatrixTransformComponent(11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34, 41, 42, 43, 44), + {input: new CSSMatrixComponent(11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34, 41, 42, 43, 44), m11: 11, m12: 12, m13: 13, m14: 14, m21: 21, m22: 22, m23: 23, m24: 24, m31: 31, m32: 32, m33: 33, m34: 34, m41: 41, m42: 42, m43: 43, m44: 44, is2D: false, cssText: "matrix3d(11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34, 41, 42, 43, 44)"}, - {input: new CSSMatrixTransformComponent(1.1, 1.2, -13, -1.4, 2, 0, -2, 4, 3.1, 3, 3, 3.4, -4.1, 42, 43, 4.4), + {input: new CSSMatrixComponent(1.1, 1.2, -13, -1.4, 2, 0, -2, 4, 3.1, 3, 3, 3.4, -4.1, 42, 43, 4.4), m11: 1.1, m12: 1.2, m13: -13, m14: -1.4, m21: 2, m22: 0, m23: -2, m24: 4, m31: 3.1, m32: 3, m33: 3, m34: 3.4, m41: -4.1, m42: 42, m43: 43, m44: 4.4, is2D: false, cssText: "matrix3d(1.1, 1.2, -13, -1.4, 2, 0, -2, 4, 3.1, 3, 3, 3.4, -4.1, 42, 43, 4.4)"} @@ -42,27 +42,27 @@ assert_equals(values[i].input[attribute], values[i][attribute]); } } -}, "Test that the (a, ... , f) and (m11, ... , m44) attributes for CSSMatrixTransformComponent are correct."); +}, "Test that the (a, ... , f) and (m11, ... , m44) attributes for CSSMatrixComponent are correct."); test(function() { for (var i = 0; i < values.length; ++i) { assert_equals(values[i].input.is2D(), values[i].is2D); } -}, "Test that the is2D values for CSSMatrixTransformComponent are correct."); +}, "Test that the is2D values for CSSMatrixComponent are correct."); test(function() { for (var i = 0; i < values.length; ++i) { assert_equals(values[i].input.cssText, values[i].cssText); } -}, "Test that the cssText for CSSMatrixTransformComponent is correct."); +}, "Test that the cssText for CSSMatrixComponent is correct."); test(function() { - assert_throws(null, function() { new CSSMatrixTransformComponent(); }); - assert_throws(null, function() { new CSSMatrixTransformComponent(0); }); - assert_throws(null, function() { new CSSMatrixTransformComponent(0, 1, 2, 3, 4); }); - assert_throws(null, function() { new CSSMatrixTransformComponent(0, 1, 2, 3, 4, 5, 6); }); - assert_throws(null, function() { new CSSMatrixTransformComponent(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14); }); -}, "Test that invalid number of arguments for CSSMatrixTransformComponent throws an exception."); + assert_throws(null, function() { new CSSMatrixComponent(); }); + assert_throws(null, function() { new CSSMatrixComponent(0); }); + assert_throws(null, function() { new CSSMatrixComponent(0, 1, 2, 3, 4); }); + assert_throws(null, function() { new CSSMatrixComponent(0, 1, 2, 3, 4, 5, 6); }); + assert_throws(null, function() { new CSSMatrixComponent(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14); }); +}, "Test that invalid number of arguments for CSSMatrixComponent throws an exception."); test(function() { var attributeValues = attributeValues2D.concat(attributeValues3D); @@ -75,6 +75,6 @@ assert_equals(inputAsMatrix.is2D(), values[i].input.is2D()); assert_equals(inputAsMatrix.cssText, values[i].input.cssText); } -}, "Test that asMatrix has all the same properties as the original CSSMatrixTransformComponent."); +}, "Test that asMatrix has all the same properties as the original CSSMatrixComponent."); </script>
diff --git a/third_party/WebKit/LayoutTests/typedcssom/cssRotation.html b/third_party/WebKit/LayoutTests/typedcssom/cssRotation.html index a00655b..93fc095 100644 --- a/third_party/WebKit/LayoutTests/typedcssom/cssRotation.html +++ b/third_party/WebKit/LayoutTests/typedcssom/cssRotation.html
@@ -10,33 +10,33 @@ var values = [ {input: new CSSRotation(angle(0)), angle: 0, x: 0, y: 0, z: 1, is2D: true, cssText: "rotate(0deg)", - asMatrix: new CSSMatrixTransformComponent(1, 0, 0, 1, 0, 0)}, + asMatrix: new CSSMatrixComponent(1, 0, 0, 1, 0, 0)}, {input: new CSSRotation(angle(10)), angle: 10, x: 0, y: 0, z: 1, is2D: true, cssText: "rotate(10deg)", - asMatrix: new CSSMatrixTransformComponent(0.9848077, 0.1736481, -0.1736481, 0.9848077, 0, 0)}, + asMatrix: new CSSMatrixComponent(0.9848077, 0.1736481, -0.1736481, 0.9848077, 0, 0)}, {input: new CSSRotation(angle(-21)), angle: -21, x: 0, y: 0, z: 1, is2D: true, cssText: "rotate(-21deg)", - asMatrix: new CSSMatrixTransformComponent(0.9335804, -0.3583679, 0.3583679, 0.9335804, 0, 0)}, + asMatrix: new CSSMatrixComponent(0.9335804, -0.3583679, 0.3583679, 0.9335804, 0, 0)}, {input: new CSSRotation(angle(3.2)), angle: 3.2, x: 0, y: 0, z: 1, is2D: true, cssText: "rotate(3.2deg)", - asMatrix: new CSSMatrixTransformComponent(0.9984407, 0.0558215, -0.0558215, 0.9984407, 0, 0)}, + asMatrix: new CSSMatrixComponent(0.9984407, 0.0558215, -0.0558215, 0.9984407, 0, 0)}, {input: new CSSRotation(0, 0, 1, angle(90)), angle: 90, x: 0, y: 0, z: 1, is2D: false, cssText: "rotate3d(0, 0, 1, 90deg)", - asMatrix: new CSSMatrixTransformComponent(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)}, + asMatrix: new CSSMatrixComponent(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)}, {input: new CSSRotation(2.7, -3, 4.4, angle(0)), angle: 0, x: 2.7, y: -3, z: 4.4, is2D: false, cssText: "rotate3d(2.7, -3, 4.4, 0deg)", - asMatrix: new CSSMatrixTransformComponent(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)}, + asMatrix: new CSSMatrixComponent(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)}, {input: new CSSRotation(2, 3, 4, angle(10)), angle: 10, x: 2, y: 3, z: 4, is2D: false, cssText: "rotate3d(2, 3, 4, 10deg)", - asMatrix: new CSSMatrixTransformComponent(0.9869032, 0.1321258, -0.0925460, 0, -0.1258394, + asMatrix: new CSSMatrixComponent(0.9869032, 0.1321258, -0.0925460, 0, -0.1258394, 0.9895225, 0.0707777, 0, 0.1009279, -0.0582048, 0.9931896, 0, 0, 0, 0, 1)}, {input: new CSSRotation(2, 3.7, -4, angle(-1.2)), angle: -1.2, x: 2, y: 3.7, z: -4, is2D: false, cssText: "rotate3d(2, 3.7, -4, -1.2deg)", - asMatrix: new CSSMatrixTransformComponent(0.9998067, 0.01448049, 0.0132978, 0, -0.0143841, + asMatrix: new CSSMatrixComponent(0.9998067, 0.01448049, 0.0132978, 0, -0.0143841, 0.9998698, -0.0073125, 0, -0.0134019, 0.0071198, 0.9998848, 0, 0, 0, 0, 1)}, {input: new CSSRotation(1, 0, 0, new CSSAngleValue(0.5, 'turn')), angle: 180, x: 1, y: 0, z: 0, is2D: false, cssText: "rotate3d(1, 0, 0, 0.5turn)", - asMatrix: new CSSMatrixTransformComponent(1, 0, 0, 0, 0, -1, 1.2246467991473532e-16, 0, 0, + asMatrix: new CSSMatrixComponent(1, 0, 0, 0, 0, -1, 1.2246467991473532e-16, 0, 0, -1.2246467991473532e-16, -1, 0, 0, 0, 0, 1)} ];
diff --git a/third_party/WebKit/LayoutTests/typedcssom/cssScale.html b/third_party/WebKit/LayoutTests/typedcssom/cssScale.html index e2d5b17..30ff36b 100644 --- a/third_party/WebKit/LayoutTests/typedcssom/cssScale.html +++ b/third_party/WebKit/LayoutTests/typedcssom/cssScale.html
@@ -79,8 +79,8 @@ var inputAsMatrix = input.asMatrix(); assert_equals(inputAsMatrix.is2D(), input.is2D()); - var expectedMatrix = input.is2D() ? new CSSMatrixTransformComponent(input.x, 0, 0, input.y, 0, 0) : - new CSSMatrixTransformComponent(input.x, 0, 0, 0, 0, input.y, 0, 0, 0, 0, input.z, 0, 0, 0, 0, 1); + var expectedMatrix = input.is2D() ? new CSSMatrixComponent(input.x, 0, 0, input.y, 0, 0) : + new CSSMatrixComponent(input.x, 0, 0, 0, 0, input.y, 0, 0, 0, 0, input.z, 0, 0, 0, 0, 1); for (var attribute in expectedMatrix) { if (typeof expectedMatrix[attribute] === "number") { assert_approx_equals(inputAsMatrix[attribute], expectedMatrix[attribute], EPSILON);
diff --git a/third_party/WebKit/LayoutTests/typedcssom/cssSkew.html b/third_party/WebKit/LayoutTests/typedcssom/cssSkew.html index b19e00f..f41de0c 100644 --- a/third_party/WebKit/LayoutTests/typedcssom/cssSkew.html +++ b/third_party/WebKit/LayoutTests/typedcssom/cssSkew.html
@@ -55,7 +55,7 @@ assert_true(inputAsMatrix.is2D()); var tanAx = tanDegrees(input.ax.degrees); var tanAy = tanDegrees(input.ay.degrees); - var expectedMatrix = new CSSMatrixTransformComponent(1, tanAy, tanAx, 1, 0, 0); + var expectedMatrix = new CSSMatrixComponent(1, tanAy, tanAx, 1, 0, 0); for (var attribute in expectedMatrix) { if (typeof expectedMatrix[attribute] === "number") { assert_approx_equals(inputAsMatrix[attribute], expectedMatrix[attribute], EPSILON);
diff --git a/third_party/WebKit/LayoutTests/typedcssom/cssTransformValue.html b/third_party/WebKit/LayoutTests/typedcssom/cssTransformValue.html index affeaf1..fec9fad0 100644 --- a/third_party/WebKit/LayoutTests/typedcssom/cssTransformValue.html +++ b/third_party/WebKit/LayoutTests/typedcssom/cssTransformValue.html
@@ -12,21 +12,21 @@ test(function() { var transformArray = [new CSSScale(2,2), - new CSSMatrixTransformComponent(1,1,1,1,1,1), new CSSScale(5,6)]; + new CSSMatrixComponent(1,1,1,1,1,1), new CSSScale(5,6)]; var transformValue = new CSSTransformValue(transformArray); assert_true(transformValue.is2D()); }, "is2D returns true for transformValues containing only 2D transformComponents"); test(function() { var transformArray = [new CSSScale(2,2), - new CSSMatrixTransformComponent(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1), new CSSScale(5,6)]; + new CSSMatrixComponent(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1), new CSSScale(5,6)]; var transformValue = new CSSTransformValue(transformArray); assert_false(transformValue.is2D()); }, "is2D returns false for transformValues containing both 2D and 3D transformComponents"); test(function() { var transformArray = [new CSSScale(2,2), - new CSSMatrixTransformComponent(1,1,1,1,1,1), new CSSScale(5,6)]; + new CSSMatrixComponent(1,1,1,1,1,1), new CSSScale(5,6)]; var transformValue = new CSSTransformValue(transformArray); var newTransformArray = []; @@ -35,7 +35,7 @@ } assert_true(newTransformArray.length == 3); assert_true(newTransformArray[0] instanceof CSSScale); - assert_true(newTransformArray[1] instanceof CSSMatrixTransformComponent); + assert_true(newTransformArray[1] instanceof CSSMatrixComponent); assert_true(newTransformArray[2] instanceof CSSScale); }, "CSSTransformValue can iterate through all its all its transformComponent members");
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index a2db1a12..ccea9da 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -527,7 +527,7 @@ method divide method multiply method subtract -interface CSSMatrixTransformComponent : CSSTransformComponent +interface CSSMatrixComponent : CSSTransformComponent attribute @@toStringTag getter a getter b
diff --git a/third_party/WebKit/ManualTests/animate-duration.html b/third_party/WebKit/ManualTests/animate-duration.html index b155c70..9b3c823 100644 --- a/third_party/WebKit/ManualTests/animate-duration.html +++ b/third_party/WebKit/ManualTests/animate-duration.html
@@ -22,22 +22,22 @@ margin: 10px; background-color: blue; z-index: 0; - -webkit-animation-name: slide; - -webkit-animation-duration: 1s; - -webkit-animation-direction: alternate; - -webkit-animation-timing-function: ease-in-out; - -webkit-animation-iteration-count: infinite; + animation-name: slide; + animation-duration: 1s; + animation-direction: alternate; + animation-timing-function: ease-in-out; + animation-iteration-count: infinite; } .one { - -webkit-animation-duration: 0s; + animation-duration: 0s; } .two { - -webkit-animation-duration: 0; + animation-duration: 0; } - @-webkit-keyframes slide { + @keyframes slide { from { transform: translateX(0); } to { transform: translateX(280px); } }
diff --git a/third_party/WebKit/ManualTests/animate-left.html b/third_party/WebKit/ManualTests/animate-left.html index 3ced2ec..360b2808 100644 --- a/third_party/WebKit/ManualTests/animate-left.html +++ b/third_party/WebKit/ManualTests/animate-left.html
@@ -12,14 +12,14 @@ height: 200px; width: 200px; background-color: #9bb; - -webkit-animation-name: bounce; - -webkit-animation-duration: 2s; - -webkit-animation-iteration-count: infinite; - -webkit-animation-direction: alternate; - -webkit-animation-timing-function: ease-in-out; + animation-name: bounce; + animation-duration: 2s; + animation-iteration-count: infinite; + animation-direction: alternate; + animation-timing-function: ease-in-out; } - @-webkit-keyframes bounce { + @keyframes bounce { from { left: 100px; }
diff --git a/third_party/WebKit/ManualTests/animation-with-transition.html b/third_party/WebKit/ManualTests/animation-with-transition.html index 37a75898..eaff5ed 100644 --- a/third_party/WebKit/ManualTests/animation-with-transition.html +++ b/third_party/WebKit/ManualTests/animation-with-transition.html
@@ -10,17 +10,17 @@ width: 200px; height: 200px; background-color: #696; - -webkit-transition: left 5s, top 5s; + transition: left 5s, top 5s; } .animate { - -webkit-animation-name: simple; - -webkit-animation-duration: 2s; - -webkit-animation-timing-function: linear; - -webkit-animation-fill-mode: backwards; + animation-name: simple; + animation-duration: 2s; + animation-timing-function: linear; + animation-fill-mode: backwards; } - @-webkit-keyframes simple { + @keyframes simple { 50% { left: 300px; }
diff --git a/third_party/WebKit/ManualTests/animation/animation-direction-reverse-timing-functions-hardware.html b/third_party/WebKit/ManualTests/animation/animation-direction-reverse-timing-functions-hardware.html index db8573e..9217fcf 100644 --- a/third_party/WebKit/ManualTests/animation/animation-direction-reverse-timing-functions-hardware.html +++ b/third_party/WebKit/ManualTests/animation/animation-direction-reverse-timing-functions-hardware.html
@@ -16,30 +16,30 @@ .animated { background-color: green; /* This timing function has value 0 at inputs of 1/3 and 2/3. Chosen because it's very asymmetric about x = y. */ - -webkit-animation: move 3000000s 2 cubic-bezier(0.333333, 0.333333, 0.666666, -0.833333) forwards; + animation: move 3000000s 2 cubic-bezier(0.333333, 0.333333, 0.666666, -0.833333) forwards; margin-bottom: 4px; } .delay_zero { - -webkit-animation-delay: 0s; + animation-delay: 0s; } .delay_one_third { - -webkit-animation-delay: -1000000s; + animation-delay: -1000000s; } .delay_two_thirds { - -webkit-animation-delay: -2000000s; + animation-delay: -2000000s; } .delay_three_thirds { - -webkit-animation-delay: -3000000s; + animation-delay: -3000000s; } .delay_four_thirds { - -webkit-animation-delay: -4000000s; + animation-delay: -4000000s; } .delay_five_thirds { - -webkit-animation-delay: -5000000s; + animation-delay: -5000000s; } .delay_six_thirds { - -webkit-animation-delay: -6000000s; + animation-delay: -6000000s; } .expected { @@ -59,19 +59,19 @@ } #normal div { - -webkit-animation-direction: normal; + animation-direction: normal; } #alternate div { - -webkit-animation-direction: alternate; + animation-direction: alternate; } #reverse div { - -webkit-animation-direction: reverse; + animation-direction: reverse; } #alternate-reverse div { - -webkit-animation-direction: alternate-reverse; + animation-direction: alternate-reverse; } - @-webkit-keyframes move { + @keyframes move { from { transform: translateX(100px); } to { transform: translateX(200px); } }
diff --git a/third_party/WebKit/ManualTests/animation/compositor-animation-delay.html b/third_party/WebKit/ManualTests/animation/compositor-animation-delay.html index 089880a..def757ad 100644 --- a/third_party/WebKit/ManualTests/animation/compositor-animation-delay.html +++ b/third_party/WebKit/ManualTests/animation/compositor-animation-delay.html
@@ -6,39 +6,39 @@ width: 100px; background: blue; transform: translateZ(0); - -webkit-animation-direction: alternate; - -webkit-animation-duration: 2s; - -webkit-animation-timing-function: linear; - -webkit-animation-iteration-count: 6; + animation-direction: alternate; + animation-duration: 2s; + animation-timing-function: linear; + animation-iteration-count: 6; } .test0 { - -webkit-animation-delay: -30s; + animation-delay: -30s; } .test1 { - -webkit-animation-delay: -3s; + animation-delay: -3s; } .test2 { - -webkit-animation-delay: 0s; + animation-delay: 0s; } .test3 { - -webkit-animation-delay: 3s; + animation-delay: 3s; } .anim-left { - -webkit-animation-name: anim-left; + animation-name: anim-left; z-index: 100; } .anim-transform { - -webkit-animation-name: anim-transform; + animation-name: anim-transform; z-index: 200; } -@-webkit-keyframes anim-left { +@keyframes anim-left { 0% { left: 0px; } @@ -47,7 +47,7 @@ } } -@-webkit-keyframes anim-transform { +@keyframes anim-transform { 0% { transform: translateX(0px); }
diff --git a/third_party/WebKit/ManualTests/animation/compositor-animation-direction.html b/third_party/WebKit/ManualTests/animation/compositor-animation-direction.html index ac3ab7e..14fadfb 100644 --- a/third_party/WebKit/ManualTests/animation/compositor-animation-direction.html +++ b/third_party/WebKit/ManualTests/animation/compositor-animation-direction.html
@@ -6,39 +6,39 @@ width: 100px; background: blue; transform: translateZ(0); - -webkit-animation-duration: 2s; - -webkit-animation-timing-function: linear; - -webkit-animation-fill-mode: both; - -webkit-animation-iteration-count: 2; + animation-duration: 2s; + animation-timing-function: linear; + animation-fill-mode: both; + animation-iteration-count: 2; } .normal { - -webkit-animation-direction: normal; + animation-direction: normal; } .reverse { - -webkit-animation-direction: reverse; + animation-direction: reverse; } .alternate { - -webkit-animation-direction: alternate; + animation-direction: alternate; } .alternate-reverse { - -webkit-animation-direction: alternate-reverse; + animation-direction: alternate-reverse; } .anim-left { - -webkit-animation-name: anim-left; + animation-name: anim-left; z-index: 100; } .anim-transform { - -webkit-animation-name: anim-transform; + animation-name: anim-transform; z-index: 200; } -@-webkit-keyframes anim-left { +@keyframes anim-left { 0% { left: 0px; } @@ -47,7 +47,7 @@ } } -@-webkit-keyframes anim-transform { +@keyframes anim-transform { 0% { transform: translateX(0px); }
diff --git a/third_party/WebKit/ManualTests/animation/compositor-animation-fill.html b/third_party/WebKit/ManualTests/animation/compositor-animation-fill.html index 9538ffa..cd2fdfef 100644 --- a/third_party/WebKit/ManualTests/animation/compositor-animation-fill.html +++ b/third_party/WebKit/ManualTests/animation/compositor-animation-fill.html
@@ -6,40 +6,40 @@ width: 100px; background: blue; transform: translateZ(0); - -webkit-animation-direction: alternate; - -webkit-animation-duration: 2s; - -webkit-animation-timing-function: linear; - -webkit-animation-iteration-count: 1; - -webkit-animation-delay: 1s; + animation-direction: alternate; + animation-duration: 2s; + animation-timing-function: linear; + animation-iteration-count: 1; + animation-delay: 1s; } .fill-both { - -webkit-animation-fill-mode: both; + animation-fill-mode: both; } .fill-none { - -webkit-animation-fill-mode: none; + animation-fill-mode: none; } .fill-forwards { - -webkit-animation-fill-mode: forwards; + animation-fill-mode: forwards; } .fill-backwards { - -webkit-animation-fill-mode: backwards; + animation-fill-mode: backwards; } .anim-left { - -webkit-animation-name: anim-left; + animation-name: anim-left; z-index: 100; } .anim-transform { - -webkit-animation-name: anim-transform; + animation-name: anim-transform; z-index: 200; } -@-webkit-keyframes anim-left { +@keyframes anim-left { 0% { left: 250px; } @@ -48,7 +48,7 @@ } } -@-webkit-keyframes anim-transform { +@keyframes anim-transform { 0% { transform: translateX(250px); }
diff --git a/third_party/WebKit/ManualTests/animation/compositor-animation-iteration-count.html b/third_party/WebKit/ManualTests/animation/compositor-animation-iteration-count.html index a6659c2..0393eca8 100644 --- a/third_party/WebKit/ManualTests/animation/compositor-animation-iteration-count.html +++ b/third_party/WebKit/ManualTests/animation/compositor-animation-iteration-count.html
@@ -6,47 +6,47 @@ width: 100px; background: blue; transform: translateZ(0); - -webkit-animation-direction: alternate; - -webkit-animation-duration: 2s; - -webkit-animation-timing-function: linear; - -webkit-animation-fill-mode: both; + animation-direction: alternate; + animation-duration: 2s; + animation-timing-function: linear; + animation-fill-mode: both; } .test0 { - -webkit-animation-iteration-count: 0; + animation-iteration-count: 0; } .test1 { - -webkit-animation-iteration-count: 0.5; + animation-iteration-count: 0.5; } .test2 { - -webkit-animation-iteration-count: 1; + animation-iteration-count: 1; } .test3 { - -webkit-animation-iteration-count: 1.5; + animation-iteration-count: 1.5; } .test4 { - -webkit-animation-iteration-count: 2; + animation-iteration-count: 2; } .test5 { - -webkit-animation-iteration-count: 2.5; + animation-iteration-count: 2.5; } .anim-left { - -webkit-animation-name: anim-left; + animation-name: anim-left; z-index: 100; } .anim-transform { - -webkit-animation-name: anim-transform; + animation-name: anim-transform; z-index: 200; } -@-webkit-keyframes anim-left { +@keyframes anim-left { 0% { left: 0px; } @@ -55,7 +55,7 @@ } } -@-webkit-keyframes anim-transform { +@keyframes anim-transform { 0% { transform: translateX(0px); }
diff --git a/third_party/WebKit/ManualTests/animation/compositor-neutral-keyframes.html b/third_party/WebKit/ManualTests/animation/compositor-neutral-keyframes.html index ec44af1..fb725441 100644 --- a/third_party/WebKit/ManualTests/animation/compositor-neutral-keyframes.html +++ b/third_party/WebKit/ManualTests/animation/compositor-neutral-keyframes.html
@@ -7,26 +7,26 @@ background: blue; will-change: transform; left: 0px; - -webkit-animation-duration: 2s; - -webkit-animation-timing-function: linear; - -webkit-animation-iteration-count: 2; + animation-duration: 2s; + animation-timing-function: linear; + animation-iteration-count: 2; } .anim-left { - -webkit-animation-name: anim-left; + animation-name: anim-left; z-index: 100; } .anim-transform { - -webkit-animation-name: anim-transform; + animation-name: anim-transform; z-index: 200; } -@-webkit-keyframes anim-left { +@keyframes anim-left { 100% { left: 300px; } } -@-webkit-keyframes anim-transform { +@keyframes anim-transform { 100% { transform: translateX(300px); } } </style>
diff --git a/third_party/WebKit/ManualTests/animation/transition-during-transition-with-load.html b/third_party/WebKit/ManualTests/animation/transition-during-transition-with-load.html index 8994e803..56f008a 100644 --- a/third_party/WebKit/ManualTests/animation/transition-during-transition-with-load.html +++ b/third_party/WebKit/ManualTests/animation/transition-during-transition-with-load.html
@@ -6,10 +6,10 @@ width: 100px; background: blue; left: 0px; - -webkit-transform: translate3d(0px, 0px, 0px); - -webkit-transition-duration: 1s; - -webkit-transition-timing-function: linear; - -webkit-transition-property: -webkit-transform; + transform: translate3d(0px, 0px, 0px); + transition-duration: 1s; + transition-timing-function: linear; + transition-property: transform; } </style> <body> @@ -29,7 +29,7 @@ var starTime; function transitionAgain() { - box.style.webkitTransform = "translate3d(200px, 0px, 0px)"; + box.style.transform = "translate3d(200px, 0px, 0px)"; } var animate = function() { @@ -47,7 +47,7 @@ requestAnimationFrame(animate); startTime = window.performance.now(); - box.style.webkitTransform = "translate3d(100px, 0px, 0px)"; + box.style.transform = "translate3d(100px, 0px, 0px)"; } </script>
diff --git a/third_party/WebKit/ManualTests/animation/transition-on-and-offscreen-animation.html b/third_party/WebKit/ManualTests/animation/transition-on-and-offscreen-animation.html index e41f0fe..28d0db9 100644 --- a/third_party/WebKit/ManualTests/animation/transition-on-and-offscreen-animation.html +++ b/third_party/WebKit/ManualTests/animation/transition-on-and-offscreen-animation.html
@@ -12,7 +12,7 @@ width: 200px; border: 1px solid black; background-color : red; - -webkit-transition: -webkit-transform 3s; + transition: transform 3s; } </style> @@ -22,19 +22,19 @@ var box = document.getElementById("box"); window.setTimeout(function() { - box.style.webkitTransform = "translateX(" + window.innerWidth * 2.5 + "px)"; + box.style.transform = "translateX(" + window.innerWidth * 2.5 + "px)"; }, 3000); window.setTimeout(function() { - box.style.webkitTransform = "translateX(0px)"; + box.style.transform = "translateX(0px)"; }, 6000); window.setTimeout(function() { - box.style.webkitTransform = "translateX(" + window.innerWidth * 2.5 + "px)"; + box.style.transform = "translateX(" + window.innerWidth * 2.5 + "px)"; }, 9000); window.setTimeout(function() { - box.style.webkitTransform = "translateX(0px)"; + box.style.transform = "translateX(0px)"; }, 12000); } window.addEventListener('load', runTest, false)
diff --git a/third_party/WebKit/ManualTests/animation/transitions-and-paused-animations.html b/third_party/WebKit/ManualTests/animation/transitions-and-paused-animations.html index a1e2e53b7..34a623d 100644 --- a/third_party/WebKit/ManualTests/animation/transitions-and-paused-animations.html +++ b/third_party/WebKit/ManualTests/animation/transitions-and-paused-animations.html
@@ -11,7 +11,7 @@ height: 200px; width: 200px; border: 1px solid black; - -webkit-transition: -webkit-transform 0.5s; + transition: transform 0.5s; } .moved { @@ -25,14 +25,14 @@ margin: 50px; background-color: blue; transform: translateZ(0); - -webkit-animation: fade 1s infinite linear alternate; + animation: fade 1s infinite linear alternate; } .moved .box { - -webkit-animation-play-state: paused; + animation-play-state: paused; } - @-webkit-keyframes fade { + @keyframes fade { from { transform: rotate(-20deg); } to { transform: rotate(20deg); } }
diff --git a/third_party/WebKit/ManualTests/compositing/requires-backing-change.html b/third_party/WebKit/ManualTests/compositing/requires-backing-change.html index 94ba59e0..5bb9a4a 100644 --- a/third_party/WebKit/ManualTests/compositing/requires-backing-change.html +++ b/third_party/WebKit/ManualTests/compositing/requires-backing-change.html
@@ -7,7 +7,7 @@ height: 100px; width: 100px; margin: 10px 0; - -webkit-perspective: 1000px; + perspective: 1000px; } #container.transformed, #container2.transformed {
diff --git a/third_party/WebKit/ManualTests/image-resampling-with-scale.html b/third_party/WebKit/ManualTests/image-resampling-with-scale.html index 35a1a8cb..718724a 100644 --- a/third_party/WebKit/ManualTests/image-resampling-with-scale.html +++ b/third_party/WebKit/ManualTests/image-resampling-with-scale.html
@@ -16,8 +16,8 @@ image2.setAttribute('src', imgSrc); intervalId = setInterval(function() { scale += 0.001; - image1.style.webkitTransform = 'scale(' + scale + ')'; - layer2.style.webkitTransform = 'scale(' + scale + ')'; + image1.style.transform = 'scale(' + scale + ')'; + layer2.style.transform = 'scale(' + scale + ')'; if (scale > 1.5) window.clearInterval(intervalId); }, 10);
diff --git a/third_party/WebKit/ManualTests/interrupted-compound-transform.html b/third_party/WebKit/ManualTests/interrupted-compound-transform.html index dbd5646c..587e44e 100644 --- a/third_party/WebKit/ManualTests/interrupted-compound-transform.html +++ b/third_party/WebKit/ManualTests/interrupted-compound-transform.html
@@ -11,14 +11,14 @@ height: 400px; margin: 20px; border: 1px solid black; - perspective: 800; + perspective: 800px; } #tester { width: 300px; height: 300px; margin: 50px; background-color: blue; - -webkit-transition: transform 3s linear; + transition: transform 3s linear; transform: rotateX(65deg) translateZ(75px) rotateZ(0deg); transform-style: preserve-3d; }
diff --git a/third_party/WebKit/ManualTests/svg-css-animate-compound.html b/third_party/WebKit/ManualTests/svg-css-animate-compound.html index 254e541..63520e5 100644 --- a/third_party/WebKit/ManualTests/svg-css-animate-compound.html +++ b/third_party/WebKit/ManualTests/svg-css-animate-compound.html
@@ -31,7 +31,7 @@ height: 60px; width: 60px; border: 1px dotted black; - -webkit-transform-origin: top left; /* to match SVG */ + transform-origin: top left; /* to match SVG */ } .final { @@ -39,14 +39,14 @@ } #target, #ref { - -webkit-animation-name: bounce; - -webkit-animation-duration: 2s; - -webkit-animation-iteration-count: infinite; - -webkit-animation-direction: alternate; - -webkit-animation-timing-function: ease-in-out; + animation-name: bounce; + animation-duration: 2s; + animation-iteration-count: infinite; + animation-direction: alternate; + animation-timing-function: ease-in-out; } - @-webkit-keyframes bounce { + @keyframes bounce { from { transform: translate(0px, 0px) scale(1) rotate(0deg); } @@ -57,7 +57,7 @@ </style> </head> <body> - <h1>CSS Animation of 'webkit-transform:' property for SVG</h1> + <h1>CSS Animation of 'transform:' property for SVG</h1> <p>The SVG animation should be identical with the CSS one</p>
diff --git a/third_party/WebKit/ManualTests/svg-css-transition-compound.html b/third_party/WebKit/ManualTests/svg-css-transition-compound.html index 0cd9069..15f46d98 100644 --- a/third_party/WebKit/ManualTests/svg-css-transition-compound.html +++ b/third_party/WebKit/ManualTests/svg-css-transition-compound.html
@@ -32,7 +32,7 @@ height: 60px; width: 60px; border: 1px dotted black; - -webkit-transform-origin: top left; /* to match SVG */ + transform-origin: top left; /* to match SVG */ } .final { @@ -40,8 +40,8 @@ } #target, #ref { - -webkit-transition-property: -webkit-transform; - -webkit-transition-duration: 1s; + transition-property: transform; + transition-duration: 1s; } </style> @@ -53,19 +53,19 @@ var divElm = document.getElementById("ref"); if (flag) { - svgElm.style.webkitTransform = "translate(75px, 25px) scale(2) rotate(45deg)"; - divElm.style.webkitTransform = "translate(75px, 25px) scale(2) rotate(45deg)"; + svgElm.style.transform = "translate(75px, 25px) scale(2) rotate(45deg)"; + divElm.style.transform = "translate(75px, 25px) scale(2) rotate(45deg)"; } else { - svgElm.style.webkitTransform = "translate(0px, 0px) scale(1) rotate(0deg)"; - divElm.style.webkitTransform = "translate(0px, 0px) scale(1) rotate(0deg)"; + svgElm.style.transform = "translate(0px, 0px) scale(1) rotate(0deg)"; + divElm.style.transform = "translate(0px, 0px) scale(1) rotate(0deg)"; } flag = !flag; } </script> </head> <body> - <h1>CSS Transition of "-webkit-trasform" property for SVG elements</h1> + <h1>CSS Transition of "trasform" property for SVG elements</h1> <p>The element below should transition when button is clicked</p> <p>The SVG transition should be identical with the CSS one</p>
diff --git a/third_party/WebKit/ManualTests/transition-events.html b/third_party/WebKit/ManualTests/transition-events.html index 36cf940..4c2ef172 100644 --- a/third_party/WebKit/ManualTests/transition-events.html +++ b/third_party/WebKit/ManualTests/transition-events.html
@@ -13,8 +13,8 @@ margin: 10px; background-color: blue; z-index: 0; - -webkit-transition-property: left; - -webkit-transition-duration: 2s; + transition-property: left; + transition-duration: 2s; left: 0px; } @@ -25,8 +25,8 @@ margin: 10px; background-color: red; z-index: 0; - -webkit-transition-property: left; - -webkit-transition-duration: 2s; + transition-property: left; + transition-duration: 2s; left: 0px; } @@ -43,7 +43,7 @@ var switch1 = true; var switch2 = false; - document.addEventListener('webkitTransitionEnd', function(e) { + document.addEventListener('transitionend', function(e) { var id = "1"; if (switch1) { id = "2";
diff --git a/third_party/WebKit/ManualTests/transition-left.html b/third_party/WebKit/ManualTests/transition-left.html index 492e306..7666fcd 100644 --- a/third_party/WebKit/ManualTests/transition-left.html +++ b/third_party/WebKit/ManualTests/transition-left.html
@@ -12,8 +12,8 @@ height: 200px; width: 300px; background-color: #9bb; - -webkit-transition-property: left; - -webkit-transition-duration: 1s; + transition-property: left; + transition-duration: 1s; } </style> <script type="text/javascript" charset="utf-8">
diff --git a/third_party/WebKit/ManualTests/transitions.html b/third_party/WebKit/ManualTests/transitions.html index 33a9cff3..887ea7e 100644 --- a/third_party/WebKit/ManualTests/transitions.html +++ b/third_party/WebKit/ManualTests/transitions.html
@@ -8,15 +8,15 @@ div.green { width: 100px; background-color: green; - -webkit-transition-property: background-color; - -webkit-transition-duration: 5s; + transition-property: background-color; + transition-duration: 5s; } div.square { width: 100px; height: 100px; - -webkit-transition-property: height; - -webkit-transition-duration: 2s; + transition-property: height; + transition-duration: 2s; } </style> <p id="instructions">
diff --git a/third_party/WebKit/ManualTests/win/milliondollar.html b/third_party/WebKit/ManualTests/win/milliondollar.html index e18baf9..565563e 100644 --- a/third_party/WebKit/ManualTests/win/milliondollar.html +++ b/third_party/WebKit/ManualTests/win/milliondollar.html
@@ -12,9 +12,9 @@ .grid {height: 1000px; width:1000px; position:relative;z-index:153;xoverflow:hidden;} .row {background:url(100grid_inv.png) #000;height: 100px; text-align: left; position:relative;width:1000px;z-index:10;} #lq {width:1000px;position:relative;z-index:0;text-align:left;} - .bz {-webkit-perspective: 1500;-webkit-perspective-origin: 50% 325px;} - .fc {-webkit-transform-style: preserve-3d;transform: rotateY(0deg) ;opacity: 1.0;} - @-webkit-keyframes spin_3d { + .bz {perspective: 1500px;perspective-origin: 50% 325px;} + .fc {transform-style: preserve-3d;transform: rotateY(0deg) ;opacity: 1.0;} + @keyframes spin_3d { 0% { transform: rotateY(0) rotateZ(0); } 33% { transform: rotateY(-20deg) rotateZ(-20deg); } 65% { transform: rotateY(20deg) rotateZ(20deg); } @@ -25,7 +25,7 @@ position: absolute; opacity:0.5; background-repeat:no-repeat; - -webkit-transition: -webkit-transform 0.3s, opacity 0s;-webkit-backface-visibility: visible;} + transition: transform 0.3s, opacity 0s;-webkit-backface-visibility: visible;} </style> <script type="text/javascript"> @@ -113,7 +113,7 @@ return "<div class='a_cube'><div class='plane one' style='background-color: red;height:"+dw+"px;width:"+dw+"px;top:"+y1+"px;left:"+x1+"px;transform:rotateY(90deg) rotateZ(-90deg) translateX(0px) translateY(-"+(dw/2)+"px) translateZ("+(dw/2)+"px) translateY(0px);position:absolute;'></div><div class='plane two' style='background-color: blue;height:"+dw+"px;width:"+dw+"px;top:"+y1+"px;left:"+x1+"px;transform:rotateY(90deg) rotateX(180deg) rotateZ(-90deg) translateX(0px) translateY(-"+(dw/2)+"px) translateZ("+(dw/2)+"px) translateY(0px);position:absolute;'></div><div class='plane three' style='background-color: green;height:"+dw+"px;width:"+dw+"px;top:"+y1+"px;left:"+x1+"px;transform:rotateX(-90deg) translateX(0px) translateZ("+(dw/2)+"px) translateY(-"+(dw/2)+"px);position:absolute;'></div><div class='plane four' style='background-color: yellow;height:"+dw+"px;width:"+dw+"px;top:"+y1+"px;left:"+x1+"px;transform:rotateY(90deg) rotateX(90deg) rotateZ(-90deg) translateY(-"+(dw/2)+"px) translateX(0px) translateZ("+(dw/2)+"px) translateY(0px);position:absolute;'></div><div class='plane five' style='background-color: gray;height:"+dw+"px;width:"+dw+"px;top:"+y1+"px;left:"+x1+"px;transform:rotateY(0deg) translateX(0px) translateZ("+(dw)+"px) translateY(0px);position:absolute;'></div></div>"; } - document.getElementById("grid").style.webkitAnimation = "spin_3d 36s infinite linear"; + document.getElementById("grid").style.animation = "spin_3d 36s infinite linear"; }; </script>
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index 1a1449e..af3524a1 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -244,6 +244,8 @@ "testing/DeathAwareScriptWrappable.h", "testing/DictionaryTest.cpp", "testing/DictionaryTest.h", + "testing/DummyModulator.cpp", + "testing/DummyModulator.h", "testing/DummyPageHolder.cpp", "testing/DummyPageHolder.h", "testing/GCObservation.cpp", @@ -1168,6 +1170,7 @@ "dom/IdleDeadlineTest.cpp", "dom/LayoutTreeBuilderTraversalTest.cpp", "dom/ModulatorTest.cpp", + "dom/ModuleMapTest.cpp", "dom/MutationObserverTest.cpp", "dom/NodeTest.cpp", "dom/NthIndexCacheTest.cpp",
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni index 8a5e782e..8130a5c 100644 --- a/third_party/WebKit/Source/core/core_idl_files.gni +++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -68,7 +68,7 @@ "css/cssom/CSSImageValue.idl", "css/cssom/CSSKeywordValue.idl", "css/cssom/CSSLengthValue.idl", - "css/cssom/CSSMatrixTransformComponent.idl", + "css/cssom/CSSMatrixComponent.idl", "css/cssom/CSSNumberValue.idl", "css/cssom/CSSPerspective.idl", "css/cssom/CSSPositionValue.idl",
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn index 1302b64..0066c15 100644 --- a/third_party/WebKit/Source/core/css/BUILD.gn +++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -254,8 +254,8 @@ "cssom/CSSKeywordValue.h", "cssom/CSSLengthValue.cpp", "cssom/CSSLengthValue.h", - "cssom/CSSMatrixTransformComponent.cpp", - "cssom/CSSMatrixTransformComponent.h", + "cssom/CSSMatrixComponent.cpp", + "cssom/CSSMatrixComponent.h", "cssom/CSSNumberValue.h", "cssom/CSSOMKeywords.h", "cssom/CSSOMTypes.h",
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5 index 15f86228..ef2d5c6b 100644 --- a/third_party/WebKit/Source/core/css/CSSProperties.json5 +++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -30,7 +30,7 @@ }, // - api_class: true|"classname" - // Specifies the existance (and optionally name) of a CSSPropertyAPI + // Specifies the existence (and optionally name) of a CSSPropertyAPI // implementation for the property to be used by make_css_property_apis.py. // See core/css/properties/CSSPropertyAPI.h for API details. // * Add this flag if the API has been implemented for this property.
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.cpp b/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.cpp new file mode 100644 index 0000000..75c53daa --- /dev/null +++ b/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.cpp
@@ -0,0 +1,101 @@ +// Copyright 2016 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 "core/css/cssom/CSSMatrixComponent.h" + +#include <cmath> +#include <memory> +#include "core/css/CSSPrimitiveValue.h" +#include "wtf/MathExtras.h" + +namespace blink { + +CSSFunctionValue* CSSMatrixComponent::toCSSValue() const { + CSSFunctionValue* result = + CSSFunctionValue::create(m_is2D ? CSSValueMatrix : CSSValueMatrix3d); + + if (m_is2D) { + double values[6] = {a(), b(), c(), d(), e(), f()}; + for (double value : values) { + result->append(*CSSPrimitiveValue::create( + value, CSSPrimitiveValue::UnitType::Number)); + } + } else { + double values[16] = {m11(), m12(), m13(), m14(), m21(), m22(), + m23(), m24(), m31(), m32(), m33(), m34(), + m41(), m42(), m43(), m44()}; + for (double value : values) { + result->append(*CSSPrimitiveValue::create( + value, CSSPrimitiveValue::UnitType::Number)); + } + } + + return result; +} + +CSSMatrixComponent* CSSMatrixComponent::perspective(double length) { + std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); + if (length != 0) + matrix->setM34(-1 / length); + return new CSSMatrixComponent(std::move(matrix), PerspectiveType); +} + +CSSMatrixComponent* CSSMatrixComponent::rotate(double angle) { + std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); + matrix->rotate(angle); + return new CSSMatrixComponent(std::move(matrix), RotationType); +} + +CSSMatrixComponent* CSSMatrixComponent::rotate3d(double angle, + double x, + double y, + double z) { + std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); + matrix->rotate3d(x, y, z, angle); + return new CSSMatrixComponent(std::move(matrix), Rotation3DType); +} + +CSSMatrixComponent* CSSMatrixComponent::scale(double x, double y) { + std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); + matrix->setM11(x); + matrix->setM22(y); + return new CSSMatrixComponent(std::move(matrix), ScaleType); +} + +CSSMatrixComponent* CSSMatrixComponent::scale3d(double x, double y, double z) { + std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); + matrix->setM11(x); + matrix->setM22(y); + matrix->setM33(z); + return new CSSMatrixComponent(std::move(matrix), Scale3DType); +} + +CSSMatrixComponent* CSSMatrixComponent::skew(double ax, double ay) { + double tanAx = std::tan(deg2rad(ax)); + double tanAy = std::tan(deg2rad(ay)); + + std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); + matrix->setM12(tanAy); + matrix->setM21(tanAx); + return new CSSMatrixComponent(std::move(matrix), SkewType); +} + +CSSMatrixComponent* CSSMatrixComponent::translate(double x, double y) { + std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); + matrix->setM41(x); + matrix->setM42(y); + return new CSSMatrixComponent(std::move(matrix), TranslationType); +} + +CSSMatrixComponent* CSSMatrixComponent::translate3d(double x, + double y, + double z) { + std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); + matrix->setM41(x); + matrix->setM42(y); + matrix->setM43(z); + return new CSSMatrixComponent(std::move(matrix), Translation3DType); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.h b/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.h new file mode 100644 index 0000000..e181a4d --- /dev/null +++ b/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.h
@@ -0,0 +1,162 @@ +// Copyright 2016 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 CSSMatrixComponent_h +#define CSSMatrixComponent_h + +#include <memory> +#include "core/css/cssom/CSSTransformComponent.h" +#include "platform/transforms/TransformationMatrix.h" + +namespace blink { + +class CORE_EXPORT CSSMatrixComponent final : public CSSTransformComponent { + WTF_MAKE_NONCOPYABLE(CSSMatrixComponent); + DEFINE_WRAPPERTYPEINFO(); + + public: + static CSSMatrixComponent* create(double a, + double b, + double c, + double d, + double e, + double f) { + return new CSSMatrixComponent(a, b, c, d, e, f); + } + + static CSSMatrixComponent* create(double m11, + double m12, + double m13, + double m14, + double m21, + double m22, + double m23, + double m24, + double m31, + double m32, + double m33, + double m34, + double m41, + double m42, + double m43, + double m44) { + return new CSSMatrixComponent(m11, m12, m13, m14, m21, m22, m23, m24, m31, + m32, m33, m34, m41, m42, m43, m44); + } + + static CSSMatrixComponent* fromCSSValue(const CSSFunctionValue& value) { + return nullptr; + } + + // 2D matrix attributes + double a() const { return m_matrix->a(); } + double b() const { return m_matrix->b(); } + double c() const { return m_matrix->c(); } + double d() const { return m_matrix->d(); } + double e() const { return m_matrix->e(); } + double f() const { return m_matrix->f(); } + + // 3D matrix attributes + double m11() const { return m_matrix->m11(); } + double m12() const { return m_matrix->m12(); } + double m13() const { return m_matrix->m13(); } + double m14() const { return m_matrix->m14(); } + double m21() const { return m_matrix->m21(); } + double m22() const { return m_matrix->m22(); } + double m23() const { return m_matrix->m23(); } + double m24() const { return m_matrix->m24(); } + double m31() const { return m_matrix->m31(); } + double m32() const { return m_matrix->m32(); } + double m33() const { return m_matrix->m33(); } + double m34() const { return m_matrix->m34(); } + double m41() const { return m_matrix->m41(); } + double m42() const { return m_matrix->m42(); } + double m43() const { return m_matrix->m43(); } + double m44() const { return m_matrix->m44(); } + + TransformComponentType type() const override { + return m_is2D ? MatrixType : Matrix3DType; + } + + // Bindings require a non const return value. + CSSMatrixComponent* asMatrix() const override { + return const_cast<CSSMatrixComponent*>(this); + } + + CSSFunctionValue* toCSSValue() const override; + + static CSSMatrixComponent* perspective(double length); + + static CSSMatrixComponent* rotate(double angle); + static CSSMatrixComponent* rotate3d(double angle, + double x, + double y, + double z); + + static CSSMatrixComponent* scale(double x, double y); + static CSSMatrixComponent* scale3d(double x, double y, double z); + + static CSSMatrixComponent* skew(double x, double y); + + static CSSMatrixComponent* translate(double x, double y); + static CSSMatrixComponent* translate3d(double x, double y, double z); + + private: + CSSMatrixComponent(double a, double b, double c, double d, double e, double f) + : CSSTransformComponent(), + m_matrix(TransformationMatrix::create(a, b, c, d, e, f)), + m_is2D(true) {} + + CSSMatrixComponent(double m11, + double m12, + double m13, + double m14, + double m21, + double m22, + double m23, + double m24, + double m31, + double m32, + double m33, + double m34, + double m41, + double m42, + double m43, + double m44) + : CSSTransformComponent(), + m_matrix(TransformationMatrix::create(m11, + m12, + m13, + m14, + m21, + m22, + m23, + m24, + m31, + m32, + m33, + m34, + m41, + m42, + m43, + m44)), + m_is2D(false) {} + + CSSMatrixComponent(std::unique_ptr<const TransformationMatrix> matrix, + TransformComponentType fromType) + : CSSTransformComponent(), + m_matrix(std::move(matrix)), + m_is2D(is2DComponentType(fromType)) {} + + // TransformationMatrix needs to be 16-byte aligned. PartitionAlloc + // supports 16-byte alignment but Oilpan doesn't. So we use an std::unique_ptr + // to allocate TransformationMatrix on PartitionAlloc. + // TODO(oilpan): Oilpan should support 16-byte aligned allocations. + std::unique_ptr<const TransformationMatrix> m_matrix; + bool m_is2D; +}; + +} // namespace blink + +#endif
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSMatrixTransformComponent.idl b/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.idl similarity index 94% rename from third_party/WebKit/Source/core/css/cssom/CSSMatrixTransformComponent.idl rename to third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.idl index 62ae2d5a5..b149eaf 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSMatrixTransformComponent.idl +++ b/third_party/WebKit/Source/core/css/cssom/CSSMatrixComponent.idl
@@ -10,7 +10,7 @@ double m41, double m42, double m43, double m44), Exposed=(Window,PaintWorklet), RuntimeEnabled=CSSTypedOM -] interface CSSMatrixTransformComponent : CSSTransformComponent { +] interface CSSMatrixComponent : CSSTransformComponent { readonly attribute double a; readonly attribute double b; readonly attribute double c;
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSMatrixTransformComponent.cpp b/third_party/WebKit/Source/core/css/cssom/CSSMatrixTransformComponent.cpp deleted file mode 100644 index 33b44a5..0000000 --- a/third_party/WebKit/Source/core/css/cssom/CSSMatrixTransformComponent.cpp +++ /dev/null
@@ -1,106 +0,0 @@ -// Copyright 2016 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 "core/css/cssom/CSSMatrixTransformComponent.h" - -#include "core/css/CSSPrimitiveValue.h" -#include "wtf/MathExtras.h" -#include <cmath> -#include <memory> - -namespace blink { - -CSSFunctionValue* CSSMatrixTransformComponent::toCSSValue() const { - CSSFunctionValue* result = - CSSFunctionValue::create(m_is2D ? CSSValueMatrix : CSSValueMatrix3d); - - if (m_is2D) { - double values[6] = {a(), b(), c(), d(), e(), f()}; - for (double value : values) { - result->append(*CSSPrimitiveValue::create( - value, CSSPrimitiveValue::UnitType::Number)); - } - } else { - double values[16] = {m11(), m12(), m13(), m14(), m21(), m22(), - m23(), m24(), m31(), m32(), m33(), m34(), - m41(), m42(), m43(), m44()}; - for (double value : values) { - result->append(*CSSPrimitiveValue::create( - value, CSSPrimitiveValue::UnitType::Number)); - } - } - - return result; -} - -CSSMatrixTransformComponent* CSSMatrixTransformComponent::perspective( - double length) { - std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); - if (length != 0) - matrix->setM34(-1 / length); - return new CSSMatrixTransformComponent(std::move(matrix), PerspectiveType); -} - -CSSMatrixTransformComponent* CSSMatrixTransformComponent::rotate(double angle) { - std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); - matrix->rotate(angle); - return new CSSMatrixTransformComponent(std::move(matrix), RotationType); -} - -CSSMatrixTransformComponent* CSSMatrixTransformComponent::rotate3d(double angle, - double x, - double y, - double z) { - std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); - matrix->rotate3d(x, y, z, angle); - return new CSSMatrixTransformComponent(std::move(matrix), Rotation3DType); -} - -CSSMatrixTransformComponent* CSSMatrixTransformComponent::scale(double x, - double y) { - std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); - matrix->setM11(x); - matrix->setM22(y); - return new CSSMatrixTransformComponent(std::move(matrix), ScaleType); -} - -CSSMatrixTransformComponent* CSSMatrixTransformComponent::scale3d(double x, - double y, - double z) { - std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); - matrix->setM11(x); - matrix->setM22(y); - matrix->setM33(z); - return new CSSMatrixTransformComponent(std::move(matrix), Scale3DType); -} - -CSSMatrixTransformComponent* CSSMatrixTransformComponent::skew(double ax, - double ay) { - double tanAx = std::tan(deg2rad(ax)); - double tanAy = std::tan(deg2rad(ay)); - - std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); - matrix->setM12(tanAy); - matrix->setM21(tanAx); - return new CSSMatrixTransformComponent(std::move(matrix), SkewType); -} - -CSSMatrixTransformComponent* CSSMatrixTransformComponent::translate(double x, - double y) { - std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); - matrix->setM41(x); - matrix->setM42(y); - return new CSSMatrixTransformComponent(std::move(matrix), TranslationType); -} - -CSSMatrixTransformComponent* -CSSMatrixTransformComponent::translate3d(double x, double y, double z) { - std::unique_ptr<TransformationMatrix> matrix = TransformationMatrix::create(); - matrix->setM41(x); - matrix->setM42(y); - matrix->setM43(z); - return new CSSMatrixTransformComponent(std::move(matrix), Translation3DType); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSMatrixTransformComponent.h b/third_party/WebKit/Source/core/css/cssom/CSSMatrixTransformComponent.h deleted file mode 100644 index 24ed6dd..0000000 --- a/third_party/WebKit/Source/core/css/cssom/CSSMatrixTransformComponent.h +++ /dev/null
@@ -1,171 +0,0 @@ -// Copyright 2016 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 CSSMatrixTransformComponent_h -#define CSSMatrixTransformComponent_h - -#include "core/css/cssom/CSSTransformComponent.h" -#include "platform/transforms/TransformationMatrix.h" -#include <memory> - -namespace blink { - -class CORE_EXPORT CSSMatrixTransformComponent final - : public CSSTransformComponent { - WTF_MAKE_NONCOPYABLE(CSSMatrixTransformComponent); - DEFINE_WRAPPERTYPEINFO(); - - public: - static CSSMatrixTransformComponent* create(double a, - double b, - double c, - double d, - double e, - double f) { - return new CSSMatrixTransformComponent(a, b, c, d, e, f); - } - - static CSSMatrixTransformComponent* create(double m11, - double m12, - double m13, - double m14, - double m21, - double m22, - double m23, - double m24, - double m31, - double m32, - double m33, - double m34, - double m41, - double m42, - double m43, - double m44) { - return new CSSMatrixTransformComponent(m11, m12, m13, m14, m21, m22, m23, - m24, m31, m32, m33, m34, m41, m42, - m43, m44); - } - - static CSSMatrixTransformComponent* fromCSSValue( - const CSSFunctionValue& value) { - return nullptr; - } - - // 2D matrix attributes - double a() const { return m_matrix->a(); } - double b() const { return m_matrix->b(); } - double c() const { return m_matrix->c(); } - double d() const { return m_matrix->d(); } - double e() const { return m_matrix->e(); } - double f() const { return m_matrix->f(); } - - // 3D matrix attributes - double m11() const { return m_matrix->m11(); } - double m12() const { return m_matrix->m12(); } - double m13() const { return m_matrix->m13(); } - double m14() const { return m_matrix->m14(); } - double m21() const { return m_matrix->m21(); } - double m22() const { return m_matrix->m22(); } - double m23() const { return m_matrix->m23(); } - double m24() const { return m_matrix->m24(); } - double m31() const { return m_matrix->m31(); } - double m32() const { return m_matrix->m32(); } - double m33() const { return m_matrix->m33(); } - double m34() const { return m_matrix->m34(); } - double m41() const { return m_matrix->m41(); } - double m42() const { return m_matrix->m42(); } - double m43() const { return m_matrix->m43(); } - double m44() const { return m_matrix->m44(); } - - TransformComponentType type() const override { - return m_is2D ? MatrixType : Matrix3DType; - } - - // Bindings require a non const return value. - CSSMatrixTransformComponent* asMatrix() const override { - return const_cast<CSSMatrixTransformComponent*>(this); - } - - CSSFunctionValue* toCSSValue() const override; - - static CSSMatrixTransformComponent* perspective(double length); - - static CSSMatrixTransformComponent* rotate(double angle); - static CSSMatrixTransformComponent* rotate3d(double angle, - double x, - double y, - double z); - - static CSSMatrixTransformComponent* scale(double x, double y); - static CSSMatrixTransformComponent* scale3d(double x, double y, double z); - - static CSSMatrixTransformComponent* skew(double x, double y); - - static CSSMatrixTransformComponent* translate(double x, double y); - static CSSMatrixTransformComponent* translate3d(double x, double y, double z); - - private: - CSSMatrixTransformComponent(double a, - double b, - double c, - double d, - double e, - double f) - : CSSTransformComponent(), - m_matrix(TransformationMatrix::create(a, b, c, d, e, f)), - m_is2D(true) {} - - CSSMatrixTransformComponent(double m11, - double m12, - double m13, - double m14, - double m21, - double m22, - double m23, - double m24, - double m31, - double m32, - double m33, - double m34, - double m41, - double m42, - double m43, - double m44) - : CSSTransformComponent(), - m_matrix(TransformationMatrix::create(m11, - m12, - m13, - m14, - m21, - m22, - m23, - m24, - m31, - m32, - m33, - m34, - m41, - m42, - m43, - m44)), - m_is2D(false) {} - - CSSMatrixTransformComponent( - std::unique_ptr<const TransformationMatrix> matrix, - TransformComponentType fromType) - : CSSTransformComponent(), - m_matrix(std::move(matrix)), - m_is2D(is2DComponentType(fromType)) {} - - // TransformationMatrix needs to be 16-byte aligned. PartitionAlloc - // supports 16-byte alignment but Oilpan doesn't. So we use an std::unique_ptr - // to allocate TransformationMatrix on PartitionAlloc. - // TODO(oilpan): Oilpan should support 16-byte aligned allocations. - std::unique_ptr<const TransformationMatrix> m_matrix; - bool m_is2D; -}; - -} // namespace blink - -#endif
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSPerspective.h b/third_party/WebKit/Source/core/css/cssom/CSSPerspective.h index 3061c4c3..7803cf3 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSPerspective.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSPerspective.h
@@ -29,7 +29,7 @@ TransformComponentType type() const override { return PerspectiveType; } // TODO: Implement asMatrix for CSSPerspective. - CSSMatrixTransformComponent* asMatrix() const override { return nullptr; } + CSSMatrixComponent* asMatrix() const override { return nullptr; } CSSFunctionValue* toCSSValue() const override;
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSRotation.h b/third_party/WebKit/Source/core/css/cssom/CSSRotation.h index 25628f0..8c0d4d95 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSRotation.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSRotation.h
@@ -6,7 +6,7 @@ #define CSSRotation_h #include "core/css/cssom/CSSAngleValue.h" -#include "core/css/cssom/CSSMatrixTransformComponent.h" +#include "core/css/cssom/CSSMatrixComponent.h" #include "core/css/cssom/CSSTransformComponent.h" namespace blink { @@ -42,10 +42,10 @@ return m_is2D ? RotationType : Rotation3DType; } - CSSMatrixTransformComponent* asMatrix() const override { - return m_is2D ? CSSMatrixTransformComponent::rotate(m_angle->degrees()) - : CSSMatrixTransformComponent::rotate3d(m_angle->degrees(), - m_x, m_y, m_z); + CSSMatrixComponent* asMatrix() const override { + return m_is2D ? CSSMatrixComponent::rotate(m_angle->degrees()) + : CSSMatrixComponent::rotate3d(m_angle->degrees(), m_x, m_y, + m_z); } CSSFunctionValue* toCSSValue() const override;
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSScale.h b/third_party/WebKit/Source/core/css/cssom/CSSScale.h index cceb683..552f3e6 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSScale.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSScale.h
@@ -5,7 +5,7 @@ #ifndef CSSScale_h #define CSSScale_h -#include "core/css/cssom/CSSMatrixTransformComponent.h" +#include "core/css/cssom/CSSMatrixComponent.h" #include "core/css/cssom/CSSTransformComponent.h" namespace blink { @@ -31,9 +31,9 @@ return m_is2D ? ScaleType : Scale3DType; } - CSSMatrixTransformComponent* asMatrix() const override { - return m_is2D ? CSSMatrixTransformComponent::scale(m_x, m_y) - : CSSMatrixTransformComponent::scale3d(m_x, m_y, m_z); + CSSMatrixComponent* asMatrix() const override { + return m_is2D ? CSSMatrixComponent::scale(m_x, m_y) + : CSSMatrixComponent::scale3d(m_x, m_y, m_z); } CSSFunctionValue* toCSSValue() const override;
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSSkew.h b/third_party/WebKit/Source/core/css/cssom/CSSSkew.h index e7b715f..bf890e3 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSSkew.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSSkew.h
@@ -6,7 +6,7 @@ #define CSSSkew_h #include "core/css/cssom/CSSAngleValue.h" -#include "core/css/cssom/CSSMatrixTransformComponent.h" +#include "core/css/cssom/CSSMatrixComponent.h" #include "core/css/cssom/CSSTransformComponent.h" namespace blink { @@ -29,8 +29,8 @@ TransformComponentType type() const override { return SkewType; } - CSSMatrixTransformComponent* asMatrix() const override { - return CSSMatrixTransformComponent::skew(m_ax->degrees(), m_ay->degrees()); + CSSMatrixComponent* asMatrix() const override { + return CSSMatrixComponent::skew(m_ax->degrees(), m_ay->degrees()); } CSSFunctionValue* toCSSValue() const override;
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.cpp b/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.cpp index 13c1531..d0d1a6f8 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.cpp +++ b/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.cpp
@@ -4,7 +4,7 @@ #include "core/css/cssom/CSSTransformComponent.h" -#include "core/css/cssom/CSSMatrixTransformComponent.h" +#include "core/css/cssom/CSSMatrixComponent.h" #include "core/css/cssom/CSSPerspective.h" #include "core/css/cssom/CSSRotation.h" #include "core/css/cssom/CSSScale.h" @@ -22,7 +22,7 @@ switch (functionValue.functionType()) { case CSSValueMatrix: case CSSValueMatrix3d: - return CSSMatrixTransformComponent::fromCSSValue(functionValue); + return CSSMatrixComponent::fromCSSValue(functionValue); case CSSValuePerspective: return CSSPerspective::fromCSSValue(functionValue); case CSSValueRotate:
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.h b/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.h index 22ee7d64..0ba5747 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.h
@@ -12,7 +12,7 @@ namespace blink { -class CSSMatrixTransformComponent; +class CSSMatrixComponent; class CORE_EXPORT CSSTransformComponent : public GarbageCollectedFinalized<CSSTransformComponent>, @@ -51,7 +51,7 @@ String cssText() const { return toCSSValue()->cssText(); } virtual CSSFunctionValue* toCSSValue() const = 0; - virtual CSSMatrixTransformComponent* asMatrix() const = 0; + virtual CSSMatrixComponent* asMatrix() const = 0; DEFINE_INLINE_VIRTUAL_TRACE() {}
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.idl b/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.idl index 8173d5e00..74da28ea4 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.idl +++ b/third_party/WebKit/Source/core/css/cssom/CSSTransformComponent.idl
@@ -8,5 +8,5 @@ ] interface CSSTransformComponent { readonly attribute DOMString cssText; boolean is2D(); - CSSMatrixTransformComponent asMatrix(); + CSSMatrixComponent asMatrix(); };
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSTranslation.h b/third_party/WebKit/Source/core/css/cssom/CSSTranslation.h index 41a32f4..f08bda4 100644 --- a/third_party/WebKit/Source/core/css/cssom/CSSTranslation.h +++ b/third_party/WebKit/Source/core/css/cssom/CSSTranslation.h
@@ -40,7 +40,7 @@ } // TODO: Implement asMatrix for CSSTranslation. - CSSMatrixTransformComponent* asMatrix() const override { return nullptr; } + CSSMatrixComponent* asMatrix() const override { return nullptr; } CSSFunctionValue* toCSSValue() const override;
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp index de20d7cc..52e4430 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -337,12 +337,6 @@ return settings; } -static CSSValue* consumeWebkitHighlight(CSSParserTokenRange& range) { - if (range.peek().id() == CSSValueNone) - return consumeIdent(range); - return consumeString(range); -} - static CSSIdentifierValue* consumeFontVariantCSS21(CSSParserTokenRange& range) { return consumeIdent<CSSValueNormal, CSSValueSmallCaps>(range); } @@ -2056,8 +2050,6 @@ return cssPropertyDesc.parseSingleValue(m_range, m_context); switch (property) { - case CSSPropertyWebkitHighlight: - return consumeWebkitHighlight(m_range); case CSSPropertyFontFeatureSettings: return consumeFontFeatureSettings(m_range); case CSSPropertyFontFamily:
diff --git a/third_party/WebKit/Source/core/dom/BUILD.gn b/third_party/WebKit/Source/core/dom/BUILD.gn index 09ff510..51a55eb 100644 --- a/third_party/WebKit/Source/core/dom/BUILD.gn +++ b/third_party/WebKit/Source/core/dom/BUILD.gn
@@ -183,6 +183,8 @@ "MessagePort.cpp", "Modulator.cpp", "Modulator.h", + "ModuleMap.cpp", + "ModuleMap.h", "ModuleScript.cpp", "ModuleScript.h", "MutationCallback.h", @@ -246,6 +248,7 @@ "ScopedWindowFocusAllowedIndicator.h", "ScriptLoader.cpp", "ScriptLoader.h", + "ScriptModuleResolver.h", "ScriptRunner.cpp", "ScriptRunner.h", "ScriptableDocumentParser.cpp",
diff --git a/third_party/WebKit/Source/core/dom/ElementVisibilityObserverTest.cpp b/third_party/WebKit/Source/core/dom/ElementVisibilityObserverTest.cpp index 02f03b0..efff024 100644 --- a/third_party/WebKit/Source/core/dom/ElementVisibilityObserverTest.cpp +++ b/third_party/WebKit/Source/core/dom/ElementVisibilityObserverTest.cpp
@@ -21,7 +21,7 @@ // alow callers to set the parent/top frames by calling |setParent|. It is used // in ElementVisibilityObserverTest in order to mock a RemoteFrame parent of a // LocalFrame. -class StubFrameLoaderClient final : public EmptyFrameLoaderClient { +class StubLocalFrameClient final : public EmptyLocalFrameClient { public: Frame* parent() const override { return m_parent; } Frame* top() const override { return m_parent; } @@ -30,7 +30,7 @@ DEFINE_INLINE_VIRTUAL_TRACE() { visitor->trace(m_parent); - EmptyFrameLoaderClient::trace(visitor); + EmptyLocalFrameClient::trace(visitor); } private: @@ -40,9 +40,9 @@ class ElementVisibilityObserverTest : public ::testing::Test { protected: void SetUp() override { - m_frameLoaderClient = new StubFrameLoaderClient(); + m_localFrameClient = new StubLocalFrameClient(); m_dummyPageHolder = DummyPageHolder::create( - IntSize(), nullptr, m_frameLoaderClient, nullptr, nullptr); + IntSize(), nullptr, m_localFrameClient, nullptr, nullptr); } void TearDown() override { @@ -51,13 +51,11 @@ Document& document() { return m_dummyPageHolder->document(); } FrameHost& frameHost() { return m_dummyPageHolder->page().frameHost(); } - StubFrameLoaderClient* frameLoaderClient() const { - return m_frameLoaderClient; - } + StubLocalFrameClient* localFrameClient() const { return m_localFrameClient; } private: std::unique_ptr<DummyPageHolder> m_dummyPageHolder; - Persistent<StubFrameLoaderClient> m_frameLoaderClient; + Persistent<StubLocalFrameClient> m_localFrameClient; }; TEST_F(ElementVisibilityObserverTest, ObserveElementWithoutDocumentFrame) { @@ -73,7 +71,7 @@ TEST_F(ElementVisibilityObserverTest, ObserveElementInRemoteFrame) { Persistent<RemoteFrame> remoteFrame = RemoteFrame::create(new EmptyRemoteFrameClient(), &frameHost(), nullptr); - frameLoaderClient()->setParent(remoteFrame); + localFrameClient()->setParent(remoteFrame); Persistent<HTMLElement> element = HTMLDivElement::create(document()); ElementVisibilityObserver* observer =
diff --git a/third_party/WebKit/Source/core/dom/Modulator.h b/third_party/WebKit/Source/core/dom/Modulator.h index 6f923196..393d2557 100644 --- a/third_party/WebKit/Source/core/dom/Modulator.h +++ b/third_party/WebKit/Source/core/dom/Modulator.h
@@ -12,6 +12,23 @@ namespace blink { class LocalFrame; +class ModuleScript; +class ModuleScriptFetchRequest; +class ModuleScriptLoaderClient; +class ScriptModuleResolver; +class WebTaskRunner; + +// A SingleModuleClient is notified when single module script node (node as in a +// module tree graph) load is complete and its corresponding entry is created in +// module map. +class SingleModuleClient : public GarbageCollectedMixin { + public: + virtual void notifyModuleLoadFinished(ModuleScript*) = 0; +}; + +// spec: "top-level module fetch flag" +// https://html.spec.whatwg.org/multipage/webappapis.html#fetching-scripts-is-top-level +enum class ModuleGraphLevel { TopLevelModuleFetch, DependentModuleFetch }; // A Modulator is an interface for "environment settings object" concept for // module scripts. @@ -22,9 +39,23 @@ public: static Modulator* from(LocalFrame*); + virtual ScriptModuleResolver* scriptModuleResolver() = 0; + virtual WebTaskRunner* taskRunner() = 0; + // https://html.spec.whatwg.org/#resolve-a-module-specifier static KURL resolveModuleSpecifier(const String& moduleRequest, const KURL& baseURL); + + private: + friend class ModuleMap; + + // Fetches a single module script. + // This is triggered from fetchSingle() implementation (which is in ModuleMap) + // if the cached entry doesn't exist. + // The client can be notified either synchronously or asynchronously. + virtual void fetchNewSingleModule(const ModuleScriptFetchRequest&, + ModuleGraphLevel, + ModuleScriptLoaderClient*) = 0; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/ModuleMap.cpp b/third_party/WebKit/Source/core/dom/ModuleMap.cpp new file mode 100644 index 0000000..e68643d4 --- /dev/null +++ b/third_party/WebKit/Source/core/dom/ModuleMap.cpp
@@ -0,0 +1,146 @@ +// Copyright 2017 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 "core/dom/ModuleMap.h" + +#include "core/dom/Modulator.h" +#include "core/dom/ModuleScript.h" +#include "core/dom/ScriptModuleResolver.h" +#include "core/loader/modulescript/ModuleScriptFetchRequest.h" +#include "core/loader/modulescript/ModuleScriptLoaderClient.h" +#include "platform/WebTaskRunner.h" + +namespace blink { + +// Entry struct represents a value in "module map" spec object. +// https://html.spec.whatwg.org/multipage/webappapis.html#module-map +class ModuleMap::Entry final : public GarbageCollectedFinalized<Entry>, + public ModuleScriptLoaderClient { + USING_GARBAGE_COLLECTED_MIXIN(ModuleMap::Entry); + + public: + static Entry* create(ModuleMap* map) { return new Entry(map); } + ~Entry() override {} + + DECLARE_TRACE(); + + // Notify fetched |m_moduleScript| to the client asynchronously. + void addClient(SingleModuleClient*); + + // This is only to be used from ScriptModuleResolver implementations. + ModuleScript* getModuleScript() const; + + private: + explicit Entry(ModuleMap*); + + void dispatchFinishedNotificationAsync(SingleModuleClient*); + + // Implements ModuleScriptLoaderClient + void notifyNewSingleModuleFinished(ModuleScript*) override; + + Member<ModuleScript> m_moduleScript; + Member<ModuleMap> m_map; + + // Correspond to the HTML spec: "fetching" state. + bool m_isFetching = true; + + HeapHashSet<Member<SingleModuleClient>> m_clients; +}; + +ModuleMap::Entry::Entry(ModuleMap* map) : m_map(map) { + DCHECK(m_map); +} + +DEFINE_TRACE(ModuleMap::Entry) { + visitor->trace(m_moduleScript); + visitor->trace(m_map); + visitor->trace(m_clients); +} + +void ModuleMap::Entry::dispatchFinishedNotificationAsync( + SingleModuleClient* client) { + m_map->modulator()->taskRunner()->postTask( + BLINK_FROM_HERE, + WTF::bind(&SingleModuleClient::notifyModuleLoadFinished, + wrapPersistent(client), wrapPersistent(m_moduleScript.get()))); +} + +void ModuleMap::Entry::addClient(SingleModuleClient* newClient) { + DCHECK(!m_clients.contains(newClient)); + if (!m_isFetching) { + DCHECK(m_clients.isEmpty()); + dispatchFinishedNotificationAsync(newClient); + return; + } + + m_clients.insert(newClient); +} + +void ModuleMap::Entry::notifyNewSingleModuleFinished( + ModuleScript* moduleScript) { + CHECK(m_isFetching); + m_moduleScript = moduleScript; + m_isFetching = false; + + if (m_moduleScript) { + m_map->modulator()->scriptModuleResolver()->registerModuleScript( + m_moduleScript); + } + + for (const auto& client : m_clients) { + dispatchFinishedNotificationAsync(client); + } + m_clients.clear(); +} + +ModuleScript* ModuleMap::Entry::getModuleScript() const { + DCHECK(!m_isFetching); + return m_moduleScript.get(); +} + +ModuleMap::ModuleMap(Modulator* modulator) : m_modulator(modulator) { + DCHECK(modulator); +} + +DEFINE_TRACE(ModuleMap) { + visitor->trace(m_map); + visitor->trace(m_modulator); +} + +void ModuleMap::fetchSingleModuleScript(const ModuleScriptFetchRequest& request, + ModuleGraphLevel level, + SingleModuleClient* client) { + // https://html.spec.whatwg.org/#fetch-a-single-module-script + + // Step 1. Let moduleMap be module map settings object's module map. + // Note: This is the ModuleMap. + + // Step 2. If moduleMap[url] is "fetching", wait in parallel until that + // entry's value changes, then queue a task on the networking task source to + // proceed with running the following steps. + MapImpl::AddResult result = m_map.insert(request.url(), nullptr); + Member<Entry>& entry = result.storedValue->value; + if (result.isNewEntry) { + entry = Entry::create(this); + + // Steps 4-9 loads a new single module script. + // Delegates to ModuleScriptLoader via Modulator. + m_modulator->fetchNewSingleModule(request, level, entry); + } + DCHECK(entry); + + // Step 3. If moduleMap[url] exists, asynchronously complete this algorithm + // with moduleMap[url], and abort these steps. + // Step 10. Set moduleMap[url] to module script, and asynchronously complete + // this algorithm with module script. + entry->addClient(client); +} + +ModuleScript* ModuleMap::getFetchedModuleScript(const KURL& url) const { + MapImpl::const_iterator it = m_map.find(url); + CHECK_NE(it, m_map.end()); + return it->value->getModuleScript(); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/ModuleMap.h b/third_party/WebKit/Source/core/dom/ModuleMap.h new file mode 100644 index 0000000..742bca5 --- /dev/null +++ b/third_party/WebKit/Source/core/dom/ModuleMap.h
@@ -0,0 +1,60 @@ +// Copyright 2017 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 ModuleMap_h +#define ModuleMap_h + +#include "core/CoreExport.h" +#include "platform/heap/Handle.h" +#include "platform/weborigin/KURL.h" +#include "platform/weborigin/KURLHash.h" +#include "wtf/HashMap.h" + +namespace blink { + +class Modulator; +class ModuleScript; +class ModuleScriptFetchRequest; +class SingleModuleClient; +enum class ModuleGraphLevel; + +// A ModuleMap implements "module map" spec. +// https://html.spec.whatwg.org/#module-map +class CORE_EXPORT ModuleMap final : public GarbageCollected<ModuleMap> { + WTF_MAKE_NONCOPYABLE(ModuleMap); + class Entry; + class LoaderHost; + + public: + static ModuleMap* create(Modulator* modulator) { + return new ModuleMap(modulator); + } + DECLARE_TRACE(); + + // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script + void fetchSingleModuleScript(const ModuleScriptFetchRequest&, + ModuleGraphLevel, + SingleModuleClient*); + + // Synchronously get the ModuleScript for a given URL. + // Note: fetchSingleModuleScript of the ModuleScript must be complete before + // calling this. + ModuleScript* getFetchedModuleScript(const KURL&) const; + + Modulator* modulator() { return m_modulator; } + + private: + explicit ModuleMap(Modulator*); + + using MapImpl = HeapHashMap<KURL, Member<Entry>>; + + // A module map is a map of absolute URLs to map entry. + MapImpl m_map; + + Member<Modulator> m_modulator; +}; + +} // namespace blink + +#endif
diff --git a/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp b/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp new file mode 100644 index 0000000..ac18a99 --- /dev/null +++ b/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp
@@ -0,0 +1,248 @@ +// Copyright 2017 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 "core/dom/ModuleMap.h" + +#include "core/dom/Document.h" +#include "core/dom/Modulator.h" +#include "core/dom/ModuleScript.h" +#include "core/dom/ScriptModuleResolver.h" +#include "core/loader/modulescript/ModuleScriptFetchRequest.h" +#include "core/loader/modulescript/ModuleScriptLoaderClient.h" +#include "core/testing/DummyModulator.h" +#include "core/testing/DummyPageHolder.h" +#include "platform/heap/Handle.h" +#include "platform/testing/TestingPlatformSupport.h" +#include "public/platform/Platform.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace blink { + +namespace { + +class TestSingleModuleClient final + : public GarbageCollectedFinalized<TestSingleModuleClient>, + public SingleModuleClient { + USING_GARBAGE_COLLECTED_MIXIN(TestSingleModuleClient); + + public: + TestSingleModuleClient() = default; + virtual ~TestSingleModuleClient() {} + + DEFINE_INLINE_TRACE() { visitor->trace(m_moduleScript); } + + void notifyModuleLoadFinished(ModuleScript* moduleScript) override { + m_wasNotifyFinished = true; + m_moduleScript = moduleScript; + } + + bool wasNotifyFinished() const { return m_wasNotifyFinished; } + ModuleScript* moduleScript() { return m_moduleScript; } + + private: + bool m_wasNotifyFinished = false; + Member<ModuleScript> m_moduleScript; +}; + +class TestScriptModuleResolver final : public ScriptModuleResolver { + public: + TestScriptModuleResolver() {} + + int registerModuleScriptCallCount() const { + return m_registerModuleScriptCallCount; + } + + void registerModuleScript(ModuleScript*) override { + m_registerModuleScriptCallCount++; + } + + ScriptModule resolve(const String& specifier, + const ScriptModule& referrer, + ExceptionState&) override { + NOTREACHED(); + return ScriptModule(); + } + + private: + int m_registerModuleScriptCallCount = 0; +}; + +} // namespace + +class ModuleMapTestModulator final : public DummyModulator { + public: + ModuleMapTestModulator(); + virtual ~ModuleMapTestModulator() {} + + DECLARE_TRACE(); + + TestScriptModuleResolver* testScriptModuleResolver() { + return m_resolver.get(); + } + void resolveFetches(); + + private: + // Implements Modulator: + + ScriptModuleResolver* scriptModuleResolver() override { + return m_resolver.get(); + } + + WebTaskRunner* taskRunner() override { + return Platform::current()->currentThread()->getWebTaskRunner(); + }; + + void fetchNewSingleModule(const ModuleScriptFetchRequest&, + ModuleGraphLevel, + ModuleScriptLoaderClient*) override; + + struct TestRequest : public GarbageCollectedFinalized<TestRequest> { + KURL url; + String nonce; + Member<ModuleScriptLoaderClient> client; + + DEFINE_INLINE_TRACE() { visitor->trace(client); } + }; + HeapVector<Member<TestRequest>> m_testRequests; + + Member<TestScriptModuleResolver> m_resolver; +}; + +ModuleMapTestModulator::ModuleMapTestModulator() + : m_resolver(new TestScriptModuleResolver) {} + +DEFINE_TRACE(ModuleMapTestModulator) { + visitor->trace(m_testRequests); + visitor->trace(m_resolver); + DummyModulator::trace(visitor); +} + +void ModuleMapTestModulator::fetchNewSingleModule( + const ModuleScriptFetchRequest& request, + ModuleGraphLevel, + ModuleScriptLoaderClient* client) { + TestRequest* testRequest = new TestRequest; + testRequest->url = request.url(); + testRequest->nonce = request.nonce(); + testRequest->client = client; + m_testRequests.push_back(testRequest); +} + +void ModuleMapTestModulator::resolveFetches() { + for (const auto& testRequest : m_testRequests) { + ModuleScript* moduleScript = ModuleScript::create( + ScriptModule(), testRequest->url, testRequest->nonce, ParserInserted, + WebURLRequest::FetchCredentialsModeOmit); + taskRunner()->postTask( + BLINK_FROM_HERE, + WTF::bind(&ModuleScriptLoaderClient::notifyNewSingleModuleFinished, + wrapPersistent(testRequest->client.get()), + wrapPersistent(moduleScript))); + } + m_testRequests.clear(); +} + +class ModuleMapTest : public testing::Test { + public: + void SetUp() override; + + ModuleMapTestModulator* modulator() { return m_modulator.get(); } + ModuleMap* map() { return m_map; } + + protected: + Persistent<ModuleMapTestModulator> m_modulator; + Persistent<ModuleMap> m_map; +}; + +void ModuleMapTest::SetUp() { + m_modulator = new ModuleMapTestModulator(); + m_map = ModuleMap::create(m_modulator.get()); +} + +TEST_F(ModuleMapTest, sequentialRequests) { + ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> + platform; + platform->advanceClockSeconds(1.); // For non-zero DocumentParserTimings + + KURL url(KURL(), "https://example.com/foo.js"); + ModuleScriptFetchRequest moduleRequest( + url, String(), ParserInserted, WebURLRequest::FetchCredentialsModeOmit); + + // First request + TestSingleModuleClient* client = new TestSingleModuleClient; + map()->fetchSingleModuleScript(moduleRequest, + ModuleGraphLevel::TopLevelModuleFetch, client); + modulator()->resolveFetches(); + EXPECT_FALSE(client->wasNotifyFinished()) + << "fetchSingleModuleScript shouldn't complete synchronously"; + platform->runUntilIdle(); + + EXPECT_EQ( + modulator()->testScriptModuleResolver()->registerModuleScriptCallCount(), + 1); + EXPECT_TRUE(client->wasNotifyFinished()); + EXPECT_TRUE(client->moduleScript()); + EXPECT_EQ(client->moduleScript()->instantiationState(), + ModuleInstantiationState::Uninstantiated); + + // Secondary request + TestSingleModuleClient* client2 = new TestSingleModuleClient; + map()->fetchSingleModuleScript( + moduleRequest, ModuleGraphLevel::TopLevelModuleFetch, client2); + modulator()->resolveFetches(); + EXPECT_FALSE(client2->wasNotifyFinished()) + << "fetchSingleModuleScript shouldn't complete synchronously"; + platform->runUntilIdle(); + + EXPECT_EQ( + modulator()->testScriptModuleResolver()->registerModuleScriptCallCount(), + 1) + << "registerModuleScript sholudn't be called in secondary request."; + EXPECT_TRUE(client2->wasNotifyFinished()); + EXPECT_TRUE(client2->moduleScript()); + EXPECT_EQ(client2->moduleScript()->instantiationState(), + ModuleInstantiationState::Uninstantiated); +} + +TEST_F(ModuleMapTest, concurrentRequestsShouldJoin) { + ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> + platform; + platform->advanceClockSeconds(1.); // For non-zero DocumentParserTimings + + KURL url(KURL(), "https://example.com/foo.js"); + ModuleScriptFetchRequest moduleRequest( + url, String(), ParserInserted, WebURLRequest::FetchCredentialsModeOmit); + + // First request + TestSingleModuleClient* client = new TestSingleModuleClient; + map()->fetchSingleModuleScript(moduleRequest, + ModuleGraphLevel::TopLevelModuleFetch, client); + + // Secondary request (which should join the first request) + TestSingleModuleClient* client2 = new TestSingleModuleClient; + map()->fetchSingleModuleScript( + moduleRequest, ModuleGraphLevel::TopLevelModuleFetch, client2); + + modulator()->resolveFetches(); + EXPECT_FALSE(client->wasNotifyFinished()) + << "fetchSingleModuleScript shouldn't complete synchronously"; + EXPECT_FALSE(client2->wasNotifyFinished()) + << "fetchSingleModuleScript shouldn't complete synchronously"; + platform->runUntilIdle(); + + EXPECT_EQ( + modulator()->testScriptModuleResolver()->registerModuleScriptCallCount(), + 1); + + EXPECT_TRUE(client->wasNotifyFinished()); + EXPECT_TRUE(client->moduleScript()); + EXPECT_EQ(client->moduleScript()->instantiationState(), + ModuleInstantiationState::Uninstantiated); + EXPECT_TRUE(client2->wasNotifyFinished()); + EXPECT_TRUE(client2->moduleScript()); + EXPECT_EQ(client2->moduleScript()->instantiationState(), + ModuleInstantiationState::Uninstantiated); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/PendingScript.cpp b/third_party/WebKit/Source/core/dom/PendingScript.cpp index cdcf2948..7ea0742 100644 --- a/third_party/WebKit/Source/core/dom/PendingScript.cpp +++ b/third_party/WebKit/Source/core/dom/PendingScript.cpp
@@ -221,19 +221,13 @@ MemoryCoordinatorClient::trace(visitor); } -NOINLINE ScriptSourceCode PendingScript::getSource(const KURL& documentURL, - bool& errorOccurred) const { +ScriptSourceCode PendingScript::getSource(const KURL& documentURL, + bool& errorOccurred) const { checkState(); errorOccurred = this->errorOccurred(); if (resource()) { - // For investigating https://crbug.com/692856. - CHECK(resource()->isLoaded() || - (resource()->isLoading() && resource()->hasRevalidated())); - CHECK(resource()->isLoaded() || - (resource()->isLoading() && resource()->isCacheValidator())); - CHECK(resource()->isLoaded()); - + DCHECK(resource()->isLoaded()); if (m_streamer && !m_streamer->streamingSuppressed()) return ScriptSourceCode(m_streamer, resource()); return ScriptSourceCode(resource());
diff --git a/third_party/WebKit/Source/core/dom/ScriptModuleResolver.h b/third_party/WebKit/Source/core/dom/ScriptModuleResolver.h new file mode 100644 index 0000000..72816c9b --- /dev/null +++ b/third_party/WebKit/Source/core/dom/ScriptModuleResolver.h
@@ -0,0 +1,43 @@ +// Copyright 2017 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 ScriptModuleResolver_h +#define ScriptModuleResolver_h + +#include "bindings/core/v8/ExceptionState.h" +#include "platform/heap/Handle.h" +#include "wtf/text/WTFString.h" + +namespace blink { + +class ScriptModule; +class ModuleScript; + +// The ScriptModuleResolver interface is used from V8 module bindings +// when it need the ScriptModule's descendants. +// +// When a module writes import 'x', the module is called the referrer, 'x' is +// the specifier, and the module identified by 'x' is the descendant. +// ScriptModuleResolver, given a referrer and specifier, can look up the +// descendant. +class ScriptModuleResolver : public GarbageCollected<ScriptModuleResolver> { + public: + DEFINE_INLINE_VIRTUAL_TRACE() {} + + // Notify the ScriptModuleResolver that a ModuleScript exists. + // This hook gives a chance for the resolver impl to populate module record + // identifier -> ModuleScript mapping entry. + virtual void registerModuleScript(ModuleScript*) = 0; + + // Implements "Runtime Semantics: HostResolveImportedModule" + // https://tc39.github.io/ecma262/#sec-hostresolveimportedmodule + // This returns a null ScriptModule when an exception is thrown. + virtual ScriptModule resolve(const String& specifier, + const ScriptModule& referrer, + ExceptionState&) = 0; +}; + +} // namespace blink + +#endif // ScriptModuleResolver_h
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp index 99b128a2..78d50f6 100644 --- a/third_party/WebKit/Source/core/editing/Editor.cpp +++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -156,7 +156,6 @@ // TODO(yosin): We should make |Editor::selectionForCommand()| to return // |SelectionInDOMTree| instead of |VisibleSelection|. VisibleSelection Editor::selectionForCommand(Event* event) { - frame().selection().updateIfNeeded(); VisibleSelection selection = frame().selection().computeVisibleSelectionInDOMTreeDeprecated(); if (!event) @@ -734,9 +733,9 @@ return hasEditableStyle(*startContainer) && hasEditableStyle(*endContainer); } -void Editor::respondToChangedContents(const VisibleSelection& endingSelection) { +void Editor::respondToChangedContents(const Position& position) { if (frame().settings() && frame().settings()->getAccessibilityEnabled()) { - Node* node = endingSelection.start().anchorNode(); + Node* node = position.anchorNode(); if (AXObjectCache* cache = frame().document()->existingAXObjectCache()) cache->handleEditableTextContentChanged(node); } @@ -917,7 +916,7 @@ m_undoStack->registerUndoStep(m_lastEditCommand->ensureUndoStep()); } - respondToChangedContents(newSelection); + respondToChangedContents(newSelection.start()); } static VisibleSelection correctedVisibleSelection( @@ -956,7 +955,7 @@ m_lastEditCommand = nullptr; m_undoStack->registerRedoStep(cmd); - respondToChangedContents(newSelection); + respondToChangedContents(newSelection.start()); } void Editor::reappliedEditing(UndoStep* cmd) { @@ -985,7 +984,7 @@ m_lastEditCommand = nullptr; m_undoStack->registerUndoStep(cmd); - respondToChangedContents(newSelection); + respondToChangedContents(newSelection.start()); } Editor* Editor::create(LocalFrame& frame) {
diff --git a/third_party/WebKit/Source/core/editing/Editor.h b/third_party/WebKit/Source/core/editing/Editor.h index dc3081d6..3d71258 100644 --- a/third_party/WebKit/Source/core/editing/Editor.h +++ b/third_party/WebKit/Source/core/editing/Editor.h
@@ -106,7 +106,7 @@ void transpose(); - void respondToChangedContents(const VisibleSelection& endingSelection); + void respondToChangedContents(const Position&); bool selectionStartHasStyle(CSSPropertyID, const String& value) const; TriState selectionHasStyle(CSSPropertyID, const String& value) const;
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp index 791876c..de34916 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp +++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -1151,11 +1151,6 @@ CursorAlignOnScroll::IfNeeded, granularity); } -void FrameSelection::updateIfNeeded() { - DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); - m_selectionEditor->updateIfNeeded(); -} - void FrameSelection::setCaretVisible(bool caretIsVisible) { m_frameCaret->setCaretVisibility(caretIsVisible ? CaretVisibility::Visible : CaretVisibility::Hidden);
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.h b/third_party/WebKit/Source/core/editing/FrameSelection.h index d78e98a..cb80378 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelection.h +++ b/third_party/WebKit/Source/core/editing/FrameSelection.h
@@ -269,12 +269,6 @@ bool shouldShowBlockCursor() const; void setShouldShowBlockCursor(bool); - // TODO(yosin): We should check DOM tree version and style version in - // |FrameSelection::selection()| to make sure we use updated selection, - // rather than having |updateIfNeeded()|. Once, we update all layout tests - // to use updated selection, we should make |updateIfNeeded()| private. - void updateIfNeeded(); - void cacheRangeOfDocument(Range*); Range* documentCachedRange() const; void clearDocumentCachedRange();
diff --git a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp index e284266e..63aaf27a 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp +++ b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
@@ -242,31 +242,4 @@ "after it."; } -TEST_F(FrameSelectionTest, updateIfNeededAndFrameCaret) { - setBodyContent("<style id=sample></style>"); - document().setDesignMode("on"); - updateAllLifecyclePhases(); - Element* sample = document().getElementById("sample"); - selection().setSelection( - SelectionInDOMTree::Builder().collapse(Position(sample, 0)).build()); - EXPECT_EQ(Position(document().body(), 0), - selection().computeVisibleSelectionInDOMTreeDeprecated().start()); - EXPECT_EQ(selection().computeVisibleSelectionInDOMTreeDeprecated().start(), - caretPosition().position()); - document().body()->remove(); - EXPECT_EQ(Position(), - selection().computeVisibleSelectionInDOMTreeDeprecated().start()) - << "Selection has been removed by BODY.remove()."; - EXPECT_EQ(selection().computeVisibleSelectionInDOMTreeDeprecated().start(), - caretPosition().position()); - document().updateStyleAndLayout(); - selection().updateIfNeeded(); - - EXPECT_EQ(Position(), - selection().computeVisibleSelectionInDOMTreeDeprecated().start()) - << "selection().updateIfNeeded() does nothing."; - EXPECT_EQ(selection().computeVisibleSelectionInDOMTreeDeprecated().start(), - caretPosition().position()); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/SelectionEditor.cpp b/third_party/WebKit/Source/core/editing/SelectionEditor.cpp index 7d38c7e..cbf5174bb 100644 --- a/third_party/WebKit/Source/core/editing/SelectionEditor.cpp +++ b/third_party/WebKit/Source/core/editing/SelectionEditor.cpp
@@ -375,12 +375,6 @@ return frame()->editor().behavior().shouldConsiderSelectionAsDirectional(); } -void SelectionEditor::updateIfNeeded() { - // TODO(yosin): We should unify |SelectionEditor::updateIfNeeded()| and - // |updateCachedVisibleSelectionIfNeeded()| - updateCachedVisibleSelectionIfNeeded(); -} - bool SelectionEditor::needsUpdateVisibleSelection() const { return m_cacheIsDirty || m_styleVersion != document().styleVersion(); }
diff --git a/third_party/WebKit/Source/core/editing/SelectionEditor.h b/third_party/WebKit/Source/core/editing/SelectionEditor.h index cde5ee9..e853cfe 100644 --- a/third_party/WebKit/Source/core/editing/SelectionEditor.h +++ b/third_party/WebKit/Source/core/editing/SelectionEditor.h
@@ -70,10 +70,6 @@ void resetLogicalRange(); void setLogicalRange(Range*); - // Updates |m_selection| and |m_selectionInFlatTree| with up-to-date - // layout if needed. - void updateIfNeeded(); - void cacheRangeOfDocument(Range*); Range* documentCachedRange() const; void clearDocumentCachedRange();
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp index 21ce048f..4ebc607 100644 --- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -1884,10 +1884,6 @@ Event* event, EditorCommandSource) { frame.document()->updateStyleAndLayoutIgnorePendingStylesheets(); - - // We should update selection to canonicalize with current layout and style, - // before accessing |FrameSelection::selection()|. - frame.selection().updateIfNeeded(); return frame.editor().selectionForCommand(event).rootEditableElement(); } @@ -1910,10 +1906,6 @@ Event*, EditorCommandSource) { frame.document()->updateStyleAndLayoutIgnorePendingStylesheets(); - - // We should update selection to canonicalize with current layout and style, - // before accessing |FrameSelection::selection()|. - frame.selection().updateIfNeeded(); return !frame.selection() .computeVisibleSelectionInDOMTreeDeprecated() .isNone() && @@ -1937,10 +1929,6 @@ Event*, EditorCommandSource) { frame.document()->updateStyleAndLayoutIgnorePendingStylesheets(); - - // We should update selection to canonicalize with current layout and style, - // before accessing |FrameSelection::selection()|. - frame.selection().updateIfNeeded(); return frame.selection() .computeVisibleSelectionInDOMTreeDeprecated() .isRange() && @@ -1953,10 +1941,6 @@ Event*, EditorCommandSource) { frame.document()->updateStyleAndLayoutIgnorePendingStylesheets(); - - // We should update selection to canonicalize with current layout and style, - // before accessing |FrameSelection::selection()|. - frame.selection().updateIfNeeded(); return frame.selection() .computeVisibleSelectionInDOMTreeDeprecated() .isRange() &&
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.cpp b/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.cpp index 7230fff..cfdac39e 100644 --- a/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.cpp +++ b/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.cpp
@@ -53,21 +53,13 @@ &IdleSpellCheckCallback::coldModeTimerFired) {} SpellCheckRequester& IdleSpellCheckCallback::spellCheckRequester() const { - // TODO(xiaochengh): decouple with SpellChecker after SpellCheckRequester is - // moved to IdleSpellCheckCallback. return frame().spellChecker().spellCheckRequester(); } bool IdleSpellCheckCallback::isSpellCheckingEnabled() const { - // TODO(xiaochengh): decouple with SpellChecker. return frame().spellChecker().isSpellCheckingEnabled(); } -void IdleSpellCheckCallback::prepareForLeakDetection() { - if (RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled()) - spellCheckRequester().prepareForLeakDetection(); -} - void IdleSpellCheckCallback::requestInvocation() { IdleRequestOptions options; options.setTimeout(kRequestTimeoutMS);
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.h b/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.h index b3b1a93..7ddc2c4e 100644 --- a/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.h +++ b/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.h
@@ -37,14 +37,6 @@ // Exposed for testing only. SpellCheckRequester& spellCheckRequester() const; - // The leak detector will report leaks should queued requests be posted - // while it GCs repeatedly, as the requests keep their associated element - // alive. - // - // Hence allow the leak detector to effectively stop the spell checker to - // ensure leak reporting stability. - void prepareForLeakDetection(); - DECLARE_VIRTUAL_TRACE(); private:
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp index ac588cc2..bbde6b09 100644 --- a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp +++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
@@ -43,6 +43,7 @@ #include "core/editing/commands/TypingCommand.h" #include "core/editing/iterators/CharacterIterator.h" #include "core/editing/markers/DocumentMarkerController.h" +#include "core/editing/spellcheck/IdleSpellCheckCallback.h" #include "core/editing/spellcheck/SpellCheckRequester.h" #include "core/editing/spellcheck/TextCheckingParagraph.h" #include "core/frame/LocalFrame.h" @@ -169,7 +170,8 @@ SpellChecker::SpellChecker(LocalFrame& frame) : m_frame(&frame), - m_spellCheckRequester(SpellCheckRequester::create(frame)) {} + m_spellCheckRequester(SpellCheckRequester::create(frame)), + m_idleSpellCheckCallback(IdleSpellCheckCallback::create(frame)) {} bool SpellChecker::isSpellCheckingEnabled() const { return spellCheckerClient().isSpellCheckingEnabled(); @@ -1102,11 +1104,11 @@ DEFINE_TRACE(SpellChecker) { visitor->trace(m_frame); visitor->trace(m_spellCheckRequester); + visitor->trace(m_idleSpellCheckCallback); } void SpellChecker::prepareForLeakDetection() { - if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled()) - m_spellCheckRequester->prepareForLeakDetection(); + m_spellCheckRequester->prepareForLeakDetection(); } Vector<TextCheckingResult> SpellChecker::findMisspellings(const String& text) {
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.h b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.h index 1df14ed..2fd2cf8 100644 --- a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.h +++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.h
@@ -36,6 +36,7 @@ namespace blink { class CompositeEditCommand; +class IdleSpellCheckCallback; class LocalFrame; class ReplaceSelectionCommand; class SpellCheckerClient; @@ -128,9 +129,8 @@ Member<LocalFrame> m_frame; - // TODO(xiaochengh): Move it to IdleSpellCheckCallback after idle time spell - // checking reaches status=stable. const Member<SpellCheckRequester> m_spellCheckRequester; + const Member<IdleSpellCheckCallback> m_idleSpellCheckCallback; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp index 5c03337..6739e36c 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -42,7 +42,6 @@ #include "core/editing/FrameSelection.h" #include "core/editing/InputMethodController.h" #include "core/editing/serializers/Serialization.h" -#include "core/editing/spellcheck/IdleSpellCheckCallback.h" #include "core/editing/spellcheck/SpellChecker.h" #include "core/events/Event.h" #include "core/frame/EventHandlerRegistry.h" @@ -358,7 +357,6 @@ visitor->trace(m_eventHandler); visitor->trace(m_console); visitor->trace(m_inputMethodController); - visitor->trace(m_idleSpellCheckCallback); Frame::trace(visitor); Supplementable<LocalFrame>::trace(visitor); } @@ -866,7 +864,6 @@ m_eventHandler(new EventHandler(*this)), m_console(FrameConsole::create(*this)), m_inputMethodController(InputMethodController::create(*this)), - m_idleSpellCheckCallback(IdleSpellCheckCallback::create(*this)), m_navigationDisableCount(0), m_pageZoomFactor(parentPageZoomFactor(this)), m_textZoomFactor(parentTextZoomFactor(this)),
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.h b/third_party/WebKit/Source/core/frame/LocalFrame.h index 2336c92..fbe9ac6 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrame.h +++ b/third_party/WebKit/Source/core/frame/LocalFrame.h
@@ -58,7 +58,6 @@ class FrameConsole; class FrameSelection; class FrameView; -class IdleSpellCheckCallback; class InputMethodController; class InstrumentingAgents; class InterfaceProvider; @@ -147,7 +146,6 @@ ScriptController& script() const; SpellChecker& spellChecker() const; FrameConsole& console() const; - IdleSpellCheckCallback& idleSpellCheckCallback() const; // This method is used to get the highest level LocalFrame in this // frame's in-process subtree. @@ -261,7 +259,6 @@ const Member<EventHandler> m_eventHandler; const Member<FrameConsole> m_console; const Member<InputMethodController> m_inputMethodController; - const Member<IdleSpellCheckCallback> m_idleSpellCheckCallback; int m_navigationDisableCount; @@ -331,11 +328,6 @@ return *m_eventHandler; } -inline IdleSpellCheckCallback& LocalFrame::idleSpellCheckCallback() const { - DCHECK(m_idleSpellCheckCallback); - return *m_idleSpellCheckCallback; -} - DEFINE_TYPE_CASTS(LocalFrame, Frame, localFrame,
diff --git a/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp b/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp index 332d2491..b1e9a3d4c 100644 --- a/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp
@@ -28,13 +28,13 @@ #include "core/events/KeyboardEvent.h" #include "core/events/MouseEvent.h" #include "core/frame/FrameHost.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/Settings.h" #include "core/frame/UseCounter.h" #include "core/html/HTMLImageElement.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/layout/LayoutBox.h" #include "core/loader/FrameLoadRequest.h" -#include "core/loader/FrameLoaderClient.h" #include "core/loader/PingLoader.h" #include "core/page/ChromeClient.h" #include "platform/network/NetworkHints.h"
diff --git a/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp b/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp index dd201c9..da88411 100644 --- a/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp
@@ -29,13 +29,13 @@ #include "core/dom/Attribute.h" #include "core/dom/ElementTraversal.h" #include "core/dom/shadow/ShadowRoot.h" +#include "core/frame/LocalFrameClient.h" #include "core/html/HTMLImageLoader.h" #include "core/html/HTMLObjectElement.h" #include "core/html/PluginDocument.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/layout/LayoutPart.h" #include "core/layout/api/LayoutEmbeddedItem.h" -#include "core/loader/FrameLoaderClient.h" namespace blink {
diff --git a/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.cpp b/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.cpp index d26221eb..daed2a7 100644 --- a/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.cpp +++ b/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.cpp
@@ -26,9 +26,9 @@ #include "core/frame/FrameHost.h" #include "core/frame/LocalFrame.h" +#include "core/frame/LocalFrameClient.h" #include "core/html/HTMLFormElement.h" #include "core/html/forms/FormController.h" -#include "core/loader/FrameLoaderClient.h" #include "core/page/ChromeClient.h" namespace blink {
diff --git a/third_party/WebKit/Source/core/html/HTMLFormElement.cpp b/third_party/WebKit/Source/core/html/HTMLFormElement.cpp index f8de78a..43b5606b 100644 --- a/third_party/WebKit/Source/core/html/HTMLFormElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLFormElement.cpp
@@ -25,6 +25,7 @@ #include "core/html/HTMLFormElement.h" +#include <limits> #include "bindings/core/v8/RadioNodeListOrElement.h" #include "bindings/core/v8/ScriptController.h" #include "bindings/core/v8/ScriptEventListener.h" @@ -37,6 +38,7 @@ #include "core/events/ScopedEventQueue.h" #include "core/frame/LocalDOMWindow.h" #include "core/frame/LocalFrame.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/RemoteFrame.h" #include "core/frame/UseCounter.h" #include "core/frame/csp/ContentSecurityPolicy.h" @@ -52,14 +54,12 @@ #include "core/layout/LayoutObject.h" #include "core/loader/FormSubmission.h" #include "core/loader/FrameLoader.h" -#include "core/loader/FrameLoaderClient.h" #include "core/loader/MixedContentChecker.h" #include "core/loader/NavigationScheduler.h" #include "platform/UserGestureIndicator.h" #include "public/platform/WebInsecureRequestPolicy.h" #include "wtf/AutoReset.h" #include "wtf/text/AtomicString.h" -#include <limits> namespace blink {
diff --git a/third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp b/third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp index 88be669..05af446 100644 --- a/third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp +++ b/third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp
@@ -31,12 +31,12 @@ #include "core/dom/Document.h" #include "core/frame/FrameView.h" #include "core/frame/LocalFrame.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/RemoteFrame.h" #include "core/frame/RemoteFrameView.h" #include "core/frame/csp/ContentSecurityPolicy.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/loader/FrameLoader.h" -#include "core/loader/FrameLoaderClient.h" #include "core/page/FocusController.h" #include "core/page/Page.h"
diff --git a/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp b/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp index ab7e818..2ce38adc 100644 --- a/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp
@@ -28,11 +28,11 @@ #include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" #include "core/frame/LocalFrame.h" +#include "core/frame/LocalFrameClient.h" #include "core/layout/LayoutPart.h" #include "core/layout/api/LayoutPartItem.h" #include "core/loader/FrameLoadRequest.h" #include "core/loader/FrameLoader.h" -#include "core/loader/FrameLoaderClient.h" #include "core/plugins/PluginView.h" #include "platform/weborigin/SecurityOrigin.h"
diff --git a/third_party/WebKit/Source/core/html/HTMLFrameSetElement.cpp b/third_party/WebKit/Source/core/html/HTMLFrameSetElement.cpp index db7c2f08..581d619 100644 --- a/third_party/WebKit/Source/core/html/HTMLFrameSetElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLFrameSetElement.cpp
@@ -31,10 +31,10 @@ #include "core/events/Event.h" #include "core/events/MouseEvent.h" #include "core/frame/LocalFrame.h" +#include "core/frame/LocalFrameClient.h" #include "core/html/HTMLCollection.h" #include "core/html/HTMLFrameElement.h" #include "core/layout/LayoutFrameSet.h" -#include "core/loader/FrameLoaderClient.h" namespace blink {
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp index 7e97fcc..989d4898 100644 --- a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
@@ -31,12 +31,12 @@ #include "core/dom/Document.h" #include "core/dom/TaskRunnerHelper.h" #include "core/events/Event.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/UseCounter.h" #include "core/html/CrossOriginAttribute.h" #include "core/html/LinkManifest.h" #include "core/html/imports/LinkImport.h" #include "core/inspector/ConsoleMessage.h" -#include "core/loader/FrameLoaderClient.h" #include "core/loader/NetworkHintsInterface.h" #include "core/origin_trials/OriginTrials.h" #include "platform/weborigin/SecurityPolicy.h"
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp index ee9fcef..7c10b4a 100644 --- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -26,6 +26,7 @@ #include "core/html/HTMLMediaElement.h" +#include <limits> #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/Microtask.h" #include "bindings/core/v8/ScriptController.h" @@ -43,6 +44,7 @@ #include "core/events/Event.h" #include "core/frame/FrameView.h" #include "core/frame/LocalFrame.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/Settings.h" #include "core/frame/UseCounter.h" #include "core/frame/csp/ContentSecurityPolicy.h" @@ -69,7 +71,6 @@ #include "core/layout/api/LayoutViewItem.h" #include "core/layout/compositing/PaintLayerCompositor.h" #include "core/loader/FrameLoader.h" -#include "core/loader/FrameLoaderClient.h" #include "core/page/ChromeClient.h" #include "core/page/NetworkStateNotifier.h" #include "platform/Histogram.h" @@ -97,7 +98,6 @@ #include "wtf/MathExtras.h" #include "wtf/PtrUtil.h" #include "wtf/text/CString.h" -#include <limits> #ifndef BLINK_MEDIA_LOG #define BLINK_MEDIA_LOG DVLOG(3) @@ -3915,8 +3915,8 @@ LocalFrame* frame = document().frame(); if (!frame) return false; - FrameLoaderClient* frameLoaderClient = frame->loader().client(); - return frameLoaderClient && frameLoaderClient->allowAutoplay(true); + LocalFrameClient* localFrameClient = frame->loader().client(); + return localFrameClient && localFrameClient->allowAutoplay(true); } void HTMLMediaElement::setNetworkState(NetworkState state) {
diff --git a/third_party/WebKit/Source/core/html/HTMLMetaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMetaElement.cpp index 7c1376b..b09f5764 100644 --- a/third_party/WebKit/Source/core/html/HTMLMetaElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLMetaElement.cpp
@@ -26,11 +26,11 @@ #include "core/dom/Document.h" #include "core/dom/ElementTraversal.h" #include "core/frame/LocalFrame.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/Settings.h" #include "core/html/HTMLHeadElement.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/inspector/ConsoleMessage.h" -#include "core/loader/FrameLoaderClient.h" #include "core/loader/HttpEquiv.h" #include "platform/RuntimeEnabledFeatures.h" #include "wtf/text/StringToNumber.h"
diff --git a/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp b/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp index 780bb4b..afa08e86 100644 --- a/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
@@ -33,13 +33,13 @@ #include "core/dom/Text.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/frame/LocalFrame.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/Settings.h" #include "core/html/HTMLImageLoader.h" #include "core/html/HTMLMetaElement.h" #include "core/html/HTMLParamElement.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/layout/api/LayoutEmbeddedItem.h" -#include "core/loader/FrameLoaderClient.h" #include "core/plugins/PluginView.h" #include "platform/Widget.h" #include "platform/network/mime/MIMETypeRegistry.h"
diff --git a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp index 41a2aaa9..123c9140 100644 --- a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
@@ -31,6 +31,7 @@ #include "core/events/Event.h" #include "core/frame/FrameView.h" #include "core/frame/LocalFrame.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/Settings.h" #include "core/frame/csp/ContentSecurityPolicy.h" #include "core/html/HTMLContentElement.h" @@ -41,7 +42,6 @@ #include "core/layout/LayoutImage.h" #include "core/layout/LayoutPart.h" #include "core/layout/api/LayoutEmbeddedItem.h" -#include "core/loader/FrameLoaderClient.h" #include "core/loader/MixedContentChecker.h" #include "core/page/Page.h" #include "core/page/scrolling/ScrollingCoordinator.h" @@ -525,9 +525,9 @@ } else { bool loadManually = document().isPluginDocument() && !document().containsPlugins(); - FrameLoaderClient::DetachedPluginPolicy policy = - requireLayoutObject ? FrameLoaderClient::FailOnDetachedPlugin - : FrameLoaderClient::AllowDetachedPlugin; + LocalFrameClient::DetachedPluginPolicy policy = + requireLayoutObject ? LocalFrameClient::FailOnDetachedPlugin + : LocalFrameClient::AllowDetachedPlugin; Widget* widget = frame->loader().client()->createPlugin( this, url, paramNames, paramValues, mimeType, loadManually, policy); if (!widget) {
diff --git a/third_party/WebKit/Source/core/html/HTMLVideoElementTest.cpp b/third_party/WebKit/Source/core/html/HTMLVideoElementTest.cpp index d954c0f..0d438b60 100644 --- a/third_party/WebKit/Source/core/html/HTMLVideoElementTest.cpp +++ b/third_party/WebKit/Source/core/html/HTMLVideoElementTest.cpp
@@ -64,9 +64,9 @@ MOCK_METHOD1(setBufferingStrategy, void(BufferingStrategy)); }; -class StubFrameLoaderClient : public EmptyFrameLoaderClient { +class StubLocalFrameClient : public EmptyLocalFrameClient { public: - static StubFrameLoaderClient* create() { return new StubFrameLoaderClient; } + static StubLocalFrameClient* create() { return new StubLocalFrameClient; } std::unique_ptr<WebMediaPlayer> createWebMediaPlayer( HTMLMediaElement&, @@ -84,7 +84,7 @@ : m_dummyPageHolder( DummyPageHolder::create(IntSize(640, 360), nullptr, - StubFrameLoaderClient::create())) { + StubLocalFrameClient::create())) { // TODO(sandersd): This should be done by a settings initializer. networkStateNotifier().setWebConnection(WebConnectionTypeWifi, 54.0); m_video = HTMLVideoElement::create(m_dummyPageHolder->document());
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp index cb58274..571451c 100644 --- a/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp +++ b/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp
@@ -79,9 +79,9 @@ MOCK_CONST_METHOD0(screenInfo, WebScreenInfo()); }; -class StubFrameLoaderClient : public EmptyFrameLoaderClient { +class StubLocalFrameClient : public EmptyLocalFrameClient { public: - static StubFrameLoaderClient* create() { return new StubFrameLoaderClient; } + static StubLocalFrameClient* create() { return new StubLocalFrameClient; } std::unique_ptr<WebMediaPlayer> createWebMediaPlayer( HTMLMediaElement&, @@ -144,7 +144,7 @@ clients.chromeClient = m_chromeClient.get(); m_pageHolder = DummyPageHolder::create(IntSize(800, 600), &clients, - StubFrameLoaderClient::create()); + StubLocalFrameClient::create()); document().write("<body><video></body>"); m_video = toHTMLVideoElement(*document().querySelector("video"));
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlsTest.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControlsTest.cpp index d6fc73e..271c810 100644 --- a/third_party/WebKit/Source/core/html/shadow/MediaControlsTest.cpp +++ b/third_party/WebKit/Source/core/html/shadow/MediaControlsTest.cpp
@@ -82,9 +82,9 @@ WebRemotePlaybackAvailability::Unknown; }; -class StubFrameLoaderClient : public EmptyFrameLoaderClient { +class StubLocalFrameClient : public EmptyLocalFrameClient { public: - static StubFrameLoaderClient* create() { return new StubFrameLoaderClient; } + static StubLocalFrameClient* create() { return new StubLocalFrameClient; } std::unique_ptr<WebMediaPlayer> createWebMediaPlayer( HTMLMediaElement&, @@ -143,7 +143,7 @@ protected: virtual void SetUp() { m_pageHolder = DummyPageHolder::create(IntSize(800, 600), nullptr, - StubFrameLoaderClient::create()); + StubLocalFrameClient::create()); Document& document = this->document(); document.write("<video>");
diff --git a/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp b/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp index 10cd9e9..0467cbb 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp
@@ -15,7 +15,7 @@ class LayoutObjectTest : public RenderingTest { public: - LayoutObjectTest() : RenderingTest(EmptyFrameLoaderClient::create()) {} + LayoutObjectTest() : RenderingTest(EmptyLocalFrameClient::create()) {} }; TEST_F(LayoutObjectTest, LayoutDecoratedNameCalledWithPositionedObject) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutTestHelper.cpp b/third_party/WebKit/Source/core/layout/LayoutTestHelper.cpp index 3ac6e59a..edd0450 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTestHelper.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutTestHelper.cpp
@@ -16,14 +16,14 @@ namespace blink { -LocalFrame* SingleChildFrameLoaderClient::createFrame( +LocalFrame* SingleChildLocalFrameClient::createFrame( const FrameLoadRequest&, const AtomicString& name, HTMLFrameOwnerElement* ownerElement) { DCHECK(!m_child) << "This test helper only supports one child frame."; LocalFrame* parentFrame = ownerElement->document().frame(); - auto* childClient = FrameLoaderClientWithParent::create(parentFrame); + auto* childClient = LocalFrameClientWithParent::create(parentFrame); m_child = LocalFrame::create(childClient, parentFrame->host(), ownerElement); m_child->createView(IntSize(500, 500), Color(), true /* transparent */); m_child->init(); @@ -31,8 +31,8 @@ return m_child.get(); } -void FrameLoaderClientWithParent::detached(FrameDetachType) { - static_cast<SingleChildFrameLoaderClient*>(parent()->client()) +void LocalFrameClientWithParent::detached(FrameDetachType) { + static_cast<SingleChildLocalFrameClient*>(parent()->client()) ->didDetachChild(); }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTestHelper.h b/third_party/WebKit/Source/core/layout/LayoutTestHelper.h index ffe6a7b8..24064c58 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTestHelper.h +++ b/third_party/WebKit/Source/core/layout/LayoutTestHelper.h
@@ -5,9 +5,13 @@ #ifndef LayoutTestHelper_h #define LayoutTestHelper_h +#include <gtest/gtest.h> +#include <memory> + #include "core/dom/Document.h" #include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/Settings.h" #include "core/html/HTMLElement.h" #include "core/layout/api/LayoutAPIShim.h" @@ -15,20 +19,18 @@ #include "core/loader/EmptyClients.h" #include "core/testing/DummyPageHolder.h" #include "wtf/Allocator.h" -#include <gtest/gtest.h> -#include <memory> namespace blink { -class SingleChildFrameLoaderClient final : public EmptyFrameLoaderClient { +class SingleChildLocalFrameClient final : public EmptyLocalFrameClient { public: - static SingleChildFrameLoaderClient* create() { - return new SingleChildFrameLoaderClient(); + static SingleChildLocalFrameClient* create() { + return new SingleChildLocalFrameClient(); } DEFINE_INLINE_VIRTUAL_TRACE() { visitor->trace(m_child); - EmptyFrameLoaderClient::trace(visitor); + EmptyLocalFrameClient::trace(visitor); } // FrameLoaderClient overrides: @@ -40,20 +42,20 @@ void didDetachChild() { m_child = nullptr; } private: - explicit SingleChildFrameLoaderClient() {} + explicit SingleChildLocalFrameClient() {} Member<LocalFrame> m_child; }; -class FrameLoaderClientWithParent final : public EmptyFrameLoaderClient { +class LocalFrameClientWithParent final : public EmptyLocalFrameClient { public: - static FrameLoaderClientWithParent* create(LocalFrame* parent) { - return new FrameLoaderClientWithParent(parent); + static LocalFrameClientWithParent* create(LocalFrame* parent) { + return new LocalFrameClientWithParent(parent); } DEFINE_INLINE_VIRTUAL_TRACE() { visitor->trace(m_parent); - EmptyFrameLoaderClient::trace(visitor); + EmptyLocalFrameClient::trace(visitor); } // FrameClient overrides: @@ -61,7 +63,7 @@ LocalFrame* parent() const override { return m_parent.get(); } private: - explicit FrameLoaderClientWithParent(LocalFrame* parent) : m_parent(parent) {} + explicit LocalFrameClientWithParent(LocalFrame* parent) : m_parent(parent) {} Member<LocalFrame> m_parent; }; @@ -75,7 +77,7 @@ } virtual ChromeClient& chromeClient() const; - RenderingTest(FrameLoaderClient* = nullptr); + RenderingTest(LocalFrameClient* = nullptr); protected: void SetUp() override;
diff --git a/third_party/WebKit/Source/core/layout/MapCoordinatesTest.cpp b/third_party/WebKit/Source/core/layout/MapCoordinatesTest.cpp index 3e92f19..623e8ea 100644 --- a/third_party/WebKit/Source/core/layout/MapCoordinatesTest.cpp +++ b/third_party/WebKit/Source/core/layout/MapCoordinatesTest.cpp
@@ -19,7 +19,7 @@ public: MapCoordinatesTest() : ScopedRootLayerScrollingForTest(GetParam()), - RenderingTest(SingleChildFrameLoaderClient::create()) {} + RenderingTest(SingleChildLocalFrameClient::create()) {} FloatPoint mapLocalToAncestor(const LayoutObject*, const LayoutBoxModelObject* ancestor, FloatPoint,
diff --git a/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp b/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp index 1f0486a..af9aa37 100644 --- a/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp +++ b/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp
@@ -13,7 +13,7 @@ class VisualRectMappingTest : public RenderingTest { public: VisualRectMappingTest() - : RenderingTest(SingleChildFrameLoaderClient::create()) {} + : RenderingTest(SingleChildLocalFrameClient::create()) {} protected: LayoutView& layoutView() const { return *document().layoutView(); }
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp index 7e308c20..de3edba 100644 --- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp
@@ -24,7 +24,7 @@ public: CompositedLayerMappingTest() : ScopedRootLayerScrollingForTest(GetParam()), - RenderingTest(SingleChildFrameLoaderClient::create()) {} + RenderingTest(SingleChildLocalFrameClient::create()) {} protected: IntRect recomputeInterestRect(const GraphicsLayer* graphicsLayer) {
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositingReasonFinderTest.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositingReasonFinderTest.cpp index 932784d7..ce5ddb7 100644 --- a/third_party/WebKit/Source/core/layout/compositing/CompositingReasonFinderTest.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/CompositingReasonFinderTest.cpp
@@ -17,7 +17,7 @@ class CompositingReasonFinderTest : public RenderingTest { public: CompositingReasonFinderTest() - : RenderingTest(EmptyFrameLoaderClient::create()) {} + : RenderingTest(EmptyLocalFrameClient::create()) {} private: void SetUp() override {
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_units.cc b/third_party/WebKit/Source/core/layout/ng/ng_units.cc index c3c21c28..b77f9b3 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_units.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_units.cc
@@ -59,6 +59,16 @@ size.block_size.toString().ascii().data()); } +NGPixelSnappedPhysicalRect NGPhysicalRect::SnapToDevicePixels() const { + NGPixelSnappedPhysicalRect snappedRect; + snappedRect.left = roundToInt(location.left); + snappedRect.top = roundToInt(location.top); + snappedRect.width = snapSizeToPixel(size.width, location.left); + snappedRect.height = snapSizeToPixel(size.height, location.top); + + return snappedRect; +} + NGPhysicalOffset NGLogicalOffset::ConvertToPhysical( NGWritingMode mode, TextDirection direction,
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_units.h b/third_party/WebKit/Source/core/layout/ng/ng_units.h index c3ed32c3..53b898a 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_units.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_units.h
@@ -17,6 +17,7 @@ struct NGPhysicalOffset; struct NGPhysicalSize; struct NGBoxStrut; +struct NGPixelSnappedPhysicalRect; #define NGSizeIndefinite LayoutUnit(-1) @@ -150,12 +151,22 @@ // NGPhysicalLocation is the position of a rect (typically a fragment) relative // to the root document. struct NGPhysicalLocation { + NGPhysicalLocation() {} + NGPhysicalLocation(LayoutUnit left, LayoutUnit top) : left(left), top(top) {} LayoutUnit left; LayoutUnit top; }; -struct NGPhysicalRect { - NGPhysicalOffset offset; +struct CORE_EXPORT NGPhysicalRect { + NGPhysicalRect(); + NGPhysicalRect(const NGPhysicalLocation& location, const NGPhysicalSize& size) + : location(location), size(size) {} + + NGPhysicalLocation Location() const { return location; } + NGPhysicalSize Size() const { return size; } + NGPixelSnappedPhysicalRect SnapToDevicePixels() const; + + NGPhysicalLocation location; NGPhysicalSize size; };
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_units_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_units_test.cc index 17c3fa70..bf6684ac 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_units_test.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_units_test.cc
@@ -116,6 +116,40 @@ EXPECT_EQ(LayoutUnit(200), sizes.ShrinkToFit(LayoutUnit(100))); } +TEST(NGUnitsTest, SnapToDevicePixels) { + NGPhysicalRect rect(NGPhysicalLocation(LayoutUnit(4.5), LayoutUnit(9.5)), + NGPhysicalSize(LayoutUnit(10.5), LayoutUnit(11.5))); + NGPixelSnappedPhysicalRect snappedRect = rect.SnapToDevicePixels(); + EXPECT_EQ(5, snappedRect.left); + EXPECT_EQ(10, snappedRect.top); + EXPECT_EQ(10, snappedRect.width); + EXPECT_EQ(11, snappedRect.height); + + rect = NGPhysicalRect(NGPhysicalLocation(LayoutUnit(4), LayoutUnit(9)), + NGPhysicalSize(LayoutUnit(10.5), LayoutUnit(11.5))); + snappedRect = rect.SnapToDevicePixels(); + EXPECT_EQ(4, snappedRect.left); + EXPECT_EQ(9, snappedRect.top); + EXPECT_EQ(11, snappedRect.width); + EXPECT_EQ(12, snappedRect.height); + + rect = NGPhysicalRect(NGPhysicalLocation(LayoutUnit(1.3), LayoutUnit(1.6)), + NGPhysicalSize(LayoutUnit(5.8), LayoutUnit(4.3))); + snappedRect = rect.SnapToDevicePixels(); + EXPECT_EQ(1, snappedRect.left); + EXPECT_EQ(2, snappedRect.top); + EXPECT_EQ(6, snappedRect.width); + EXPECT_EQ(4, snappedRect.height); + + rect = NGPhysicalRect(NGPhysicalLocation(LayoutUnit(1.6), LayoutUnit(1.3)), + NGPhysicalSize(LayoutUnit(5.8), LayoutUnit(4.3))); + snappedRect = rect.SnapToDevicePixels(); + EXPECT_EQ(2, snappedRect.left); + EXPECT_EQ(1, snappedRect.top); + EXPECT_EQ(5, snappedRect.width); + EXPECT_EQ(5, snappedRect.height); +} + } // namespace } // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/BUILD.gn b/third_party/WebKit/Source/core/loader/BUILD.gn index e58fc416..c7d1aa8 100644 --- a/third_party/WebKit/Source/core/loader/BUILD.gn +++ b/third_party/WebKit/Source/core/loader/BUILD.gn
@@ -56,6 +56,7 @@ "appcache/ApplicationCacheHost.cpp", "appcache/ApplicationCacheHost.h", "modulescript/ModuleScriptFetchRequest.h", + "modulescript/ModuleScriptLoaderClient.h", "private/CrossOriginPreflightResultCache.cpp", "private/CrossOriginPreflightResultCache.h", "private/FrameClientHintsPreferencesContext.cpp",
diff --git a/third_party/WebKit/Source/core/loader/EmptyClients.cpp b/third_party/WebKit/Source/core/loader/EmptyClients.cpp index b3bd635..308465ad 100644 --- a/third_party/WebKit/Source/core/loader/EmptyClients.cpp +++ b/third_party/WebKit/Source/core/loader/EmptyClients.cpp
@@ -127,7 +127,7 @@ return WTF::makeUnique<EmptyFrameScheduler>(); } -NavigationPolicy EmptyFrameLoaderClient::decidePolicyForNavigation( +NavigationPolicy EmptyLocalFrameClient::decidePolicyForNavigation( const ResourceRequest&, DocumentLoader*, NavigationType, @@ -138,11 +138,11 @@ return NavigationPolicyIgnore; } -void EmptyFrameLoaderClient::dispatchWillSendSubmitEvent(HTMLFormElement*) {} +void EmptyLocalFrameClient::dispatchWillSendSubmitEvent(HTMLFormElement*) {} -void EmptyFrameLoaderClient::dispatchWillSubmitForm(HTMLFormElement*) {} +void EmptyLocalFrameClient::dispatchWillSubmitForm(HTMLFormElement*) {} -DocumentLoader* EmptyFrameLoaderClient::createDocumentLoader( +DocumentLoader* EmptyLocalFrameClient::createDocumentLoader( LocalFrame* frame, const ResourceRequest& request, const SubstituteData& substituteData, @@ -153,30 +153,30 @@ clientRedirectPolicy); } -LocalFrame* EmptyFrameLoaderClient::createFrame(const FrameLoadRequest&, - const AtomicString&, - HTMLFrameOwnerElement*) { +LocalFrame* EmptyLocalFrameClient::createFrame(const FrameLoadRequest&, + const AtomicString&, + HTMLFrameOwnerElement*) { return nullptr; } -Widget* EmptyFrameLoaderClient::createPlugin(HTMLPlugInElement*, - const KURL&, - const Vector<String>&, - const Vector<String>&, - const String&, - bool, - DetachedPluginPolicy) { +Widget* EmptyLocalFrameClient::createPlugin(HTMLPlugInElement*, + const KURL&, + const Vector<String>&, + const Vector<String>&, + const String&, + bool, + DetachedPluginPolicy) { return nullptr; } -std::unique_ptr<WebMediaPlayer> EmptyFrameLoaderClient::createWebMediaPlayer( +std::unique_ptr<WebMediaPlayer> EmptyLocalFrameClient::createWebMediaPlayer( HTMLMediaElement&, const WebMediaPlayerSource&, WebMediaPlayerClient*) { return nullptr; } -WebRemotePlaybackClient* EmptyFrameLoaderClient::createWebRemotePlaybackClient( +WebRemotePlaybackClient* EmptyLocalFrameClient::createWebRemotePlaybackClient( HTMLMediaElement&) { return nullptr; } @@ -186,12 +186,12 @@ void EmptyTextCheckerClient::cancelAllPendingRequests() {} std::unique_ptr<WebServiceWorkerProvider> -EmptyFrameLoaderClient::createServiceWorkerProvider() { +EmptyLocalFrameClient::createServiceWorkerProvider() { return nullptr; } std::unique_ptr<WebApplicationCacheHost> -EmptyFrameLoaderClient::createApplicationCacheHost( +EmptyLocalFrameClient::createApplicationCacheHost( WebApplicationCacheHostClient*) { return nullptr; }
diff --git a/third_party/WebKit/Source/core/loader/EmptyClients.h b/third_party/WebKit/Source/core/loader/EmptyClients.h index 24f7fcb..71531ea 100644 --- a/third_party/WebKit/Source/core/loader/EmptyClients.h +++ b/third_party/WebKit/Source/core/loader/EmptyClients.h
@@ -29,9 +29,11 @@ #ifndef EmptyClients_h #define EmptyClients_h +#include <memory> + #include "core/CoreExport.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/RemoteFrameClient.h" -#include "core/loader/FrameLoaderClient.h" #include "core/page/ChromeClient.h" #include "core/page/ContextMenuClient.h" #include "core/page/EditorClient.h" @@ -47,9 +49,8 @@ #include "platform/text/TextCheckerClient.h" #include "public/platform/WebFocusType.h" #include "public/platform/WebScreenInfo.h" +#include "v8/include/v8.h" #include "wtf/Forward.h" -#include <memory> -#include <v8.h> /* This file holds empty Client stubs for use by WebCore. @@ -235,12 +236,12 @@ BlameContext*) override; }; -class CORE_EXPORT EmptyFrameLoaderClient : public FrameLoaderClient { - WTF_MAKE_NONCOPYABLE(EmptyFrameLoaderClient); +class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient { + WTF_MAKE_NONCOPYABLE(EmptyLocalFrameClient); public: - static EmptyFrameLoaderClient* create() { return new EmptyFrameLoaderClient; } - ~EmptyFrameLoaderClient() override {} + static EmptyLocalFrameClient* create() { return new EmptyLocalFrameClient; } + ~EmptyLocalFrameClient() override {} bool hasWebView() const override { return true; } // mainly for assertions @@ -365,7 +366,7 @@ WebApplicationCacheHostClient*) override; protected: - EmptyFrameLoaderClient() {} + EmptyLocalFrameClient() {} }; class CORE_EXPORT EmptyTextCheckerClient : public TextCheckerClient {
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp index 3f78de4..31c5c3d4 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp +++ b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
@@ -56,28 +56,28 @@ namespace blink { -class StubFrameLoaderClientWithParent final : public EmptyFrameLoaderClient { +class StubLocalFrameClientWithParent final : public EmptyLocalFrameClient { public: - static StubFrameLoaderClientWithParent* create(Frame* parent) { - return new StubFrameLoaderClientWithParent(parent); + static StubLocalFrameClientWithParent* create(Frame* parent) { + return new StubLocalFrameClientWithParent(parent); } DEFINE_INLINE_VIRTUAL_TRACE() { visitor->trace(m_parent); - EmptyFrameLoaderClient::trace(visitor); + EmptyLocalFrameClient::trace(visitor); } Frame* parent() const override { return m_parent.get(); } private: - explicit StubFrameLoaderClientWithParent(Frame* parent) : m_parent(parent) {} + explicit StubLocalFrameClientWithParent(Frame* parent) : m_parent(parent) {} Member<Frame> m_parent; }; -class MockFrameLoaderClient : public EmptyFrameLoaderClient { +class MockLocalFrameClient : public EmptyLocalFrameClient { public: - MockFrameLoaderClient() : EmptyFrameLoaderClient() {} + MockLocalFrameClient() : EmptyLocalFrameClient() {} MOCK_METHOD1(didDisplayContentWithCertificateErrors, void(const KURL&)); MOCK_METHOD2(dispatchDidLoadResourceFromMemoryCache, void(const ResourceRequest&, const ResourceResponse&)); @@ -118,7 +118,7 @@ } FrameFetchContext* createChildFrame() { - childClient = StubFrameLoaderClientWithParent::create(document->frame()); + childClient = StubLocalFrameClientWithParent::create(document->frame()); childFrame = LocalFrame::create(childClient.get(), document->frame()->host(), owner.get()); childFrame->setView(FrameView::create(*childFrame, IntSize(500, 500))); @@ -138,7 +138,7 @@ Persistent<Document> document; Persistent<FrameFetchContext> fetchContext; - Persistent<StubFrameLoaderClientWithParent> childClient; + Persistent<StubLocalFrameClientWithParent> childClient; Persistent<LocalFrame> childFrame; Persistent<Document> childDocument; Persistent<DummyFrameOwner> owner; @@ -194,7 +194,7 @@ void SetUp() override { url = KURL(KURL(), "https://example.test/foo"); mainResourceUrl = KURL(KURL(), "https://www.example.test"); - client = new testing::NiceMock<MockFrameLoaderClient>(); + client = new testing::NiceMock<MockLocalFrameClient>(); dummyPageHolder = DummyPageHolder::create(IntSize(500, 500), nullptr, client); dummyPageHolder->page().setDeviceScaleFactor(1.0); @@ -209,7 +209,7 @@ KURL url; KURL mainResourceUrl; - Persistent<testing::NiceMock<MockFrameLoaderClient>> client; + Persistent<testing::NiceMock<MockLocalFrameClient>> client; }; class FrameFetchContextModifyRequestTest : public FrameFetchContextTest {
diff --git a/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp b/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp index 859a79c..333530a 100644 --- a/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp +++ b/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp
@@ -103,9 +103,9 @@ namespace { -class MockFrameLoaderClient : public EmptyFrameLoaderClient { +class MockLocalFrameClient : public EmptyLocalFrameClient { public: - MockFrameLoaderClient() : EmptyFrameLoaderClient() {} + MockLocalFrameClient() : EmptyLocalFrameClient() {} MOCK_METHOD1(didDisplayContentWithCertificateErrors, void(const KURL&)); MOCK_METHOD1(didRunContentWithCertificateErrors, void(const KURL&)); }; @@ -113,7 +113,7 @@ } // namespace TEST(MixedContentCheckerTest, HandleCertificateError) { - MockFrameLoaderClient* client = new MockFrameLoaderClient; + MockLocalFrameClient* client = new MockLocalFrameClient; std::unique_ptr<DummyPageHolder> dummyPageHolder = DummyPageHolder::create(IntSize(1, 1), nullptr, client);
diff --git a/third_party/WebKit/Source/core/loader/PingLoaderTest.cpp b/third_party/WebKit/Source/core/loader/PingLoaderTest.cpp index c5128a4..106ade6 100644 --- a/third_party/WebKit/Source/core/loader/PingLoaderTest.cpp +++ b/third_party/WebKit/Source/core/loader/PingLoaderTest.cpp
@@ -20,7 +20,7 @@ namespace { -class PingFrameLoaderClient : public EmptyFrameLoaderClient { +class PingFrameLoaderClient : public EmptyLocalFrameClient { public: void dispatchWillSendRequest(ResourceRequest& request) override { if (request.httpContentType() == "text/ping")
diff --git a/third_party/WebKit/Source/core/loader/ProgressTrackerTest.cpp b/third_party/WebKit/Source/core/loader/ProgressTrackerTest.cpp index 0672f2d..662d28e 100644 --- a/third_party/WebKit/Source/core/loader/ProgressTrackerTest.cpp +++ b/third_party/WebKit/Source/core/loader/ProgressTrackerTest.cpp
@@ -12,7 +12,7 @@ namespace blink { -class ProgressClient : public EmptyFrameLoaderClient { +class ProgressClient : public EmptyLocalFrameClient { public: ProgressClient() : m_lastProgress(0.0) {}
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderClient.h b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderClient.h new file mode 100644 index 0000000..b992048c --- /dev/null +++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderClient.h
@@ -0,0 +1,31 @@ +// Copyright 2017 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 ModuleScriptLoaderClient_h +#define ModuleScriptLoaderClient_h + +#include "platform/heap/Handle.h" + +namespace blink { + +class ModuleScript; + +// A ModuleScriptLoaderClient is notified when a single module script load is +// complete. +// Note: Its corresponding module map entry is typically not yet created at the +// time of callback. +class ModuleScriptLoaderClient : public GarbageCollectedMixin { + public: + virtual ~ModuleScriptLoaderClient(){}; + + private: + friend class ModuleScriptLoader; + friend class ModuleMapTestModulator; + + virtual void notifyNewSingleModuleFinished(ModuleScript*) = 0; +}; + +} // namespace blink + +#endif
diff --git a/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp b/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp index 9e77ec4..d3be9db 100644 --- a/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp +++ b/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp
@@ -83,11 +83,8 @@ dump->guid(), String(WTF::Partitions::kAllocatedObjectPoolName)); } -NOINLINE const String& ScriptResource::script() { - // For investigating https://crbug.com/692856. - CHECK(isLoaded() || (isLoading() && hasRevalidated())); - CHECK(isLoaded() || (isLoading() && isCacheValidator())); - CHECK(isLoaded()); +const String& ScriptResource::script() { + DCHECK(isLoaded()); if (m_script.isNull() && data()) { String script = decodedText();
diff --git a/third_party/WebKit/Source/core/page/FrameTree.cpp b/third_party/WebKit/Source/core/page/FrameTree.cpp index 5f69da38..36ae58dc 100644 --- a/third_party/WebKit/Source/core/page/FrameTree.cpp +++ b/third_party/WebKit/Source/core/page/FrameTree.cpp
@@ -116,7 +116,7 @@ Frame* FrameTree::top() const { // FIXME: top() should never return null, so here are some hacks to deal - // with EmptyFrameLoaderClient and cases where the frame is detached + // with EmptyLocalFrameClient and cases where the frame is detached // already... if (!m_thisFrame->client()) return m_thisFrame;
diff --git a/third_party/WebKit/Source/core/page/PrintContextTest.cpp b/third_party/WebKit/Source/core/page/PrintContextTest.cpp index 17cad95..26bb950 100644 --- a/third_party/WebKit/Source/core/page/PrintContextTest.cpp +++ b/third_party/WebKit/Source/core/page/PrintContextTest.cpp
@@ -144,7 +144,7 @@ class PrintContextFrameTest : public PrintContextTest { public: PrintContextFrameTest() - : PrintContextTest(SingleChildFrameLoaderClient::create()) {} + : PrintContextTest(SingleChildLocalFrameClient::create()) {} }; #define EXPECT_SKRECT_EQ(expectedX, expectedY, expectedWidth, expectedHeight, \
diff --git a/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp b/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp index 970035cc..9f398b4b3 100644 --- a/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp +++ b/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp
@@ -19,7 +19,7 @@ public: BoxPaintInvalidatorTest() : ScopedRootLayerScrollingForTest(GetParam()), - RenderingTest(SingleChildFrameLoaderClient::create()) {} + RenderingTest(SingleChildLocalFrameClient::create()) {} protected: const RasterInvalidationTracking* getRasterInvalidationTracking() const {
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp index 4e63d42..ca5eb027 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp
@@ -20,7 +20,7 @@ public: PaintLayerClipperTest() : ScopedSlimmingPaintV2ForTest(GetParam()), - RenderingTest(EmptyFrameLoaderClient::create()) {} + RenderingTest(EmptyLocalFrameClient::create()) {} void SetUp() override { LayoutTestSupport::setMockThemeEnabledForTest(true);
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp index d0cb1b8..216494b 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp
@@ -33,7 +33,7 @@ class PaintLayerScrollableAreaTest : public RenderingTest { public: PaintLayerScrollableAreaTest() - : RenderingTest(EmptyFrameLoaderClient::create()), + : RenderingTest(EmptyLocalFrameClient::create()), m_chromeClient(new MockChromeClient) {} ~PaintLayerScrollableAreaTest() {
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp index d952793..91bf169 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
@@ -23,7 +23,7 @@ PaintLayerTest() : ScopedSlimmingPaintV2ForTest(GetParam().first), ScopedRootLayerScrollingForTest(GetParam().second), - RenderingTest(SingleChildFrameLoaderClient::create()) {} + RenderingTest(SingleChildLocalFrameClient::create()) {} }; SlimmingPaintAndRootLayerScrolling foo[] = {
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.h b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.h index 6c023f6..ec76253b 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.h +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.h
@@ -24,7 +24,7 @@ PaintPropertyTreeBuilderTest() : ScopedSlimmingPaintV2ForTest(true), ScopedRootLayerScrollingForTest(GetParam()), - RenderingTest(SingleChildFrameLoaderClient::create()) {} + RenderingTest(SingleChildLocalFrameClient::create()) {} protected: void loadTestData(const char* fileName);
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreePrinterTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreePrinterTest.cpp index 4cf9a15..885d1f1 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreePrinterTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreePrinterTest.cpp
@@ -24,7 +24,7 @@ PaintPropertyTreePrinterTest() : ScopedSlimmingPaintV2ForTest(true), ScopedRootLayerScrollingForTest(GetParam()), - RenderingTest(SingleChildFrameLoaderClient::create()) {} + RenderingTest(SingleChildLocalFrameClient::create()) {} private: void SetUp() override {
diff --git a/third_party/WebKit/Source/core/paint/PrePaintTreeWalkTest.cpp b/third_party/WebKit/Source/core/paint/PrePaintTreeWalkTest.cpp index dcb708f..7ddfcb4 100644 --- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalkTest.cpp +++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalkTest.cpp
@@ -30,7 +30,7 @@ PrePaintTreeWalkTest() : ScopedSlimmingPaintV2ForTest(true), ScopedRootLayerScrollingForTest(GetParam()), - RenderingTest(EmptyFrameLoaderClient::create()) {} + RenderingTest(EmptyLocalFrameClient::create()) {} const TransformPaintPropertyNode* framePreTranslation() { FrameView* frameView = document().view();
diff --git a/third_party/WebKit/Source/core/paint/VideoPainterTest.cpp b/third_party/WebKit/Source/core/paint/VideoPainterTest.cpp index af01aa16d..1e649de57 100644 --- a/third_party/WebKit/Source/core/paint/VideoPainterTest.cpp +++ b/third_party/WebKit/Source/core/paint/VideoPainterTest.cpp
@@ -79,7 +79,7 @@ ReadyState m_readyState = ReadyStateHaveNothing; }; -class StubFrameLoaderClient : public EmptyFrameLoaderClient { +class StubLocalFrameClient : public EmptyLocalFrameClient { public: // FrameLoaderClient std::unique_ptr<WebMediaPlayer> createWebMediaPlayer( @@ -98,12 +98,12 @@ protected: void SetUp() override { m_chromeClient = new StubChromeClientForSPv2(); - m_frameLoaderClient = new StubFrameLoaderClient; + m_localFrameClient = new StubLocalFrameClient; Page::PageClients clients; fillWithEmptyClients(clients); clients.chromeClient = m_chromeClient.get(); m_pageHolder = DummyPageHolder::create( - IntSize(800, 600), &clients, m_frameLoaderClient.get(), + IntSize(800, 600), &clients, m_localFrameClient.get(), [](Settings& settings) { settings.setAcceleratedCompositingEnabled(true); }); @@ -119,7 +119,7 @@ private: Persistent<StubChromeClientForSPv2> m_chromeClient; - Persistent<StubFrameLoaderClient> m_frameLoaderClient; + Persistent<StubLocalFrameClient> m_localFrameClient; std::unique_ptr<DummyPageHolder> m_pageHolder; };
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp index f767fa7..85f1284 100644 --- a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp +++ b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
@@ -33,6 +33,7 @@ #include "core/dom/shadow/FlatTreeTraversal.h" #include "core/frame/FrameView.h" #include "core/frame/LocalFrame.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/Settings.h" #include "core/layout/LayoutView.h" #include "core/layout/svg/LayoutSVGRoot.h" @@ -579,8 +580,8 @@ // types. EventDispatchForbiddenScope::AllowUserAgentEvents allowUserAgentEvents; - DEFINE_STATIC_LOCAL(FrameLoaderClient, dummyFrameLoaderClient, - (EmptyFrameLoaderClient::create())); + DEFINE_STATIC_LOCAL(LocalFrameClient, dummyLocalFrameClient, + (EmptyLocalFrameClient::create())); if (m_page) { toLocalFrame(m_page->mainFrame()) @@ -634,8 +635,7 @@ LocalFrame* frame = nullptr; { TRACE_EVENT0("blink", "SVGImage::dataChanged::createFrame"); - frame = - LocalFrame::create(&dummyFrameLoaderClient, &page->frameHost(), 0); + frame = LocalFrame::create(&dummyLocalFrameClient, &page->frameHost(), 0); frame->setView(FrameView::create(*frame)); frame->init(); }
diff --git a/third_party/WebKit/Source/core/testing/DummyModulator.cpp b/third_party/WebKit/Source/core/testing/DummyModulator.cpp new file mode 100644 index 0000000..0ca4b1b --- /dev/null +++ b/third_party/WebKit/Source/core/testing/DummyModulator.cpp
@@ -0,0 +1,31 @@ +// Copyright 2017 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 "core/testing/DummyModulator.h" + +namespace blink { + +DummyModulator::DummyModulator() {} + +DummyModulator::~DummyModulator() {} + +DEFINE_TRACE(DummyModulator) {} + +ScriptModuleResolver* DummyModulator::scriptModuleResolver() { + NOTREACHED(); + return nullptr; +} + +WebTaskRunner* DummyModulator::taskRunner() { + NOTREACHED(); + return nullptr; +}; + +void DummyModulator::fetchNewSingleModule(const ModuleScriptFetchRequest&, + ModuleGraphLevel, + ModuleScriptLoaderClient*) { + NOTREACHED(); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/testing/DummyModulator.h b/third_party/WebKit/Source/core/testing/DummyModulator.h new file mode 100644 index 0000000..9d72dc1e --- /dev/null +++ b/third_party/WebKit/Source/core/testing/DummyModulator.h
@@ -0,0 +1,43 @@ +// Copyright 2017 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 DummyModulator_h +#define DummyModulator_h + +#include "core/dom/Modulator.h" +#include "platform/heap/Handle.h" + +namespace blink { + +class ModuleScriptLoaderClient; +class ScriptModuleResolver; +class WebTaskRunner; +class ModuleScriptFetchRequest; + +// DummyModulator provides empty Modulator interface implementation w/ +// NOTREACHED(). +// +// DummyModulator is useful for unit-testing. +// Not all module implementation components require full-blown Modulator +// implementation. Unit tests can implement a subset of Modulator interface +// which is exercised from unit-under-test. +class DummyModulator : public GarbageCollectedFinalized<DummyModulator>, + public Modulator { + USING_GARBAGE_COLLECTED_MIXIN(DummyModulator); + + public: + DummyModulator(); + virtual ~DummyModulator(); + DECLARE_TRACE(); + + ScriptModuleResolver* scriptModuleResolver() override; + WebTaskRunner* taskRunner() override; + void fetchNewSingleModule(const ModuleScriptFetchRequest&, + ModuleGraphLevel, + ModuleScriptLoaderClient*) override; +}; + +} // namespace blink + +#endif // DummyModulator_h
diff --git a/third_party/WebKit/Source/core/testing/DummyPageHolder.cpp b/third_party/WebKit/Source/core/testing/DummyPageHolder.cpp index 0b06c34e..e0d5903 100644 --- a/third_party/WebKit/Source/core/testing/DummyPageHolder.cpp +++ b/third_party/WebKit/Source/core/testing/DummyPageHolder.cpp
@@ -78,7 +78,7 @@ m_frameLoaderClient = frameLoaderClient; if (!m_frameLoaderClient) - m_frameLoaderClient = EmptyFrameLoaderClient::create(); + m_frameLoaderClient = EmptyLocalFrameClient::create(); m_frame = LocalFrame::create(m_frameLoaderClient.get(), &m_page->frameHost(), nullptr, interfaceProvider);
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp index 8449f7f..981251a 100644 --- a/third_party/WebKit/Source/core/testing/Internals.cpp +++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -67,7 +67,6 @@ #include "core/editing/markers/DocumentMarker.h" #include "core/editing/markers/DocumentMarkerController.h" #include "core/editing/serializers/Serialization.h" -#include "core/editing/spellcheck/IdleSpellCheckCallback.h" #include "core/editing/spellcheck/SpellCheckRequester.h" #include "core/editing/spellcheck/SpellChecker.h" #include "core/frame/EventHandlerRegistry.h" @@ -210,9 +209,7 @@ static SpellCheckRequester* spellCheckRequester(Document* document) { if (!document || !document->frame()) return 0; - if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled()) - return &document->frame()->spellChecker().spellCheckRequester(); - return &document->frame()->idleSpellCheckCallback().spellCheckRequester(); + return &document->frame()->spellChecker().spellCheckRequester(); } static ScrollableArea* scrollableAreaForNode(Node* node) {
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContextTest.cpp b/third_party/WebKit/Source/modules/webaudio/BaseAudioContextTest.cpp index 0dba8a3..c143063 100644 --- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContextTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContextTest.cpp
@@ -27,7 +27,7 @@ const char* const kCrossOriginMetric = "WebAudio.Autoplay.CrossOrigin"; -class MockCrossOriginFrameLoaderClient final : public EmptyFrameLoaderClient { +class MockCrossOriginFrameLoaderClient final : public EmptyLocalFrameClient { public: static MockCrossOriginFrameLoaderClient* create(Frame* parent) { return new MockCrossOriginFrameLoaderClient(parent); @@ -35,7 +35,7 @@ DEFINE_INLINE_VIRTUAL_TRACE() { visitor->trace(m_parent); - EmptyFrameLoaderClient::trace(visitor); + EmptyLocalFrameClient::trace(visitor); } Frame* parent() const override { return m_parent.get(); }
diff --git a/third_party/WebKit/Source/platform/fonts/FontCache.cpp b/third_party/WebKit/Source/platform/fonts/FontCache.cpp index 9525ac4c..d5a4e3d 100644 --- a/third_party/WebKit/Source/platform/fonts/FontCache.cpp +++ b/third_party/WebKit/Source/platform/fonts/FontCache.cpp
@@ -441,18 +441,9 @@ gGeneration++; HeapVector<Member<FontCacheClient>> clients; - size_t numClients = fontCacheClients().size(); - clients.reserveInitialCapacity(numClients); - HeapHashSet<WeakMember<FontCacheClient>>::iterator end = - fontCacheClients().end(); - for (HeapHashSet<WeakMember<FontCacheClient>>::iterator it = - fontCacheClients().begin(); - it != end; ++it) - clients.push_back(*it); - - ASSERT(numClients == clients.size()); - for (size_t i = 0; i < numClients; ++i) - clients[i]->fontCacheInvalidated(); + copyToVector(fontCacheClients(), clients); + for (const auto& client : clients) + client->fontCacheInvalidated(); purge(ForcePurge); }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp index 46294ce..42e0614 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
@@ -568,7 +568,6 @@ DCHECK(!request.isNull()); CHECK(!m_isRevalidationStartForbidden); m_isRevalidating = true; - m_hasRevalidated = true; m_resourceRequest = request; m_status = ResourceStatus::NotStarted; }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.h b/third_party/WebKit/Source/platform/loader/fetch/Resource.h index 26e6b974..c17ba26 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/Resource.h +++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.h
@@ -266,9 +266,6 @@ bool hasCacheControlNoStoreHeader() const; bool mustReloadDueToVaryHeader(const ResourceRequest& newRequest) const; - // For investigating https://crbug.com/692856. - bool hasRevalidated() const { return m_hasRevalidated; } - bool isEligibleForIntegrityCheck(SecurityOrigin*) const; void setIntegrityMetadata(const IntegrityMetadataSet& metadata) { @@ -462,12 +459,6 @@ bool m_needsSynchronousCacheHit; bool m_linkPreload; bool m_isRevalidating; - - // For investigating https://crbug.com/692856. - // Indicates whether at least one revalidation is done for |this|. - // Used for assertions only. - bool m_hasRevalidated = false; - bool m_isAlive; bool m_isAddRemoveClientProhibited; bool m_isRevalidationStartForbidden = false;
diff --git a/third_party/WebKit/Source/web/InspectorOverlay.cpp b/third_party/WebKit/Source/web/InspectorOverlay.cpp index 721586a..b7d9e4c 100644 --- a/third_party/WebKit/Source/web/InspectorOverlay.cpp +++ b/third_party/WebKit/Source/web/InspectorOverlay.cpp
@@ -28,6 +28,8 @@ #include "web/InspectorOverlay.h" +#include <memory> + #include "bindings/core/v8/ScriptController.h" #include "bindings/core/v8/ScriptSourceCode.h" #include "bindings/core/v8/V8InspectorOverlayHost.h" @@ -36,6 +38,7 @@ #include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" #include "core/frame/LocalFrame.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/Settings.h" #include "core/frame/VisualViewport.h" #include "core/input/EventHandler.h" @@ -50,13 +53,12 @@ #include "platform/graphics/paint/CullRect.h" #include "public/platform/Platform.h" #include "public/platform/WebData.h" +#include "v8/include/v8.h" #include "web/ChromeClientImpl.h" #include "web/PageOverlay.h" #include "web/WebInputEventConversion.h" #include "web/WebLocalFrameImpl.h" #include "wtf/AutoReset.h" -#include <memory> -#include <v8.h> namespace blink { @@ -502,8 +504,8 @@ ScriptForbiddenScope::AllowUserAgentScript allowScript; - DEFINE_STATIC_LOCAL(FrameLoaderClient, dummyFrameLoaderClient, - (EmptyFrameLoaderClient::create())); + DEFINE_STATIC_LOCAL(LocalFrameClient, dummyLocalFrameClient, + (EmptyLocalFrameClient::create())); Page::PageClients pageClients; fillWithEmptyClients(pageClients); DCHECK(!m_overlayChromeClient); @@ -538,7 +540,7 @@ // through some non-composited paint function. overlaySettings.setAcceleratedCompositingEnabled(false); - LocalFrame* frame = LocalFrame::create(&dummyFrameLoaderClient, + LocalFrame* frame = LocalFrame::create(&dummyLocalFrameClient, &m_overlayPage->frameHost(), 0); frame->setView(FrameView::create(*frame)); frame->init();
diff --git a/third_party/WebKit/Source/web/WebLeakDetector.cpp b/third_party/WebKit/Source/web/WebLeakDetector.cpp index 9efed05..ada00b4 100644 --- a/third_party/WebKit/Source/web/WebLeakDetector.cpp +++ b/third_party/WebKit/Source/web/WebLeakDetector.cpp
@@ -31,7 +31,6 @@ #include "public/web/WebLeakDetector.h" #include "bindings/core/v8/V8GCController.h" -#include "core/editing/spellcheck/IdleSpellCheckCallback.h" #include "core/editing/spellcheck/SpellChecker.h" #include "core/workers/InProcessWorkerMessagingProxy.h" #include "core/workers/WorkerThread.h" @@ -102,10 +101,7 @@ // Stop the spellchecker to prevent this. if (frame->isWebLocalFrame()) { WebLocalFrameImpl* localFrame = toWebLocalFrameImpl(frame); - if (RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled()) - localFrame->frame()->idleSpellCheckCallback().prepareForLeakDetection(); - else - localFrame->frame()->spellChecker().prepareForLeakDetection(); + localFrame->frame()->spellChecker().prepareForLeakDetection(); } // FIXME: HTML5 Notification should be closed because notification affects the
diff --git a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp index 3da1db0c..148cd0e 100644 --- a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp +++ b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
@@ -35,6 +35,7 @@ #include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" #include "core/frame/LocalFrame.h" +#include "core/frame/LocalFrameClient.h" #include "core/frame/Settings.h" #include "core/frame/VisualViewport.h" #include "core/input/EventHandler.h" @@ -305,10 +306,10 @@ mainSettings.getScrollAnimatorEnabled()); provideContextFeaturesTo(*m_page, WTF::makeUnique<PagePopupFeaturesClient>()); - DEFINE_STATIC_LOCAL(FrameLoaderClient, emptyFrameLoaderClient, - (EmptyFrameLoaderClient::create())); + DEFINE_STATIC_LOCAL(LocalFrameClient, emptyLocalFrameClient, + (EmptyLocalFrameClient::create())); LocalFrame* frame = - LocalFrame::create(&emptyFrameLoaderClient, &m_page->frameHost(), 0); + LocalFrame::create(&emptyLocalFrameClient, &m_page->frameHost(), 0); frame->setPagePopupOwner(m_popupClient->ownerElement()); frame->setView(FrameView::create(*frame)); frame->init();
diff --git a/tools/grit/grit/format/resource_map.py b/tools/grit/grit/format/resource_map.py index e5fdd16..aca302b7 100755 --- a/tools/grit/grit/format/resource_map.py +++ b/tools/grit/grit/format/resource_map.py
@@ -56,7 +56,7 @@ #ifndef GRIT_RESOURCE_MAP_STRUCT_ #define GRIT_RESOURCE_MAP_STRUCT_ struct GritResourceMap { - const char* const name; + const char* name; int value; }; #endif // GRIT_RESOURCE_MAP_STRUCT_
diff --git a/tools/grit/grit/format/resource_map_unittest.py b/tools/grit/grit/format/resource_map_unittest.py index ecc997a..31d481e 100755 --- a/tools/grit/grit/format/resource_map_unittest.py +++ b/tools/grit/grit/format/resource_map_unittest.py
@@ -58,7 +58,7 @@ #ifndef GRIT_RESOURCE_MAP_STRUCT_ #define GRIT_RESOURCE_MAP_STRUCT_ struct GritResourceMap { - const char* const name; + const char* name; int value; }; #endif // GRIT_RESOURCE_MAP_STRUCT_ @@ -150,7 +150,7 @@ #ifndef GRIT_RESOURCE_MAP_STRUCT_ #define GRIT_RESOURCE_MAP_STRUCT_ struct GritResourceMap { - const char* const name; + const char* name; int value; }; #endif // GRIT_RESOURCE_MAP_STRUCT_ @@ -235,7 +235,7 @@ #ifndef GRIT_RESOURCE_MAP_STRUCT_ #define GRIT_RESOURCE_MAP_STRUCT_ struct GritResourceMap { - const char* const name; + const char* name; int value; }; #endif // GRIT_RESOURCE_MAP_STRUCT_ @@ -313,7 +313,7 @@ #ifndef GRIT_RESOURCE_MAP_STRUCT_ #define GRIT_RESOURCE_MAP_STRUCT_ struct GritResourceMap { - const char* const name; + const char* name; int value; }; #endif // GRIT_RESOURCE_MAP_STRUCT_
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 18e186e..102d9ce 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -4983,6 +4983,9 @@ </histogram> <histogram name="BlinkGC.TimeForThreadLocalWeakProcessing" units="ms"> + <obsolete> + As of 02/2017, the code for thread-local weak processing was removed. + </obsolete> <owner>haraken@chromium.org</owner> <summary>Duration of time taken to run thread-local weak processing.</summary> </histogram>