diff --git a/DEPS b/DEPS index cc8f18d..be4a6af2 100644 --- a/DEPS +++ b/DEPS
@@ -44,7 +44,7 @@ # 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': 'b30d0b12cfea2dd6235e37fb3be301da34098b4d', + 'v8_revision': '7fb6b9426d6970cde5c338a2bf2189800db0b775', # 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/base/task_scheduler/task_scheduler_impl.cc b/base/task_scheduler/task_scheduler_impl.cc index 7f56f48..b4fcc62 100644 --- a/base/task_scheduler/task_scheduler_impl.cc +++ b/base/task_scheduler/task_scheduler_impl.cc
@@ -6,7 +6,6 @@ #include <utility> -#include "base/memory/ptr_util.h" #include "base/task_scheduler/delayed_task_manager.h" #include "base/task_scheduler/environment_config.h" #include "base/task_scheduler/scheduler_worker_pool_params.h" @@ -18,10 +17,13 @@ namespace base { namespace internal { -TaskSchedulerImpl::TaskSchedulerImpl(StringPiece name) +TaskSchedulerImpl::TaskSchedulerImpl( + StringPiece name, + std::unique_ptr<TaskTrackerImpl> task_tracker) : name_(name), service_thread_("TaskSchedulerServiceThread"), - single_thread_task_runner_manager_(&task_tracker_, + task_tracker_(std::move(task_tracker)), + single_thread_task_runner_manager_(task_tracker_.get(), &delayed_task_manager_) { static_assert(arraysize(worker_pools_) == ENVIRONMENT_COUNT, "The size of |worker_pools_| must match ENVIRONMENT_COUNT."); @@ -33,7 +35,7 @@ ++environment_type) { worker_pools_[environment_type] = MakeUnique<SchedulerWorkerPoolImpl>( name_ + kEnvironmentParams[environment_type].name_suffix, - kEnvironmentParams[environment_type].priority_hint, &task_tracker_, + kEnvironmentParams[environment_type].priority_hint, task_tracker_.get(), &delayed_task_manager_); } } @@ -61,11 +63,11 @@ #if defined(OS_POSIX) && !defined(OS_NACL_SFI) // Needs to happen after starting the service thread to get its // message_loop(). - task_tracker_.set_watch_file_descriptor_message_loop( + task_tracker_->set_watch_file_descriptor_message_loop( static_cast<MessageLoopForIO*>(service_thread_.message_loop())); #if DCHECK_IS_ON() - task_tracker_.set_service_thread_handle(service_thread_.GetThreadHandle()); + task_tracker_->set_service_thread_handle(service_thread_.GetThreadHandle()); #endif // DCHECK_IS_ON() #endif // defined(OS_POSIX) && !defined(OS_NACL_SFI) @@ -138,11 +140,11 @@ void TaskSchedulerImpl::Shutdown() { // TODO(fdoray): Increase the priority of BACKGROUND tasks blocking shutdown. - task_tracker_.Shutdown(); + task_tracker_->Shutdown(); } void TaskSchedulerImpl::FlushForTesting() { - task_tracker_.Flush(); + task_tracker_->Flush(); } void TaskSchedulerImpl::JoinForTesting() {
diff --git a/base/task_scheduler/task_scheduler_impl.h b/base/task_scheduler/task_scheduler_impl.h index 4907ce2..1e35639 100644 --- a/base/task_scheduler/task_scheduler_impl.h +++ b/base/task_scheduler/task_scheduler_impl.h
@@ -12,6 +12,7 @@ #include "base/callback.h" #include "base/logging.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" #include "base/strings/string_piece.h" #include "base/synchronization/atomic_flag.h" @@ -38,8 +39,19 @@ // Default TaskScheduler implementation. This class is thread-safe. class BASE_EXPORT TaskSchedulerImpl : public TaskScheduler { public: - // |name| is used to label threads and histograms. - explicit TaskSchedulerImpl(StringPiece name); + using TaskTrackerImpl = +#if defined(OS_POSIX) && !defined(OS_NACL_SFI) + TaskTrackerPosix; +#else + TaskTracker; +#endif + + // |name| is used to label threads and histograms. |task_tracker| can be used + // for tests that need more execution control. By default, the production + // TaskTracker is used. + explicit TaskSchedulerImpl(StringPiece name, + std::unique_ptr<TaskTrackerImpl> task_tracker = + MakeUnique<TaskTrackerImpl>()); ~TaskSchedulerImpl() override; // TaskScheduler: @@ -74,11 +86,7 @@ const std::string name_; Thread service_thread_; -#if defined(OS_POSIX) && !defined(OS_NACL_SFI) - TaskTrackerPosix task_tracker_; -#else - TaskTracker task_tracker_; -#endif + const std::unique_ptr<TaskTrackerImpl> task_tracker_; DelayedTaskManager delayed_task_manager_; SchedulerSingleThreadTaskRunnerManager single_thread_task_runner_manager_;
diff --git a/base/task_scheduler/task_tracker.cc b/base/task_scheduler/task_tracker.cc index 55230aa9..ebf43152 100644 --- a/base/task_scheduler/task_tracker.cc +++ b/base/task_scheduler/task_tracker.cc
@@ -388,6 +388,10 @@ } #endif +int TaskTracker::GetNumPendingUndelayedTasksForTesting() const { + return subtle::NoBarrier_Load(&num_pending_undelayed_tasks_); +} + bool TaskTracker::BeforePostTask(TaskShutdownBehavior shutdown_behavior) { if (shutdown_behavior == TaskShutdownBehavior::BLOCK_SHUTDOWN) { // BLOCK_SHUTDOWN tasks block shutdown between the moment they are posted
diff --git a/base/task_scheduler/task_tracker.h b/base/task_scheduler/task_tracker.h index 1a1977d..b80e661c 100644 --- a/base/task_scheduler/task_tracker.h +++ b/base/task_scheduler/task_tracker.h
@@ -90,6 +90,10 @@ virtual bool IsPostingBlockShutdownTaskAfterShutdownAllowed(); #endif + // Returns the number of undelayed tasks that haven't completed their + // execution. + int GetNumPendingUndelayedTasksForTesting() const; + private: class State;
diff --git a/base/task_scheduler/task_tracker_posix.h b/base/task_scheduler/task_tracker_posix.h index a98b464c..7a17f75 100644 --- a/base/task_scheduler/task_tracker_posix.h +++ b/base/task_scheduler/task_tracker_posix.h
@@ -50,11 +50,12 @@ } #endif - private: + protected: // TaskTracker: void PerformRunTask(std::unique_ptr<Task> task, const SequenceToken& sequence_token) override; + private: #if DCHECK_IS_ON() bool IsPostingBlockShutdownTaskAfterShutdownAllowed() override; #endif
diff --git a/base/test/scoped_task_environment.cc b/base/test/scoped_task_environment.cc index 672ffb05..8129162 100644 --- a/base/test/scoped_task_environment.cc +++ b/base/test/scoped_task_environment.cc
@@ -4,9 +4,15 @@ #include "base/test/scoped_task_environment.h" +#include "base/bind_helpers.h" +#include "base/logging.h" #include "base/run_loop.h" -#include "base/task_scheduler/scheduler_worker_pool_params.h" +#include "base/synchronization/condition_variable.h" +#include "base/synchronization/lock.h" +#include "base/task_scheduler/post_task.h" #include "base/task_scheduler/task_scheduler.h" +#include "base/task_scheduler/task_scheduler_impl.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" namespace base { @@ -21,25 +27,69 @@ // MessageLoop::TaskObserver: void WillProcessTask(const PendingTask& pending_task) override {} void DidProcessTask(const PendingTask& pending_task) override { - ran_task_ = true; + ++task_count_; } - bool ran_task() const { return ran_task_; } + int task_count() const { return task_count_; } private: - bool ran_task_ = false; + int task_count_ = 0; + DISALLOW_COPY_AND_ASSIGN(TaskObserver); }; } // namespace -ScopedTaskEnvironment::ScopedTaskEnvironment(MainThreadType main_thread_type) - : message_loop_(main_thread_type == MainThreadType::DEFAULT +class ScopedTaskEnvironment::TestTaskTracker + : public internal::TaskSchedulerImpl::TaskTrackerImpl { + public: + TestTaskTracker(); + + void RegisterOnQueueEmptyClosure(OnceClosure queue_empty_closure); + void AssertOnQueueEmptyClosureIsNull(); + + // Allow running tasks. + void AllowRunRask(); + + // Disallow running tasks. No-ops and returns false if a task is running. + bool DisallowRunTasks(); + + private: + friend class ScopedTaskEnvironment; + + // internal::TaskSchedulerImpl::TaskTrackerImpl: + void PerformRunTask(std::unique_ptr<internal::Task> task, + const SequenceToken& sequence_token) override; + + // Synchronizes accesses to members below. + Lock lock_; + + // Closure posted to the main thread when the task queue becomes empty. + OnceClosure queue_empty_closure_; + + // True if running tasks is allowed. + bool can_run_tasks_ = true; + + // Signaled when |can_run_tasks_| becomes true. + ConditionVariable can_run_tasks_cv_; + + // Number of tasks that are currently running. + int num_tasks_running_ = 0; + + DISALLOW_COPY_AND_ASSIGN(TestTaskTracker); +}; + +ScopedTaskEnvironment::ScopedTaskEnvironment( + MainThreadType main_thread_type, + ExecutionMode execution_control_mode) + : execution_control_mode_(execution_control_mode), + message_loop_(main_thread_type == MainThreadType::DEFAULT ? MessageLoop::TYPE_DEFAULT : (main_thread_type == MainThreadType::UI ? MessageLoop::TYPE_UI - : MessageLoop::TYPE_IO)) { - DCHECK(!TaskScheduler::GetInstance()); + : MessageLoop::TYPE_IO)), + task_tracker_(new TestTaskTracker()) { + CHECK(!TaskScheduler::GetInstance()); // Instantiate a TaskScheduler with 1 thread in each of its 4 pools. Threads // stay alive even when they don't have work. @@ -48,10 +98,14 @@ const SchedulerWorkerPoolParams worker_pool_params( SchedulerWorkerPoolParams::StandbyThreadPolicy::ONE, kMaxThreads, kSuggestedReclaimTime); - TaskScheduler::Create("ScopedTaskEnvironment"); + TaskScheduler::SetInstance(MakeUnique<internal::TaskSchedulerImpl>( + "ScopedTaskEnvironment", WrapUnique(task_tracker_))); task_scheduler_ = TaskScheduler::GetInstance(); TaskScheduler::GetInstance()->Start({worker_pool_params, worker_pool_params, worker_pool_params, worker_pool_params}); + + if (execution_control_mode_ == ExecutionMode::QUEUED) + CHECK(task_tracker_->DisallowRunTasks()); } ScopedTaskEnvironment::~ScopedTaskEnvironment() { @@ -59,10 +113,10 @@ // infinite post loop in the remaining work but this isn't possible right now // because base::~MessageLoop() didn't use to do this and adding it here would // make the migration away from MessageLoop that much harder. - - DCHECK_EQ(TaskScheduler::GetInstance(), task_scheduler_); + CHECK_EQ(TaskScheduler::GetInstance(), task_scheduler_); // Without FlushForTesting(), DeleteSoon() and ReleaseSoon() tasks could be // skipped, resulting in memory leaks. + task_tracker_->AllowRunRask(); TaskScheduler::GetInstance()->FlushForTesting(); TaskScheduler::GetInstance()->Shutdown(); TaskScheduler::GetInstance()->JoinForTesting(); @@ -76,15 +130,108 @@ void ScopedTaskEnvironment::RunUntilIdle() { for (;;) { - TaskScheduler::GetInstance()->FlushForTesting(); + RunLoop run_loop; + // Register a closure to stop running tasks on the main thread when the + // TaskScheduler queue becomes empty. + task_tracker_->RegisterOnQueueEmptyClosure(run_loop.QuitWhenIdleClosure()); + + // The closure registered above may never run if the TaskScheduler queue + // starts empty. Post a TaskScheduler tasks to make sure that the queue + // doesn't start empty. + PostTask(FROM_HERE, BindOnce(&DoNothing)); + + // Run main thread and TaskScheduler tasks. + task_tracker_->AllowRunRask(); TaskObserver task_observer; MessageLoop::current()->AddTaskObserver(&task_observer); - RunLoop().RunUntilIdle(); + run_loop.Run(); MessageLoop::current()->RemoveTaskObserver(&task_observer); - if (!task_observer.ran_task()) - return; + task_tracker_->AssertOnQueueEmptyClosureIsNull(); + + // If tasks other than the QuitWhenIdle closure ran on the main thread, they + // may have posted TaskScheduler tasks that didn't run yet. Another + // iteration is required to run them. + // + // If the ExecutionMode is QUEUED and DisallowRunTasks() fails, + // another iteration is required to make sure that RunUntilIdle() doesn't + // return while TaskScheduler tasks are still allowed to run. + // + // Note: DisallowRunTasks() fails when a TaskScheduler task is running. A + // TaskScheduler task may be running after the TaskScheduler queue became + // empty even if no tasks ran on the main thread in these cases: + // - An undelayed task became ripe for execution. + // - A task was posted from an external thread. + if (task_observer.task_count() == 1 && + (execution_control_mode_ != ExecutionMode::QUEUED || + task_tracker_->DisallowRunTasks())) { + break; + } + } +} + +ScopedTaskEnvironment::TestTaskTracker::TestTaskTracker() + : can_run_tasks_cv_(&lock_) {} + +void ScopedTaskEnvironment::TestTaskTracker::RegisterOnQueueEmptyClosure( + OnceClosure queue_empty_closure) { + AutoLock auto_lock(lock_); + CHECK(!queue_empty_closure_); + queue_empty_closure_ = std::move(queue_empty_closure); +} + +void ScopedTaskEnvironment::TestTaskTracker::AssertOnQueueEmptyClosureIsNull() { + AutoLock auto_lock(lock_); + CHECK(!queue_empty_closure_); +} + +void ScopedTaskEnvironment::TestTaskTracker::AllowRunRask() { + AutoLock auto_lock(lock_); + can_run_tasks_ = true; + can_run_tasks_cv_.Broadcast(); +} + +bool ScopedTaskEnvironment::TestTaskTracker::DisallowRunTasks() { + AutoLock auto_lock(lock_); + + // Can't disallow run task if there are tasks running. + if (num_tasks_running_ > 0) + return false; + + can_run_tasks_ = false; + return true; +} + +void ScopedTaskEnvironment::TestTaskTracker::PerformRunTask( + std::unique_ptr<internal::Task> task, + const SequenceToken& sequence_token) { + { + AutoLock auto_lock(lock_); + + while (!can_run_tasks_) + can_run_tasks_cv_.Wait(); + + ++num_tasks_running_; + } + + internal::TaskSchedulerImpl::TaskTrackerImpl::PerformRunTask(std::move(task), + sequence_token); + + { + AutoLock auto_lock(lock_); + + CHECK_GT(num_tasks_running_, 0); + CHECK(can_run_tasks_); + + // Notify the main thread when no task other than the current one is running + // or queued. + if (num_tasks_running_ == 1 && + GetNumPendingUndelayedTasksForTesting() == 1 && queue_empty_closure_) { + std::move(queue_empty_closure_).Run(); + } + + --num_tasks_running_; } }
diff --git a/base/test/scoped_task_environment.h b/base/test/scoped_task_environment.h index f46b516..5166a5e7 100644 --- a/base/test/scoped_task_environment.h +++ b/base/test/scoped_task_environment.h
@@ -26,7 +26,9 @@ // RunLoop::Run(UntilIdle) or ScopedTaskEnvironment::RunUntilIdle is called on // the thread where the ScopedTaskEnvironment lives. // -// Tasks posted through base/task_scheduler/post_task.h run on dedicated threads +// Tasks posted through base/task_scheduler/post_task.h run on dedicated +// threads. If ExecutionMode is QUEUED, they run when RunUntilIdle() or +// ~ScopedTaskEnvironment is called. If ExecutionMode is ASYNC, they run // as they are posted. // // All methods of ScopedTaskEnvironment must be called from the same thread. @@ -61,8 +63,18 @@ IO, }; + enum class ExecutionMode { + // Tasks are queued and only executed when RunUntilIdle() is explicitly + // called. + QUEUED, + // Tasks run as they are posted. RunUntilIdle() can still be used to block + // until done. + ASYNC, + }; + ScopedTaskEnvironment( - MainThreadType main_thread_type = MainThreadType::DEFAULT); + MainThreadType main_thread_type = MainThreadType::DEFAULT, + ExecutionMode execution_control_mode = ExecutionMode::ASYNC); // Waits until no undelayed TaskScheduler tasks remain. Then, unregisters the // TaskScheduler and the (Thread|Sequenced)TaskRunnerHandle. @@ -71,11 +83,15 @@ // Returns a TaskRunner that schedules tasks on the main thread. scoped_refptr<base::SingleThreadTaskRunner> GetMainThreadTaskRunner(); - // Synchronously runs (Thread|Sequenced)TaskRunnerHandle tasks until no - // undelayed (Thread|Sequenced)TaskRunnerHandle or TaskScheduler tasks remain. + // Runs tasks until both the (Thread|Sequenced)TaskRunnerHandle and the + // TaskScheduler queues are empty. void RunUntilIdle(); private: + class TestTaskTracker; + + const ExecutionMode execution_control_mode_; + // Note: |message_loop_| is an implementation detail and will be replaced in // the future, do NOT rely on the presence of a MessageLoop beyond // (Thread|Sequenced)TaskRunnerHandle and RunLoop. @@ -83,6 +99,9 @@ const TaskScheduler* task_scheduler_ = nullptr; + // Owned by |task_scheduler_|. + TestTaskTracker* const task_tracker_; + DISALLOW_COPY_AND_ASSIGN(ScopedTaskEnvironment); };
diff --git a/base/test/scoped_task_environment_unittest.cc b/base/test/scoped_task_environment_unittest.cc index 245cda28..93a980a 100644 --- a/base/test/scoped_task_environment_unittest.cc +++ b/base/test/scoped_task_environment_unittest.cc
@@ -6,7 +6,10 @@ #include "base/bind.h" #include "base/synchronization/atomic_flag.h" +#include "base/synchronization/waitable_event.h" #include "base/task_scheduler/post_task.h" +#include "base/test/test_timeouts.h" +#include "base/threading/platform_thread.h" #include "base/threading/thread_task_runner_handle.h" #include "testing/gtest/include/gtest/gtest.h" @@ -22,11 +25,11 @@ task_ran->Set(); } -} // namespace - -TEST(ScopedTaskEnvironmentTest, RunUntilIdle) { +void RunUntilIdleTest( + ScopedTaskEnvironment::ExecutionMode execution_control_mode) { AtomicFlag run_until_idle_returned; - ScopedTaskEnvironment scoped_task_environment; + ScopedTaskEnvironment scoped_task_environment( + ScopedTaskEnvironment::MainThreadType::DEFAULT, execution_control_mode); AtomicFlag first_main_thread_task_ran; ThreadTaskRunnerHandle::Get()->PostTask( @@ -58,5 +61,76 @@ EXPECT_TRUE(second_main_thread_task_ran.IsSet()); } +} // namespace + +TEST(ScopedTaskEnvironmentTest, QueuedRunUntilIdle) { + RunUntilIdleTest(ScopedTaskEnvironment::ExecutionMode::QUEUED); +} + +TEST(ScopedTaskEnvironmentTest, AsyncRunUntilIdle) { + RunUntilIdleTest(ScopedTaskEnvironment::ExecutionMode::ASYNC); +} + +// Verify that tasks posted to an ExecutionMode::QUEUED ScopedTaskEnvironment do +// not run outside of RunUntilIdle(). +TEST(ScopedTaskEnvironmentTest, QueuedTasksDoNotRunOutsideOfRunUntilIdle) { + ScopedTaskEnvironment scoped_task_environment( + ScopedTaskEnvironment::MainThreadType::DEFAULT, + ScopedTaskEnvironment::ExecutionMode::QUEUED); + + AtomicFlag run_until_idle_called; + PostTask(FROM_HERE, BindOnce( + [](AtomicFlag* run_until_idle_called) { + EXPECT_TRUE(run_until_idle_called->IsSet()); + }, + Unretained(&run_until_idle_called))); + PlatformThread::Sleep(TestTimeouts::tiny_timeout()); + run_until_idle_called.Set(); + scoped_task_environment.RunUntilIdle(); + + AtomicFlag other_run_until_idle_called; + PostTask(FROM_HERE, BindOnce( + [](AtomicFlag* other_run_until_idle_called) { + EXPECT_TRUE(other_run_until_idle_called->IsSet()); + }, + Unretained(&other_run_until_idle_called))); + PlatformThread::Sleep(TestTimeouts::tiny_timeout()); + other_run_until_idle_called.Set(); + scoped_task_environment.RunUntilIdle(); +} + +// Verify that a task posted to an ExecutionMode::ASYNC ScopedTaskEnvironment +// can run without a call to RunUntilIdle(). +TEST(ScopedTaskEnvironmentTest, AsyncTasksRunAsTheyArePosted) { + ScopedTaskEnvironment scoped_task_environment( + ScopedTaskEnvironment::MainThreadType::DEFAULT, + ScopedTaskEnvironment::ExecutionMode::ASYNC); + + WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + PostTask(FROM_HERE, + BindOnce([](WaitableEvent* task_ran) { task_ran->Signal(); }, + Unretained(&task_ran))); + task_ran.Wait(); +} + +// Verify that a task posted to an ExecutionMode::ASYNC ScopedTaskEnvironment +// after a call to RunUntilIdle() can run without another call to +// RunUntilIdle(). +TEST(ScopedTaskEnvironmentTest, AsyncTasksRunAsTheyArePostedAfterRunUntilIdle) { + ScopedTaskEnvironment scoped_task_environment( + ScopedTaskEnvironment::MainThreadType::DEFAULT, + ScopedTaskEnvironment::ExecutionMode::ASYNC); + + scoped_task_environment.RunUntilIdle(); + + WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + PostTask(FROM_HERE, + BindOnce([](WaitableEvent* task_ran) { task_ran->Signal(); }, + Unretained(&task_ran))); + task_ran.Wait(); +} + } // namespace test } // namespace base
diff --git a/build/config/fuchsia/rules.gni b/build/config/fuchsia/rules.gni new file mode 100644 index 0000000..b3e7f3b --- /dev/null +++ b/build/config/fuchsia/rules.gni
@@ -0,0 +1,78 @@ +# 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. + +assert(is_fuchsia) + +# This template is used to generate a runner script for test binaries into the +# build dir for Fuchsia. It's generally used from the "test" template. +template("test_runner_script") { + testonly = true + _test_name = invoker.test_name + + # This runtime_deps file is used at runtime and thus cannot go in + # target_gen_dir. + _target_dir_name = get_label_info(":$target_name", "dir") + _runtime_deps_file = + "$root_out_dir/gen.runtime/$_target_dir_name/$target_name.runtime_deps" + _runtime_deps_target = "${target_name}__write_deps" + group(_runtime_deps_target) { + forward_variables_from(invoker, + [ + "data", + "data_deps", + "deps", + "public_deps", + ]) + write_runtime_deps = _runtime_deps_file + } + + action(target_name) { + forward_variables_from(invoker, + [ + "data_deps", + "deps", + ]) + if (!defined(deps)) { + deps = [] + } + if (!defined(data_deps)) { + data_deps = [] + } + + script = "//build/fuchsia/create_test_runner_script.py" + depfile = "$target_gen_dir/$target_name.d" + + data = [] + test_runner_args = [] + + generated_script = "$root_build_dir/bin/run_${_test_name}" + outputs = [ + generated_script, + ] + data += [ generated_script ] + + test_runner_args += [ + "--output-directory", + rebase_path(root_build_dir, root_build_dir), + ] + + deps += [ ":$_runtime_deps_target" ] + data += [ _runtime_deps_file ] + test_runner_args += [ + "--runtime-deps-path", + rebase_path(_runtime_deps_file, root_build_dir), + ] + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--script-output-path", + rebase_path(generated_script, root_build_dir), + "--test-name", + _test_name, + ] + + args += test_runner_args + } +}
diff --git a/build/fuchsia/create_test_runner_script.py b/build/fuchsia/create_test_runner_script.py new file mode 100755 index 0000000..d6e067b --- /dev/null +++ b/build/fuchsia/create_test_runner_script.py
@@ -0,0 +1,88 @@ +#!/usr/bin/env python +# +# 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. + +"""Creates a script to run a Fushsia test (typically on QEMU) by delegating to +build/fuchsia/test_runner.py. +""" + +import argparse +import os +import pipes +import re +import sys + + +SCRIPT_TEMPLATE = """\ +#!/bin/sh +exec {test_runner_path} {test_runner_args} "$@" +""" + + +def MakeDirectory(dir_path): + try: + os.makedirs(dir_path) + except OSError: + pass + + +def WriteDepfile(depfile_path, first_gn_output, inputs=None): + assert depfile_path != first_gn_output + inputs = inputs or [] + MakeDirectory(os.path.dirname(depfile_path)) + # Ninja does not support multiple outputs in depfiles. + with open(depfile_path, 'w') as depfile: + depfile.write(first_gn_output.replace(' ', '\\ ')) + depfile.write(': ') + depfile.write(' '.join(i.replace(' ', '\\ ') for i in inputs)) + depfile.write('\n') + + +def main(args): + parser = argparse.ArgumentParser() + parser.add_argument('--script-output-path', + help='Output path for executable script.') + parser.add_argument('--depfile', + help='Path to the depfile. This must be specified as ' + 'the action\'s first output.') + parser.add_argument('--test-runner-path', + help='Path to test_runner.py (optional).') + group = parser.add_argument_group('Test runner path arguments.') + group.add_argument('--output-directory') + group.add_argument('--runtime-deps-path') + group.add_argument('--test-name') + args, test_runner_args = parser.parse_known_args(args) + + def ResolvePath(path): + return os.path.abspath(os.path.join( + os.path.dirname(args.script_output_path), '..', path)) + + test_runner_path = args.test_runner_path or os.path.join( + os.path.dirname(__file__), 'test_runner.py') + test_runner_path = ResolvePath(test_runner_path) + + if args.output_directory: + test_runner_args.extend( + ['--output-directory', ResolvePath(args.output_directory)]) + if args.runtime_deps_path: + test_runner_args.extend( + ['--runtime-deps-path', ResolvePath(args.runtime_deps_path)]) + if args.test_name: + test_runner_args.extend(['--test-name', args.test_name]) + + with open(args.script_output_path, 'w') as script: + script.write(SCRIPT_TEMPLATE.format( + test_runner_path=test_runner_path, + test_runner_args=' '.join(pipes.quote(x) for x in test_runner_args))) + + os.chmod(args.script_output_path, 0750) + + if args.depfile: + WriteDepfile(args.depfile, args.script_output_path, + [__file__]) + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:]))
diff --git a/build/fuchsia/test_runner.py b/build/fuchsia/test_runner.py new file mode 100755 index 0000000..d79fdae --- /dev/null +++ b/build/fuchsia/test_runner.py
@@ -0,0 +1,19 @@ +#!/usr/bin/env python +# +# 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. + +"""Stub for script that will run a Fuchsia binary on QEMU or hardware.""" + +import sys + + +def main(): + print sys.argv + print 'TODO(fuchsia): Implement test runner. https://crbug.com/706592.' + return 1 + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index b259642..58f30f86 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2025,14 +2025,14 @@ } if (enable_spellcheck) { sources += [ + "spellchecker/spell_check_host_impl.cc", + "spellchecker/spell_check_host_impl.h", "spellchecker/spellcheck_custom_dictionary.cc", "spellchecker/spellcheck_custom_dictionary.h", "spellchecker/spellcheck_factory.cc", "spellchecker/spellcheck_factory.h", "spellchecker/spellcheck_hunspell_dictionary.cc", "spellchecker/spellcheck_hunspell_dictionary.h", - "spellchecker/spellcheck_message_filter.cc", - "spellchecker/spellcheck_message_filter.h", "spellchecker/spellcheck_message_filter_platform_mac.cc", "spellchecker/spellcheck_service.cc", "spellchecker/spellcheck_service.h", @@ -4414,6 +4414,7 @@ if (use_vulcanize) { deps += [ + "//chrome/browser/resources/md_bookmarks:build", "//chrome/browser/resources/md_downloads:build", "//chrome/browser/resources/md_history:build", ]
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 77382fa2..a5d48f14 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -266,42 +266,50 @@ <if expr="not is_android and not is_ios"> <!-- MD Bookmarks. --> - <include name="IDR_MD_BOOKMARKS_ACTIONS_HTML" file="resources\md_bookmarks\actions.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_ACTIONS_JS" file="resources\md_bookmarks\actions.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_API_LISTENER_HTML" file="resources\md_bookmarks\api_listener.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_API_LISTENER_JS" file="resources\md_bookmarks\api_listener.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_APP_HTML" file="resources\md_bookmarks\app.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_APP_JS" file="resources\md_bookmarks\app.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_BOOKMARKS_HTML" file="resources\md_bookmarks\bookmarks.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_COMMAND_MANAGER_HTML" file="resources\md_bookmarks\command_manager.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_COMMAND_MANAGER_JS" file="resources\md_bookmarks\command_manager.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_CONSTANTS_HTML" file="resources\md_bookmarks\constants.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_CONSTANTS_JS" file="resources\md_bookmarks\constants.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_DND_MANAGER_HTML" file="resources\md_bookmarks\dnd_manager.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_DND_MANAGER_JS" file="resources\md_bookmarks\dnd_manager.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_EDIT_DIALOG_HTML" file="resources\md_bookmarks\edit_dialog.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_EDIT_DIALOG_JS" file="resources\md_bookmarks\edit_dialog.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_FOLDER_NODE_HTML" file="resources\md_bookmarks\folder_node.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_FOLDER_NODE_JS" file="resources\md_bookmarks\folder_node.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_ICONS_HTML" file="resources\md_bookmarks\icons.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_ITEM_HTML" file="resources\md_bookmarks\item.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_ITEM_JS" file="resources\md_bookmarks\item.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_LIST_HTML" file="resources\md_bookmarks\list.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_LIST_JS" file="resources\md_bookmarks\list.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_REDUCERS_HTML" file="resources\md_bookmarks\reducers.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_REDUCERS_JS" file="resources\md_bookmarks\reducers.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_ROUTER_HTML" file="resources\md_bookmarks\router.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_ROUTER_JS" file="resources\md_bookmarks\router.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_SHARED_STYLE_HTML" file="resources\md_bookmarks\shared_style.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_SHARED_VARS_HTML" file="resources\md_bookmarks\shared_vars.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_STORE_CLIENT_HTML" file="resources\md_bookmarks\store_client.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_STORE_CLIENT_JS" file="resources\md_bookmarks\store_client.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_STORE_HTML" file="resources\md_bookmarks\store.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_STORE_JS" file="resources\md_bookmarks\store.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_TOOLBAR_HTML" file="resources\md_bookmarks\toolbar.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_TOOLBAR_JS" file="resources\md_bookmarks\toolbar.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_UTIL_HTML" file="resources\md_bookmarks\util.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_UTIL_JS" file="resources\md_bookmarks\util.js" type="BINDATA" /> + <if expr="use_vulcanize"> + <then> + <include name="IDR_MD_BOOKMARKS_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\md_bookmarks\vulcanized.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" /> + <include name="IDR_MD_BOOKMARKS_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\md_bookmarks\crisper.js" use_base_dir="false" flattenhtml="true" type="BINDATA" compress="gzip" /> + </then> + <else> + <include name="IDR_MD_BOOKMARKS_ACTIONS_HTML" file="resources\md_bookmarks\actions.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_ACTIONS_JS" file="resources\md_bookmarks\actions.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_API_LISTENER_HTML" file="resources\md_bookmarks\api_listener.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_API_LISTENER_JS" file="resources\md_bookmarks\api_listener.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_APP_HTML" file="resources\md_bookmarks\app.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_APP_JS" file="resources\md_bookmarks\app.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_BOOKMARKS_HTML" file="resources\md_bookmarks\bookmarks.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_COMMAND_MANAGER_HTML" file="resources\md_bookmarks\command_manager.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_COMMAND_MANAGER_JS" file="resources\md_bookmarks\command_manager.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_CONSTANTS_HTML" file="resources\md_bookmarks\constants.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_CONSTANTS_JS" file="resources\md_bookmarks\constants.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_DND_MANAGER_HTML" file="resources\md_bookmarks\dnd_manager.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_DND_MANAGER_JS" file="resources\md_bookmarks\dnd_manager.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_EDIT_DIALOG_HTML" file="resources\md_bookmarks\edit_dialog.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_EDIT_DIALOG_JS" file="resources\md_bookmarks\edit_dialog.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_FOLDER_NODE_HTML" file="resources\md_bookmarks\folder_node.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_FOLDER_NODE_JS" file="resources\md_bookmarks\folder_node.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_ICONS_HTML" file="resources\md_bookmarks\icons.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_ITEM_HTML" file="resources\md_bookmarks\item.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_ITEM_JS" file="resources\md_bookmarks\item.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_LIST_HTML" file="resources\md_bookmarks\list.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_LIST_JS" file="resources\md_bookmarks\list.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_REDUCERS_HTML" file="resources\md_bookmarks\reducers.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_REDUCERS_JS" file="resources\md_bookmarks\reducers.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_ROUTER_HTML" file="resources\md_bookmarks\router.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_ROUTER_JS" file="resources\md_bookmarks\router.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_SHARED_STYLE_HTML" file="resources\md_bookmarks\shared_style.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_SHARED_VARS_HTML" file="resources\md_bookmarks\shared_vars.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_STORE_CLIENT_HTML" file="resources\md_bookmarks\store_client.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_STORE_CLIENT_JS" file="resources\md_bookmarks\store_client.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_STORE_HTML" file="resources\md_bookmarks\store.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_STORE_JS" file="resources\md_bookmarks\store.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_TOOLBAR_HTML" file="resources\md_bookmarks\toolbar.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_TOOLBAR_JS" file="resources\md_bookmarks\toolbar.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_UTIL_HTML" file="resources\md_bookmarks\util.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_UTIL_JS" file="resources\md_bookmarks\util.js" type="BINDATA" /> + </else> + </if> <!-- MD History. --> <include name="IDR_MD_HISTORY_CONSTANTS_HTML" file="resources\md_history\constants.html" type="BINDATA" />
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index e90776d..840d9a1 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -359,7 +359,7 @@ #endif #if BUILDFLAG(ENABLE_SPELLCHECK) -#include "chrome/browser/spellchecker/spellcheck_message_filter.h" +#include "chrome/browser/spellchecker/spell_check_host_impl.h" #endif #if BUILDFLAG(USE_BROWSER_SPELLCHECKER) @@ -1205,9 +1205,6 @@ #if BUILDFLAG(ENABLE_PRINTING) host->AddFilter(new printing::PrintingMessageFilter(id, profile)); #endif -#if BUILDFLAG(ENABLE_SPELLCHECK) - host->AddFilter(new SpellCheckMessageFilter(id)); -#endif #if BUILDFLAG(USE_BROWSER_SPELLCHECKER) host->AddFilter(new SpellCheckMessageFilterPlatform(id)); #endif @@ -3071,6 +3068,11 @@ registry->AddInterface( base::Bind(&BudgetServiceImpl::Create, render_process_host->GetID()), ui_task_runner); +#if BUILDFLAG(ENABLE_SPELLCHECK) + registry->AddInterface( + base::Bind(&SpellCheckHostImpl::Create, render_process_host->GetID()), + ui_task_runner); +#endif registry->AddInterface( base::Bind(&rappor::RapporRecorderImpl::Create, g_browser_process->rappor_service()),
diff --git a/chrome/browser/chrome_content_browser_manifest_overlay.json b/chrome/browser/chrome_content_browser_manifest_overlay.json index 887404b..8f8676b 100644 --- a/chrome/browser/chrome_content_browser_manifest_overlay.json +++ b/chrome/browser/chrome_content_browser_manifest_overlay.json
@@ -13,6 +13,7 @@ "metrics::mojom::LeakDetector", "mojom::ModuleEventSink", "rappor::mojom::RapporRecorder", + "spellcheck::mojom::SpellCheckHost", "startup_metric_utils::mojom::StartupMetricHost", "translate::mojom::ContentTranslateDriver" ],
diff --git a/chrome/browser/chrome_site_per_process_browsertest.cc b/chrome/browser/chrome_site_per_process_browsertest.cc index 1c6047f..27e813c 100644 --- a/chrome/browser/chrome_site_per_process_browsertest.cc +++ b/chrome/browser/chrome_site_per_process_browsertest.cc
@@ -38,7 +38,9 @@ #include "url/gurl.h" #if BUILDFLAG(ENABLE_SPELLCHECK) +#include "components/spellcheck/common/spellcheck.mojom.h" #include "components/spellcheck/common/spellcheck_messages.h" +#include "services/service_manager/public/cpp/bind_source_info.h" #endif class ChromeSitePerProcessTest : public InProcessBrowserTest { @@ -560,58 +562,87 @@ } #if BUILDFLAG(ENABLE_SPELLCHECK) -// Class to sniff incoming IPCs for spell check messages. -class TestSpellCheckMessageFilter : public content::BrowserMessageFilter { +// Class to sniff incoming spellcheck IPC / Mojo SpellCheckHost messages. +class TestSpellCheckMessageFilter : public content::BrowserMessageFilter, + spellcheck::mojom::SpellCheckHost { public: explicit TestSpellCheckMessageFilter(content::RenderProcessHost* process_host) : content::BrowserMessageFilter(SpellCheckMsgStart), process_host_(process_host), text_received_(false), message_loop_runner_( - base::MakeRefCounted<content::MessageLoopRunner>()) {} + base::MakeRefCounted<content::MessageLoopRunner>()), + binding_(this) {} - bool OnMessageReceived(const IPC::Message& message) override { - IPC_BEGIN_MESSAGE_MAP(TestSpellCheckMessageFilter, message) -#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) - IPC_MESSAGE_HANDLER(SpellCheckHostMsg_CallSpellingService, HandleMessage) -#else - IPC_MESSAGE_HANDLER(SpellCheckHostMsg_RequestTextCheck, HandleMessage) -#endif - IPC_END_MESSAGE_MAP() - return false; - } + content::RenderProcessHost* process() const { return process_host_; } - base::string16 last_text() const { return last_text_; } + const base::string16& text() const { return text_; } void Wait() { if (!text_received_) message_loop_runner_->Run(); } - content::RenderProcessHost* process() const { return process_host_; } + bool OnMessageReceived(const IPC::Message& message) override { +#if BUILDFLAG(USE_BROWSER_SPELLCHECKER) + IPC_BEGIN_MESSAGE_MAP(TestSpellCheckMessageFilter, message) + // TODO(crbug.com/714480): convert the RequestTextCheck IPC to mojo. + IPC_MESSAGE_HANDLER(SpellCheckHostMsg_RequestTextCheck, HandleMessage) + IPC_END_MESSAGE_MAP() +#endif + return false; + } + +#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) + void ShellCheckHostRequest(const service_manager::BindSourceInfo& source_info, + spellcheck::mojom::SpellCheckHostRequest request) { + EXPECT_FALSE(binding_.is_bound()); + binding_.Bind(std::move(request)); + } +#endif private: ~TestSpellCheckMessageFilter() override {} +#if BUILDFLAG(USE_BROWSER_SPELLCHECKER) void HandleMessage(int, int, const base::string16& text) { content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::BindOnce(&TestSpellCheckMessageFilter::HandleMessageOnUI, this, - text)); + base::BindOnce(&TestSpellCheckMessageFilter::HandleMessageOnUIThread, + this, text)); } +#endif - void HandleMessageOnUI(const base::string16& text) { - last_text_ = text; + void HandleMessageOnUIThread(const base::string16& text) { if (!text_received_) { text_received_ = true; + text_ = text; message_loop_runner_->Quit(); + } else { + NOTREACHED(); } } + // spellcheck::mojom::SpellCheckHost: + void RequestDictionary() override {} + + void NotifyChecked(const base::string16& word, bool misspelled) override {} + + void CallSpellingService(const base::string16& text, + CallSpellingServiceCallback callback) override { +#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + std::move(callback).Run(true, std::vector<SpellCheckResult>()); + binding_.Close(); + HandleMessageOnUIThread(text); +#endif + } + content::RenderProcessHost* process_host_; bool text_received_; - base::string16 last_text_; + base::string16 text_; scoped_refptr<content::MessageLoopRunner> message_loop_runner_; + mojo::Binding<spellcheck::mojom::SpellCheckHost> binding_; DISALLOW_COPY_AND_ASSIGN(TestSpellCheckMessageFilter); }; @@ -629,6 +660,28 @@ ChromeContentBrowserClient::RenderProcessWillLaunch(process_host); } +#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) + void ExposeInterfacesToRenderer( + service_manager::BinderRegistry* registry, + content::AssociatedInterfaceRegistry* associated_registry, + content::RenderProcessHost* render_process_host) override { + // Expose the default interfaces. + ChromeContentBrowserClient::ExposeInterfacesToRenderer( + registry, associated_registry, render_process_host); + + scoped_refptr<TestSpellCheckMessageFilter> filter = + GetSpellCheckMessageFilterForProcess(render_process_host); + CHECK(filter); + + // Override the default SpellCheckHost interface. + auto ui_task_runner = content::BrowserThread::GetTaskRunnerForThread( + content::BrowserThread::UI); + registry->AddInterface( + base::Bind(&TestSpellCheckMessageFilter::ShellCheckHostRequest, filter), + ui_task_runner); + } +#endif // !BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // Retrieves the registered filter for the given RenderProcessHost. It will // return nullptr if the RenderProcessHost was initialized while a different // instance of ContentBrowserClient was in action. @@ -661,14 +714,15 @@ content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - content::RenderFrameHost* subframe = + content::RenderFrameHost* cross_site_subframe = ChildFrameAt(web_contents->GetMainFrame(), 0); + scoped_refptr<TestSpellCheckMessageFilter> filter = browser_client.GetSpellCheckMessageFilterForProcess( - subframe->GetProcess()); + cross_site_subframe->GetProcess()); filter->Wait(); - EXPECT_EQ(base::ASCIIToUTF16("zz."), filter->last_text()); + EXPECT_EQ(base::ASCIIToUTF16("zz."), filter->text()); content::SetBrowserClientForTesting(old_browser_client); }
diff --git a/chrome/browser/resources/md_bookmarks/BUILD.gn b/chrome/browser/resources/md_bookmarks/BUILD.gn new file mode 100644 index 0000000..eea759d7 --- /dev/null +++ b/chrome/browser/resources/md_bookmarks/BUILD.gn
@@ -0,0 +1,22 @@ +import("../vulcanize.gni") + +vulcanized_unbuilt = "vulcanized.unbuilt.html" + +vulcanize("vulcanize") { + host = "bookmarks" + html_in_file = "bookmarks.html" + html_out_file = vulcanized_unbuilt + + input = rebase_path(".", root_build_dir) + js_out_file = "crisper.js" + + deps = [] +} + +polymer_css_build("build") { + input_files = [ vulcanized_unbuilt ] + output_files = [ "vulcanized.html" ] + deps = [ + ":vulcanize", + ] +}
diff --git a/chrome/browser/resources/md_bookmarks/bookmarks.html b/chrome/browser/resources/md_bookmarks/bookmarks.html index 955f7fb..685fb57 100644 --- a/chrome/browser/resources/md_bookmarks/bookmarks.html +++ b/chrome/browser/resources/md_bookmarks/bookmarks.html
@@ -5,9 +5,6 @@ <title>$i18n{title}</title> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> - <link rel="import" href="chrome://resources/html/load_time_data.html"> - <script src="chrome://bookmarks/strings.js"></script> - <link rel="import" href="chrome://bookmarks/app.html"> <style> html, body { @@ -19,5 +16,9 @@ </head> <body> <bookmarks-app></bookmarks-app> + + <link rel="import" href="chrome://resources/html/load_time_data.html"> + <script src="chrome://bookmarks/strings.js"></script> + <link rel="import" href="chrome://bookmarks/app.html"> </body> </html>
diff --git a/chrome/browser/spellchecker/spell_check_host_impl.cc b/chrome/browser/spellchecker/spell_check_host_impl.cc new file mode 100644 index 0000000..788a19c --- /dev/null +++ b/chrome/browser/spellchecker/spell_check_host_impl.cc
@@ -0,0 +1,133 @@ +// 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 "chrome/browser/spellchecker/spell_check_host_impl.h" + +#include "base/bind.h" +#include "base/memory/ptr_util.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/spellchecker/spellcheck_custom_dictionary.h" +#include "chrome/browser/spellchecker/spellcheck_factory.h" +#include "chrome/browser/spellchecker/spellcheck_service.h" +#include "components/spellcheck/browser/spellcheck_host_metrics.h" +#include "components/spellcheck/common/spellcheck_result.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_process_host.h" +#include "mojo/public/cpp/bindings/strong_binding.h" + +SpellCheckHostImpl::SpellCheckHostImpl(int render_process_id) + : render_process_id_(render_process_id) {} + +SpellCheckHostImpl::~SpellCheckHostImpl() = default; + +// static +void SpellCheckHostImpl::Create( + int render_process_id, + const service_manager::BindSourceInfo& source_info, + spellcheck::mojom::SpellCheckHostRequest request) { + mojo::MakeStrongBinding( + base::MakeUnique<SpellCheckHostImpl>(render_process_id), + std::move(request)); +} + +void SpellCheckHostImpl::RequestDictionary() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + // The renderer has requested that we initialize its spellchecker. This + // generally should only be called once per session, as after the first + // call, future renderers will be passed the initialization information + // on startup (or when the dictionary changes in some way). + SpellcheckService* spellcheck = GetSpellcheckService(); + if (!spellcheck) + return; // Teardown. + + // The spellchecker initialization already started and finished; just + // send it to the renderer. + spellcheck->InitForRenderer( + content::RenderProcessHost::FromID(render_process_id_)); + + // TODO(rlp): Ensure that we do not initialize the hunspell dictionary + // more than once if we get requests from different renderers. +} + +void SpellCheckHostImpl::NotifyChecked(const base::string16& word, + bool misspelled) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + SpellcheckService* spellcheck = GetSpellcheckService(); + if (!spellcheck) + return; // Teardown. + if (spellcheck->GetMetrics()) + spellcheck->GetMetrics()->RecordCheckedWordStats(word, misspelled); +} + +void SpellCheckHostImpl::CallSpellingService( + const base::string16& text, + CallSpellingServiceCallback callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + if (text.empty()) { + std::move(callback).Run(false, std::vector<SpellCheckResult>()); + mojo::ReportBadMessage(__FUNCTION__); + return; + } + +#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) + content::RenderProcessHost* host = + content::RenderProcessHost::FromID(render_process_id_); + + // Checks the user profile and sends a JSON-RPC request to the Spelling + // service if a user enables the "Ask Google for suggestions" option. When + // a response is received (including an error) from the remote Spelling + // service, calls CallSpellingServiceDone. + client_.RequestTextCheck( + host ? host->GetBrowserContext() : nullptr, + SpellingServiceClient::SPELLCHECK, text, + base::Bind(&SpellCheckHostImpl::CallSpellingServiceDone, + base::Unretained(this), base::Passed(&callback))); +#else + std::move(callback).Run(false, std::vector<SpellCheckResult>()); +#endif +} + +#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) +void SpellCheckHostImpl::CallSpellingServiceDone( + CallSpellingServiceCallback callback, + bool success, + const base::string16& text, + const std::vector<SpellCheckResult>& service_results) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + SpellcheckService* spellcheck = GetSpellcheckService(); + if (!spellcheck) { // Teardown. + std::move(callback).Run(false, std::vector<SpellCheckResult>()); + return; + } + + std::vector<SpellCheckResult> results = FilterCustomWordResults( + base::UTF16ToUTF8(text), *spellcheck->GetCustomDictionary(), + service_results); + + std::move(callback).Run(success, results); +} + +// static +std::vector<SpellCheckResult> SpellCheckHostImpl::FilterCustomWordResults( + const std::string& text, + const SpellcheckCustomDictionary& custom_dictionary, + const std::vector<SpellCheckResult>& service_results) { + std::vector<SpellCheckResult> results; + for (const auto& result : service_results) { + const std::string word = text.substr(result.location, result.length); + if (!custom_dictionary.HasWord(word)) + results.push_back(result); + } + + return results; +} +#endif // !BUILDFLAG(USE_BROWSER_SPELLCHECKER) + +SpellcheckService* SpellCheckHostImpl::GetSpellcheckService() const { + return SpellcheckServiceFactory::GetForRenderProcessId(render_process_id_); +}
diff --git a/chrome/browser/spellchecker/spell_check_host_impl.h b/chrome/browser/spellchecker/spell_check_host_impl.h new file mode 100644 index 0000000..9349fa1 --- /dev/null +++ b/chrome/browser/spellchecker/spell_check_host_impl.h
@@ -0,0 +1,74 @@ +// 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 CHROME_BROWSER_SPELLCHECKER_SPELL_CHECK_HOST_IMPL_H_ +#define CHROME_BROWSER_SPELLCHECKER_SPELL_CHECK_HOST_IMPL_H_ + +#include "base/macros.h" +#include "components/spellcheck/browser/spelling_service_client.h" +#include "components/spellcheck/common/spellcheck.mojom.h" +#include "components/spellcheck/spellcheck_build_features.h" + +#if !BUILDFLAG(ENABLE_SPELLCHECK) +#error "Spellcheck should be enabled." +#endif + +class SpellcheckCustomDictionary; +class SpellcheckService; + +struct SpellCheckResult; + +namespace service_manager { +struct BindSourceInfo; +} + +class SpellCheckHostImpl : public spellcheck::mojom::SpellCheckHost { + public: + explicit SpellCheckHostImpl(int render_process_id); + ~SpellCheckHostImpl() override; + + static void Create(int render_process_id, + const service_manager::BindSourceInfo& source_info, + spellcheck::mojom::SpellCheckHostRequest request); + + private: + friend class TestSpellCheckHostImpl; + + // spellcheck::mojom::SpellCheckHost: + void RequestDictionary() override; + void NotifyChecked(const base::string16& word, bool misspelled) override; + void CallSpellingService(const base::string16& text, + CallSpellingServiceCallback callback) override; + +#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // Invoked when the remote Spelling service has finished checking the + // text of a CallSpellingService request. + void CallSpellingServiceDone( + CallSpellingServiceCallback callback, + bool success, + const base::string16& text, + const std::vector<SpellCheckResult>& service_results) const; + + // Filter out spelling corrections of custom dictionary words from the + // Spelling service results. + static std::vector<SpellCheckResult> FilterCustomWordResults( + const std::string& text, + const SpellcheckCustomDictionary& custom_dictionary, + const std::vector<SpellCheckResult>& service_results); +#endif + + // Returns the SpellcheckService of our |render_process_id_|. The return + // is null if the render process is being shut down. + virtual SpellcheckService* GetSpellcheckService() const; + + // The process ID of our render process host. + const int render_process_id_; + + // A JSON-RPC client that calls the remote Spelling service. + SpellingServiceClient client_; + + DISALLOW_COPY_AND_ASSIGN(SpellCheckHostImpl); +}; + +#endif // CHROME_BROWSER_SPELLCHECKER_SPELL_CHECK_HOST_IMPL_H_
diff --git a/chrome/browser/spellchecker/spell_check_host_impl_unittest.cc b/chrome/browser/spellchecker/spell_check_host_impl_unittest.cc new file mode 100644 index 0000000..22cadb6 --- /dev/null +++ b/chrome/browser/spellchecker/spell_check_host_impl_unittest.cc
@@ -0,0 +1,89 @@ +// 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 "chrome/browser/spellchecker/spell_check_host_impl.h" + +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/spellchecker/spellcheck_factory.h" +#include "chrome/browser/spellchecker/spellcheck_service.h" +#include "chrome/test/base/testing_profile.h" +#include "components/spellcheck/common/spellcheck_result.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if BUILDFLAG(USE_BROWSER_SPELLCHECKER) +#error !BUILDFLAG(USE_BROWSER_SPELLCHECKER) is required for these tests. +#endif + +class TestSpellCheckHostImpl { + public: + TestSpellCheckHostImpl() + : spellcheck_(base::MakeUnique<SpellcheckService>(&testing_profile_)) {} + + SpellcheckCustomDictionary& GetCustomDictionary() const { + EXPECT_NE(nullptr, spellcheck_.get()); + SpellcheckCustomDictionary* custom_dictionary = + spellcheck_->GetCustomDictionary(); + return *custom_dictionary; + } + + std::vector<SpellCheckResult> FilterCustomWordResults( + const std::string& text, + const std::vector<SpellCheckResult>& service_results) const { + return SpellCheckHostImpl::FilterCustomWordResults( + text, GetCustomDictionary(), service_results); + } + + private: + content::TestBrowserThreadBundle thread_bundle_; + TestingProfile testing_profile_; + std::unique_ptr<SpellcheckService> spellcheck_; + + DISALLOW_COPY_AND_ASSIGN(TestSpellCheckHostImpl); +}; + +// Spelling corrections of custom dictionary words should be removed from the +// results returned by the remote Spelling service. +TEST(SpellCheckHostImplTest, CustomSpellingResults) { + std::vector<SpellCheckResult> service_results; + service_results.push_back(SpellCheckResult(SpellCheckResult::SPELLING, 0, 6, + base::ASCIIToUTF16("Hello"))); + service_results.push_back(SpellCheckResult(SpellCheckResult::SPELLING, 7, 5, + base::ASCIIToUTF16("World"))); + TestSpellCheckHostImpl host_impl; + host_impl.GetCustomDictionary().AddWord("Helllo"); + std::vector<SpellCheckResult> results = + host_impl.FilterCustomWordResults("Helllo Warld", service_results); + ASSERT_EQ(1u, results.size()); + + EXPECT_EQ(service_results[1].decoration, results[0].decoration); + EXPECT_EQ(service_results[1].location, results[0].location); + EXPECT_EQ(service_results[1].length, results[0].length); + EXPECT_EQ(service_results[1].replacement, results[0].replacement); +} + +// Spelling corrections of words that are not in the custom dictionary should +// be retained in the results returned by the remote Spelling service. +TEST(SpellCheckHostImplTest, SpellingServiceResults) { + std::vector<SpellCheckResult> service_results; + service_results.push_back(SpellCheckResult(SpellCheckResult::SPELLING, 0, 6, + base::ASCIIToUTF16("Hello"))); + service_results.push_back(SpellCheckResult(SpellCheckResult::SPELLING, 7, 5, + base::ASCIIToUTF16("World"))); + TestSpellCheckHostImpl host_impl; + host_impl.GetCustomDictionary().AddWord("Hulo"); + std::vector<SpellCheckResult> results = + host_impl.FilterCustomWordResults("Helllo Warld", service_results); + ASSERT_EQ(service_results.size(), results.size()); + + for (size_t i = 0; i < results.size(); ++i) { + EXPECT_EQ(service_results[i].decoration, results[i].decoration); + EXPECT_EQ(service_results[i].location, results[i].location); + EXPECT_EQ(service_results[i].length, results[i].length); + EXPECT_EQ(service_results[i].replacement, results[i].replacement); + } +}
diff --git a/chrome/browser/spellchecker/spellcheck_message_filter.cc b/chrome/browser/spellchecker/spellcheck_message_filter.cc deleted file mode 100644 index 7f69a55..0000000 --- a/chrome/browser/spellchecker/spellcheck_message_filter.cc +++ /dev/null
@@ -1,156 +0,0 @@ -// Copyright (c) 2012 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 "chrome/browser/spellchecker/spellcheck_message_filter.h" - -#include <algorithm> -#include <functional> - -#include "base/bind.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/spellchecker/spellcheck_factory.h" -#include "chrome/browser/spellchecker/spellcheck_service.h" -#include "components/prefs/pref_service.h" -#include "components/spellcheck/browser/spellcheck_host_metrics.h" -#include "components/spellcheck/browser/spelling_service_client.h" -#include "components/spellcheck/common/spellcheck_messages.h" -#include "components/spellcheck/spellcheck_build_features.h" -#include "content/public/browser/render_process_host.h" -#include "net/url_request/url_fetcher.h" - -using content::BrowserThread; - -SpellCheckMessageFilter::SpellCheckMessageFilter(int render_process_id) - : BrowserMessageFilter(SpellCheckMsgStart), - render_process_id_(render_process_id), - client_(new SpellingServiceClient) { -} - -void SpellCheckMessageFilter::OverrideThreadForMessage( - const IPC::Message& message, BrowserThread::ID* thread) { - // IPC messages arrive on IO thread, but spellcheck data lives on UI thread. - // The message filter overrides the thread for these messages because they - // access spellcheck data. - if (message.type() == SpellCheckHostMsg_RequestDictionary::ID || - message.type() == SpellCheckHostMsg_NotifyChecked::ID) - *thread = BrowserThread::UI; -#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) - if (message.type() == SpellCheckHostMsg_CallSpellingService::ID) - *thread = BrowserThread::UI; -#endif -} - -bool SpellCheckMessageFilter::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(SpellCheckMessageFilter, message) - IPC_MESSAGE_HANDLER(SpellCheckHostMsg_RequestDictionary, - OnSpellCheckerRequestDictionary) - IPC_MESSAGE_HANDLER(SpellCheckHostMsg_NotifyChecked, - OnNotifyChecked) -#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) - IPC_MESSAGE_HANDLER(SpellCheckHostMsg_CallSpellingService, - OnCallSpellingService) -#endif - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - -SpellCheckMessageFilter::~SpellCheckMessageFilter() {} - -void SpellCheckMessageFilter::OnSpellCheckerRequestDictionary() { - content::RenderProcessHost* host = - content::RenderProcessHost::FromID(render_process_id_); - if (!host) - return; // Teardown. - // The renderer has requested that we initialize its spellchecker. This should - // generally only be called once per session, as after the first call, all - // future renderers will be passed the initialization information on startup - // (or when the dictionary changes in some way). - SpellcheckService* spellcheck_service = - SpellcheckServiceFactory::GetForContext(host->GetBrowserContext()); - - DCHECK(spellcheck_service); - // The spellchecker initialization already started and finished; just send - // it to the renderer. - spellcheck_service->InitForRenderer(host); - - // TODO(rlp): Ensure that we do not initialize the hunspell dictionary more - // than once if we get requests from different renderers. -} - -void SpellCheckMessageFilter::OnNotifyChecked(const base::string16& word, - bool misspelled) { - SpellcheckService* spellcheck = GetSpellcheckService(); - // Spellcheck service may not be available for a renderer process that is - // shutting down. - if (!spellcheck) - return; - if (spellcheck->GetMetrics()) - spellcheck->GetMetrics()->RecordCheckedWordStats(word, misspelled); -} - -#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) -void SpellCheckMessageFilter::OnCallSpellingService( - int route_id, - int identifier, - const base::string16& text) { - DCHECK(!text.empty()); - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - CallSpellingService(text, route_id, identifier); -} - -void SpellCheckMessageFilter::OnTextCheckComplete( - int route_id, - int identifier, - bool success, - const base::string16& text, - const std::vector<SpellCheckResult>& results) { - SpellcheckService* spellcheck = GetSpellcheckService(); - // Spellcheck service may not be available for a renderer process that is - // shutting down. - if (!spellcheck) - return; - std::vector<SpellCheckResult> results_copy = results; - - // Erase custom dictionary words from the spellcheck results and record - // in-dictionary feedback. - std::vector<SpellCheckResult>::iterator write_iter; - std::vector<SpellCheckResult>::iterator iter; - std::string text_copy = base::UTF16ToUTF8(text); - for (iter = write_iter = results_copy.begin(); - iter != results_copy.end(); - ++iter) { - if (!spellcheck->GetCustomDictionary()->HasWord( - text_copy.substr(iter->location, iter->length))) { - if (write_iter != iter) - *write_iter = *iter; - ++write_iter; - } - } - results_copy.erase(write_iter, results_copy.end()); - - Send(new SpellCheckMsg_RespondSpellingService( - route_id, identifier, success, text, results_copy)); -} - -// CallSpellingService always executes the callback OnTextCheckComplete. -// (Which, in turn, sends a SpellCheckMsg_RespondSpellingService) -void SpellCheckMessageFilter::CallSpellingService(const base::string16& text, - int route_id, - int identifier) { - content::RenderProcessHost* host = - content::RenderProcessHost::FromID(render_process_id_); - - client_->RequestTextCheck( - host ? host->GetBrowserContext() : NULL, - SpellingServiceClient::SPELLCHECK, text, - base::Bind(&SpellCheckMessageFilter::OnTextCheckComplete, - base::Unretained(this), route_id, identifier)); -} -#endif - -SpellcheckService* SpellCheckMessageFilter::GetSpellcheckService() const { - return SpellcheckServiceFactory::GetForRenderProcessId(render_process_id_); -}
diff --git a/chrome/browser/spellchecker/spellcheck_message_filter.h b/chrome/browser/spellchecker/spellcheck_message_filter.h deleted file mode 100644 index 8f62b1e5..0000000 --- a/chrome/browser/spellchecker/spellcheck_message_filter.h +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright (c) 2012 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 CHROME_BROWSER_SPELLCHECKER_SPELLCHECK_MESSAGE_FILTER_H_ -#define CHROME_BROWSER_SPELLCHECKER_SPELLCHECK_MESSAGE_FILTER_H_ - -#include <stdint.h> - -#include <memory> - -#include "base/compiler_specific.h" -#include "components/spellcheck/browser/spelling_service_client.h" -#include "components/spellcheck/spellcheck_build_features.h" -#include "content/public/browser/browser_message_filter.h" - -class SpellcheckService; -struct SpellCheckResult; - -// A message filter implementation that receives spell checker requests from -// SpellCheckProvider. -class SpellCheckMessageFilter : public content::BrowserMessageFilter { - public: - explicit SpellCheckMessageFilter(int render_process_id); - - // content::BrowserMessageFilter implementation. - void OverrideThreadForMessage(const IPC::Message& message, - content::BrowserThread::ID* thread) override; - bool OnMessageReceived(const IPC::Message& message) override; - - private: - friend class TestingSpellCheckMessageFilter; - - ~SpellCheckMessageFilter() override; - - void OnSpellCheckerRequestDictionary(); - void OnNotifyChecked(const base::string16& word, bool misspelled); -#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) - void OnCallSpellingService(int route_id, - int identifier, - const base::string16& text); - - // A callback function called when the Spelling service finishes checking - // text. Sends the given results to a renderer. - void OnTextCheckComplete( - int route_id, - int identifier, - bool success, - const base::string16& text, - const std::vector<SpellCheckResult>& results); - - // Checks the user profile and sends a JSON-RPC request to the Spelling - // service if a user enables the "Ask Google for suggestions" option. When we - // receive a response (including an error) from the service, it calls - // OnTextCheckComplete. When this function is called before we receive a - // response for the previous request, this function cancels the previous - // request and sends a new one. - void CallSpellingService(const base::string16& text, - int route_id, - int identifier); -#endif - - // Can be overridden for testing. - virtual SpellcheckService* GetSpellcheckService() const; - - int render_process_id_; - - // A JSON-RPC client that calls the Spelling service in the background. - std::unique_ptr<SpellingServiceClient> client_; -}; - -#endif // CHROME_BROWSER_SPELLCHECKER_SPELLCHECK_MESSAGE_FILTER_H_
diff --git a/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc b/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc deleted file mode 100644 index 62d445f9..0000000 --- a/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc +++ /dev/null
@@ -1,148 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> - -#include <memory> -#include <tuple> -#include <vector> - -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/spellchecker/spellcheck_factory.h" -#include "chrome/browser/spellchecker/spellcheck_message_filter.h" -#include "chrome/browser/spellchecker/spellcheck_service.h" -#include "chrome/test/base/testing_profile.h" -#include "components/spellcheck/common/spellcheck_messages.h" -#include "components/spellcheck/spellcheck_build_features.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "ipc/ipc_message.h" -#include "testing/gtest/include/gtest/gtest.h" - -class TestingSpellCheckMessageFilter : public SpellCheckMessageFilter { - public: - TestingSpellCheckMessageFilter() - : SpellCheckMessageFilter(0), - spellcheck_(new SpellcheckService(&profile_)) {} - - bool Send(IPC::Message* message) override { - sent_messages.push_back(base::WrapUnique(message)); - return true; - } - - SpellcheckService* GetSpellcheckService() const override { - return spellcheck_.get(); - } - -#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) - void OnTextCheckComplete(int route_id, - int identifier, - bool success, - const base::string16& text, - const std::vector<SpellCheckResult>& results) { - SpellCheckMessageFilter::OnTextCheckComplete(route_id, identifier, success, - text, results); - } -#endif - - std::vector<std::unique_ptr<IPC::Message>> sent_messages; - - private: - ~TestingSpellCheckMessageFilter() override {} - - content::TestBrowserThreadBundle thread_bundle_; - TestingProfile profile_; - std::unique_ptr<SpellcheckService> spellcheck_; - - DISALLOW_COPY_AND_ASSIGN(TestingSpellCheckMessageFilter); -}; - -TEST(SpellCheckMessageFilterTest, TestOverrideThread) { - static const uint32_t kSpellcheckMessages[] = { - SpellCheckHostMsg_RequestDictionary::ID, - SpellCheckHostMsg_NotifyChecked::ID, -#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) - SpellCheckHostMsg_CallSpellingService::ID, -#endif - }; - content::BrowserThread::ID thread; - IPC::Message message; - scoped_refptr<TestingSpellCheckMessageFilter> filter( - new TestingSpellCheckMessageFilter); - for (size_t i = 0; i < arraysize(kSpellcheckMessages); ++i) { - message.SetHeaderValues( - 0, kSpellcheckMessages[i], IPC::Message::PRIORITY_NORMAL); - thread = content::BrowserThread::IO; - filter->OverrideThreadForMessage(message, &thread); - EXPECT_EQ(content::BrowserThread::UI, thread); - } -} - -#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) -TEST(SpellCheckMessageFilterTest, OnTextCheckCompleteTestCustomDictionary) { - static const std::string kCustomWord = "Helllo"; - static const int kRouteId = 0; - static const int kCallbackId = 0; - static const base::string16 kText = base::ASCIIToUTF16("Helllo warld."); - static const bool kSuccess = true; - static const SpellCheckResult::Decoration kDecoration = - SpellCheckResult::SPELLING; - static const int kLocation = 7; - static const int kLength = 5; - static const base::string16 kReplacement = base::ASCIIToUTF16("world"); - - std::vector<SpellCheckResult> results; - results.push_back(SpellCheckResult( - SpellCheckResult::SPELLING, 0, 6, base::ASCIIToUTF16("Hello"))); - results.push_back( - SpellCheckResult(kDecoration, kLocation, kLength, kReplacement)); - - scoped_refptr<TestingSpellCheckMessageFilter> filter( - new TestingSpellCheckMessageFilter); - filter->GetSpellcheckService()->GetCustomDictionary()->AddWord(kCustomWord); - filter->OnTextCheckComplete(kRouteId, kCallbackId, kSuccess, kText, results); - ASSERT_EQ(1U, filter->sent_messages.size()); - - SpellCheckMsg_RespondSpellingService::Param params; - bool ok = SpellCheckMsg_RespondSpellingService::Read( - filter->sent_messages[0].get(), ¶ms); - int sent_identifier = std::get<0>(params); - bool sent_success = std::get<1>(params); - base::string16 sent_text = std::get<2>(params); - std::vector<SpellCheckResult> sent_results = std::get<3>(params); - EXPECT_TRUE(ok); - EXPECT_EQ(kCallbackId, sent_identifier); - EXPECT_EQ(kSuccess, sent_success); - EXPECT_EQ(kText, sent_text); - ASSERT_EQ(1U, sent_results.size()); - EXPECT_EQ(kDecoration, sent_results[0].decoration); - EXPECT_EQ(kLocation, sent_results[0].location); - EXPECT_EQ(kLength, sent_results[0].length); - EXPECT_EQ(kReplacement, sent_results[0].replacement); -} - -TEST(SpellCheckMessageFilterTest, OnTextCheckCompleteTest) { - std::vector<SpellCheckResult> results; - results.push_back(SpellCheckResult( - SpellCheckResult::SPELLING, 0, 6, base::ASCIIToUTF16("Hello"))); - results.push_back(SpellCheckResult( - SpellCheckResult::SPELLING, 7, 7, base::ASCIIToUTF16("world"))); - - scoped_refptr<TestingSpellCheckMessageFilter> filter( - new TestingSpellCheckMessageFilter); - filter->OnTextCheckComplete(1, 1, true, base::ASCIIToUTF16("Helllo walrd"), - results); - ASSERT_EQ(1U, filter->sent_messages.size()); - - SpellCheckMsg_RespondSpellingService::Param params; - bool ok = SpellCheckMsg_RespondSpellingService::Read( - filter->sent_messages[0].get(), ¶ms); - EXPECT_TRUE(ok); - - std::vector<SpellCheckResult> sent_results = std::get<3>(params); - EXPECT_EQ(2U, sent_results.size()); -} -#endif
diff --git a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc index 5abe4b7..2afbf90 100644 --- a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc +++ b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
@@ -4,54 +4,40 @@ #include "chrome/browser/spellchecker/spellcheck_service.h" -#include <stddef.h> -#include <stdint.h> #include <string> -#include <tuple> #include <vector> -#include "base/command_line.h" #include "base/macros.h" #include "base/path_service.h" #include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" #include "base/synchronization/waitable_event.h" +#include "base/test/histogram_tester.h" #include "base/threading/thread_restrictions.h" #include "base/values.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/spellchecker/spell_check_host_impl.h" #include "chrome/browser/spellchecker/spellcheck_factory.h" +#include "chrome/browser/spellchecker/spellcheck_service.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/prefs/pref_service.h" #include "components/spellcheck/browser/pref_names.h" #include "components/spellcheck/common/spellcheck.mojom.h" #include "components/spellcheck/common/spellcheck_common.h" +#include "components/spellcheck/common/spellcheck_result.h" #include "components/user_prefs/user_prefs.h" #include "content/public/test/mock_render_process_host.h" #include "content/public/test/test_utils.h" -#include "url/gurl.h" +#include "services/service_manager/public/cpp/bind_source_info.h" using content::BrowserContext; - -namespace { - -// A corrupted BDICT data used in DeleteCorruptedBDICT. Please do not use this -// BDICT data for other tests. -const uint8_t kCorruptedBDICT[] = { - 0x42, 0x44, 0x69, 0x63, 0x02, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x3b, 0x00, 0x00, 0x00, 0x65, 0x72, 0xe0, 0xac, 0x27, 0xc7, 0xda, 0x66, - 0x6d, 0x1e, 0xa6, 0x35, 0xd1, 0xf6, 0xb7, 0x35, 0x32, 0x00, 0x00, 0x00, - 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, - 0x0a, 0x0a, 0x41, 0x46, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, - 0x49, 0x00, 0x68, 0x02, 0x73, 0x06, 0x74, 0x0b, 0x77, 0x11, 0x79, 0x15, -}; - -} // namespace +using content::RenderProcessHost; class SpellcheckServiceBrowserTest : public InProcessBrowserTest, public spellcheck::mojom::SpellChecker { @@ -69,13 +55,13 @@ renderer_.reset(); } - BrowserContext* GetContext() { + RenderProcessHost* GetRenderer() const { return renderer_.get(); } + + BrowserContext* GetContext() const { return static_cast<BrowserContext*>(browser()->profile()); } - PrefService* GetPrefs() { - return prefs_; - } + PrefService* GetPrefs() const { return prefs_; } void InitSpellcheck(bool enable_spellcheck, const std::string& single_dictionary, @@ -208,6 +194,11 @@ EXPECT_EQ(2u, words_added.size()); } + protected: + // Quits the RunLoop on Mojo request flow completion. + base::OnceClosure quit_; + + private: // Mocked RenderProcessHost. std::unique_ptr<content::MockRenderProcessHost> renderer_; @@ -217,9 +208,6 @@ // Binding to receive the SpellChecker request flow. mojo::Binding<spellcheck::mojom::SpellChecker> binding_; - // Quits the RunLoop on SpellChecker request flow completion. - base::OnceClosure quit_; - // Used to verify the SpellChecker request flow. bool bound_connection_closed_; bool custom_dictionary_changed_called_; @@ -229,6 +217,64 @@ DISALLOW_COPY_AND_ASSIGN(SpellcheckServiceBrowserTest); }; +class SpellcheckServiceHostBrowserTest : public SpellcheckServiceBrowserTest { + public: + SpellcheckServiceHostBrowserTest() = default; + + void RequestDictionary() { + spellcheck::mojom::SpellCheckHostPtr interface; + RequestSpellCheckHost(&interface); + + interface->RequestDictionary(); + } + + void NotifyChecked() { + spellcheck::mojom::SpellCheckHostPtr interface; + RequestSpellCheckHost(&interface); + + const bool misspelt = true; + base::UTF8ToUTF16("hallo", 5, &word_); + interface->NotifyChecked(word_, misspelt); + base::RunLoop().RunUntilIdle(); + } + + void CallSpellingService() { + spellcheck::mojom::SpellCheckHostPtr interface; + RequestSpellCheckHost(&interface); + + base::UTF8ToUTF16("hello", 5, &word_); + interface->CallSpellingService( + word_, + base::Bind(&SpellcheckServiceHostBrowserTest::SpellingServiceDone, + base::Unretained(this))); + + base::RunLoop run_loop; + quit_ = run_loop.QuitClosure(); + run_loop.Run(); + + EXPECT_TRUE(spelling_service_done_called_); + } + + private: + void RequestSpellCheckHost(spellcheck::mojom::SpellCheckHostPtr* interface) { + SpellCheckHostImpl::Create(GetRenderer()->GetID(), + service_manager::BindSourceInfo(), + mojo::MakeRequest(interface)); + } + + void SpellingServiceDone(bool success, + const std::vector<::SpellCheckResult>& results) { + spelling_service_done_called_ = true; + if (quit_) + std::move(quit_).Run(); + } + + bool spelling_service_done_called_ = false; + base::string16 word_; + + DISALLOW_COPY_AND_ASSIGN(SpellcheckServiceHostBrowserTest); +}; + // Removing a spellcheck language from accept languages should remove it from // spellcheck languages list as well. IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest, @@ -334,9 +380,49 @@ EXPECT_TRUE(GetCustomDictionaryChangedState()); } +// Starting with only a single-language spellcheck setting, the host should +// initialize the renderer's spellcheck system, and the same if the renderer +// explicity requests the spellcheck dictionaries. +IN_PROC_BROWSER_TEST_F(SpellcheckServiceHostBrowserTest, RequestDictionary) { + InitSpellcheck(true, "en-US", ""); + EXPECT_TRUE(GetEnableSpellcheckState()); + + RequestDictionary(); + EXPECT_TRUE(GetEnableSpellcheckState()); +} + +// When the renderer notifies that it corrected a word, the render process +// host should record UMA stats about the correction. +IN_PROC_BROWSER_TEST_F(SpellcheckServiceHostBrowserTest, NotifyChecked) { + const char kMisspellRatio[] = "SpellCheck.MisspellRatio"; + + base::HistogramTester tester; + tester.ExpectTotalCount(kMisspellRatio, 0); + NotifyChecked(); + tester.ExpectTotalCount(kMisspellRatio, 1); +} + +#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) +// When the renderer requests the spelling service for correcting text, the +// render process host should call the remote spelling service. +IN_PROC_BROWSER_TEST_F(SpellcheckServiceHostBrowserTest, CallSpellingService) { + CallSpellingService(); +} +#endif // !BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // Tests that we can delete a corrupted BDICT file used by hunspell. We do not // run this test on Mac because Mac does not use hunspell by default. IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest, DeleteCorruptedBDICT) { + // Corrupted BDICT data: please do not use this BDICT data for other tests. + const uint8_t kCorruptedBDICT[] = { + 0x42, 0x44, 0x69, 0x63, 0x02, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x3b, 0x00, 0x00, 0x00, 0x65, 0x72, 0xe0, 0xac, 0x27, 0xc7, 0xda, 0x66, + 0x6d, 0x1e, 0xa6, 0x35, 0xd1, 0xf6, 0xb7, 0x35, 0x32, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, + 0x0a, 0x0a, 0x41, 0x46, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, + 0x49, 0x00, 0x68, 0x02, 0x73, 0x06, 0x74, 0x0b, 0x77, 0x11, 0x79, 0x15, + }; + // Write the corrupted BDICT data to create a corrupted BDICT file. base::FilePath dict_dir; ASSERT_TRUE(PathService::Get(chrome::DIR_APP_DICTIONARIES, &dict_dir));
diff --git a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc index 521277b8b..a7e62da5 100644 --- a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc +++ b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
@@ -86,6 +86,11 @@ AddLocalizedString(source, "title", IDS_MD_BOOKMARK_MANAGER_TITLE); // Resources. +#if BUILDFLAG(USE_VULCANIZE) + source->AddResourcePath("crisper.js", IDR_MD_BOOKMARKS_CRISPER_JS); + source->SetDefaultResource(IDR_MD_BOOKMARKS_VULCANIZED_HTML); + source->UseGzip(std::unordered_set<std::string>()); +#else source->AddResourcePath("actions.html", IDR_MD_BOOKMARKS_ACTIONS_HTML); source->AddResourcePath("actions.js", IDR_MD_BOOKMARKS_ACTIONS_JS); source->AddResourcePath("api_listener.html", @@ -131,7 +136,10 @@ source->AddResourcePath("toolbar.js", IDR_MD_BOOKMARKS_TOOLBAR_JS); source->AddResourcePath("util.html", IDR_MD_BOOKMARKS_UTIL_HTML); source->AddResourcePath("util.js", IDR_MD_BOOKMARKS_UTIL_JS); + source->SetDefaultResource(IDR_MD_BOOKMARKS_BOOKMARKS_HTML); +#endif + source->SetJsonPath("strings.js"); return source;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index e0cb84f5..692da7f 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3786,11 +3786,14 @@ sources += [ "../browser/spellchecker/spellcheck_custom_dictionary_unittest.cc", "../browser/spellchecker/spellcheck_message_filter_platform_mac_unittest.cc", - "../browser/spellchecker/spellcheck_message_filter_unittest.cc", "../browser/spellchecker/spellcheck_service_unittest.cc", "../browser/spellchecker/spelling_service_client_unittest.cc", "../tools/convert_dict/convert_dict_unittest.cc", ] + + if (!use_browser_spellchecker) { + sources += [ "../browser/spellchecker/spell_check_host_impl_unittest.cc" ] + } } if (enable_one_click_signin) {
diff --git a/components/spellcheck/common/OWNERS b/components/spellcheck/common/OWNERS index ef88cc7..ed454dad 100644 --- a/components/spellcheck/common/OWNERS +++ b/components/spellcheck/common/OWNERS
@@ -2,3 +2,5 @@ per-file *_messages*.h=file://ipc/SECURITY_OWNERS per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS +per-file *.typemap=set noparent +per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/components/spellcheck/common/spellcheck.mojom b/components/spellcheck/common/spellcheck.mojom index 9195261..33b818f 100644 --- a/components/spellcheck/common/spellcheck.mojom +++ b/components/spellcheck/common/spellcheck.mojom
@@ -5,13 +5,15 @@ module spellcheck.mojom; import "mojo/common/file.mojom"; +import "mojo/common/string16.mojom"; // Render process interface exposed to the browser for receiving process- // wide spellcheck control and updates from the browser process. // interface SpellChecker { // Initialize the render process spellchecker. Called after startup and - // also in response to a render process RequestDictionary request. + // also in response to a renderer's spellcheck::mojom::SpellCheckHost + // RequestDictionary request. Initialize(array<SpellCheckBDictLanguage> dictionaries, array<string> custom_words, bool enable); @@ -26,3 +28,27 @@ mojo.common.mojom.File? file; string language; }; + +// Browser process interface exposed to the renderer for requesting spell- +// check host services. +// +interface SpellCheckHost { + // Asks the browser to initialize the renderer's spellcheck system. The + // initialize call arrives on interface spellcheck::mojom::SpellChecker + // in async response to this request. + RequestDictionary(); + + // Tracks spell checking occurrences to collect histograms, where |word| + // was checked, and |misspelled| is true if |word| was misspelt. + NotifyChecked(mojo.common.mojom.String16 word, bool misspelled); + + // Asks the host to spellcheck the |text| using a remote Spelling server + // to do the spellchecking. If the remote Spelling server is available, + // returns |success| true, and the spellchecked |results|. Note this API + // requires a !BUILDFLAG(USE_BROWSER_SPELLCHECKER) build. + CallSpellingService(mojo.common.mojom.String16 text) => + (bool success, array<SpellCheckResult> results); +}; + +[Native] +struct SpellCheckResult;
diff --git a/components/spellcheck/common/spellcheck.typemap b/components/spellcheck/common/spellcheck.typemap new file mode 100644 index 0000000..468241c --- /dev/null +++ b/components/spellcheck/common/spellcheck.typemap
@@ -0,0 +1,15 @@ +# 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. + +mojom = "//components/spellcheck/common/spellcheck.mojom" + +public_headers = [ "//components/spellcheck/common/spellcheck_result.h" ] + +traits_headers = [ "//components/spellcheck/common/spellcheck_messages.h" ] + +deps = [ + "//components/spellcheck:build_features", +] + +type_mappings = [ "spellcheck.mojom.SpellCheckResult=::SpellCheckResult" ]
diff --git a/components/spellcheck/common/spellcheck_messages.h b/components/spellcheck/common/spellcheck_messages.h index e8e83a8..fbb69e4 100644 --- a/components/spellcheck/common/spellcheck_messages.h +++ b/components/spellcheck/common/spellcheck_messages.h
@@ -12,7 +12,7 @@ #include "ipc/ipc_message_macros.h" #if !BUILDFLAG(ENABLE_SPELLCHECK) -#error "Spellcheck should be enabled" +#error "Spellcheck should be enabled." #endif #define IPC_MESSAGE_START SpellCheckMsgStart @@ -28,18 +28,6 @@ // Messages sent from the browser to the renderer. -#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) -// Sends text-check results from the Spelling service when the service finishes -// checking text received by a SpellCheckHostMsg_CallSpellingService message. -// If the service is not available, the 4th parameter should be false and the -// 5th parameter should contain the requested sentence. -IPC_MESSAGE_ROUTED4(SpellCheckMsg_RespondSpellingService, - int /* request identifier given by WebKit */, - bool /* succeeded calling service */, - base::string16 /* sentence */, - std::vector<SpellCheckResult>) -#endif - #if BUILDFLAG(USE_BROWSER_SPELLCHECKER) // Sends when NSSpellChecker finishes checking text received by a preceding // SpellCheckHostMsg_RequestTextCheck message. @@ -59,26 +47,6 @@ // Messages sent from the renderer to the browser. -// The renderer has tried to spell check a word, but couldn't because no -// dictionary was available to load. Request that the browser find an -// appropriate dictionary and return it. -IPC_MESSAGE_CONTROL0(SpellCheckHostMsg_RequestDictionary) - -// Tracks spell checking occurrence to collect histogram. -IPC_MESSAGE_ROUTED2(SpellCheckHostMsg_NotifyChecked, - base::string16 /* word */, - bool /* true if checked word is misspelled */) - -#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) -// Asks the Spelling service to check text. When the service finishes checking -// the input text, it sends a SpellingCheckMsg_RespondSpellingService with -// text-check results. -IPC_MESSAGE_CONTROL3(SpellCheckHostMsg_CallSpellingService, - int /* route_id for response */, - int /* request identifier given by WebKit */, - base::string16 /* sentence */) -#endif - #if BUILDFLAG(USE_BROWSER_SPELLCHECKER) // TODO(groby): This needs to originate from SpellcheckProvider. IPC_SYNC_MESSAGE_CONTROL2_1(SpellCheckHostMsg_CheckSpelling,
diff --git a/components/spellcheck/renderer/hunspell_engine.cc b/components/spellcheck/renderer/hunspell_engine.cc index c385348..4ef0267 100644 --- a/components/spellcheck/renderer/hunspell_engine.cc +++ b/components/spellcheck/renderer/hunspell_engine.cc
@@ -11,10 +11,12 @@ #include "base/files/memory_mapped_file.h" #include "base/time/time.h" +#include "components/spellcheck/common/spellcheck.mojom.h" #include "components/spellcheck/common/spellcheck_common.h" -#include "components/spellcheck/common/spellcheck_messages.h" #include "components/spellcheck/spellcheck_build_features.h" +#include "content/public/common/service_names.mojom.h" #include "content/public/renderer/render_thread.h" +#include "services/service_manager/public/cpp/connector.h" #include "third_party/hunspell/src/hunspell/hunspell.hxx" using content::RenderThread; @@ -119,8 +121,12 @@ bool HunspellEngine::InitializeIfNeeded() { if (!initialized_ && !dictionary_requested_) { // RenderThread will not exist in test. - if (RenderThread::Get()) - RenderThread::Get()->Send(new SpellCheckHostMsg_RequestDictionary); + if (RenderThread::Get()) { + spellcheck::mojom::SpellCheckHostPtr spell_check_host; + RenderThread::Get()->GetConnector()->BindInterface( + content::mojom::kBrowserServiceName, &spell_check_host); + spell_check_host->RequestDictionary(); + } dictionary_requested_ = true; return true; }
diff --git a/components/spellcheck/renderer/spellcheck.cc b/components/spellcheck/renderer/spellcheck.cc index 4ef53a06..c34a181f 100644 --- a/components/spellcheck/renderer/spellcheck.cc +++ b/components/spellcheck/renderer/spellcheck.cc
@@ -203,7 +203,7 @@ void SpellCheck::SpellCheckerRequest( const service_manager::BindSourceInfo& source_info, spellcheck::mojom::SpellCheckerRequest request) { - spellchecker_bindings_.AddBinding(this, std::move(request)); + bindings_.AddBinding(this, std::move(request)); } void SpellCheck::Initialize(
diff --git a/components/spellcheck/renderer/spellcheck.h b/components/spellcheck/renderer/spellcheck.h index c5a839f7..4dd5c714 100644 --- a/components/spellcheck/renderer/spellcheck.h +++ b/components/spellcheck/renderer/spellcheck.h
@@ -153,7 +153,7 @@ #endif // Bindings for SpellChecker clients. - mojo::BindingSet<spellcheck::mojom::SpellChecker> spellchecker_bindings_; + mojo::BindingSet<spellcheck::mojom::SpellChecker> bindings_; // A vector of objects used to actually check spelling, one for each enabled // language.
diff --git a/components/spellcheck/renderer/spellcheck_provider.cc b/components/spellcheck/renderer/spellcheck_provider.cc index abd2cd5..1807349e 100644 --- a/components/spellcheck/renderer/spellcheck_provider.cc +++ b/components/spellcheck/renderer/spellcheck_provider.cc
@@ -4,13 +4,18 @@ #include "components/spellcheck/renderer/spellcheck_provider.h" +#include "base/bind.h" #include "base/metrics/histogram_macros.h" +#include "components/spellcheck/common/spellcheck.mojom.h" #include "components/spellcheck/common/spellcheck_messages.h" #include "components/spellcheck/common/spellcheck_result.h" #include "components/spellcheck/renderer/spellcheck.h" #include "components/spellcheck/renderer/spellcheck_language.h" #include "components/spellcheck/spellcheck_build_features.h" +#include "content/public/common/service_names.mojom.h" #include "content/public/renderer/render_frame.h" +#include "content/public/renderer/render_thread.h" +#include "services/service_manager/public/cpp/connector.h" #include "third_party/WebKit/public/platform/WebVector.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebElement.h" @@ -47,6 +52,16 @@ SpellCheckProvider::~SpellCheckProvider() { } +spellcheck::mojom::SpellCheckHost& SpellCheckProvider::GetSpellCheckHost() { + if (spell_check_host_) + return *spell_check_host_; + + DCHECK(content::RenderThread::Get()); + content::RenderThread::Get()->GetConnector()->BindInterface( + content::mojom::kBrowserServiceName, &spell_check_host_); + return *spell_check_host_; +} + void SpellCheckProvider::RequestTextChecking( const base::string16& text, WebTextCheckingCompletion* completion) { @@ -64,34 +79,36 @@ // this text to the Spelling service only if a user enables this feature. last_request_.clear(); last_results_.Assign(blink::WebVector<blink::WebTextCheckingResult>()); + last_identifier_ = text_check_completions_.Add(completion); #if BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // TODO(crbug.com/714480): convert the RequestTextCheck IPC to mojo. // Text check (unified request for grammar and spell check) is only // available for browser process, so we ask the system spellchecker - // over IPC or return an empty result if the checker is not - // available. - Send(new SpellCheckHostMsg_RequestTextCheck( - routing_id(), text_check_completions_.Add(completion), text)); + // over IPC or return an empty result if the checker is not available. + Send(new SpellCheckHostMsg_RequestTextCheck(routing_id(), last_identifier_, + text)); #else - Send(new SpellCheckHostMsg_CallSpellingService( - routing_id(), text_check_completions_.Add(completion), - base::string16(text))); + if (!spell_check_host_ && !content::RenderThread::Get()) + return; // NULL in tests that do not provide a spell_check_host_. + GetSpellCheckHost().CallSpellingService( + text, base::Bind(&SpellCheckProvider::OnRespondSpellingService, + base::Unretained(this), last_identifier_, text)); #endif // !USE_BROWSER_SPELLCHECKER } bool SpellCheckProvider::OnMessageReceived(const IPC::Message& message) { +#if BUILDFLAG(USE_BROWSER_SPELLCHECKER) bool handled = true; IPC_BEGIN_MESSAGE_MAP(SpellCheckProvider, message) -#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) - IPC_MESSAGE_HANDLER(SpellCheckMsg_RespondSpellingService, - OnRespondSpellingService) -#endif -#if BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // TODO(crbug.com/714480): convert the RequestTextCheck IPC to mojo. IPC_MESSAGE_HANDLER(SpellCheckMsg_RespondTextCheck, OnRespondTextCheck) -#endif IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; +#else + return false; +#endif } void SpellCheckProvider::FocusedNodeChanged(const blink::WebNode& unused) { @@ -103,6 +120,7 @@ bool enabled = !element.IsNull() && element.IsEditable(); bool checked = enabled && frame->IsSpellCheckingEnabled(); + // TODO(crbug.com/714480): convert the ToggleSpellCheck IPC to mojo. Send(new SpellCheckHostMsg_ToggleSpellCheck(routing_id(), enabled, checked)); #endif // USE_BROWSER_SPELLCHECKER } @@ -129,7 +147,9 @@ UMA_HISTOGRAM_COUNTS("SpellCheck.api.check", word.size()); // If optional_suggestions is not requested, the API is called // for marking. So we use this for counting markable words. - Send(new SpellCheckHostMsg_NotifyChecked(routing_id(), word, 0 < length)); + if (!spell_check_host_ && !content::RenderThread::Get()) + return; // NULL in tests that do not provide a spell_check_host_. + GetSpellCheckHost().NotifyChecked(word, 0 < length); } } @@ -151,8 +171,8 @@ #if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) void SpellCheckProvider::OnRespondSpellingService( int identifier, - bool succeeded, const base::string16& line, + bool success, const std::vector<SpellCheckResult>& results) { WebTextCheckingCompletion* completion = text_check_completions_.Lookup(identifier); @@ -160,8 +180,8 @@ return; text_check_completions_.Remove(identifier); - // If |succeeded| is false, we use local spellcheck as a fallback. - if (!succeeded) { + // If |success| is false, we use local spellcheck as a fallback. + if (!success) { spellcheck_->RequestTextChecking(line, completion); return; }
diff --git a/components/spellcheck/renderer/spellcheck_provider.h b/components/spellcheck/renderer/spellcheck_provider.h index cead107..d31e110 100644 --- a/components/spellcheck/renderer/spellcheck_provider.h +++ b/components/spellcheck/renderer/spellcheck_provider.h
@@ -5,13 +5,11 @@ #ifndef COMPONENTS_SPELLCHECK_RENDERER_SPELLCHECK_PROVIDER_H_ #define COMPONENTS_SPELLCHECK_RENDERER_SPELLCHECK_PROVIDER_H_ -#include <stddef.h> -#include <stdint.h> - #include <vector> #include "base/id_map.h" #include "base/macros.h" +#include "components/spellcheck/common/spellcheck.mojom.h" #include "components/spellcheck/spellcheck_build_features.h" #include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_frame_observer_tracker.h" @@ -25,8 +23,8 @@ struct WebTextCheckingResult; } -// This class deals with invoking browser-side spellcheck mechanism -// which is done asynchronously. +// This class deals with asynchronously invoking text spelling and grammar +// checking services provided by the browser process (host). class SpellCheckProvider : public content::RenderFrameObserver, public content::RenderFrameObserverTracker<SpellCheckProvider>, @@ -38,14 +36,14 @@ SpellCheck* spellcheck); ~SpellCheckProvider() override; - // Requests async spell and grammar checker to the platform text - // checker, which is available on the browser process. The function does not - // have special handling for partial words, as Blink guarantees that no - // request is made when typing in the middle of a word. + // Requests async spell and grammar checks from the platform text checker + // available in the browser process. The function does not have special + // handling for partial words, as Blink guarantees that no request is made + // when typing in the middle of a word. void RequestTextChecking(const base::string16& text, blink::WebTextCheckingCompletion* completion); - // The number of ongoing IPC requests. + // The number of ongoing spell check host requests. size_t pending_text_request_size() const { return text_check_completions_.size(); } @@ -56,23 +54,31 @@ // Enables document-wide spellchecking. void EnableSpellcheck(bool enabled); - // RenderFrameObserver implementation. + // content::RenderFrameObserver: bool OnMessageReceived(const IPC::Message& message) override; void FocusedNodeChanged(const blink::WebNode& node) override; private: friend class TestingSpellCheckProvider; - // Tries to satisfy a spell check request from the cache in |last_request_|. + // Sets the SpellCheckHost (for unit tests). + void SetSpellCheckHostForTesting(spellcheck::mojom::SpellCheckHostPtr host) { + spell_check_host_ = std::move(host); + } + + // Returns the SpellCheckHost. + spellcheck::mojom::SpellCheckHost& GetSpellCheckHost(); + + // Tries to satisfy a spellcheck request from the cache in |last_request_|. // Returns true (and cancels/finishes the completion) if it can, false // if the provider should forward the query on. bool SatisfyRequestFromCache(const base::string16& text, blink::WebTextCheckingCompletion* completion); - // RenderFrameObserver implementation. + // content::RenderFrameObserver: void OnDestruct() override; - // blink::WebTextCheckClient implementation. + // blink::WebTextCheckClient: void CheckSpelling( const blink::WebString& text, int& offset, @@ -84,11 +90,10 @@ void CancelAllPendingRequests() override; #if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) - void OnRespondSpellingService( - int identifier, - bool succeeded, - const base::string16& text, - const std::vector<SpellCheckResult>& results); + void OnRespondSpellingService(int identifier, + const base::string16& text, + bool success, + const std::vector<SpellCheckResult>& results); #endif // Returns whether |text| has word characters, i.e. whether a spellchecker @@ -102,17 +107,21 @@ const std::vector<SpellCheckResult>& results); #endif - // Holds ongoing spellchecking operations, assigns IDs for the IPC routing. + // Holds ongoing spellchecking operations. WebTextCheckCompletions text_check_completions_; - // The last text sent to the browser process to spellcheck it and its - // spellchecking results. + // The last text sent to the browser process for spellchecking, and its + // spellcheck results and WebTextCheckCompletions identifier. base::string16 last_request_; blink::WebVector<blink::WebTextCheckingResult> last_results_; + int last_identifier_; - // Weak pointer to shared (per RenderView) spellcheck data. + // Weak pointer to shared (per renderer) spellcheck data. SpellCheck* spellcheck_; + // Interface to the SpellCheckHost. + spellcheck::mojom::SpellCheckHostPtr spell_check_host_; + DISALLOW_COPY_AND_ASSIGN(SpellCheckProvider); };
diff --git a/components/spellcheck/renderer/spellcheck_provider_hunspell_unittest.cc b/components/spellcheck/renderer/spellcheck_provider_hunspell_unittest.cc index 34ab0a6..40269b8 100644 --- a/components/spellcheck/renderer/spellcheck_provider_hunspell_unittest.cc +++ b/components/spellcheck/renderer/spellcheck_provider_hunspell_unittest.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <vector> - -#include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "components/spellcheck/renderer/spellcheck_provider_test.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/public/platform/WebString.h" // Tests for Hunspell functionality in SpellcheckingProvider @@ -17,14 +13,6 @@ namespace { -TEST_F(SpellCheckProviderTest, UsingHunspell) { - FakeTextCheckingCompletion completion; - provider_.RequestTextChecking(ASCIIToUTF16("hello"), &completion); - EXPECT_EQ(completion.completion_count_, 1U); - EXPECT_EQ(provider_.messages_.size(), 0U); - EXPECT_EQ(provider_.pending_text_request_size(), 0U); -} - // Tests that the SpellCheckProvider object sends a spellcheck request when a // user finishes typing a word. Also this test verifies that this object checks // only a line being edited by the user. @@ -35,18 +23,21 @@ provider_.ResetResult(); provider_.RequestTextChecking(base::string16(), &completion); EXPECT_TRUE(provider_.text_.empty()); + EXPECT_EQ(provider_.spelling_service_call_count_, 0U); // Verify that the SpellCheckProvider class spellcheck the first word when we // stop typing after finishing the first word. provider_.ResetResult(); provider_.RequestTextChecking(ASCIIToUTF16("First"), &completion); EXPECT_EQ(ASCIIToUTF16("First"), provider_.text_); + EXPECT_EQ(provider_.spelling_service_call_count_, 1U); // Verify that the SpellCheckProvider class spellcheck the first line when we // type a return key, i.e. when we finish typing a line. provider_.ResetResult(); provider_.RequestTextChecking(ASCIIToUTF16("First Second\n"), &completion); EXPECT_EQ(ASCIIToUTF16("First Second\n"), provider_.text_); + EXPECT_EQ(provider_.spelling_service_call_count_, 2U); // Verify that the SpellCheckProvider class spellcheck the lines when we // finish typing a word "Third" to the second line. @@ -54,6 +45,7 @@ provider_.RequestTextChecking(ASCIIToUTF16("First Second\nThird "), &completion); EXPECT_EQ(ASCIIToUTF16("First Second\nThird "), provider_.text_); + EXPECT_EQ(provider_.spelling_service_call_count_, 3U); // Verify that the SpellCheckProvider class does not send a spellcheck request // when a user inserts whitespace characters. @@ -61,6 +53,7 @@ provider_.RequestTextChecking(ASCIIToUTF16("First Second\nThird "), &completion); EXPECT_TRUE(provider_.text_.empty()); + EXPECT_EQ(provider_.spelling_service_call_count_, 3U); // Verify that the SpellCheckProvider class spellcheck the lines when we type // a period. @@ -68,6 +61,7 @@ provider_.RequestTextChecking(ASCIIToUTF16("First Second\nThird Fourth."), &completion); EXPECT_EQ(ASCIIToUTF16("First Second\nThird Fourth."), provider_.text_); + EXPECT_EQ(provider_.spelling_service_call_count_, 4U); } // Tests that the SpellCheckProvider class does not send requests to the
diff --git a/components/spellcheck/renderer/spellcheck_provider_test.cc b/components/spellcheck/renderer/spellcheck_provider_test.cc index ffba9d1..595ecd0 100644 --- a/components/spellcheck/renderer/spellcheck_provider_test.cc +++ b/components/spellcheck/renderer/spellcheck_provider_test.cc
@@ -5,19 +5,16 @@ #include "components/spellcheck/renderer/spellcheck_provider_test.h" #include "base/memory/ptr_util.h" -#include "base/stl_util.h" -#include "components/spellcheck/common/spellcheck_messages.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "components/spellcheck/common/spellcheck.mojom.h" +#include "components/spellcheck/common/spellcheck_result.h" #include "components/spellcheck/renderer/spellcheck.h" #include "components/spellcheck/spellcheck_build_features.h" -#include "ipc/ipc_message_macros.h" - -class MockSpellcheck: public SpellCheck { -}; +#include "ipc/ipc_message.h" FakeTextCheckingCompletion::FakeTextCheckingCompletion() -: completion_count_(0), - cancellation_count_(0) { -} + : completion_count_(0), cancellation_count_(0) {} FakeTextCheckingCompletion::~FakeTextCheckingCompletion() {} @@ -32,62 +29,76 @@ } TestingSpellCheckProvider::TestingSpellCheckProvider() - : SpellCheckProvider(NULL, new MockSpellcheck), - spelling_service_call_count_(0) { -} + : SpellCheckProvider(nullptr, new SpellCheck), + spelling_service_call_count_(0), + binding_(this) {} -TestingSpellCheckProvider::TestingSpellCheckProvider( - SpellCheck* spellcheck) +TestingSpellCheckProvider::TestingSpellCheckProvider(SpellCheck* spellcheck) : SpellCheckProvider(nullptr, spellcheck), - spelling_service_call_count_(0) { -} + spelling_service_call_count_(0), + binding_(this) {} TestingSpellCheckProvider::~TestingSpellCheckProvider() { + binding_.Close(); delete spellcheck_; } -bool TestingSpellCheckProvider::Send(IPC::Message* message) { +void TestingSpellCheckProvider::RequestTextChecking( + const base::string16& text, + blink::WebTextCheckingCompletion* completion) { #if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) - // Call our mock message handlers. - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(TestingSpellCheckProvider, *message) - IPC_MESSAGE_HANDLER(SpellCheckHostMsg_CallSpellingService, - OnCallSpellingService) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - - if (handled) { - delete message; - return true; - } + if (!loop_ && !base::MessageLoop::current()) + loop_ = base::MakeUnique<base::MessageLoop>(); + if (!binding_.is_bound()) + SetSpellCheckHostForTesting(binding_.CreateInterfacePtrAndBind()); + SpellCheckProvider::RequestTextChecking(text, completion); + base::RunLoop().RunUntilIdle(); +#else + SpellCheckProvider::RequestTextChecking(text, completion); #endif +} +bool TestingSpellCheckProvider::Send(IPC::Message* message) { messages_.push_back(base::WrapUnique<IPC::Message>(message)); return true; } -void TestingSpellCheckProvider::OnCallSpellingService( - int route_id, - int identifier, - const base::string16& text) { -#if BUILDFLAG(USE_BROWSER_SPELLCHECKER) - NOTREACHED(); +void TestingSpellCheckProvider::RequestDictionary() {} + +void TestingSpellCheckProvider::NotifyChecked(const base::string16& word, + bool misspelled) {} + +void TestingSpellCheckProvider::CallSpellingService( + const base::string16& text, + CallSpellingServiceCallback callback) { +#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) + OnCallSpellingService(text); + std::move(callback).Run(true, std::vector<SpellCheckResult>()); #else + NOTREACHED(); +#endif +} + +void TestingSpellCheckProvider::OnCallSpellingService( + const base::string16& text) { +#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) ++spelling_service_call_count_; blink::WebTextCheckingCompletion* completion = - text_check_completions_.Lookup(identifier); + text_check_completions_.Lookup(last_identifier_); if (!completion) { ResetResult(); return; } text_.assign(text); - text_check_completions_.Remove(identifier); + text_check_completions_.Remove(last_identifier_); std::vector<blink::WebTextCheckingResult> results; results.push_back(blink::WebTextCheckingResult( blink::kWebTextDecorationTypeSpelling, 0, 5, blink::WebString("hello"))); completion->DidFinishCheckingText(results); last_request_ = text; last_results_ = results; +#else + NOTREACHED(); #endif }
diff --git a/components/spellcheck/renderer/spellcheck_provider_test.h b/components/spellcheck/renderer/spellcheck_provider_test.h index 89a354e16..aa2cb77 100644 --- a/components/spellcheck/renderer/spellcheck_provider_test.h +++ b/components/spellcheck/renderer/spellcheck_provider_test.h
@@ -5,19 +5,23 @@ #ifndef COMPONENTS_SPELLCHECK_RENDERER_SPELLCHECK_PROVIDER_TEST_H_ #define COMPONENTS_SPELLCHECK_RENDERER_SPELLCHECK_PROVIDER_TEST_H_ -#include <stddef.h> - +#include <memory> #include <vector> #include "base/strings/string16.h" #include "components/spellcheck/renderer/spellcheck_provider.h" +#include "mojo/public/cpp/bindings/binding.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebVector.h" #include "third_party/WebKit/public/web/WebTextCheckingCompletion.h" #include "third_party/WebKit/public/web/WebTextCheckingResult.h" +namespace base { +class MessageLoop; +} + namespace IPC { - class Message; +class Message; } // A fake completion object for verification. @@ -35,17 +39,20 @@ }; // Faked test target, which stores sent message for verification. -class TestingSpellCheckProvider : public SpellCheckProvider { +class TestingSpellCheckProvider : public SpellCheckProvider, + public spellcheck::mojom::SpellCheckHost { public: TestingSpellCheckProvider(); // Takes ownership of |spellcheck|. explicit TestingSpellCheckProvider(SpellCheck* spellcheck); ~TestingSpellCheckProvider() override; + + void RequestTextChecking(const base::string16& text, + blink::WebTextCheckingCompletion* completion); + bool Send(IPC::Message* message) override; - void OnCallSpellingService(int route_id, - int identifier, - const base::string16& text); + void OnCallSpellingService(const base::string16& text); void ResetResult(); void SetLastResults( @@ -57,6 +64,19 @@ base::string16 text_; std::vector<std::unique_ptr<IPC::Message>> messages_; size_t spelling_service_call_count_; + + private: + // spellcheck::mojom::SpellCheckerHost: + void RequestDictionary() override; + void NotifyChecked(const base::string16& word, bool misspelled) override; + void CallSpellingService(const base::string16& text, + CallSpellingServiceCallback callback) override; + + // Message loop (if needed) to deliver the SpellCheckHost request flow. + std::unique_ptr<base::MessageLoop> loop_; + + // Binding to receive the SpellCheckHost request flow. + mojo::Binding<spellcheck::mojom::SpellCheckHost> binding_; }; // SpellCheckProvider test fixture.
diff --git a/components/typemaps.gni b/components/typemaps.gni index 57cb1505..94d94bac 100644 --- a/components/typemaps.gni +++ b/components/typemaps.gni
@@ -8,5 +8,6 @@ "//components/nacl/common/nacl.typemap", "//components/password_manager/content/common/credential_manager.typemap", "//components/signin/public/interfaces/account_id.typemap", + "//components/spellcheck/common/spellcheck.typemap", "//components/translate/content/common/translate.typemap", ]
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java index ea367d34..2d72f2f 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
@@ -460,9 +460,9 @@ mRule.waitForKeyboardStates(3, 1, 4, new Integer[] {TextInputType.NUMBER, TextInputType.NUMBER, TextInputType.TEXT}); - mRule.resetUpdateSelectionList(); mRule.setComposingText("a", 1); - mRule.waitAndVerifyUpdateSelection(0, 1, 1, 0, 1); + mRule.waitAndVerifyUpdateSelection(0, 0, 0, -1, -1); + mRule.waitAndVerifyUpdateSelection(1, 1, 1, 0, 1); mRule.resetUpdateSelectionList(); // JavaScript changes focus.
diff --git a/device/bluetooth/bluetooth_low_energy_device_mac.h b/device/bluetooth/bluetooth_low_energy_device_mac.h index f559e60..cabab11 100644 --- a/device/bluetooth/bluetooth_low_energy_device_mac.h +++ b/device/bluetooth/bluetooth_low_energy_device_mac.h
@@ -129,11 +129,11 @@ CBPeripheral* GetPeripheral(); // Returns BluetoothRemoteGattServiceMac based on the CBService. - BluetoothRemoteGattServiceMac* GetBluetoothRemoteGattService( + BluetoothRemoteGattServiceMac* GetBluetoothRemoteGattServiceMac( CBService* service) const; // Returns BluetoothRemoteGattDescriptorMac based on the CBDescriptor. - BluetoothRemoteGattDescriptorMac* GetBluetoothRemoteGattDescriptor( + BluetoothRemoteGattDescriptorMac* GetBluetoothRemoteGattDescriptorMac( CBDescriptor* cb_descriptor) const; // Callback used when the CoreBluetooth Peripheral is disconnected.
diff --git a/device/bluetooth/bluetooth_low_energy_device_mac.mm b/device/bluetooth/bluetooth_low_energy_device_mac.mm index 2f2cfa9b..8e730550 100644 --- a/device/bluetooth/bluetooth_low_energy_device_mac.mm +++ b/device/bluetooth/bluetooth_low_energy_device_mac.mm
@@ -230,7 +230,7 @@ for (CBService* cb_service in GetPeripheral().services) { BluetoothRemoteGattServiceMac* gatt_service = - GetBluetoothRemoteGattService(cb_service); + GetBluetoothRemoteGattServiceMac(cb_service); if (!gatt_service) { gatt_service = new BluetoothRemoteGattServiceMac(this, cb_service, true /* is_primary */); @@ -279,7 +279,7 @@ } BluetoothRemoteGattServiceMac* gatt_service = - GetBluetoothRemoteGattService(cb_service); + GetBluetoothRemoteGattServiceMac(cb_service); DCHECK(gatt_service); gatt_service->DidDiscoverCharacteristics(); SendNotificationIfDiscoveryComplete(); @@ -292,7 +292,7 @@ << base::SysNSStringToUTF8([invalidatedServices description]); for (CBService* cb_service in invalidatedServices) { BluetoothRemoteGattServiceMac* gatt_service = - GetBluetoothRemoteGattService(cb_service); + GetBluetoothRemoteGattServiceMac(cb_service); DCHECK(gatt_service); VLOG(1) << gatt_service->GetUUID().canonical_value(); std::unique_ptr<BluetoothRemoteGattService> scoped_service = @@ -310,7 +310,7 @@ CBCharacteristic* characteristic, NSError* error) { BluetoothRemoteGattServiceMac* gatt_service = - GetBluetoothRemoteGattService(characteristic.service); + GetBluetoothRemoteGattServiceMac(characteristic.service); DCHECK(gatt_service); gatt_service->DidUpdateValue(characteristic, error); } @@ -319,7 +319,7 @@ CBCharacteristic* characteristic, NSError* error) { BluetoothRemoteGattServiceMac* gatt_service = - GetBluetoothRemoteGattService(characteristic.service); + GetBluetoothRemoteGattServiceMac(characteristic.service); DCHECK(gatt_service); gatt_service->DidWriteValue(characteristic, error); } @@ -328,7 +328,7 @@ CBCharacteristic* characteristic, NSError* error) { BluetoothRemoteGattServiceMac* gatt_service = - GetBluetoothRemoteGattService(characteristic.service); + GetBluetoothRemoteGattServiceMac(characteristic.service); DCHECK(gatt_service); gatt_service->DidUpdateNotificationState(characteristic, error); } @@ -356,7 +356,7 @@ return; } BluetoothRemoteGattServiceMac* gatt_service = - GetBluetoothRemoteGattService(cb_characteristic.service); + GetBluetoothRemoteGattServiceMac(cb_characteristic.service); DCHECK(gatt_service); gatt_service->DidDiscoverDescriptors(cb_characteristic); SendNotificationIfDiscoveryComplete(); @@ -366,7 +366,7 @@ CBDescriptor* cb_descriptor, NSError* error) { BluetoothRemoteGattDescriptorMac* gatt_descriptor = - GetBluetoothRemoteGattDescriptor(cb_descriptor); + GetBluetoothRemoteGattDescriptorMac(cb_descriptor); DCHECK(gatt_descriptor); gatt_descriptor->DidUpdateValueForDescriptor(error); } @@ -375,7 +375,7 @@ CBDescriptor* cb_descriptor, NSError* error) { BluetoothRemoteGattDescriptorMac* gatt_descriptor = - GetBluetoothRemoteGattDescriptor(cb_descriptor); + GetBluetoothRemoteGattDescriptorMac(cb_descriptor); DCHECK(gatt_descriptor); gatt_descriptor->DidWriteValueForDescriptor(error); } @@ -451,7 +451,7 @@ } device::BluetoothRemoteGattServiceMac* -BluetoothLowEnergyDeviceMac::GetBluetoothRemoteGattService( +BluetoothLowEnergyDeviceMac::GetBluetoothRemoteGattServiceMac( CBService* cb_service) const { for (auto it = gatt_services_.begin(); it != gatt_services_.end(); ++it) { device::BluetoothRemoteGattService* gatt_service = it->second.get(); @@ -464,11 +464,11 @@ } device::BluetoothRemoteGattDescriptorMac* -BluetoothLowEnergyDeviceMac::GetBluetoothRemoteGattDescriptor( +BluetoothLowEnergyDeviceMac::GetBluetoothRemoteGattDescriptorMac( CBDescriptor* cb_descriptor) const { CBCharacteristic* cb_characteristic = cb_descriptor.characteristic; device::BluetoothRemoteGattServiceMac* gatt_service = - GetBluetoothRemoteGattService(cb_characteristic.service); + GetBluetoothRemoteGattServiceMac(cb_characteristic.service); DCHECK(gatt_service); device::BluetoothRemoteGattCharacteristicMac* gatt_characteristic = gatt_service->GetBluetoothRemoteGattCharacteristicMac(cb_characteristic);
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 2dddf9bf..4f083257 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -135,6 +135,14 @@ return base::FeatureList::IsEnabled(kBackgroundVideoPauseOptimization); } +#if defined(OS_ANDROID) + +bool IsNewRemotePlaybackPipelineEnabled() { + return base::FeatureList::IsEnabled(kNewRemotePlaybackPipeline); +} + +#endif + bool IsNetworkStateError(blink::WebMediaPlayer::NetworkState state) { bool result = state == blink::WebMediaPlayer::kNetworkStateFormatError || state == blink::WebMediaPlayer::kNetworkStateNetworkError || @@ -1164,7 +1172,7 @@ void WebMediaPlayerImpl::OnPipelineSuspended() { #if defined(OS_ANDROID) - if (IsRemote()) { + if (IsRemote() && !IsNewRemotePlaybackPipelineEnabled()) { scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner(); if (frame) compositor_->PaintSingleFrame(frame); @@ -1645,7 +1653,8 @@ } void WebMediaPlayerImpl::SuspendForRemote() { - if (pipeline_controller_.IsPipelineSuspended()) { + if (pipeline_controller_.IsPipelineSuspended() && + !IsNewRemotePlaybackPipelineEnabled()) { scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner(); if (frame) compositor_->PaintSingleFrame(frame);
diff --git a/rlz/chromeos/lib/rlz_value_store_chromeos.cc b/rlz/chromeos/lib/rlz_value_store_chromeos.cc index 347f7e5b..65b5634 100644 --- a/rlz/chromeos/lib/rlz_value_store_chromeos.cc +++ b/rlz/chromeos/lib/rlz_value_store_chromeos.cc
@@ -89,37 +89,38 @@ } RlzValueStoreChromeOS::~RlzValueStoreChromeOS() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); WriteStore(); } bool RlzValueStoreChromeOS::HasAccess(AccessType type) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return type == kReadAccess || !read_only_; } bool RlzValueStoreChromeOS::WritePingTime(Product product, int64_t time) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); rlz_store_->SetString(GetKeyName(kPingTimeKey, product), base::Int64ToString(time)); return true; } bool RlzValueStoreChromeOS::ReadPingTime(Product product, int64_t* time) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::string ping_time; return rlz_store_->GetString(GetKeyName(kPingTimeKey, product), &ping_time) && base::StringToInt64(ping_time, time); } bool RlzValueStoreChromeOS::ClearPingTime(Product product) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); rlz_store_->Remove(GetKeyName(kPingTimeKey, product), NULL); return true; } bool RlzValueStoreChromeOS::WriteAccessPointRlz(AccessPoint access_point, const char* new_rlz) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); rlz_store_->SetString( GetKeyName(kAccessPointKey, access_point), new_rlz); return true; @@ -128,7 +129,7 @@ bool RlzValueStoreChromeOS::ReadAccessPointRlz(AccessPoint access_point, char* rlz, size_t rlz_size) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::string rlz_value; rlz_store_->GetString(GetKeyName(kAccessPointKey, access_point), &rlz_value); if (rlz_value.size() < rlz_size) { @@ -141,14 +142,14 @@ } bool RlzValueStoreChromeOS::ClearAccessPointRlz(AccessPoint access_point) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); rlz_store_->Remove(GetKeyName(kAccessPointKey, access_point), NULL); return true; } bool RlzValueStoreChromeOS::AddProductEvent(Product product, const char* event_rlz) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return AddValueToList(GetKeyName(kProductEventKey, product), base::MakeUnique<base::Value>(event_rlz)); } @@ -156,7 +157,7 @@ bool RlzValueStoreChromeOS::ReadProductEvents( Product product, std::vector<std::string>* events) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::ListValue* events_list = nullptr; if (!rlz_store_->GetList(GetKeyName(kProductEventKey, product), &events_list)) return false; @@ -171,28 +172,28 @@ bool RlzValueStoreChromeOS::ClearProductEvent(Product product, const char* event_rlz) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Value event_value(event_rlz); return RemoveValueFromList(GetKeyName(kProductEventKey, product), event_value); } bool RlzValueStoreChromeOS::ClearAllProductEvents(Product product) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); rlz_store_->Remove(GetKeyName(kProductEventKey, product), NULL); return true; } bool RlzValueStoreChromeOS::AddStatefulEvent(Product product, const char* event_rlz) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return AddValueToList(GetKeyName(kStatefulEventKey, product), base::MakeUnique<base::Value>(event_rlz)); } bool RlzValueStoreChromeOS::IsStatefulEvent(Product product, const char* event_rlz) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::Value event_value(event_rlz); base::ListValue* events_list = NULL; return rlz_store_->GetList(GetKeyName(kStatefulEventKey, product), @@ -201,13 +202,13 @@ } bool RlzValueStoreChromeOS::ClearAllStatefulEvents(Product product) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); rlz_store_->Remove(GetKeyName(kStatefulEventKey, product), NULL); return true; } void RlzValueStoreChromeOS::CollectGarbage() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); NOTIMPLEMENTED(); }
diff --git a/rlz/chromeos/lib/rlz_value_store_chromeos.h b/rlz/chromeos/lib/rlz_value_store_chromeos.h index cae01ba..7222a78 100644 --- a/rlz/chromeos/lib/rlz_value_store_chromeos.h +++ b/rlz/chromeos/lib/rlz_value_store_chromeos.h
@@ -12,7 +12,7 @@ #include "base/files/file_path.h" #include "base/macros.h" -#include "base/threading/non_thread_safe.h" +#include "base/sequence_checker.h" #include "rlz/lib/rlz_value_store.h" namespace base { @@ -23,8 +23,7 @@ namespace rlz_lib { // An implementation of RlzValueStore for ChromeOS. -class RlzValueStoreChromeOS : public RlzValueStore, - public base::NonThreadSafe { +class RlzValueStoreChromeOS : public RlzValueStore { public: // Creates new instance and synchronously reads data from file. explicit RlzValueStoreChromeOS(const base::FilePath& store_path); @@ -77,6 +76,8 @@ bool read_only_; + SEQUENCE_CHECKER(sequence_checker_); + DISALLOW_COPY_AND_ASSIGN(RlzValueStoreChromeOS); };
diff --git a/testing/test.gni b/testing/test.gni index 7039e17..36e0d91 100644 --- a/testing/test.gni +++ b/testing/test.gni
@@ -12,6 +12,10 @@ import("//build/config/sanitizers/sanitizers.gni") } +if (is_fuchsia) { + import("//build/config/fuchsia/rules.gni") +} + # Define a test as an executable (or apk on Android) with the "testonly" flag # set. # Variable: @@ -220,6 +224,29 @@ test_suite = _output_name test_type = "gtest" } + } else if (is_fuchsia) { + _output_name = invoker.target_name + _test_runner_target = "${_output_name}__test_runner_script" + + test_runner_script(_test_runner_target) { + forward_variables_from(invoker, + [ + "data", + "data_deps", + "deps", + "public_deps", + ]) + test_name = _output_name + } + + executable(target_name) { + testonly = true + forward_variables_from(invoker, "*") + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += [ ":$_test_runner_target" ] + } } else if (is_ios) { import("//build/config/ios/ios_sdk.gni") import("//build/config/ios/rules.gni")
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index f2491d8..e84b8c78 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2693,8 +2693,6 @@ # [css-grid] crbug.com/659610 fast/css-grid-layout/grid-baseline.html [ Failure ] crbug.com/659610 fast/css-grid-layout/grid-baseline-margins.html [ Failure ] -crbug.com/725903 external/wpt/css/css-grid-1/abspos/orthogonal-positioned-grid-items-013.html [ Failure ] -crbug.com/725903 external/wpt/css/css-grid-1/abspos/orthogonal-positioned-grid-items-017.html [ Failure ] crbug.com/511177 external/wpt/css/css-grid-1/grid-layout-properties.html [ Failure ] crbug.com/707359 [ Mac ] fast/css-grid-layout/grid-align-baseline-vertical.html [ Failure ] crbug.com/707359 [ Mac ] fast/css-grid-layout/grid-self-baseline-03.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-001.html new file mode 100644 index 0000000..b25b4713 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-001.html
@@ -0,0 +1,57 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="Grid items with 'stretch' value for align-self and/or justify-self are stretched along the column and/or row axis respectively; they will be sized as fit-content otherwise."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="10" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="0" data-expected-width="60" data-expected-height="150" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="0" data-offset-y="150" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="150" data-expected-width="150" data-expected-height="100" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-002.html new file mode 100644 index 0000000..b9a354e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-002.html
@@ -0,0 +1,61 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + margin-right: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + margin-bottom: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + margin-right: 20px; + margin-bottom: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="90" data-expected-height="10" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="0" data-expected-width="60" data-expected-height="130" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="0" data-offset-y="150" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="150" data-expected-width="130" data-expected-height="90" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-003.html new file mode 100644 index 0000000..0af4081 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-003.html
@@ -0,0 +1,62 @@ + <!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis include their defined border-box."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; +} +.grid > div { border-style: solid; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + border-width: 0px 10px 0px 0px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + border-width: 0px 0px 20px 0px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; + border-width: 0px 0px 0px 0px; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + border-width: 0px 20px 10px 0px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="10" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="0" data-expected-width="60" data-expected-height="150" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="0" data-offset-y="150" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="150" data-expected-width="150" data-expected-height="100" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-004.html new file mode 100644 index 0000000..ad76f52 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-004.html
@@ -0,0 +1,61 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis include their defined padding-box."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + padding-right: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + padding-bottom: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + padding-right: 20px; + padding-bottom: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="10" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="0" data-expected-width="60" data-expected-height="150" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="0" data-offset-y="150" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="150" data-expected-width="150" data-expected-height="100" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-005.html new file mode 100644 index 0000000..68e794bd --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-005.html
@@ -0,0 +1,58 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="Orthogonal grid items with 'stretch' value for align-self and/or justify-self are stretched along the column and/or row axis respectively; they will be sized as fit-content otherwise."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; +} +.grid > div { writing-mode: vertical-lr; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="60" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="0" data-expected-width="40" data-expected-height="150" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="0" data-offset-y="150" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="150" data-expected-width="150" data-expected-height="100" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-006.html new file mode 100644 index 0000000..94c65d0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-006.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; +} +.grid > div { writing-mode: vertical-lr; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + margin-right: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + margin-bottom: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + margin-right: 20px; + margin-bottom: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="90" data-expected-height="60" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="0" data-expected-width="40" data-expected-height="130" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="0" data-offset-y="150" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="150" data-expected-width="130" data-expected-height="90" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-007.html new file mode 100644 index 0000000..8cb459ed9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-007.html
@@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis include their defined border-box."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; +} +.grid > div { writing-mode: vertical-lr; } +.grid > div { border-style: solid; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + border-width: 0px 10px 0px 0px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + border-width: 0px 0px 20px 0px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; + border-width: 0px 0px 0px 0px; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + border-width: 0px 20px 10px 0px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="60" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="0" data-expected-width="40" data-expected-height="150" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="0" data-offset-y="150" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="150" data-expected-width="150" data-expected-height="100" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-008.html new file mode 100644 index 0000000..52337ee --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-008.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis include their defined padding-box."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; +} +.grid > div { writing-mode: vertical-lr; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + padding-right: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + padding-bottom: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + padding-right: 20px; + padding-bottom: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="60" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="0" data-expected-width="40" data-expected-height="150" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="0" data-offset-y="150" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="150" data-expected-width="150" data-expected-height="100" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-009.html new file mode 100644 index 0000000..22bcc707 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-009.html
@@ -0,0 +1,57 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="Grid items with 'stretch' value for align-self and/or justify-self are stretched along the column and/or row axis respectively; they will be sized as fit-content otherwise."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="125" data-expected-height="20" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="125" data-offset-y="0" data-expected-width="80" data-expected-height="125" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="0" data-offset-y="125" data-expected-width="80" data-expected-height="20" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="125" data-offset-y="125" data-expected-width="125" data-expected-height="125" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-010.html new file mode 100644 index 0000000..02e138e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-010.html
@@ -0,0 +1,61 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + margin-right: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + margin-bottom: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + margin-right: 20px; + margin-bottom: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="110" data-expected-height="20" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="0" data-expected-width="80" data-expected-height="110" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="0" data-offset-y="130" data-expected-width="80" data-expected-height="20" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="130" data-expected-width="110" data-expected-height="110" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-011.html new file mode 100644 index 0000000..060e025 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-011.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; +} +.grid > div { border-style: solid; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + border-width: 0px 10px 0px 0px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + border-width: 0px 0px 20px 0px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; + border-width: 0px 0px 0px 0px; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + border-width: 0px 20px 10px 0px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="120" data-expected-height="20" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="0" data-expected-width="80" data-expected-height="130" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="0" data-offset-y="130" data-expected-width="80" data-expected-height="20" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="130" data-expected-width="130" data-expected-height="120" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-012.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-012.html new file mode 100644 index 0000000..422d2eb0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-012.html
@@ -0,0 +1,61 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis include their defined padding-box."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + padding-right: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + padding-bottom: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + padding-right: 20px; + padding-bottom: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="120" data-expected-height="20" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="0" data-expected-width="80" data-expected-height="130" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="0" data-offset-y="130" data-expected-width="80" data-expected-height="20" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="130" data-expected-width="130" data-expected-height="120" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-013.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-013.html new file mode 100644 index 0000000..ba88de0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-013.html
@@ -0,0 +1,58 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="Orthogonal grid items with 'stretch' value for align-self and/or justify-self are stretched along the column and/or row axis respectively; they will be sized as fit-content otherwise."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; +} +.grid > div { writing-mode: vertical-lr; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="125" data-expected-height="80" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="125" data-offset-y="0" data-expected-width="20" data-expected-height="125" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="0" data-offset-y="125" data-expected-width="20" data-expected-height="80" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="125" data-offset-y="125" data-expected-width="125" data-expected-height="125" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-014.html new file mode 100644 index 0000000..9b3d64d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-014.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; +} +.grid > div { writing-mode: vertical-lr; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + margin-right: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + margin-bottom: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + margin-right: 20px; + margin-bottom: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="110" data-expected-height="80" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="0" data-expected-width="20" data-expected-height="110" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="0" data-offset-y="130" data-expected-width="20" data-expected-height="80" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="130" data-expected-width="110" data-expected-height="110" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-015.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-015.html new file mode 100644 index 0000000..c7290f7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-015.html
@@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis include their defined border-box."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; +} +.grid > div { writing-mode: vertical-lr; } +.grid > div { border-style: solid; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + border-width: 0px 10px 0px 0px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + border-width: 0px 0px 20px 0px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; + border-width: 0px 0px 0px 0px; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + border-width: 0px 20px 10px 0px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="120" data-expected-height="80" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="0" data-expected-width="20" data-expected-height="130" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="0" data-offset-y="130" data-expected-width="20" data-expected-height="80" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="130" data-expected-width="130" data-expected-height="120" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-016.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-016.html new file mode 100644 index 0000000..1365b709 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-016.html
@@ -0,0 +1,61 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis include their defined padding-box."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; +} +.grid > div { writing-mode: vertical-lr; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + padding-right: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + padding-bottom: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + padding-right: 20px; + padding-bottom: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="120" data-expected-height="80" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="0" data-expected-width="20" data-expected-height="130" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="0" data-offset-y="130" data-expected-width="20" data-expected-height="80" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="130" data-expected-width="130" data-expected-height="120" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-001.html new file mode 100644 index 0000000..ac300a5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-001.html
@@ -0,0 +1,58 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="Grid items with 'stretch' value for align-self and/or justify-self are stretched along the column and/or row axis respectively; they will be sized as fit-content otherwise."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-lr; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="150" data-expected-height="60" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="150" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="150" data-offset-y="100" data-expected-width="100" data-expected-height="150" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-002.html new file mode 100644 index 0000000..00e4ca7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-002.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-lr; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + margin-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + margin-right: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + margin-bottom: 20px; + margin-right: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="90" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="130" data-expected-height="60" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="150" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="150" data-offset-y="100" data-expected-width="90" data-expected-height="130" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-003.html new file mode 100644 index 0000000..dd96194 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-003.html
@@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis include their defined border-box."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-lr; +} +.grid > div { border-style: solid; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + border-width: 0px 0px 10px 0px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + border-width: 0px 20px 0px 0px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; + border-width: 0px 0px 0px 0px; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + border-width: 0px 10px 20px 0px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="150" data-expected-height="60" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="150" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="150" data-offset-y="100" data-expected-width="100" data-expected-height="150" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-004.html new file mode 100644 index 0000000..8b5882c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-004.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis include their defined padding-box."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-lr; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + padding-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + padding-right: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + padding-bottom: 20px; + padding-right: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="150" data-expected-height="60" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="150" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="150" data-offset-y="100" data-expected-width="100" data-expected-height="150" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-005.html new file mode 100644 index 0000000..4b29aa7c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-005.html
@@ -0,0 +1,59 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="Orthogonal grid items with 'stretch' value for align-self and/or justify-self are stretched along the column and/or row axis respectively; they will be sized as fit-content otherwise."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-lr; +} +.grid > div { writing-mode: horizontal-tb; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="60" data-expected-height="100" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="150" data-expected-height="40" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="150" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="150" data-offset-y="100" data-expected-width="100" data-expected-height="150" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-006.html new file mode 100644 index 0000000..a72fbd13 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-006.html
@@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-lr; +} +.grid > div { writing-mode: horizontal-tb; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + margin-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + margin-right: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + margin-bottom: 20px; + margin-right: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="60" data-expected-height="90" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="130" data-expected-height="40" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="150" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="150" data-offset-y="100" data-expected-width="90" data-expected-height="130" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-007.html new file mode 100644 index 0000000..ab190d39 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-007.html
@@ -0,0 +1,64 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis include their defined border-box."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-lr; +} +.grid > div { writing-mode: horizontal-tb; } +.grid > div { border-style: solid; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + border-width: 0px 0px 10px 0px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + border-width: 0px 20px 0px 0px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; + border-width: 0px 0px 0px 0px; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + border-width: 0px 10px 20px 0px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="60" data-expected-height="100" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="150" data-expected-height="40" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="150" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="150" data-offset-y="100" data-expected-width="100" data-expected-height="150" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-008.html new file mode 100644 index 0000000..5be8653 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-008.html
@@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis include their defined padding-box."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-lr; +} +.grid > div { writing-mode: horizontal-tb; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + padding-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + padding-right: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + padding-bottom: 20px; + padding-right: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="60" data-expected-height="100" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="150" data-expected-height="40" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="150" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="150" data-offset-y="100" data-expected-width="100" data-expected-height="150" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-009.html new file mode 100644 index 0000000..f38ceb6a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-009.html
@@ -0,0 +1,58 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="Grid items with 'stretch' value for align-self and/or justify-self are stretched along the column and/or row axis respectively; they will be sized as fit-content otherwise."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-lr; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="125" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="125" data-expected-width="125" data-expected-height="80" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="125" data-offset-y="0" data-expected-width="20" data-expected-height="80" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="125" data-offset-y="125" data-expected-width="125" data-expected-height="125" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-010.html new file mode 100644 index 0000000..6744c05 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-010.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-lr; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + margin-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + margin-right: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + margin-bottom: 20px; + margin-right: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="110" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="120" data-expected-width="110" data-expected-height="80" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="130" data-offset-y="00" data-expected-width="20" data-expected-height="80" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="130" data-offset-y="120" data-expected-width="110" data-expected-height="110" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-011.html new file mode 100644 index 0000000..fa50dff --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-011.html
@@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-lr; +} +.grid > div { border-style: solid; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + border-width: 0px 0px 10px 0px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + border-width: 0px 20px 0px 0px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; + border-width: 0px 0px 0px 0px; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + border-width: 0px 10px 20px 0px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="120" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="120" data-expected-width="130" data-expected-height="80" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="130" data-offset-y="0" data-expected-width="20" data-expected-height="80" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="130" data-offset-y="120" data-expected-width="120" data-expected-height="130" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-012.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-012.html new file mode 100644 index 0000000..94773382 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-012.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis include their defined padding-box."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-lr; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + padding-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + padding-right: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + padding-bottom: 20px; + padding-right: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="120" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="120" data-expected-width="130" data-expected-height="80" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="130" data-offset-y="0" data-expected-width="20" data-expected-height="80" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="130" data-offset-y="120" data-expected-width="120" data-expected-height="130" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-013.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-013.html new file mode 100644 index 0000000..25baada --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-013.html
@@ -0,0 +1,59 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="Orthogonal grid items with 'stretch' value for align-self and/or justify-self are stretched along the column and/or row axis respectively; they will be sized as fit-content otherwise."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-lr; +} +.grid > div { writing-mode: horizontal-tb; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="80" data-expected-height="125" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="125" data-expected-width="125" data-expected-height="20" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="125" data-offset-y="0" data-expected-width="80" data-expected-height="20" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="125" data-offset-y="125" data-expected-width="125" data-expected-height="125" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-014.html new file mode 100644 index 0000000..19a8ede --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-014.html
@@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-lr; +} +.grid > div { writing-mode: horizontal-tb; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + margin-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + margin-right: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + margin-bottom: 20px; + margin-right: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="80" data-expected-height="110" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="120" data-expected-width="110" data-expected-height="20" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="130" data-offset-y="0" data-expected-width="80" data-expected-height="20" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="130" data-offset-y="120" data-expected-width="110" data-expected-height="110" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-015.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-015.html new file mode 100644 index 0000000..45c8b75 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-015.html
@@ -0,0 +1,64 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis include their defined border-box."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-lr; +} +.grid > div { writing-mode: horizontal-tb; } +.grid > div { border-style: solid; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + border-width: 0px 0px 10px 0px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + border-width: 0px 20px 0px 0px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; + border-width: 0px 0px 0px 0px; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + border-width: 0px 10px 20px 0px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="80" data-expected-height="120" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="120" data-expected-width="130" data-expected-height="20" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="130" data-offset-y="0" data-expected-width="80" data-expected-height="20" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="130" data-offset-y="120" data-expected-width="120" data-expected-height="130" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-016.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-016.html new file mode 100644 index 0000000..2a47e02 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-016.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis include their defined padding-box."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-lr; +} +.grid > div { writing-mode: horizontal-tb; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + padding-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + padding-right: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + padding-bottom: 20px; + padding-right: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="80" data-expected-height="120" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="120" data-expected-width="130" data-expected-height="20" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="130" data-offset-y="0" data-expected-width="80" data-expected-height="20" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="130" data-offset-y="120" data-expected-width="120" data-expected-height="130" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-001.html new file mode 100644 index 0000000..1afde93 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-001.html
@@ -0,0 +1,58 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="Grid items with 'stretch' value for align-self and/or justify-self are stretched along the column and/or row axis respectively; they will be sized as fit-content otherwise."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-rl; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="240" data-offset-y="0" data-expected-width="10" data-expected-height="100" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="100" data-expected-width="150" data-expected-height="60" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="90" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="100" data-expected-height="150" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-002.html new file mode 100644 index 0000000..a7a1c97 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-002.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-rl; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + margin-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + margin-left: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + margin-bottom: 20px; + margin-left: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="240" data-offset-y="0" data-expected-width="10" data-expected-height="90" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="120" data-offset-y="100" data-expected-width="130" data-expected-height="60" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="90" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="10" data-offset-y="100" data-expected-width="90" data-expected-height="130" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-003.html new file mode 100644 index 0000000..96cbad3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-003.html
@@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis include their defined border-box."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-rl; +} +.grid > div { border-style: solid; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + border-width: 0px 0px 10px 0px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + border-width: 0px 0px 0px 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; + border-width: 0px 0px 0px 0px; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + border-width: 0px 0px 20px 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="240" data-offset-y="0" data-expected-width="10" data-expected-height="100" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="100" data-expected-width="150" data-expected-height="60" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="90" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="100" data-expected-height="150" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-004.html new file mode 100644 index 0000000..c93b7b6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-004.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis include their defined padding-box."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-rl; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + padding-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + padding-left: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + padding-bottom: 20px; + padding-left: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="240" data-offset-y="0" data-expected-width="10" data-expected-height="100" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="100" data-expected-width="150" data-expected-height="60" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="90" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="100" data-expected-height="150" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-005.html new file mode 100644 index 0000000..73f7a6f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-005.html
@@ -0,0 +1,59 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="Orthogonal grid items with 'stretch' value for align-self and/or justify-self are stretched along the column and/or row axis respectively; they will be sized as fit-content otherwise."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-rl; +} +.grid > div { writing-mode: horizontal-tb; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="190" data-offset-y="0" data-expected-width="60" data-expected-height="100" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="100" data-expected-width="150" data-expected-height="40" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="40" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="100" data-expected-height="150" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-006.html new file mode 100644 index 0000000..0a6d003f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-006.html
@@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-rl; +} +.grid > div { writing-mode: horizontal-tb; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + margin-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + margin-right: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + margin-bottom: 20px; + margin-right: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="190" data-offset-y="0" data-expected-width="60" data-expected-height="90" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="100" data-expected-width="130" data-expected-height="40" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="40" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="90" data-expected-height="130" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-007.html new file mode 100644 index 0000000..ac92314 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-007.html
@@ -0,0 +1,64 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis include their defined border-box."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-rl; +} +.grid > div { writing-mode: horizontal-tb; } +.grid > div { border-style: solid; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + border-width: 0px 0px 10px 0px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + border-width: 0px 20px 0px 0px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; + border-width: 0px 0px 0px 0px; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + border-width: 0px 10px 20px 0px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="190" data-offset-y="0" data-expected-width="60" data-expected-height="100" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="100" data-expected-width="150" data-expected-height="40" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="40" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="100" data-expected-height="150" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-008.html new file mode 100644 index 0000000..4756ebad --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-008.html
@@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on fixed-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis include their defined padding-box."> +<style> +.grid { + position: relative; + display: inline-grid; + grid-template-columns: 100px 150px; + grid-template-rows: 150px 100px; + font: 10px/1 Ahem; + background: grey; + writing-mode: vertical-rl; +} +.grid > div { writing-mode: horizontal-tb; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + padding-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + padding-right: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + padding-bottom: 20px; + padding-right: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="190" data-offset-y="0" data-expected-width="60" data-expected-height="100" class="firstRowFirstColumn">X XX X</div> + <div data-offset-x="100" data-offset-y="100" data-expected-width="150" data-expected-height="40" class="firstRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="40" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="100" data-expected-height="150" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-009.html new file mode 100644 index 0000000..4d05c9f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-009.html
@@ -0,0 +1,58 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="Grid items with 'stretch' value for align-self and/or justify-self are stretched along the column and/or row axis respectively; they will be sized as fit-content otherwise."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-rl; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="230" data-offset-y="0" data-expected-width="20" data-expected-height="125" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="125" data-offset-y="125" data-expected-width="125" data-expected-height="80" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="105" data-offset-y="0" data-expected-width="20" data-expected-height="80" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="125" data-expected-width="125" data-expected-height="125" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-010.html new file mode 100644 index 0000000..1cb5b8dc7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-010.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-rl; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + margin-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + margin-left: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + margin-bottom: 20px; + margin-left: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="230" data-offset-y="0" data-expected-width="20" data-expected-height="110" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="140" data-offset-y="120" data-expected-width="110" data-expected-height="80" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="100" data-offset-y="00" data-expected-width="20" data-expected-height="80" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="10" data-offset-y="120" data-expected-width="110" data-expected-height="110" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-011.html new file mode 100644 index 0000000..535d57c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-011.html
@@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-rl; +} +.grid > div { border-style: solid; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + border-width: 0px 0px 10px 0px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + border-width: 0px 0px 00px 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; + border-width: 0px 0px 0px 0px; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + border-width: 0px 0px 20px 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="230" data-offset-y="0" data-expected-width="20" data-expected-height="120" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="120" data-expected-width="130" data-expected-height="80" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="80" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="120" data-expected-width="120" data-expected-height="130" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-012.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-012.html new file mode 100644 index 0000000..8ed59c7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-012.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched grid items along the column and/or row axis include their defined padding-box."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-rl; +} +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + padding-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + padding-left: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + padding-bottom: 20px; + padding-left: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="230" data-offset-y="0" data-expected-width="20" data-expected-height="120" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="120" data-expected-width="130" data-expected-height="80" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="80" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="120" data-expected-width="120" data-expected-height="130" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-013.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-013.html new file mode 100644 index 0000000..4070c2e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-013.html
@@ -0,0 +1,59 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="Orthogonal grid items with 'stretch' value for align-self and/or justify-self are stretched along the column and/or row axis respectively; they will be sized as fit-content otherwise."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-rl; +} +.grid > div { writing-mode: horizontal-tb; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="170" data-offset-y="0" data-expected-width="80" data-expected-height="125" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="125" data-offset-y="125" data-expected-width="125" data-expected-height="20" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="45" data-offset-y="0" data-expected-width="80" data-expected-height="20" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="125" data-expected-width="125" data-expected-height="125" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-014.html new file mode 100644 index 0000000..d6a6b30 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-014.html
@@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis respect their defined margin-box's boundaries."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-rl; +} +.grid > div { writing-mode: horizontal-tb; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + margin-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + margin-right: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + margin-bottom: 20px; + margin-right: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="170" data-offset-y="0" data-expected-width="80" data-expected-height="110" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="120" data-expected-width="110" data-expected-height="20" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="40" data-offset-y="0" data-expected-width="80" data-expected-height="20" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="120" data-expected-width="110" data-expected-height="110" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-015.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-015.html new file mode 100644 index 0000000..e6ef67df --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-015.html
@@ -0,0 +1,64 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis include their defined border-box."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-rl; +} +.grid > div { writing-mode: horizontal-tb; } +.grid > div { border-style: solid; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + border-width: 0px 0px 10px 0px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + border-width: 0px 20px 0px 0px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; + border-width: 0px 0px 0px 0px; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + border-width: 0px 10px 20px 0px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="170" data-offset-y="0" data-expected-width="80" data-expected-height="120" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="120" data-expected-width="130" data-expected-height="20" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="40" data-offset-y="0" data-expected-width="80" data-expected-height="20" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="120" data-expected-width="120" data-expected-height="130" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-016.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-016.html new file mode 100644 index 0000000..5e26d140 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-016.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Self-Alignment and stretch on auto-sized tracks</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self"> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-justify-self-stretch"> +<meta name="assert" content="The stretched orthogonal grid items along the column and/or row axis include their defined padding-box."> +<style> +.grid { + position: relative; + display: inline-grid; + font: 20px/1 Ahem; + background: grey; + width: 250px; + height: 250px; + writing-mode: vertical-rl; +} +.grid > div { writing-mode: horizontal-tb; } +.firstRowFirstColumn { + grid-row: 1; + grid-column: 1; + background: green; + justify-self: stretch; + align-self: start; + padding-bottom: 10px; +} +.firstRowSecondColumn { + grid-row: 1; + grid-column: 2; + background: blue; + justify-self: start; + align-self: stretch; + padding-right: 20px; +} +.secondRowFirstColumn { + grid-row: 2; + grid-column: 1; + background: yellow; + justify-self: start; + align-self: start; +} +.secondRowSecondColumn { + grid-row: 2; + grid-column: 2; + background: red; + justify-self: stretch; + align-self: stretch; + padding-bottom: 20px; + padding-right: 10px; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/check-layout-th.js"></script> +<body onload="checkLayout('.grid')"> +<div class="grid"> + <div data-offset-x="170" data-offset-y="0" data-expected-width="80" data-expected-height="120" class="firstRowFirstColumn">XX X</div> + <div data-offset-x="120" data-offset-y="120" data-expected-width="130" data-expected-height="20" class="firstRowSecondColumn">XX X</div> + <div data-offset-x="40" data-offset-y="0" data-expected-width="80" data-expected-height="20" class="secondRowFirstColumn">XX X</div> + <div data-offset-x="0" data-offset-y="120" data-expected-width="120" data-expected-height="130" class="secondRowSecondColumn">XX X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/support/check-layout-th.js b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/support/check-layout-th.js new file mode 100644 index 0000000..3f257d4a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/support/check-layout-th.js
@@ -0,0 +1,195 @@ +(function() { +// Test is initiated from body.onload, so explicit done() call is required. +setup({ explicit_done: true }); + +function checkSubtreeExpectedValues(t, parent, prefix) +{ + var checkedLayout = checkExpectedValues(t, parent, prefix); + Array.prototype.forEach.call(parent.childNodes, function(node) { + checkedLayout |= checkSubtreeExpectedValues(t, node, prefix); + }); + return checkedLayout; +} + +function checkAttribute(output, node, attribute) +{ + var result = node.getAttribute && node.getAttribute(attribute); + output.checked |= !!result; + return result; +} + +function assert_tolerance(actual, expected, message) +{ + if (isNaN(expected) || Math.abs(actual - expected) >= 1) { + assert_equals(actual, Number(expected), message); + } +} + +function checkExpectedValues(t, node, prefix) +{ + var output = { checked: false }; + + var expectedWidth = checkAttribute(output, node, "data-expected-width"); + if (expectedWidth) { + assert_tolerance(node.offsetWidth, expectedWidth, prefix + "width"); + } + + var expectedHeight = checkAttribute(output, node, "data-expected-height"); + if (expectedHeight) { + assert_tolerance(node.offsetHeight, expectedHeight, prefix + "height"); + } + + var expectedOffset = checkAttribute(output, node, "data-offset-x"); + if (expectedOffset) { + assert_tolerance(node.offsetLeft, expectedOffset, prefix + "offsetLeft"); + } + + var expectedOffset = checkAttribute(output, node, "data-offset-y"); + if (expectedOffset) { + assert_tolerance(node.offsetTop, expectedOffset, prefix + "offsetTop"); + } + + var expectedWidth = checkAttribute(output, node, "data-expected-client-width"); + if (expectedWidth) { + assert_tolerance(node.clientWidth, expectedWidth, prefix + "clientWidth"); + } + + var expectedHeight = checkAttribute(output, node, "data-expected-client-height"); + if (expectedHeight) { + assert_tolerance(node.clientHeight, expectedHeight, prefix + "clientHeight"); + } + + var expectedWidth = checkAttribute(output, node, "data-expected-scroll-width"); + if (expectedWidth) { + assert_tolerance(node.scrollWidth, expectedWidth, prefix + "scrollWidth"); + } + + var expectedHeight = checkAttribute(output, node, "data-expected-scroll-height"); + if (expectedHeight) { + assert_tolerance(node.scrollHeight, expectedHeight, prefix + "scrollHeight"); + } + + var expectedWidth = checkAttribute(output, node, "data-expected-bounding-client-rect-width"); + if (expectedWidth) { + assert_tolerance(node.getBoundingClientRect().width, expectedWidth, prefix + "getBoundingClientRect().width"); + } + + var expectedOffset = checkAttribute(output, node, "data-total-x"); + if (expectedOffset) { + var totalLeft = node.clientLeft + node.offsetLeft; + assert_tolerance(totalLeft, expectedOffset, prefix + + "clientLeft+offsetLeft (" + node.clientLeft + " + " + node.offsetLeft + ")"); + } + + var expectedOffset = checkAttribute(output, node, "data-total-y"); + if (expectedOffset) { + var totalTop = node.clientTop + node.offsetTop; + assert_tolerance(totalTop, expectedOffset, prefix + + "clientTop+offsetTop (" + node.clientTop + " + " + node.offsetTop + ")"); + } + + var expectedDisplay = checkAttribute(output, node, "data-expected-display"); + if (expectedDisplay) { + var actualDisplay = getComputedStyle(node).display; + assert_equals(actualDisplay, expectedDisplay, prefix + "display"); + } + + var expectedPaddingTop = checkAttribute(output, node, "data-expected-padding-top"); + if (expectedPaddingTop) { + var actualPaddingTop = getComputedStyle(node).paddingTop; + // Trim the unit "px" from the output. + actualPaddingTop = actualPaddingTop.slice(0, -2); + assert_equals(actualPaddingTop, expectedPaddingTop, prefix + "padding-top"); + } + + var expectedPaddingBottom = checkAttribute(output, node, "data-expected-padding-bottom"); + if (expectedPaddingBottom) { + var actualPaddingBottom = getComputedStyle(node).paddingBottom; + // Trim the unit "px" from the output. + actualPaddingBottom = actualPaddingBottom.slice(0, -2); + assert_equals(actualPaddingBottom, expectedPaddingBottom, prefix + "padding-bottom"); + } + + var expectedPaddingLeft = checkAttribute(output, node, "data-expected-padding-left"); + if (expectedPaddingLeft) { + var actualPaddingLeft = getComputedStyle(node).paddingLeft; + // Trim the unit "px" from the output. + actualPaddingLeft = actualPaddingLeft.slice(0, -2); + assert_equals(actualPaddingLeft, expectedPaddingLeft, prefix + "padding-left"); + } + + var expectedPaddingRight = checkAttribute(output, node, "data-expected-padding-right"); + if (expectedPaddingRight) { + var actualPaddingRight = getComputedStyle(node).paddingRight; + // Trim the unit "px" from the output. + actualPaddingRight = actualPaddingRight.slice(0, -2); + assert_equals(actualPaddingRight, expectedPaddingRight, prefix + "padding-right"); + } + + var expectedMarginTop = checkAttribute(output, node, "data-expected-margin-top"); + if (expectedMarginTop) { + var actualMarginTop = getComputedStyle(node).marginTop; + // Trim the unit "px" from the output. + actualMarginTop = actualMarginTop.slice(0, -2); + assert_equals(actualMarginTop, expectedMarginTop, prefix + "margin-top"); + } + + var expectedMarginBottom = checkAttribute(output, node, "data-expected-margin-bottom"); + if (expectedMarginBottom) { + var actualMarginBottom = getComputedStyle(node).marginBottom; + // Trim the unit "px" from the output. + actualMarginBottom = actualMarginBottom.slice(0, -2); + assert_equals(actualMarginBottom, expectedMarginBottom, prefix + "margin-bottom"); + } + + var expectedMarginLeft = checkAttribute(output, node, "data-expected-margin-left"); + if (expectedMarginLeft) { + var actualMarginLeft = getComputedStyle(node).marginLeft; + // Trim the unit "px" from the output. + actualMarginLeft = actualMarginLeft.slice(0, -2); + assert_equals(actualMarginLeft, expectedMarginLeft, prefix + "margin-left"); + } + + var expectedMarginRight = checkAttribute(output, node, "data-expected-margin-right"); + if (expectedMarginRight) { + var actualMarginRight = getComputedStyle(node).marginRight; + // Trim the unit "px" from the output. + actualMarginRight = actualMarginRight.slice(0, -2); + assert_equals(actualMarginRight, expectedMarginRight, prefix + "margin-right"); + } + + return output.checked; +} + +window.checkLayout = function(selectorList, outputContainer) +{ + if (!selectorList) { + console.error("You must provide a CSS selector of nodes to check."); + return; + } + var nodes = document.querySelectorAll(selectorList); + var testNumber = 0; + nodes = Array.prototype.slice.call(nodes); + nodes.reverse(); + var checkedLayout = false; + Array.prototype.forEach.call(nodes, function(node) { + test(function(t) { + var container = node.parentNode.className == 'container' ? node.parentNode : node; + var prefix = "\n" + container.outerHTML + "\n"; + var passed = false; + try { + checkedLayout |= checkExpectedValues(t, node.parentNode, prefix); + checkedLayout |= checkSubtreeExpectedValues(t, node, prefix); + passed = true; + } finally { + checkedLayout |= !passed; + } + }, selectorList + ' ' + String(++testNumber)); + }); + if (!checkedLayout) { + console.error("No valid data-* attributes found in selector list : " + selectorList); + } + done(); +}; + +})();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/scroll-into-view/check-scroll-position.html b/third_party/WebKit/LayoutTests/external/wpt/scroll-into-view/check-scroll-position.html new file mode 100644 index 0000000..200491a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/scroll-into-view/check-scroll-position.html
@@ -0,0 +1,77 @@ +<!DOCTYPE HTML> +<script src='/resources/testharness.js'></script> +<script src='/resources/testharnessreport.js'></script> +<title> Check End Position of ScrollIntoView</title> +<div id='container' style='height: 2500px; width: 2500px;'> + <div id='content' style='height: 500px; width: 500px;margin-left: 1000px; margin-right: 1000px; margin-top: 1000px;margin-bottom: 1000px'> + </div> +</div> +<script> + +var frames = 0; +var content_height = 500; +var content_width = 500; +var window_height = document.documentElement.clientHeight; +var window_width = document.documentElement.clientWidth; +var content = document.getElementById('content'); + +function animate (funct, x, y, next) { + if (frames < 500) { + ++frames; + requestAnimationFrame(animate.bind(null, funct, x, y, next)); + } else { + funct.step(function() { + assert_approx_equals(window.scrollX, x, 1); + assert_approx_equals(window.scrollY, y, 1); + funct.done(); + if (next) + next(); + }); + } +} + +var checkNearest = async_test("Smooth ScrollIntoView should scroll the element to the 'nearest' position"); +checkNearest.step(function() { + content.scrollIntoView( + {behavior: 'smooth', block: 'nearest', inlinePosition: 'nearest'}); + frames = 0; + var x = content.offsetLeft + content_width - window_width; + var y = content.offsetTop + content_height - window_height; + animate(checkNearest, x, y, test2); +}); + +var checkStart = async_test("Smooth ScrollIntoView should scroll the element to the 'start' position"); +function test2() { + checkStart.step(function() { + content.scrollIntoView( + {behavior: 'smooth', block: 'start', inlinePosition: 'start'}); + frames = 0; + animate(checkStart, content.offsetLeft, content.offsetTop, test3); + }); +} + +var checkCenter = async_test("Smooth ScrollIntoView should scroll the element to the 'center' position"); +function test3() { + checkCenter.step(function() { + content.scrollIntoView( + {behavior: 'smooth', block: 'center', inlinePosition: 'center'}); + frames = 0; + var x = content.offsetLeft + (content_width - window_width) / 2; + var y = content.offsetTop + (content_height - window_height) / 2; + animate(checkCenter, x, y, test4); + }); +} + +var checkEnd = async_test("Smooth ScrollIntoView should scroll the element to the 'end' position"); +function test4() { + checkEnd.step(function() { + content.scrollIntoView( + {behavior: 'smooth', block: 'end', inlinePosition: 'end'}); + frames = 0; + var x = content.offsetLeft + content_width - window_width; + var y = content.offsetTop + content_height - window_height; + animate(checkEnd, x, y, null); + }); +} + +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-item-stretching-must-not-depend-on-previous-layouts-expected.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-item-stretching-must-not-depend-on-previous-layouts-expected.html new file mode 100644 index 0000000..fbbab3b9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-item-stretching-must-not-depend-on-previous-layouts-expected.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<style> +body { overflow: hidden; } /* Ensure there wont be scrollbar to avoid the extra layout. */ +.grid { + display: inline-grid; + border: solid thick; + grid: 100px / 100px; + align-items: start; +} +.item { + background: magenta; + writing-mode: vertical-lr; + margin-right: 25px; +} +</style> +<p>Check whether stretching logic is not affected by multiple layouts becuase of the grid item's override height.<br>The test passes if there is a margin-right of 25px.</p> +<div class="grid"> + <div class="item">item</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-item-stretching-must-not-depend-on-previous-layouts.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-item-stretching-must-not-depend-on-previous-layouts.html new file mode 100644 index 0000000..16ec9a85 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-item-stretching-must-not-depend-on-previous-layouts.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<link rel="match" href="grid-item-stretching-must-not-depend-on-previous-layouts-expected.html"> +<style> +.grid { + display: inline-grid; + border: solid thick; + grid: 100px / 100px; + align-items: start; +} +.item { + background: magenta; + writing-mode: vertical-lr; + margin-right: 25px; +} +</style> +<p>Check whether stretching logic is not affected by multiple layouts becuase of the grid item's override height.<br>The test passes if there is a margin-right of 25px.</p> +<div class="grid"> + <div class="item">item</div> +</div>
diff --git a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn index b723540..894fa7d 100644 --- a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn +++ b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
@@ -109,6 +109,8 @@ "$blink_core_output_dir/fileapi/BlobPropertyBag.h", "$blink_core_output_dir/fileapi/FilePropertyBag.cpp", "$blink_core_output_dir/fileapi/FilePropertyBag.h", + "$blink_core_output_dir/frame/ScrollIntoViewOptions.cpp", + "$blink_core_output_dir/frame/ScrollIntoViewOptions.h", "$blink_core_output_dir/frame/ScrollOptions.cpp", "$blink_core_output_dir/frame/ScrollOptions.h", "$blink_core_output_dir/frame/ScrollToOptions.cpp", @@ -220,6 +222,8 @@ "$bindings_core_v8_output_dir/NodeOrString.h", "$bindings_core_v8_output_dir/RadioNodeListOrElement.cpp", "$bindings_core_v8_output_dir/RadioNodeListOrElement.h", + "$bindings_core_v8_output_dir/ScrollIntoViewOptionsOrBoolean.cpp", + "$bindings_core_v8_output_dir/ScrollIntoViewOptionsOrBoolean.h", "$bindings_core_v8_output_dir/StringOrArrayBuffer.cpp", "$bindings_core_v8_output_dir/StringOrArrayBuffer.h", "$bindings_core_v8_output_dir/StringOrArrayBufferOrArrayBufferView.cpp",
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni index 9dad1a5..e997194 100644 --- a/third_party/WebKit/Source/core/core_idl_files.gni +++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -559,6 +559,7 @@ "events/WheelEventInit.idl", "fileapi/BlobPropertyBag.idl", "fileapi/FilePropertyBag.idl", + "frame/ScrollIntoViewOptions.idl", "frame/ScrollOptions.idl", "frame/ScrollToOptions.idl", "html/AssignedNodesOptions.idl",
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp index 3f81b6d..18ec4fe 100644 --- a/third_party/WebKit/Source/core/dom/Element.cpp +++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -30,6 +30,7 @@ #include "bindings/core/v8/Dictionary.h" #include "bindings/core/v8/ExceptionMessages.h" #include "bindings/core/v8/ExceptionState.h" +#include "bindings/core/v8/ScrollIntoViewOptionsOrBoolean.h" #include "bindings/core/v8/V8DOMActivityLogger.h" #include "core/CSSValueKeywords.h" #include "core/SVGNames.h" @@ -95,6 +96,7 @@ #include "core/frame/LocalDOMWindow.h" #include "core/frame/LocalFrame.h" #include "core/frame/LocalFrameView.h" +#include "core/frame/ScrollIntoViewOptions.h" #include "core/frame/ScrollToOptions.h" #include "core/frame/Settings.h" #include "core/frame/UseCounter.h" @@ -141,6 +143,7 @@ #include "platform/graphics/CompositorMutableProperties.h" #include "platform/graphics/CompositorMutation.h" #include "platform/scroll/ScrollableArea.h" +#include "platform/scroll/SmoothScrollSequencer.h" #include "platform/wtf/BitVector.h" #include "platform/wtf/HashFunctions.h" #include "platform/wtf/text/CString.h" @@ -438,27 +441,88 @@ EnsureElementRareData().SetNonce(nonce); } +void Element::scrollIntoView(ScrollIntoViewOptionsOrBoolean arg) { + ScrollIntoViewOptions options; + if (arg.isBoolean()) { + if (arg.getAsBoolean()) + options.setBlock("start"); + else + options.setBlock("end"); + options.setInlinePosition("nearest"); + } else if (arg.isScrollIntoViewOptions()) { + options = arg.getAsScrollIntoViewOptions(); + if (!RuntimeEnabledFeatures::cssomSmoothScrollEnabled() && + options.behavior() == "smooth") { + options.setBehavior("instant"); + } + } + scrollIntoViewWithOptions(options); +} + void Element::scrollIntoView(bool align_to_top) { + ScrollIntoViewOptionsOrBoolean arg; + arg.setBoolean(align_to_top); + scrollIntoView(arg); +} + +static ScrollAlignment ToPhysicalAlignment(const ScrollIntoViewOptions& options, + ScrollOrientation axis, + bool is_horizontal_writing_mode) { + String alignment = + ((axis == kHorizontalScroll && is_horizontal_writing_mode) || + (axis == kVerticalScroll && !is_horizontal_writing_mode)) + ? options.inlinePosition() + : options.block(); + + if (alignment == "center") + return ScrollAlignment::kAlignCenterAlways; + if (alignment == "nearest") + return ScrollAlignment::kAlignToEdgeIfNeeded; + if (alignment == "start") { + return (axis == kHorizontalScroll) ? ScrollAlignment::kAlignLeftAlways + : ScrollAlignment::kAlignTopAlways; + } + if (alignment == "end") { + return (axis == kHorizontalScroll) ? ScrollAlignment::kAlignRightAlways + : ScrollAlignment::kAlignBottomAlways; + } + + // Default values + if (is_horizontal_writing_mode) { + return (axis == kHorizontalScroll) ? ScrollAlignment::kAlignToEdgeIfNeeded + : ScrollAlignment::kAlignTopAlways; + } + return (axis == kHorizontalScroll) ? ScrollAlignment::kAlignLeftAlways + : ScrollAlignment::kAlignToEdgeIfNeeded; +} + +void Element::scrollIntoViewWithOptions(const ScrollIntoViewOptions& options) { GetDocument().EnsurePaintLocationDataValidForNode(this); - if (!GetLayoutObject()) + if (!GetLayoutObject() || !GetDocument().GetPage()) return; bool make_visible_in_visual_viewport = !GetDocument().GetPage()->GetSettings().GetInertVisualViewport(); + ScrollBehavior behavior = (options.behavior() == "smooth") + ? kScrollBehaviorSmooth + : kScrollBehaviorAuto; + + bool is_horizontal_writing_mode = + GetComputedStyle()->IsHorizontalWritingMode(); + ScrollAlignment align_x = ToPhysicalAlignment(options, kHorizontalScroll, + is_horizontal_writing_mode); + ScrollAlignment align_y = + ToPhysicalAlignment(options, kVerticalScroll, is_horizontal_writing_mode); + + GetDocument().GetPage()->GetSmoothScrollSequencer()->AbortAnimations(); LayoutRect bounds = BoundingBox(); - // Align to the top / bottom and to the closest edge. - if (align_to_top) - GetLayoutObject()->ScrollRectToVisible( - bounds, ScrollAlignment::kAlignToEdgeIfNeeded, - ScrollAlignment::kAlignTopAlways, kProgrammaticScroll, - make_visible_in_visual_viewport); - else - GetLayoutObject()->ScrollRectToVisible( - bounds, ScrollAlignment::kAlignToEdgeIfNeeded, - ScrollAlignment::kAlignBottomAlways, kProgrammaticScroll, - make_visible_in_visual_viewport); + GetLayoutObject()->ScrollRectToVisible( + bounds, align_x, align_y, kProgrammaticScroll, + make_visible_in_visual_viewport, behavior); + + GetDocument().GetPage()->GetSmoothScrollSequencer()->RunQueuedAnimations(); GetDocument().SetSequentialFocusNavigationStartingPoint(this); }
diff --git a/third_party/WebKit/Source/core/dom/Element.h b/third_party/WebKit/Source/core/dom/Element.h index 692a381..5323a536 100644 --- a/third_party/WebKit/Source/core/dom/Element.h +++ b/third_party/WebKit/Source/core/dom/Element.h
@@ -65,6 +65,8 @@ class PseudoStyleRequest; class ResizeObservation; class ResizeObserver; +class ScrollIntoViewOptions; +class ScrollIntoViewOptionsOrBoolean; class ScrollState; class ScrollStateCallback; class ScrollToOptions; @@ -227,7 +229,9 @@ // attributes. AttributeCollection AttributesWithoutUpdate() const; + void scrollIntoView(ScrollIntoViewOptionsOrBoolean); void scrollIntoView(bool align_to_top = true); + void scrollIntoViewWithOptions(const ScrollIntoViewOptions&); void scrollIntoViewIfNeeded(bool center_if_needed = true); int OffsetLeft();
diff --git a/third_party/WebKit/Source/core/dom/Element.idl b/third_party/WebKit/Source/core/dom/Element.idl index 47867a1..b9ea6a7 100644 --- a/third_party/WebKit/Source/core/dom/Element.idl +++ b/third_party/WebKit/Source/core/dom/Element.idl
@@ -93,8 +93,8 @@ // return DOMRectList and DOMRect respectively. ClientRectList getClientRects(); ClientRect getBoundingClientRect(); - // FIXME: scrollIntoView() should have a ScrollIntoViewOptions dictionary argument. - void scrollIntoView(optional boolean alignWithTop); + + void scrollIntoView(optional (ScrollIntoViewOptions or boolean)? arg); [RuntimeEnabled=CSSOMSmoothScroll, ImplementedAs=scrollTo] void scroll(optional ScrollToOptions options); [RuntimeEnabled=CSSOMSmoothScroll, ImplementedAs=scrollTo] void scroll(unrestricted double x, unrestricted double y); [RuntimeEnabled=CSSOMSmoothScroll] void scrollTo(optional ScrollToOptions options);
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp index 2e8f1551..c0f23e6 100644 --- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp +++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -1180,6 +1180,21 @@ return GetFrame()->DevicePixelRatio(); } +void LocalDOMWindow::scrollViewportTo(ScrollableArea* viewport, + const ScrollOffset& offset, + ScrollBehavior scroll_behavior) const { + if (SmoothScrollSequencer* sequencer = + GetFrame()->GetPage()->GetSmoothScrollSequencer()) { + sequencer->AbortAnimations(); + if (scroll_behavior == kScrollBehaviorSmooth) { + sequencer->QueueAnimation(viewport, offset); + sequencer->RunQueuedAnimations(); + } else { + viewport->SetScrollOffset(offset, kProgrammaticScroll, scroll_behavior); + } + } +} + void LocalDOMWindow::scrollBy(double x, double y, ScrollBehavior scroll_behavior) const { @@ -1207,8 +1222,7 @@ ScrollOffset scaled_delta(x * GetFrame()->PageZoomFactor(), y * GetFrame()->PageZoomFactor()); - viewport->SetScrollOffset(current_offset + scaled_delta, kProgrammaticScroll, - scroll_behavior); + scrollViewportTo(viewport, current_offset + scaled_delta, scroll_behavior); } void LocalDOMWindow::scrollBy(const ScrollToOptions& scroll_to_options) const { @@ -1249,8 +1263,7 @@ ScrollableArea* viewport = page->GetSettings().GetInertVisualViewport() ? view->LayoutViewportScrollableArea() : view->GetScrollableArea(); - viewport->SetScrollOffset(layout_offset, kProgrammaticScroll, - kScrollBehaviorAuto); + scrollViewportTo(viewport, layout_offset, kScrollBehaviorAuto); } void LocalDOMWindow::scrollTo(const ScrollToOptions& scroll_to_options) const { @@ -1297,8 +1310,7 @@ ScrollableArea::ScrollBehaviorFromString(scroll_to_options.behavior(), scroll_behavior); - viewport->SetScrollOffset(ScrollOffset(scaled_x, scaled_y), - kProgrammaticScroll, scroll_behavior); + scrollViewportTo(viewport, ScrollOffset(scaled_x, scaled_y), scroll_behavior); } void LocalDOMWindow::moveBy(int x, int y) const {
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h index 2ad0b6a..987f1cad 100644 --- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h +++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
@@ -195,6 +195,9 @@ // FIXME: ScrollBehaviorSmooth is currently unsupported in VisualViewport. // crbug.com/434497 + void scrollViewportTo(ScrollableArea*, + const ScrollOffset&, + ScrollBehavior) const; void scrollBy(double x, double y, ScrollBehavior = kScrollBehaviorAuto) const; void scrollBy(const ScrollToOptions&) const; void scrollTo(double x, double y) const;
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp index eb769944..0e838fd5 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -2127,6 +2127,13 @@ return &page->GetChromeClient(); } +SmoothScrollSequencer* LocalFrameView::GetSmoothScrollSequencer() const { + Page* page = GetFrame().GetPage(); + if (!page) + return nullptr; + return page->GetSmoothScrollSequencer(); +} + void LocalFrameView::ContentsResized() { if (frame_->IsMainFrame() && frame_->GetDocument()) { if (TextAutosizer* text_autosizer = @@ -4610,14 +4617,20 @@ LayoutRect LocalFrameView::ScrollIntoView(const LayoutRect& rect_in_content, const ScrollAlignment& align_x, const ScrollAlignment& align_y, + bool is_smooth, ScrollType scroll_type) { LayoutRect view_rect(VisibleContentRect()); LayoutRect expose_rect = ScrollAlignment::GetRectToExpose( view_rect, rect_in_content, align_x, align_y); if (expose_rect != view_rect) { - SetScrollOffset( - ScrollOffset(expose_rect.X().ToFloat(), expose_rect.Y().ToFloat()), - scroll_type); + ScrollOffset target_offset(expose_rect.X().ToFloat(), + expose_rect.Y().ToFloat()); + if (is_smooth) { + DCHECK(scroll_type == kProgrammaticScroll); + GetSmoothScrollSequencer()->QueueAnimation(this, target_offset); + } else { + SetScrollOffset(target_offset, scroll_type); + } } // Scrolling the LocalFrameView cannot change the input rect's location
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.h b/third_party/WebKit/Source/core/frame/LocalFrameView.h index 7c6e9386..d4dfe865 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameView.h +++ b/third_party/WebKit/Source/core/frame/LocalFrameView.h
@@ -51,6 +51,7 @@ #include "platform/graphics/GraphicsLayerClient.h" #include "platform/scroll/ScrollTypes.h" #include "platform/scroll/Scrollbar.h" +#include "platform/scroll/SmoothScrollSequencer.h" #include "platform/wtf/Allocator.h" #include "platform/wtf/AutoReset.h" #include "platform/wtf/Forward.h" @@ -470,6 +471,7 @@ LayoutRect ScrollIntoView(const LayoutRect& rect_in_content, const ScrollAlignment& align_x, const ScrollAlignment& align_y, + bool is_smooth, ScrollType = kProgrammaticScroll) override; // The window that hosts the LocalFrameView. The LocalFrameView will @@ -477,6 +479,8 @@ // coordinate space. PlatformChromeClient* GetChromeClient() const; + SmoothScrollSequencer* GetSmoothScrollSequencer() const override; + // Functions for child manipulation and inspection. bool IsSelfVisible() const { return self_visible_;
diff --git a/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp b/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp index cc76a0e..d89b8b0 100644 --- a/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp +++ b/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp
@@ -209,6 +209,7 @@ LayoutRect RootFrameViewport::ScrollIntoView(const LayoutRect& rect_in_content, const ScrollAlignment& align_x, const ScrollAlignment& align_y, + bool is_smooth, ScrollType scroll_type) { // We want to move the rect into the viewport that excludes the scrollbars so // we intersect the visual viewport with the scrollbar-excluded frameView @@ -229,8 +230,13 @@ LayoutRect target_viewport = ScrollAlignment::GetRectToExpose( view_rect_in_content, rect_in_content, align_x, align_y); if (target_viewport != view_rect_in_content) { - SetScrollOffset(ScrollOffset(target_viewport.X(), target_viewport.Y()), - scroll_type); + ScrollOffset target_offset(target_viewport.X(), target_viewport.Y()); + if (is_smooth) { + DCHECK(scroll_type == kProgrammaticScroll); + GetSmoothScrollSequencer()->QueueAnimation(this, target_offset); + } else { + SetScrollOffset(target_offset, scroll_type); + } } // RootFrameViewport only changes the viewport relative to the document so we @@ -431,6 +437,10 @@ return LayoutViewport().GetChromeClient(); } +SmoothScrollSequencer* RootFrameViewport::GetSmoothScrollSequencer() const { + return LayoutViewport().GetSmoothScrollSequencer(); +} + void RootFrameViewport::ServiceScrollAnimations(double monotonic_time) { ScrollableArea::ServiceScrollAnimations(monotonic_time); LayoutViewport().ServiceScrollAnimations(monotonic_time);
diff --git a/third_party/WebKit/Source/core/frame/RootFrameViewport.h b/third_party/WebKit/Source/core/frame/RootFrameViewport.h index 2c276dad..473b4d2 100644 --- a/third_party/WebKit/Source/core/frame/RootFrameViewport.h +++ b/third_party/WebKit/Source/core/frame/RootFrameViewport.h
@@ -61,6 +61,7 @@ LayoutRect ScrollIntoView(const LayoutRect& rect_in_content, const ScrollAlignment& align_x, const ScrollAlignment& align_y, + bool is_smooth, ScrollType = kProgrammaticScroll) override; IntRect VisibleContentRect( IncludeScrollbarsInRect = kExcludeScrollbars) const override; @@ -95,6 +96,7 @@ ScrollResult UserScroll(ScrollGranularity, const FloatSize&) override; bool ScrollAnimatorEnabled() const override; PlatformChromeClient* GetChromeClient() const override; + SmoothScrollSequencer* GetSmoothScrollSequencer() const override; void ServiceScrollAnimations(double) override; void UpdateCompositorScrollAnimations() override; void CancelProgrammaticScrollAnimation() override;
diff --git a/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp b/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp index 54d335f..b22aace 100644 --- a/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp +++ b/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp
@@ -307,15 +307,15 @@ // resized (as is the case when the ChromeOS keyboard comes up) but not // scaled. visual_viewport->SetViewportSize(IntSize(100, 100)); - root_frame_viewport->ScrollIntoView(LayoutRect(100, 250, 50, 50), - ScrollAlignment::kAlignToEdgeIfNeeded, - ScrollAlignment::kAlignToEdgeIfNeeded); + root_frame_viewport->ScrollIntoView( + LayoutRect(100, 250, 50, 50), ScrollAlignment::kAlignToEdgeIfNeeded, + ScrollAlignment::kAlignToEdgeIfNeeded, false); EXPECT_SIZE_EQ(ScrollOffset(50, 150), layout_viewport->GetScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 50), visual_viewport->GetScrollOffset()); - root_frame_viewport->ScrollIntoView(LayoutRect(25, 75, 50, 50), - ScrollAlignment::kAlignToEdgeIfNeeded, - ScrollAlignment::kAlignToEdgeIfNeeded); + root_frame_viewport->ScrollIntoView( + LayoutRect(25, 75, 50, 50), ScrollAlignment::kAlignToEdgeIfNeeded, + ScrollAlignment::kAlignToEdgeIfNeeded, false); EXPECT_SIZE_EQ(ScrollOffset(25, 75), layout_viewport->GetScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 0), visual_viewport->GetScrollOffset()); @@ -324,15 +324,15 @@ visual_viewport->SetScale(2); root_frame_viewport->SetScrollOffset(ScrollOffset(), kProgrammaticScroll); - root_frame_viewport->ScrollIntoView(LayoutRect(50, 75, 50, 75), - ScrollAlignment::kAlignToEdgeIfNeeded, - ScrollAlignment::kAlignToEdgeIfNeeded); + root_frame_viewport->ScrollIntoView( + LayoutRect(50, 75, 50, 75), ScrollAlignment::kAlignToEdgeIfNeeded, + ScrollAlignment::kAlignToEdgeIfNeeded, false); EXPECT_SIZE_EQ(ScrollOffset(0, 0), layout_viewport->GetScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(50, 75), visual_viewport->GetScrollOffset()); - root_frame_viewport->ScrollIntoView(LayoutRect(190, 290, 10, 10), - ScrollAlignment::kAlignToEdgeIfNeeded, - ScrollAlignment::kAlignToEdgeIfNeeded); + root_frame_viewport->ScrollIntoView( + LayoutRect(190, 290, 10, 10), ScrollAlignment::kAlignToEdgeIfNeeded, + ScrollAlignment::kAlignToEdgeIfNeeded, false); EXPECT_SIZE_EQ(ScrollOffset(100, 150), layout_viewport->GetScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(50, 75), visual_viewport->GetScrollOffset()); @@ -347,19 +347,21 @@ root_frame_viewport->ScrollIntoView( LayoutRect(root_frame_viewport->VisibleContentRect(kExcludeScrollbars)), ScrollAlignment::kAlignToEdgeIfNeeded, - ScrollAlignment::kAlignToEdgeIfNeeded); + ScrollAlignment::kAlignToEdgeIfNeeded, false); EXPECT_SIZE_EQ(ScrollOffset(50, 50), layout_viewport->GetScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 10), visual_viewport->GetScrollOffset()); root_frame_viewport->ScrollIntoView( LayoutRect(root_frame_viewport->VisibleContentRect(kExcludeScrollbars)), - ScrollAlignment::kAlignCenterAlways, ScrollAlignment::kAlignCenterAlways); + ScrollAlignment::kAlignCenterAlways, ScrollAlignment::kAlignCenterAlways, + false); EXPECT_SIZE_EQ(ScrollOffset(50, 50), layout_viewport->GetScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 10), visual_viewport->GetScrollOffset()); root_frame_viewport->ScrollIntoView( LayoutRect(root_frame_viewport->VisibleContentRect(kExcludeScrollbars)), - ScrollAlignment::kAlignTopAlways, ScrollAlignment::kAlignTopAlways); + ScrollAlignment::kAlignTopAlways, ScrollAlignment::kAlignTopAlways, + false); EXPECT_SIZE_EQ(ScrollOffset(50, 50), layout_viewport->GetScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 10), visual_viewport->GetScrollOffset()); }
diff --git a/third_party/WebKit/Source/core/frame/ScrollIntoViewOptions.idl b/third_party/WebKit/Source/core/frame/ScrollIntoViewOptions.idl new file mode 100644 index 0000000..49a2c831 --- /dev/null +++ b/third_party/WebKit/Source/core/frame/ScrollIntoViewOptions.idl
@@ -0,0 +1,6 @@ +enum ScrollLogicalPosition { "start", "center", "end", "nearest" }; + +dictionary ScrollIntoViewOptions : ScrollOptions { + ScrollLogicalPosition block = "center"; + ScrollLogicalPosition inlinePosition = "center"; +}; \ No newline at end of file
diff --git a/third_party/WebKit/Source/core/html/HTMLVideoElement.h b/third_party/WebKit/Source/core/html/HTMLVideoElement.h index 6c9a1f55..f8dbebc 100644 --- a/third_party/WebKit/Source/core/html/HTMLVideoElement.h +++ b/third_party/WebKit/Source/core/html/HTMLVideoElement.h
@@ -143,6 +143,9 @@ } void DisableMediaRemoting(); + void MediaRemotingStarted() final; + void MediaRemotingStopped() final; + private: friend class MediaCustomControlsFullscreenDetectorTest; friend class HTMLMediaElementEventListenersTest; @@ -167,8 +170,6 @@ void UpdateDisplayState() override; void DidMoveToNewDocument(Document& old_document) override; void SetDisplayMode(DisplayMode) override; - void MediaRemotingStarted() final; - void MediaRemotingStopped() final; Member<HTMLImageLoader> image_loader_; Member<MediaCustomControlsFullscreenDetector>
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp index 8cbc40d..382ef45 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -662,7 +662,8 @@ const ScrollAlignment& align_x, const ScrollAlignment& align_y, ScrollType scroll_type, - bool make_visible_in_visual_viewport) { + bool make_visible_in_visual_viewport, + ScrollBehavior scroll_behavior) { DCHECK(scroll_type == kProgrammaticScroll || scroll_type == kUserScroll); // Presumably the same issue as in setScrollTop. See crbug.com/343132. DisableCompositingQueryAsserts disabler; @@ -683,14 +684,18 @@ !ContainingBlock()->Style()->LineClamp().IsNone(); } + bool is_smooth = scroll_behavior == kScrollBehaviorSmooth || + (scroll_behavior == kScrollBehaviorAuto && + Style()->GetScrollBehavior() == kScrollBehaviorSmooth); + if (HasOverflowClip() && !restricted_by_line_clamp) { // Don't scroll to reveal an overflow layer that is restricted by the // -webkit-line-clamp property. This will prevent us from revealing text // hidden by the slider in Safari RSS. // TODO(eae): We probably don't need this any more as we don't share any // code with the Safari RSS reeder. - new_rect = GetScrollableArea()->ScrollIntoView(rect_to_scroll, align_x, - align_y, scroll_type); + new_rect = GetScrollableArea()->ScrollIntoView( + rect_to_scroll, align_x, align_y, is_smooth, scroll_type); if (new_rect.IsEmpty()) return; } else if (!parent_box && CanBeProgramaticallyScrolled()) { @@ -699,10 +704,10 @@ if (!IsDisallowedAutoscroll(owner_element, frame_view)) { if (make_visible_in_visual_viewport) { frame_view->GetScrollableArea()->ScrollIntoView( - rect_to_scroll, align_x, align_y, scroll_type); + rect_to_scroll, align_x, align_y, is_smooth, scroll_type); } else { frame_view->LayoutViewportScrollableArea()->ScrollIntoView( - rect_to_scroll, align_x, align_y, scroll_type); + rect_to_scroll, align_x, align_y, is_smooth, scroll_type); } if (owner_element && owner_element->GetLayoutObject()) { if (frame_view->SafeToPropagateScrollToParent()) { @@ -732,9 +737,11 @@ if (GetFrame()->GetPage()->GetAutoscrollController().AutoscrollInProgress()) parent_box = EnclosingScrollableBox(); - if (parent_box) + if (parent_box) { parent_box->ScrollRectToVisible(new_rect, align_x, align_y, scroll_type, - make_visible_in_visual_viewport); + make_visible_in_visual_viewport, + scroll_behavior); + } } void LayoutBox::AbsoluteRects(Vector<IntRect>& rects,
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h index d2b3f86..464f77a 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.h +++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -588,7 +588,8 @@ const ScrollAlignment& align_x, const ScrollAlignment& align_y, ScrollType = kProgrammaticScroll, - bool make_visible_in_visual_viewport = true); + bool make_visible_in_visual_viewport = true, + ScrollBehavior = kScrollBehaviorAuto); LayoutRectOutsets MarginBoxOutsets() const override { return margin_box_outsets_;
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp index a3d2251..7fc73fa 100644 --- a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
@@ -1483,11 +1483,12 @@ return LayoutUnit(); } -// FIXME: This logic is shared by LayoutFlexibleBox, so it should be moved to -// LayoutBox. -LayoutUnit LayoutGrid::MarginLogicalHeightForChild( +LayoutUnit LayoutGrid::MarginLogicalSizeForChild( + GridTrackSizingDirection direction, const LayoutBox& child) const { - return IsHorizontalWritingMode() ? child.MarginHeight() : child.MarginWidth(); + return FlowAwareDirectionForChild(child, direction) == kForColumns + ? child.MarginLogicalWidth() + : child.MarginLogicalHeight(); } LayoutUnit LayoutGrid::ComputeMarginLogicalSizeForChild( @@ -1520,10 +1521,12 @@ // performed before children are laid out, so we can't use the child cached // values. Hence, we need to compute margins in order to determine the // available height before stretching. + GridTrackSizingDirection child_block_flow_direction = + FlowAwareDirectionForChild(child, kForRows); return grid_area_breadth_for_child - (child.NeedsLayout() ? ComputeMarginLogicalSizeForChild(kBlockDirection, child) - : MarginLogicalHeightForChild(child)); + : MarginLogicalSizeForChild(child_block_flow_direction, child)); } StyleSelfAlignmentData LayoutGrid::AlignSelfForChild(
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.h b/third_party/WebKit/Source/core/layout/LayoutGrid.h index 34b5414..cf5354f 100644 --- a/third_party/WebKit/Source/core/layout/LayoutGrid.h +++ b/third_party/WebKit/Source/core/layout/LayoutGrid.h
@@ -205,7 +205,8 @@ void PaintChildren(const PaintInfo&, const LayoutPoint&) const override; - LayoutUnit MarginLogicalHeightForChild(const LayoutBox&) const; + LayoutUnit MarginLogicalSizeForChild(GridTrackSizingDirection, + const LayoutBox&) const; LayoutUnit ComputeMarginLogicalSizeForChild(MarginDirection, const LayoutBox&) const; LayoutUnit AvailableAlignmentSpaceForChildBeforeStretching(
diff --git a/third_party/WebKit/Source/core/layout/LayoutListBox.cpp b/third_party/WebKit/Source/core/layout/LayoutListBox.cpp index d3a45d6..fb7cbd9 100644 --- a/third_party/WebKit/Source/core/layout/LayoutListBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutListBox.cpp
@@ -133,7 +133,7 @@ DCHECK(Layer()->GetScrollableArea()); Layer()->GetScrollableArea()->ScrollIntoView( rect, ScrollAlignment::kAlignToEdgeIfNeeded, - ScrollAlignment::kAlignToEdgeIfNeeded); + ScrollAlignment::kAlignToEdgeIfNeeded, false); } }
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp index 1f6b5b50..1639492 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -631,13 +631,15 @@ const ScrollAlignment& align_x, const ScrollAlignment& align_y, ScrollType scroll_type, - bool make_visible_in_visual_viewport) { + bool make_visible_in_visual_viewport, + ScrollBehavior scroll_behavior) { LayoutBox* enclosing_box = this->EnclosingBox(); if (!enclosing_box) return false; enclosing_box->ScrollRectToVisible(rect, align_x, align_y, scroll_type, - make_visible_in_visual_viewport); + make_visible_in_visual_viewport, + scroll_behavior); return true; }
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h index 34ccc620..ed845f2 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.h +++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -280,7 +280,8 @@ const ScrollAlignment& align_x = ScrollAlignment::kAlignCenterIfNeeded, const ScrollAlignment& align_y = ScrollAlignment::kAlignCenterIfNeeded, ScrollType = kProgrammaticScroll, - bool make_visible_in_visual_viewport = true); + bool make_visible_in_visual_viewport = true, + ScrollBehavior = kScrollBehaviorAuto); // Convenience function for getting to the nearest enclosing box of a // LayoutObject.
diff --git a/third_party/WebKit/Source/core/layout/ScrollAlignment.cpp b/third_party/WebKit/Source/core/layout/ScrollAlignment.cpp index b91cd6b..f9756ff 100644 --- a/third_party/WebKit/Source/core/layout/ScrollAlignment.cpp +++ b/third_party/WebKit/Source/core/layout/ScrollAlignment.cpp
@@ -59,6 +59,10 @@ kScrollAlignmentTop, kScrollAlignmentTop, kScrollAlignmentTop}; const ScrollAlignment ScrollAlignment::kAlignBottomAlways = { kScrollAlignmentBottom, kScrollAlignmentBottom, kScrollAlignmentBottom}; +const ScrollAlignment ScrollAlignment::kAlignLeftAlways = { + kScrollAlignmentLeft, kScrollAlignmentLeft, kScrollAlignmentLeft}; +const ScrollAlignment ScrollAlignment::kAlignRightAlways = { + kScrollAlignmentRight, kScrollAlignmentRight, kScrollAlignmentRight}; #define MIN_INTERSECT_FOR_REVEAL 32
diff --git a/third_party/WebKit/Source/core/layout/ScrollAlignment.h b/third_party/WebKit/Source/core/layout/ScrollAlignment.h index 4d162cc7..cfa070b 100644 --- a/third_party/WebKit/Source/core/layout/ScrollAlignment.h +++ b/third_party/WebKit/Source/core/layout/ScrollAlignment.h
@@ -84,6 +84,8 @@ static const ScrollAlignment kAlignCenterAlways; static const ScrollAlignment kAlignTopAlways; static const ScrollAlignment kAlignBottomAlways; + static const ScrollAlignment kAlignLeftAlways; + static const ScrollAlignment kAlignRightAlways; ScrollAlignmentBehavior rect_visible_; ScrollAlignmentBehavior rect_hidden_;
diff --git a/third_party/WebKit/Source/core/page/Page.cpp b/third_party/WebKit/Source/core/page/Page.cpp index 25b883e..a8096785 100644 --- a/third_party/WebKit/Source/core/page/Page.cpp +++ b/third_party/WebKit/Source/core/page/Page.cpp
@@ -61,6 +61,7 @@ #include "platform/graphics/GraphicsLayer.h" #include "platform/loader/fetch/ResourceFetcher.h" #include "platform/plugins/PluginData.h" +#include "platform/scroll/SmoothScrollSequencer.h" #include "public/platform/Platform.h" namespace blink { @@ -172,6 +173,13 @@ return *page_scale_constraints_set_; } +SmoothScrollSequencer* Page::GetSmoothScrollSequencer() { + if (!smooth_scroll_sequencer_) + smooth_scroll_sequencer_ = new SmoothScrollSequencer(); + + return smooth_scroll_sequencer_.Get(); +} + const PageScaleConstraintsSet& Page::GetPageScaleConstraintsSet() const { return *page_scale_constraints_set_; } @@ -626,6 +634,7 @@ visitor->Trace(context_menu_controller_); visitor->Trace(pointer_lock_controller_); visitor->Trace(scrolling_coordinator_); + visitor->Trace(smooth_scroll_sequencer_); visitor->Trace(browser_controls_); visitor->Trace(console_message_storage_); visitor->Trace(event_handler_registry_);
diff --git a/third_party/WebKit/Source/core/page/Page.h b/third_party/WebKit/Source/core/page/Page.h index f1ef9635..9e0b4de 100644 --- a/third_party/WebKit/Source/core/page/Page.h +++ b/third_party/WebKit/Source/core/page/Page.h
@@ -66,6 +66,7 @@ class PointerLockController; class ScopedPageSuspender; class ScrollingCoordinator; +class SmoothScrollSequencer; class Settings; class ConsoleMessageStorage; class SpellCheckerClient; @@ -177,6 +178,8 @@ ScrollingCoordinator* GetScrollingCoordinator(); + SmoothScrollSequencer* GetSmoothScrollSequencer(); + ClientRectList* NonFastScrollableRects(const LocalFrame*); Settings& GetSettings() const { return *settings_; } @@ -302,6 +305,7 @@ const std::unique_ptr<PageScaleConstraintsSet> page_scale_constraints_set_; const Member<PointerLockController> pointer_lock_controller_; Member<ScrollingCoordinator> scrolling_coordinator_; + Member<SmoothScrollSequencer> smooth_scroll_sequencer_; const Member<BrowserControls> browser_controls_; const Member<ConsoleMessageStorage> console_message_storage_; const Member<EventHandlerRegistry> event_handler_registry_;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp index a268a74f..948b6c2 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -209,6 +209,13 @@ return nullptr; } +SmoothScrollSequencer* PaintLayerScrollableArea::GetSmoothScrollSequencer() + const { + if (Page* page = Box().GetFrame()->GetPage()) + return page->GetSmoothScrollSequencer(); + return nullptr; +} + GraphicsLayer* PaintLayerScrollableArea::LayerForScrolling() const { return Layer()->HasCompositedLayerMapping() ? Layer()->GetCompositedLayerMapping()->ScrollingContentsLayer() @@ -1731,6 +1738,7 @@ const LayoutRect& rect, const ScrollAlignment& align_x, const ScrollAlignment& align_y, + bool is_smooth, ScrollType scroll_type) { LayoutRect local_expose_rect( Box() @@ -1744,8 +1752,14 @@ ScrollOffset old_scroll_offset = GetScrollOffset(); ScrollOffset new_scroll_offset(ClampScrollOffset(RoundedIntSize( ToScrollOffset(FloatPoint(r.Location()) + old_scroll_offset)))); - SetScrollOffset(new_scroll_offset, scroll_type, kScrollBehaviorInstant); - ScrollOffset scroll_offset_difference = GetScrollOffset() - old_scroll_offset; + if (is_smooth) { + DCHECK(scroll_type == kProgrammaticScroll); + GetSmoothScrollSequencer()->QueueAnimation(this, new_scroll_offset); + } else { + SetScrollOffset(new_scroll_offset, scroll_type, kScrollBehaviorInstant); + } + ScrollOffset scroll_offset_difference = + ClampScrollOffset(new_scroll_offset) - old_scroll_offset; local_expose_rect.Move(-LayoutSize(scroll_offset_difference)); LayoutRect intersect =
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h index c396827..ff607f8f 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h +++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
@@ -240,6 +240,8 @@ PlatformChromeClient* GetChromeClient() const override; + SmoothScrollSequencer* GetSmoothScrollSequencer() const override; + // For composited scrolling, we allocate an extra GraphicsLayer to hold // onto the scrolling content. The layer can be shifted on the GPU and // composited at little cost. @@ -392,6 +394,7 @@ LayoutRect ScrollIntoView(const LayoutRect&, const ScrollAlignment& align_x, const ScrollAlignment& align_y, + bool is_smooth, ScrollType = kProgrammaticScroll) override; // Returns true if scrollable area is in the FrameView's collection of
diff --git a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp index aaa72f77..90fafd8 100644 --- a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp +++ b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp
@@ -13,6 +13,7 @@ #include "core/dom/UserGestureIndicator.h" #include "core/events/Event.h" #include "core/html/HTMLMediaElement.h" +#include "core/html/HTMLVideoElement.h" #include "core/probe/CoreProbes.h" #include "modules/EventTargetModules.h" #include "modules/remoteplayback/AvailabilityCallbackWrapper.h" @@ -269,12 +270,20 @@ switch (state_) { case WebRemotePlaybackState::kConnecting: DispatchEvent(Event::Create(EventTypeNames::connecting)); + if (RuntimeEnabledFeatures::newRemotePlaybackPipelineEnabled() && + media_element_->IsHTMLVideoElement()) { + toHTMLVideoElement(media_element_)->MediaRemotingStarted(); + } break; case WebRemotePlaybackState::kConnected: DispatchEvent(Event::Create(EventTypeNames::connect)); break; case WebRemotePlaybackState::kDisconnected: DispatchEvent(Event::Create(EventTypeNames::disconnect)); + if (RuntimeEnabledFeatures::newRemotePlaybackPipelineEnabled() && + media_element_->IsHTMLVideoElement()) { + toHTMLVideoElement(media_element_)->MediaRemotingStopped(); + } break; } }
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index e3caa04..6dcc0b1b 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -1386,6 +1386,8 @@ "scroll/ScrollbarThemeOverlay.cpp", "scroll/ScrollbarThemeOverlay.h", "scroll/ScrollbarThemeOverlayMock.h", + "scroll/SmoothScrollSequencer.cpp", + "scroll/SmoothScrollSequencer.h", "speech/PlatformSpeechSynthesisUtterance.cpp", "speech/PlatformSpeechSynthesisUtterance.h", "speech/PlatformSpeechSynthesisVoice.cpp",
diff --git a/third_party/WebKit/Source/platform/geometry/FloatSize.h b/third_party/WebKit/Source/platform/geometry/FloatSize.h index 138c452..0dbbafe 100644 --- a/third_party/WebKit/Source/platform/geometry/FloatSize.h +++ b/third_party/WebKit/Source/platform/geometry/FloatSize.h
@@ -199,4 +199,7 @@ } // namespace blink +// Allows this class to be stored in a HeapVector. +WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS(blink::FloatSize); + #endif // FloatSize_h
diff --git a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp index b717e08..1ced7257 100644 --- a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp +++ b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.cpp
@@ -10,6 +10,7 @@ #include "platform/geometry/IntSize.h" #include "platform/graphics/GraphicsLayer.h" #include "platform/scroll/ScrollableArea.h" +#include "platform/scroll/SmoothScrollSequencer.h" #include "platform/wtf/PtrUtil.h" #include "public/platform/Platform.h" #include "public/platform/WebCompositorSupport.h" @@ -39,12 +40,15 @@ NotifyOffsetChanged(offset); } -void ProgrammaticScrollAnimator::AnimateToOffset(const ScrollOffset& offset) { +void ProgrammaticScrollAnimator::AnimateToOffset( + const ScrollOffset& offset, + bool sequenced_for_smooth_scroll) { if (run_state_ == RunState::kPostAnimationCleanup) ResetAnimationState(); start_time_ = 0.0; target_offset_ = offset; + sequenced_for_smooth_scroll_ = sequenced_for_smooth_scroll; animation_curve_ = CompositorScrollOffsetAnimationCurve::Create( CompositorOffsetFromBlinkOffset(target_offset_), CompositorScrollOffsetAnimationCurve::kScrollDurationDeltaBased); @@ -76,6 +80,7 @@ if (is_finished) { run_state_ = RunState::kPostAnimationCleanup; + AnimationFinished(); } else if (!scrollable_area_->ScheduleAnimation()) { NotifyOffsetChanged(offset); ResetAnimationState(); @@ -169,6 +174,16 @@ int group_id) { DCHECK_NE(run_state_, RunState::kRunningOnCompositorButNeedsUpdate); ScrollAnimatorCompositorCoordinator::CompositorAnimationFinished(group_id); + AnimationFinished(); +} + +void ProgrammaticScrollAnimator::AnimationFinished() { + if (sequenced_for_smooth_scroll_) { + sequenced_for_smooth_scroll_ = false; + if (SmoothScrollSequencer* sequencer = + GetScrollableArea()->GetSmoothScrollSequencer()) + sequencer->RunQueuedAnimations(); + } } DEFINE_TRACE(ProgrammaticScrollAnimator) {
diff --git a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.h b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.h index f8a365c..8f1240fa 100644 --- a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.h +++ b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.h
@@ -30,7 +30,8 @@ virtual ~ProgrammaticScrollAnimator(); void ScrollToOffsetWithoutAnimation(const ScrollOffset&); - void AnimateToOffset(const ScrollOffset&); + void AnimateToOffset(const ScrollOffset&, + bool sequenced_for_smooth_scroll = false); // ScrollAnimatorCompositorCoordinator implementation. void ResetAnimationState() override; @@ -52,11 +53,13 @@ explicit ProgrammaticScrollAnimator(ScrollableArea*); void NotifyOffsetChanged(const ScrollOffset&); + void AnimationFinished(); Member<ScrollableArea> scrollable_area_; std::unique_ptr<CompositorScrollOffsetAnimationCurve> animation_curve_; ScrollOffset target_offset_; double start_time_; + bool sequenced_for_smooth_scroll_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollTypes.h b/third_party/WebKit/Source/platform/scroll/ScrollTypes.h index 63a564a..7be2896 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollTypes.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollTypes.h
@@ -181,6 +181,8 @@ enum ScrollbarOrientation { kHorizontalScrollbar, kVerticalScrollbar }; +enum ScrollOrientation { kHorizontalScroll, kVerticalScroll }; + enum ScrollbarMode { kScrollbarAuto, kScrollbarAlwaysOff, kScrollbarAlwaysOn }; enum ScrollbarControlSize { kRegularScrollbar, kSmallScrollbar };
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp b/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp index 769acc3..09a44edf 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
@@ -37,6 +37,7 @@ #include "platform/scroll/MainThreadScrollingReason.h" #include "platform/scroll/ProgrammaticScrollAnimator.h" #include "platform/scroll/ScrollbarTheme.h" +#include "platform/scroll/SmoothScrollSequencer.h" static const int kPixelsPerLineStep = 40; static const float kMinFractionToStepWhenPaging = 0.875f; @@ -227,7 +228,7 @@ CancelScrollAnimation(); if (scroll_behavior == kScrollBehaviorSmooth) - GetProgrammaticScrollAnimator().AnimateToOffset(offset); + GetProgrammaticScrollAnimator().AnimateToOffset(offset, true); else GetProgrammaticScrollAnimator().ScrollToOffsetWithoutAnimation(offset); } @@ -255,6 +256,7 @@ LayoutRect ScrollableArea::ScrollIntoView(const LayoutRect& rect_in_content, const ScrollAlignment& align_x, const ScrollAlignment& align_y, + bool is_smooth, ScrollType) { // TODO(bokan): This should really be implemented here but ScrollAlignment is // in Core which is a dependency violation.
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h index a84fe5c..728ac9b5 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
@@ -53,6 +53,7 @@ struct ScrollAlignment; class ScrollAnchor; class ScrollAnimatorBase; +class SmoothScrollSequencer; class CompositorAnimationTimeline; enum IncludeScrollbarsInRect { @@ -77,6 +78,10 @@ virtual PlatformChromeClient* GetChromeClient() const { return 0; } + virtual SmoothScrollSequencer* GetSmoothScrollSequencer() const { + return nullptr; + } + virtual ScrollResult UserScroll(ScrollGranularity, const ScrollOffset&); virtual void SetScrollOffset(const ScrollOffset&, @@ -99,6 +104,7 @@ virtual LayoutRect ScrollIntoView(const LayoutRect& rect_in_content, const ScrollAlignment& align_x, const ScrollAlignment& align_y, + bool is_smooth, ScrollType = kProgrammaticScroll); static bool ScrollBehaviorFromString(const String&, ScrollBehavior&);
diff --git a/third_party/WebKit/Source/platform/scroll/SmoothScrollSequencer.cpp b/third_party/WebKit/Source/platform/scroll/SmoothScrollSequencer.cpp new file mode 100644 index 0000000..f4ba71b --- /dev/null +++ b/third_party/WebKit/Source/platform/scroll/SmoothScrollSequencer.cpp
@@ -0,0 +1,47 @@ +// Copyright (c) 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 "platform/scroll/SmoothScrollSequencer.h" + +#include "platform/scroll/ProgrammaticScrollAnimator.h" +#include "platform/scroll/ScrollableArea.h" + +namespace blink { + +SmoothScrollSequencer::SmoothScrollSequencer() {} + +void SmoothScrollSequencer::QueueAnimation(ScrollableArea* scrollable, + ScrollOffset offset) { + ScrollerAndOffsetPair scroller_offset(scrollable, offset); + queue_.push_back(scroller_offset); +} + +void SmoothScrollSequencer::RunQueuedAnimations() { + if (queue_.IsEmpty()) { + current_scrollable_ = nullptr; + return; + } + ScrollerAndOffsetPair scroller_offset = queue_.back(); + queue_.pop_back(); + ScrollableArea* scrollable = scroller_offset.first; + current_scrollable_ = scrollable; + ScrollOffset offset = scroller_offset.second; + scrollable->SetScrollOffset(offset, kProgrammaticScroll, + kScrollBehaviorSmooth); +} + +void SmoothScrollSequencer::AbortAnimations() { + if (current_scrollable_) { + current_scrollable_->GetProgrammaticScrollAnimator().CancelAnimation(); + current_scrollable_ = nullptr; + } + queue_.clear(); +} + +DEFINE_TRACE(SmoothScrollSequencer) { + visitor->Trace(queue_); + visitor->Trace(current_scrollable_); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/platform/scroll/SmoothScrollSequencer.h b/third_party/WebKit/Source/platform/scroll/SmoothScrollSequencer.h new file mode 100644 index 0000000..3c72499 --- /dev/null +++ b/third_party/WebKit/Source/platform/scroll/SmoothScrollSequencer.h
@@ -0,0 +1,41 @@ +// Copyright (c) 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 SmoothScrollSequencer_h +#define SmoothScrollSequencer_h + +#include <utility> +#include "platform/heap/Handle.h" +#include "platform/scroll/ScrollTypes.h" + +namespace blink { + +class ScrollableArea; + +// A sequencer that queues the nested scrollers from inside to outside, +// so that they can be animated from outside to inside when smooth scroll +// is called. +class PLATFORM_EXPORT SmoothScrollSequencer final + : public GarbageCollected<SmoothScrollSequencer> { + public: + SmoothScrollSequencer(); + // Add a scroll offset animation to the back of a queue. + void QueueAnimation(ScrollableArea*, ScrollOffset); + + // Run the animation at the back of the queue. + void RunQueuedAnimations(); + + // Abort the currently running animation and all the animations in the queue. + void AbortAnimations(); + + DECLARE_TRACE(); + + private: + typedef std::pair<Member<ScrollableArea>, ScrollOffset> ScrollerAndOffsetPair; + HeapVector<ScrollerAndOffsetPair> queue_; + Member<ScrollableArea> current_scrollable_; +}; + +} // namespace blink + +#endif // SmoothScrollSequencer_h
diff --git a/third_party/WebKit/Source/platform/wtf/ThreadingPthreads.cpp b/third_party/WebKit/Source/platform/wtf/ThreadingPthreads.cpp index e813f3c..763081e 100644 --- a/third_party/WebKit/Source/platform/wtf/ThreadingPthreads.cpp +++ b/third_party/WebKit/Source/platform/wtf/ThreadingPthreads.cpp
@@ -249,11 +249,18 @@ #if DCHECK_IS_ON() static bool g_thread_created = false; +Mutex& GetThreadCreatedMutex() { + static Mutex g_thread_created_mutex; + return g_thread_created_mutex; +} + bool IsBeforeThreadCreated() { + MutexLocker locker(GetThreadCreatedMutex()); return !g_thread_created; } void WillCreateThread() { + MutexLocker locker(GetThreadCreatedMutex()); g_thread_created = true; } #endif
diff --git a/third_party/WebKit/Source/platform/wtf/ThreadingWin.cpp b/third_party/WebKit/Source/platform/wtf/ThreadingWin.cpp index 5610e95..2fd8fa3 100644 --- a/third_party/WebKit/Source/platform/wtf/ThreadingWin.cpp +++ b/third_party/WebKit/Source/platform/wtf/ThreadingWin.cpp
@@ -412,11 +412,18 @@ #if DCHECK_IS_ON() static bool g_thread_created = false; +Mutex& GetThreadCreatedMutex() { + static Mutex g_thread_created_mutex; + return g_thread_created_mutex; +} + bool IsBeforeThreadCreated() { + MutexLocker locker(GetThreadCreatedMutex()); return !g_thread_created; } void WillCreateThread() { + MutexLocker locker(GetThreadCreatedMutex()); g_thread_created = true; } #endif
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn index eb4a756..9dce615 100644 --- a/third_party/WebKit/Source/web/BUILD.gn +++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -296,6 +296,7 @@ "tests/ScrollbarsTest.cpp", "tests/ScrollingCoordinatorTest.cpp", "tests/ShadowDOMV0Test.cpp", + "tests/SmoothScrollTest.cpp", "tests/SpinLockTest.cpp", "tests/TextFinderTest.cpp", "tests/TextSelectionRepaintTest.cpp",
diff --git a/third_party/WebKit/Source/web/tests/SmoothScrollTest.cpp b/third_party/WebKit/Source/web/tests/SmoothScrollTest.cpp new file mode 100644 index 0000000..8f74a32 --- /dev/null +++ b/third_party/WebKit/Source/web/tests/SmoothScrollTest.cpp
@@ -0,0 +1,288 @@ +// 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 "bindings/core/v8/ScrollIntoViewOptionsOrBoolean.h" +#include "core/frame/ScrollIntoViewOptions.h" +#include "core/frame/ScrollToOptions.h" +#include "public/web/WebScriptSource.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "web/WebLocalFrameImpl.h" +#include "web/tests/sim/SimCompositor.h" +#include "web/tests/sim/SimDisplayItemList.h" +#include "web/tests/sim/SimRequest.h" +#include "web/tests/sim/SimTest.h" + +namespace blink { + +namespace { + +class SmoothScrollTest : public SimTest {}; + +TEST_F(SmoothScrollTest, InstantScroll) { + v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); + WebView().Resize(WebSize(800, 600)); + SimRequest request("https://example.com/test.html", "text/html"); + LoadURL("https://example.com/test.html"); + request.Complete( + "<div id='space' style='height: 1000px'></div>" + "<div id='content' style='height: 1000px'></div>"); + + Compositor().BeginFrame(); + ASSERT_EQ(Window().scrollY(), 0); + Element* content = GetDocument().getElementById("content"); + ScrollIntoViewOptionsOrBoolean arg; + ScrollIntoViewOptions options; + options.setBlock("start"); + arg.setScrollIntoViewOptions(options); + content->scrollIntoView(arg); + + ASSERT_EQ(Window().scrollY(), content->OffsetTop()); +} + +TEST_F(SmoothScrollTest, SmoothScroll) { + v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); + WebView().Resize(WebSize(800, 600)); + SimRequest request("https://example.com/test.html", "text/html"); + LoadURL("https://example.com/test.html"); + request.Complete( + "<div id='space' style='height: 1000px'></div>" + "<div id='content' style='height: 1000px'></div>"); + + Element* content = GetDocument().getElementById("content"); + ScrollIntoViewOptionsOrBoolean arg; + ScrollIntoViewOptions options; + options.setBlock("start"); + options.setBehavior("smooth"); + arg.setScrollIntoViewOptions(options); + Compositor().BeginFrame(); + ASSERT_EQ(Window().scrollY(), 0); + + content->scrollIntoView(arg); + // Scrolling the container + Compositor().BeginFrame(); // update run_state_. + Compositor().BeginFrame(); // Set start_time = now. + Compositor().BeginFrame(0.2); + ASSERT_EQ(Window().scrollY(), 299); + + // Finish scrolling the container + Compositor().BeginFrame(1); + ASSERT_EQ(Window().scrollY(), content->OffsetTop()); +} + +TEST_F(SmoothScrollTest, NestedContainer) { + v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); + WebView().Resize(WebSize(800, 600)); + SimRequest request("https://example.com/test.html", "text/html"); + LoadURL("https://example.com/test.html"); + request.Complete( + "<div id='space' style='height: 1000px'></div>" + "<div id='container' style='height: 600px; overflow: scroll'>" + " <div id='space1' style='height: 1000px'></div>" + " <div id='content' style='height: 1000px'></div>" + "</div>"); + + Element* container = GetDocument().getElementById("container"); + Element* content = GetDocument().getElementById("content"); + ScrollIntoViewOptionsOrBoolean arg; + ScrollIntoViewOptions options; + options.setBlock("start"); + options.setBehavior("smooth"); + arg.setScrollIntoViewOptions(options); + Compositor().BeginFrame(); + ASSERT_EQ(Window().scrollY(), 0); + ASSERT_EQ(container->scrollTop(), 0); + + content->scrollIntoView(arg); + // Scrolling the outer container + Compositor().BeginFrame(); // update run_state_. + Compositor().BeginFrame(); // Set start_time = now. + Compositor().BeginFrame(0.2); + ASSERT_EQ(Window().scrollY(), 299); + ASSERT_EQ(container->scrollTop(), 0); + + // Finish scrolling the outer container + Compositor().BeginFrame(1); + ASSERT_EQ(Window().scrollY(), container->OffsetTop()); + ASSERT_EQ(container->scrollTop(), 0); + + // Scrolling the inner container + Compositor().BeginFrame(); // Set start_time = now. + Compositor().BeginFrame(0.2); + ASSERT_EQ(container->scrollTop(), 299); + + // Finish scrolling the inner container + Compositor().BeginFrame(1); + ASSERT_EQ(container->scrollTop(), + content->OffsetTop() - container->OffsetTop()); +} + +TEST_F(SmoothScrollTest, NewScrollIntoViewAbortsCurrentAnimation) { + v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); + WebView().Resize(WebSize(800, 600)); + SimRequest request("https://example.com/test.html", "text/html"); + LoadURL("https://example.com/test.html"); + request.Complete( + "<div id='container2' style='height: 1000px; overflow: scroll'>" + " <div id='space2' style='height: 1200px'></div>" + " <div id='content2' style='height: 1000px'></div>" + "</div>" + "<div id='container1' style='height: 600px; overflow: scroll'>" + " <div id='space1' style='height: 1000px'></div>" + " <div id='content1' style='height: 1000px'></div>" + "</div>"); + + Element* container1 = GetDocument().getElementById("container1"); + Element* container2 = GetDocument().getElementById("container2"); + Element* content1 = GetDocument().getElementById("content1"); + Element* content2 = GetDocument().getElementById("content2"); + ScrollIntoViewOptionsOrBoolean arg; + ScrollIntoViewOptions options; + options.setBlock("start"); + options.setBehavior("smooth"); + arg.setScrollIntoViewOptions(options); + + Compositor().BeginFrame(); + ASSERT_EQ(Window().scrollY(), 0); + ASSERT_EQ(container1->scrollTop(), 0); + ASSERT_EQ(container2->scrollTop(), 0); + + content1->scrollIntoView(arg); + Compositor().BeginFrame(); // update run_state_. + Compositor().BeginFrame(); // Set start_time = now. + Compositor().BeginFrame(0.2); + ASSERT_EQ(Window().scrollY(), 299); + ASSERT_EQ(container1->scrollTop(), 0); + + content2->scrollIntoView(arg); + Compositor().BeginFrame(); // update run_state_. + Compositor().BeginFrame(); // Set start_time = now. + Compositor().BeginFrame(0.2); + ASSERT_EQ(Window().scrollY(), 61); + ASSERT_EQ(container1->scrollTop(), 0); // container1 should not scroll. + + Compositor().BeginFrame(1); + ASSERT_EQ(Window().scrollY(), container2->OffsetTop()); + ASSERT_EQ(container2->scrollTop(), 0); + + // Scrolling content2 in container2 + Compositor().BeginFrame(); // Set start_time = now. + Compositor().BeginFrame(0.2); + ASSERT_EQ(container2->scrollTop(), 300); + + // Finish all the animation to make sure there is no another animation queued + // on container1. + while (Compositor().NeedsBeginFrame()) { + Compositor().BeginFrame(); + } + ASSERT_EQ(Window().scrollY(), container2->OffsetTop()); + ASSERT_EQ(container2->scrollTop(), + content2->OffsetTop() - container2->OffsetTop()); + ASSERT_EQ(container1->scrollTop(), 0); +} + +TEST_F(SmoothScrollTest, ScrollWindowAbortsCurrentAnimation) { + v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); + WebView().Resize(WebSize(800, 600)); + SimRequest request("https://example.com/test.html", "text/html"); + LoadURL("https://example.com/test.html"); + request.Complete( + "<div id='space' style='height: 1000px'></div>" + "<div id='container' style='height: 600px; overflow: scroll'>" + " <div id='space1' style='height: 1000px'></div>" + " <div id='content' style='height: 1000px'></div>" + "</div>"); + + Element* container = GetDocument().getElementById("container"); + Element* content = GetDocument().getElementById("content"); + ScrollIntoViewOptionsOrBoolean arg; + ScrollIntoViewOptions options; + options.setBlock("start"); + options.setBehavior("smooth"); + arg.setScrollIntoViewOptions(options); + Compositor().BeginFrame(); + ASSERT_EQ(Window().scrollY(), 0); + ASSERT_EQ(container->scrollTop(), 0); + + content->scrollIntoView(arg); + // Scrolling the outer container + Compositor().BeginFrame(); // update run_state_. + Compositor().BeginFrame(); // Set start_time = now. + Compositor().BeginFrame(0.2); + ASSERT_EQ(Window().scrollY(), 299); + ASSERT_EQ(container->scrollTop(), 0); + + ScrollToOptions window_option; + window_option.setLeft(0); + window_option.setTop(0); + window_option.setBehavior("smooth"); + Window().scrollTo(window_option); + Compositor().BeginFrame(); // update run_state_. + Compositor().BeginFrame(); // Set start_time = now. + Compositor().BeginFrame(0.2); + ASSERT_EQ(Window().scrollY(), 58); + + Compositor().BeginFrame(1); + ASSERT_EQ(Window().scrollY(), 0); + ASSERT_EQ(container->scrollTop(), 0); +} + +TEST_F(SmoothScrollTest, BlockAndInlineSettings) { + v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); + WebView().Resize(WebSize(800, 600)); + SimRequest request("https://example.com/test.html", "text/html"); + LoadURL("https://example.com/test.html"); + request.Complete( + "<div id='container' style='height: 2500px; width: 2500px;'>" + "<div id='content' style='height: 500px; width: 500px;" + "margin-left: 1000px; margin-right: 1000px; margin-top: 1000px;" + "margin-bottom: 1000px'></div></div>"); + + int content_height = 500; + int content_width = 500; + int window_height = 600; + int window_width = 800; + + Element* content = GetDocument().getElementById("content"); + ScrollIntoViewOptionsOrBoolean arg1, arg2, arg3, arg4; + ScrollIntoViewOptions options; + ASSERT_EQ(Window().scrollY(), 0); + + options.setBlock("nearest"); + options.setInlinePosition("nearest"); + arg1.setScrollIntoViewOptions(options); + content->scrollIntoView(arg1); + ASSERT_EQ(Window().scrollX(), + content->OffsetLeft() + content_width - window_width); + ASSERT_EQ(Window().scrollY(), + content->OffsetTop() + content_height - window_height); + + options.setBlock("start"); + options.setInlinePosition("start"); + arg2.setScrollIntoViewOptions(options); + content->scrollIntoView(arg2); + ASSERT_EQ(Window().scrollX(), content->OffsetLeft()); + ASSERT_EQ(Window().scrollY(), content->OffsetTop()); + + options.setBlock("center"); + options.setInlinePosition("center"); + arg3.setScrollIntoViewOptions(options); + content->scrollIntoView(arg3); + ASSERT_EQ(Window().scrollX(), + content->OffsetLeft() + (content_width - window_width) / 2); + ASSERT_EQ(Window().scrollY(), + content->OffsetTop() + (content_height - window_height) / 2); + + options.setBlock("end"); + options.setInlinePosition("end"); + arg4.setScrollIntoViewOptions(options); + content->scrollIntoView(arg4); + ASSERT_EQ(Window().scrollX(), + content->OffsetLeft() + content_width - window_width); + ASSERT_EQ(Window().scrollY(), + content->OffsetTop() + content_height - window_height); +} + +} // namespace + +} // namespace blink
diff --git a/third_party/WebKit/Tools/Scripts/merge-layout-test-results b/third_party/WebKit/Tools/Scripts/merge-layout-test-results index 42778a3..e4980d73 100755 --- a/third_party/WebKit/Tools/Scripts/merge-layout-test-results +++ b/third_party/WebKit/Tools/Scripts/merge-layout-test-results
@@ -8,45 +8,39 @@ import json import logging import os +import stat import shutil import sys import tempfile import time +from webkitpy.common.system.filesystem import FileSystem from webkitpy.common.system.log_utils import configure_logging from webkitpy.layout_tests import merge_results # ------------------------------------------------------------------------ +def ensure_empty_dir(fs, directory, allow_existing, remove_existing): + """Ensure an empty directory exists. -def rmtree(dirname): - # Attempt to remove a directory tree. We try multiple times as on Windows a - # process which is currently closing could still have a file open in the - # directory. - logging.info('Removing %s', dirname) - errors = [] - def onerror(func, path, exc_info): - errors.append(path) - logging.exception('Failed at %s %s: %r', func, path, exc_info) - - attempts = 0 - while attempts < 5: - del errors[:] - shutil.rmtree(dirname, onerror=onerror) - if not errors: - break - attempts += 1 - time.sleep(1) - - # Check the path is gone. - if not os.path.exists(dirname): + Args: + allow_existing (bool): Allow the empty directory to already exist. + remove_existing (bool): Remove the contents if the directory + already exists. + """ + if not fs.exists(directory): + fs.maybe_make_directory(directory) return - logging.warning('Unable to remove %s', dirname) - for dirpath, dirnames, filenames in os.walk(dirname, onerror=onerror, topdown=False): - for fname in filenames: - logging.warning('File %s still in output dir.', os.path.join(dirpath, fname)) - for dname in dirnames: - logging.warning('Dir %s still in output dir.', os.path.join(dirpath, dname)) + logging.warning('Output directory exists %r', directory) + if not allow_existing: + raise IOError( + ('Output directory %s exists!\n' + 'Use --allow-existing-output-directory to continue') % directory) + + if remove_existing and not fs.remove_contents(directory): + raise IOError( + ('Unable to remove output directory %s contents!\n' + 'See log output for errors.') % directory) def main(argv): @@ -156,9 +150,10 @@ for result_key, build_prop_key in args.results_json_override_with_build_property: results_json_value_overrides[result_key] = build_properties[build_prop_key] - assert not args.output_directory - args.output_directory = os.getcwd() - args.remove_existing_output_directory = True + if not args.output_directory: + args.output_directory = os.getcwd() + args.allow_existing_output_directory = True + args.remove_existing_output_directory = True assert not args.input_directories args.input_directories = [os.path.dirname(f) for f in args.positional] @@ -186,14 +181,12 @@ merger = merge_results.LayoutTestDirMerger( results_json_value_overrides=results_json_value_overrides, results_json_allow_unknown_if_matching=args.results_json_allow_unknown_if_matching) - if os.path.exists(args.output_directory): - logging.warning('Output directory exists %r', args.output_directory) - if args.remove_existing_output_directory: - rmtree(args.output_directory) - elif not args.allow_existing_output_directory: - raise IOError( - ('Output directory %s exists!\n' - 'Use --allow-existing-output-directory to continue') % args.output_directory) + + ensure_empty_dir( + FileSystem(), + args.output_directory, + allow_existing=args.allow_existing_output_directory, + remove_existing=args.remove_existing_output_directory) merger.merge(args.output_directory, args.input_directories)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem.py index c06c190..f55d249 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem.py
@@ -28,19 +28,23 @@ """Wrapper object for the file system / source tree.""" -import stat import codecs import errno import exceptions import glob import hashlib +import logging import os import shutil +import stat import sys import tempfile import time +_log = logging.getLogger(__name__) + + class FileSystem(object): """FileSystem interface for webkitpy. @@ -136,8 +140,8 @@ def listdir(self, path): return os.listdir(path) - def walk(self, top): - return os.walk(top) + def walk(self, top, topdown=True, onerror=None, followlinks=False): + return os.walk(top, topdown=topdown, onerror=onerror, followlinks=followlinks) def mkdtemp(self, **kwargs): """Create and return a uniquely named directory. @@ -246,7 +250,7 @@ class _WindowsError(exceptions.OSError): """Fake exception for Linux and Mac.""" - def remove(self, path, osremove=os.remove): + def remove(self, path, osremove=os.remove, retry=True): """On Windows, if a process was recently killed and it held on to a file, the OS will hold on to the file for a short while. This makes attempts to delete the file fail. To work around that, this method @@ -266,12 +270,22 @@ except exceptions.WindowsError: time.sleep(sleep_interval) retry_timeout_sec -= sleep_interval - if retry_timeout_sec < 0: + if retry_timeout_sec < 0 and not retry: raise - def rmtree(self, path): + def rmtree(self, path, ignore_errors=True, onerror=None): """Delete the directory rooted at path, whether empty or not.""" - shutil.rmtree(path, ignore_errors=True) + shutil.rmtree(path, ignore_errors=ignore_errors, onerror=onerror) + + def remove_contents(self, dirname): + """Attempt to remove the contents of a directory tree. + Args: + dirname (string): Directory to remove the contents of. + + Returns: + bool: True if the directory is now empty. + """ + return _remove_contents(self, dirname) def copytree(self, source, destination): shutil.copytree(source, destination) @@ -286,3 +300,66 @@ def make_executable(self, file_path): os.chmod(file_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP) + + +# _remove_contents is implemented in terms of other FileSystem functions. To +# allow it to be reused on the MockFileSystem object, we define it here and +# then call it in both FileSystem and MockFileSystem classes. +def _remove_contents(fs, dirname, sleep=time.sleep): + # We try multiple times, because on Windows a process which is + # currently closing could still have a file open in the directory. + _log.info('Removing contents of %s', dirname) + errors = [] + + def onerror(func, path, exc_info): + errors.append(path) + _log.exception('Failed at %s %s: %r', func, path, exc_info) + + attempts = 0 + while attempts < 5: + del errors[:] + + for name in fs.listdir(dirname): + fullname = fs.join(dirname, name) + + isdir = True + try: + isdir = fs.isdir(fullname) + except os.error: + onerror(fs.isdir, fullname, sys.exc_info()) + continue + + if isdir: + try: + _log.debug('Removing directory %s', fullname) + fs.rmtree(fullname, ignore_errors=False, onerror=onerror) + except os.error: + onerror(fs.rmtree, fullname, sys.exc_info()) + continue + else: + try: + _log.debug('Removing file %s', fullname) + fs.remove(fullname, retry=False) + except os.error: + onerror(fs.remove, fullname, sys.exc_info()) + continue + + if not errors: + break + + _log.warning('Contents removal failed, retrying in 1 second.') + attempts += 1 + sleep(1) + + # Check the path is gone. + if not fs.listdir(dirname): + return True + + _log.warning('Unable to remove %s', dirname) + for dirpath, dirnames, filenames in fs.walk(dirname, onerror=onerror, topdown=False): + for fname in filenames: + _log.warning('File %s still in output dir.', fs.join(dirpath, fname)) + for dname in dirnames: + _log.warning('Dir %s still in output dir.', fs.join(dirpath, dname)) + + return False
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem_mock.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem_mock.py index e4d94a1..fd570c9 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem_mock.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem_mock.py
@@ -33,8 +33,12 @@ import StringIO import unittest +from webkitpy.common.system.filesystem import _remove_contents + class MockFileSystem(object): + # pylint: disable=unused-argument + sep = '/' pardir = '..' @@ -386,13 +390,13 @@ return dot_dot + rel_path - def remove(self, path): + def remove(self, path, retry=True): if self.files[path] is None: self._raise_not_found(path) self.files[path] = None self.written_files[path] = None - def rmtree(self, path_to_remove): + def rmtree(self, path_to_remove, ignore_errors=True, onerror=None): path_to_remove = self.normpath(path_to_remove) for file_path in self.files: @@ -406,6 +410,9 @@ self.dirs = {d for d in self.dirs if not should_remove(d)} + def remove_contents(self, dirname): + return _remove_contents(self, dirname, sleep=lambda *args, **kw: None) + def copytree(self, source, destination): source = self.normpath(source) destination = self.normpath(destination)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py index 9318ca031..858c47c8 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py
@@ -119,6 +119,15 @@ self.assertFalse(self.fs.exists('foodir')) self.assertFalse(self.fs.exists(self.fs.join('foodir', 'baz'))) + def test_remove_contents(self): + self.fs.chdir(self.generic_test_dir) + + self.assertTrue(self.fs.exists('foodir')) + self.assertTrue(self.fs.exists(self.fs.join('foodir', 'baz'))) + self.assertTrue(self.fs.remove_contents('foodir')) + self.assertTrue(self.fs.exists('foodir')) + self.assertFalse(self.fs.exists(self.fs.join('foodir', 'baz'))) + def test_copytree(self): self.fs.chdir(self.generic_test_dir) self.fs.copytree('foodir/', 'bardir/')