diff --git a/DEPS b/DEPS index 85f3530..1c50f2c 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': 'fbb5cc3948000ada904820c84fccb4ddd00e51b2', + 'v8_revision': 'cb99d142e27d0570b871503bbae9a5f1b19a594a', # 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. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '683b84f3b6813fe0f7a2379048138876ae0d88c1', + 'catapult_revision': '57b62a2ef4f17b18b83ea6700865eb0c2459f8fe', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/WATCHLISTS b/WATCHLISTS index 1857a51..6ed1c7e 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1217,7 +1217,7 @@ '|third_party/WebKit/Source/platform/.*Event' }, 'blink_fetch': { - 'filepath': 'third_party/WebKit/Source/core/fetch', + 'filepath': 'third_party/WebKit/Source/platform/loader/fetch' }, 'blink_heap': { 'filepath': 'third_party/WebKit/Source/platform/heap' \ @@ -1227,7 +1227,8 @@ 'filepath': 'third_party/WebKit/Source/core/html/' }, 'blink_loader': { - 'filepath': 'third_party/WebKit/Source/core/loader', + 'filepath': 'third_party/WebKit/Source/core/loader', \ + 'filepath': 'third_party/WebKit/Source/platform/loader' }, 'blink_modules': { 'filepath': 'third_party/WebKit/Source/modules'
diff --git a/base/test/scoped_mock_time_message_loop_task_runner.cc b/base/test/scoped_mock_time_message_loop_task_runner.cc index 03c9c42..5b1c03f 100644 --- a/base/test/scoped_mock_time_message_loop_task_runner.cc +++ b/base/test/scoped_mock_time_message_loop_task_runner.cc
@@ -6,6 +6,7 @@ #include <deque> +#include "base/bind.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" @@ -14,6 +15,13 @@ #include "base/time/time.h" namespace base { +namespace { + +void RunOnceClosure(OnceClosure closure) { + std::move(closure).Run(); +} + +} // namespace ScopedMockTimeMessageLoopTaskRunner::ScopedMockTimeMessageLoopTaskRunner() : task_runner_(new TestMockTimeTaskRunner), @@ -28,9 +36,12 @@ ScopedMockTimeMessageLoopTaskRunner::~ScopedMockTimeMessageLoopTaskRunner() { DCHECK(previous_task_runner_->RunsTasksOnCurrentThread()); DCHECK_EQ(task_runner_, ThreadTaskRunnerHandle::Get()); - for (const auto& pending_task : task_runner_->TakePendingTasks()) { + for (auto& pending_task : task_runner_->TakePendingTasks()) { + // TODO(tzik): Remove RunOnceClosure once TaskRunner migrates from Closure + // to OnceClosure. previous_task_runner_->PostDelayedTask( - pending_task.location, pending_task.task, + pending_task.location, + Bind(&RunOnceClosure, Passed(&pending_task.task)), pending_task.GetTimeToRun() - task_runner_->NowTicks()); } MessageLoop::current()->SetTaskRunner(std::move(previous_task_runner_));
diff --git a/base/test/scoped_mock_time_message_loop_task_runner_unittest.cc b/base/test/scoped_mock_time_message_loop_task_runner_unittest.cc index 4d782e2..daca782 100644 --- a/base/test/scoped_mock_time_message_loop_task_runner_unittest.cc +++ b/base/test/scoped_mock_time_message_loop_task_runner_unittest.cc
@@ -26,9 +26,13 @@ return MessageLoop::current()->task_runner().get(); } +void AssignTrue(bool* out) { + *out = true; +} + // Pops a task from the front of |pending_tasks| and returns it. TestPendingTask PopFront(std::deque<TestPendingTask>* pending_tasks) { - TestPendingTask task = pending_tasks->front(); + TestPendingTask task = std::move(pending_tasks->front()); pending_tasks->pop_front(); return task; } @@ -69,10 +73,13 @@ auto scoped_task_runner_ = base::MakeUnique<ScopedMockTimeMessageLoopTaskRunner>(); + bool task_10_has_run = false; + bool task_11_has_run = false; + Closure task_1 = Bind(&DoNothing); Closure task_2 = Bind(&DoNothing); - Closure task_10 = Bind(&DoNothing); - Closure task_11 = Bind(&DoNothing); + Closure task_10 = Bind(&AssignTrue, &task_10_has_run); + Closure task_11 = Bind(&AssignTrue, &task_11_has_run); constexpr TimeDelta task_1_delay = TimeDelta::FromSeconds(1); constexpr TimeDelta task_2_delay = TimeDelta::FromSeconds(2); @@ -96,11 +103,15 @@ EXPECT_EQ(2U, pending_tasks.size()); TestPendingTask pending_task = PopFront(&pending_tasks); - EXPECT_TRUE(task_10.Equals(pending_task.task)); + EXPECT_FALSE(task_10_has_run); + std::move(pending_task.task).Run(); + EXPECT_TRUE(task_10_has_run); EXPECT_EQ(task_10_delay - step_time_by, pending_task.delay); pending_task = PopFront(&pending_tasks); - EXPECT_TRUE(task_11.Equals(pending_task.task)); + EXPECT_FALSE(task_11_has_run); + std::move(pending_task.task).Run(); + EXPECT_TRUE(task_11_has_run); EXPECT_EQ(task_11_delay - step_time_by, pending_task.delay); }
diff --git a/base/test/test_mock_time_task_runner.cc b/base/test/test_mock_time_task_runner.cc index f0ba9aa..eaaceb6 100644 --- a/base/test/test_mock_time_task_runner.cc +++ b/base/test/test_mock_time_task_runner.cc
@@ -83,9 +83,15 @@ TimeDelta delay, size_t ordinal, TestNestability nestability); + TestOrderedPendingTask(TestOrderedPendingTask&&); ~TestOrderedPendingTask(); + TestOrderedPendingTask& operator=(TestOrderedPendingTask&&); + size_t ordinal; + + private: + DISALLOW_COPY_AND_ASSIGN(TestOrderedPendingTask); }; TestMockTimeTaskRunner::TestOrderedPendingTask::TestOrderedPendingTask() @@ -93,6 +99,9 @@ } TestMockTimeTaskRunner::TestOrderedPendingTask::TestOrderedPendingTask( + TestOrderedPendingTask&&) = default; + +TestMockTimeTaskRunner::TestOrderedPendingTask::TestOrderedPendingTask( const tracked_objects::Location& location, const Closure& task, TimeTicks post_time, @@ -100,12 +109,15 @@ size_t ordinal, TestNestability nestability) : base::TestPendingTask(location, task, post_time, delay, nestability), - ordinal(ordinal) { -} + ordinal(ordinal) {} TestMockTimeTaskRunner::TestOrderedPendingTask::~TestOrderedPendingTask() { } +TestMockTimeTaskRunner::TestOrderedPendingTask& +TestMockTimeTaskRunner::TestOrderedPendingTask::operator=( + TestOrderedPendingTask&&) = default; + // TestMockTimeTaskRunner ----------------------------------------------------- bool TestMockTimeTaskRunner::TemporalOrder::operator()( @@ -176,7 +188,10 @@ std::deque<TestPendingTask> TestMockTimeTaskRunner::TakePendingTasks() { std::deque<TestPendingTask> tasks; while (!tasks_.empty()) { - tasks.push_back(tasks_.top()); + // It's safe to remove const and consume |task| here, since |task| is not + // used for ordering the item. + tasks.push_back( + std::move(const_cast<TestOrderedPendingTask&>(tasks_.top()))); tasks_.pop(); } return tasks; @@ -248,7 +263,7 @@ // be less than |now_ticks_|. ForwardClocksUntilTickTime() takes care of not // moving the clock backwards in this case. ForwardClocksUntilTickTime(task_info.GetTimeToRun()); - task_info.task.Run(); + std::move(task_info.task).Run(); OnAfterTaskRun(); } } @@ -268,7 +283,9 @@ AutoLock scoped_lock(tasks_lock_); if (!tasks_.empty() && (tasks_.top().GetTimeToRun() - reference) <= max_delta) { - *next_task = tasks_.top(); + // It's safe to remove const and consume |task| here, since |task| is not + // used for ordering the item. + *next_task = std::move(const_cast<TestOrderedPendingTask&>(tasks_.top())); tasks_.pop(); return true; }
diff --git a/base/test/test_pending_task.cc b/base/test/test_pending_task.cc index 87b107e..98bc017 100644 --- a/base/test/test_pending_task.cc +++ b/base/test/test_pending_task.cc
@@ -22,7 +22,9 @@ delay(delay), nestability(nestability) {} -TestPendingTask::TestPendingTask(const TestPendingTask& other) = default; +TestPendingTask::TestPendingTask(TestPendingTask&& other) = default; + +TestPendingTask& TestPendingTask::operator=(TestPendingTask&& other) = default; TimeTicks TestPendingTask::GetTimeToRun() const { return post_time + delay;
diff --git a/base/test/test_pending_task.h b/base/test/test_pending_task.h index 2dbdb7e..42f3f42c 100644 --- a/base/test/test_pending_task.h +++ b/base/test/test_pending_task.h
@@ -21,7 +21,7 @@ enum TestNestability { NESTABLE, NON_NESTABLE }; TestPendingTask(); - TestPendingTask(const TestPendingTask& other); + TestPendingTask(TestPendingTask&& other); TestPendingTask(const tracked_objects::Location& location, const Closure& task, TimeTicks post_time, @@ -29,6 +29,8 @@ TestNestability nestability); ~TestPendingTask(); + TestPendingTask& operator=(TestPendingTask&& other); + // Returns post_time + delay. TimeTicks GetTimeToRun() const; @@ -51,7 +53,7 @@ bool ShouldRunBefore(const TestPendingTask& other) const; tracked_objects::Location location; - Closure task; + OnceClosure task; TimeTicks post_time; TimeDelta delay; TestNestability nestability; @@ -61,6 +63,9 @@ void AsValueInto(base::trace_event::TracedValue* state) const; std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue() const; std::string ToString() const; + + private: + DISALLOW_COPY_AND_ASSIGN(TestPendingTask); }; // gtest helpers which allow pretty printing of the tasks, very useful in unit
diff --git a/base/test/test_simple_task_runner.cc b/base/test/test_simple_task_runner.cc index 94d8e48..e777918 100644 --- a/base/test/test_simple_task_runner.cc +++ b/base/test/test_simple_task_runner.cc
@@ -78,8 +78,8 @@ tasks_to_run.swap(pending_tasks_); } - for (const auto& task : tasks_to_run) - task.task.Run(); + for (auto& task : tasks_to_run) + std::move(task.task).Run(); } void TestSimpleTaskRunner::RunUntilIdle() {
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index 3a5f4d8..e09090c 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -75,6 +75,8 @@ "input/scrollbar_animation_controller_thinning.cc", "input/scrollbar_animation_controller_thinning.h", "input/selection.h", + "input/single_scrollbar_animation_controller_thinning.cc", + "input/single_scrollbar_animation_controller_thinning.h", "layers/append_quads_data.h", "layers/content_layer_client.h", "layers/draw_properties.cc", @@ -756,6 +758,7 @@ "input/scroll_state_unittest.cc", "input/scrollbar_animation_controller_linear_fade_unittest.cc", "input/scrollbar_animation_controller_thinning_unittest.cc", + "input/single_scrollbar_animation_controller_thinning_unittest.cc", "ipc/cc_param_traits_unittest.cc", "ipc/struct_traits_unittest.cc", "layers/heads_up_display_layer_impl_unittest.cc",
diff --git a/cc/base/delayed_unique_notifier_unittest.cc b/cc/base/delayed_unique_notifier_unittest.cc index ae9ad17..5f5f50b 100644 --- a/cc/base/delayed_unique_notifier_unittest.cc +++ b/cc/base/delayed_unique_notifier_unittest.cc
@@ -73,7 +73,7 @@ ASSERT_EQ(1u, tasks.size()); EXPECT_EQ(base::TimeTicks() + delay, tasks[0].GetTimeToRun()); - tasks[0].task.Run(); + std::move(tasks[0].task).Run(); EXPECT_EQ(1, NotificationCount()); // 5 schedules should result in only one run. @@ -84,7 +84,7 @@ ASSERT_EQ(1u, tasks.size()); EXPECT_EQ(base::TimeTicks() + delay, tasks[0].GetTimeToRun()); - tasks[0].task.Run(); + std::move(tasks[0].task).Run(); EXPECT_EQ(2, NotificationCount()); } @@ -110,7 +110,7 @@ EXPECT_EQ(base::TimeTicks() + delay, tasks[0].GetTimeToRun()); // It's not yet time to run, so we expect no notifications. - tasks[0].task.Run(); + std::move(tasks[0].task).Run(); EXPECT_EQ(0, NotificationCount()); tasks = TakePendingTasks(); @@ -127,7 +127,7 @@ notifier.SetNow(notifier.Now() + base::TimeDelta::FromInternalValue(19)); // It's not yet time to run, so we expect no notifications. - tasks[0].task.Run(); + std::move(tasks[0].task).Run(); EXPECT_EQ(0, NotificationCount()); tasks = TakePendingTasks(); @@ -141,7 +141,7 @@ notifier.SetNow(notifier.Now() + base::TimeDelta::FromInternalValue(1)); // It's time to run! - tasks[0].task.Run(); + std::move(tasks[0].task).Run(); EXPECT_EQ(1, NotificationCount()); tasks = TakePendingTasks(); @@ -172,7 +172,7 @@ EXPECT_EQ(base::TimeTicks() + delay, tasks[0].GetTimeToRun()); // It's not yet time to run, so we expect no notifications. - tasks[0].task.Run(); + std::move(tasks[0].task).Run(); EXPECT_EQ(0, NotificationCount()); } @@ -186,7 +186,7 @@ EXPECT_EQ(base::TimeTicks() + delay, tasks[0].GetTimeToRun()); // Time to run! - tasks[0].task.Run(); + std::move(tasks[0].task).Run(); EXPECT_EQ(1, NotificationCount()); } @@ -216,7 +216,7 @@ EXPECT_EQ(base::TimeTicks() + delay, tasks[0].GetTimeToRun()); // Time to run, but a canceled task! - tasks[0].task.Run(); + std::move(tasks[0].task).Run(); EXPECT_EQ(0, NotificationCount()); EXPECT_FALSE(notifier.HasPendingNotification()); @@ -234,7 +234,7 @@ notifier.SetNow(notifier.Now() + delay); // This should run since it wasn't canceled. - tasks[0].task.Run(); + std::move(tasks[0].task).Run(); EXPECT_EQ(1, NotificationCount()); EXPECT_FALSE(notifier.HasPendingNotification()); @@ -252,7 +252,7 @@ // Time to run, but a canceled task! notifier.SetNow(notifier.Now() + delay); - tasks[0].task.Run(); + std::move(tasks[0].task).Run(); EXPECT_EQ(1, NotificationCount()); tasks = TakePendingTasks(); @@ -284,7 +284,7 @@ ASSERT_EQ(1u, tasks.size()); // Running the task after shutdown does nothing since it's cancelled. - tasks[0].task.Run(); + std::move(tasks[0].task).Run(); EXPECT_EQ(0, NotificationCount()); tasks = TakePendingTasks();
diff --git a/cc/input/scrollbar_animation_controller.cc b/cc/input/scrollbar_animation_controller.cc index a8fb1d0..56bf965 100644 --- a/cc/input/scrollbar_animation_controller.cc +++ b/cc/input/scrollbar_animation_controller.cc
@@ -23,29 +23,52 @@ scroll_layer_id_(scroll_layer_id), currently_scrolling_(false), scroll_gesture_has_scrolled_(false), - weak_factory_(this) {} + weak_factory_(this) { +} ScrollbarAnimationController::~ScrollbarAnimationController() {} +SingleScrollbarAnimationControllerThinning& +ScrollbarAnimationController::GetScrollbarAnimationController( + ScrollbarOrientation orientation) const { + DCHECK(NeedThinningAnimation()); + if (orientation == ScrollbarOrientation::VERTICAL) + return *(vertical_controller_.get()); + else + return *(horizontal_controller_.get()); +} + bool ScrollbarAnimationController::Animate(base::TimeTicks now) { - if (!is_animating_) - return false; + bool animated = false; - if (last_awaken_time_.is_null()) - last_awaken_time_ = now; + if (is_animating_) { + if (last_awaken_time_.is_null()) + last_awaken_time_ = now; - float progress = AnimationProgressAtTime(now); - RunAnimationFrame(progress); + float progress = AnimationProgressAtTime(now); + RunAnimationFrame(progress); - if (is_animating_) - client_->SetNeedsAnimateForScrollbarAnimation(); - return true; + if (is_animating_) + client_->SetNeedsAnimateForScrollbarAnimation(); + animated = true; + } + + if (NeedThinningAnimation()) { + animated |= vertical_controller_->Animate(now); + animated |= horizontal_controller_->Animate(now); + } + + return animated; } bool ScrollbarAnimationController::ScrollbarsHidden() const { return false; } +bool ScrollbarAnimationController::NeedThinningAnimation() const { + return false; +} + float ScrollbarAnimationController::AnimationProgressAtTime( base::TimeTicks now) { base::TimeDelta delta = now - last_awaken_time_; @@ -77,6 +100,75 @@ currently_scrolling_ = false; } +void ScrollbarAnimationController::DidMouseDown() { + if (!NeedThinningAnimation() || ScrollbarsHidden()) + return; + + vertical_controller_->DidMouseDown(); + horizontal_controller_->DidMouseDown(); +} + +void ScrollbarAnimationController::DidMouseUp() { + if (!NeedThinningAnimation()) + return; + + vertical_controller_->DidMouseUp(); + horizontal_controller_->DidMouseUp(); + + if (!mouse_is_near_any_scrollbar()) + PostDelayedAnimationTask(false); +} + +void ScrollbarAnimationController::DidMouseLeave() { + if (!NeedThinningAnimation()) + return; + + vertical_controller_->DidMouseLeave(); + horizontal_controller_->DidMouseLeave(); +} + +void ScrollbarAnimationController::DidMouseMoveNear( + ScrollbarOrientation orientation, + float distance) { + if (!NeedThinningAnimation()) + return; + + GetScrollbarAnimationController(orientation).DidMouseMoveNear(distance); + + if (ScrollbarsHidden() || Captured()) + return; + + if (mouse_is_near_any_scrollbar()) { + ApplyOpacityToScrollbars(1); + StopAnimation(); + } else if (!animating_fade()) { + PostDelayedAnimationTask(false); + } +} + +bool ScrollbarAnimationController::mouse_is_over_scrollbar( + ScrollbarOrientation orientation) const { + DCHECK(NeedThinningAnimation()); + return GetScrollbarAnimationController(orientation).mouse_is_over_scrollbar(); +} + +bool ScrollbarAnimationController::mouse_is_near_scrollbar( + ScrollbarOrientation orientation) const { + DCHECK(NeedThinningAnimation()); + return GetScrollbarAnimationController(orientation).mouse_is_near_scrollbar(); +} + +bool ScrollbarAnimationController::mouse_is_near_any_scrollbar() const { + DCHECK(NeedThinningAnimation()); + return vertical_controller_->mouse_is_near_scrollbar() || + horizontal_controller_->mouse_is_near_scrollbar(); +} + +bool ScrollbarAnimationController::Captured() const { + DCHECK(NeedThinningAnimation()); + return vertical_controller_->captured() || horizontal_controller_->captured(); +} + void ScrollbarAnimationController::PostDelayedAnimationTask(bool on_resize) { base::TimeDelta delay = on_resize ? resize_delay_before_starting_ : delay_before_starting_; @@ -103,4 +195,10 @@ return client_->ScrollbarsFor(scroll_layer_id_); } +void ScrollbarAnimationController::set_mouse_move_distance_for_test( + float distance) { + vertical_controller_->set_mouse_move_distance_for_test(distance); + horizontal_controller_->set_mouse_move_distance_for_test(distance); +} + } // namespace cc
diff --git a/cc/input/scrollbar_animation_controller.h b/cc/input/scrollbar_animation_controller.h index bb3f810a..25e12966 100644 --- a/cc/input/scrollbar_animation_controller.h +++ b/cc/input/scrollbar_animation_controller.h
@@ -9,14 +9,13 @@ #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "cc/base/cc_export.h" +#include "cc/input/single_scrollbar_animation_controller_thinning.h" #include "cc/layers/layer_impl.h" #include "cc/layers/scrollbar_layer_impl_base.h" #include "ui/gfx/geometry/vector2d_f.h" namespace cc { -class ScrollbarAnimationController; - class CC_EXPORT ScrollbarAnimationControllerClient { public: virtual void PostDelayedScrollbarAnimationTask(const base::Closure& task, @@ -33,6 +32,10 @@ // This abstract class represents the compositor-side analogy of // ScrollbarAnimator. Individual platforms should subclass it to provide // specialized implementation. +// This class also passes the mouse state to each +// SingleScrollbarAnimationControllerThinning. The thinning animations are +// independent between vertical/horizontal and are managed by the +// SingleScrollbarAnimationControllerThinnings. class CC_EXPORT ScrollbarAnimationController { public: virtual ~ScrollbarAnimationController(); @@ -42,11 +45,19 @@ virtual void DidScrollBegin(); virtual void DidScrollUpdate(bool on_resize); virtual void DidScrollEnd(); - virtual void DidMouseDown() {} - virtual void DidMouseUp() {} - virtual void DidMouseLeave() {} - virtual void DidMouseMoveNear(float distance) {} virtual bool ScrollbarsHidden() const; + virtual bool NeedThinningAnimation() const; + + void DidMouseDown(); + void DidMouseUp(); + void DidMouseLeave(); + void DidMouseMoveNear(ScrollbarOrientation, float); + + bool mouse_is_over_scrollbar(ScrollbarOrientation orientation) const; + bool mouse_is_near_scrollbar(ScrollbarOrientation orientation) const; + bool mouse_is_near_any_scrollbar() const; + + void set_mouse_move_distance_for_test(float distance); protected: ScrollbarAnimationController(int scroll_layer_id, @@ -56,6 +67,7 @@ virtual void RunAnimationFrame(float progress) = 0; virtual const base::TimeDelta& Duration() = 0; + virtual void ApplyOpacityToScrollbars(float opacity) = 0; void StartAnimation(); void StopAnimation(); @@ -67,11 +79,23 @@ int scroll_layer_id() const { return scroll_layer_id_; } + bool animating_fade() const { return is_animating_; } + + bool Captured() const; + + std::unique_ptr<SingleScrollbarAnimationControllerThinning> + vertical_controller_; + std::unique_ptr<SingleScrollbarAnimationControllerThinning> + horizontal_controller_; + private: // Returns how far through the animation we are as a progress value from // 0 to 1. float AnimationProgressAtTime(base::TimeTicks now); + SingleScrollbarAnimationControllerThinning& GetScrollbarAnimationController( + ScrollbarOrientation) const; + base::TimeTicks last_awaken_time_; base::TimeDelta delay_before_starting_; base::TimeDelta resize_delay_before_starting_;
diff --git a/cc/input/scrollbar_animation_controller_linear_fade.h b/cc/input/scrollbar_animation_controller_linear_fade.h index d3acc82..62dddcf7 100644 --- a/cc/input/scrollbar_animation_controller_linear_fade.h +++ b/cc/input/scrollbar_animation_controller_linear_fade.h
@@ -40,7 +40,7 @@ private: float OpacityAtTime(base::TimeTicks now) const; - void ApplyOpacityToScrollbars(float opacity); + void ApplyOpacityToScrollbars(float opacity) override; base::TimeDelta duration_;
diff --git a/cc/input/scrollbar_animation_controller_thinning.cc b/cc/input/scrollbar_animation_controller_thinning.cc index 358a9cef..548f4624 100644 --- a/cc/input/scrollbar_animation_controller_thinning.cc +++ b/cc/input/scrollbar_animation_controller_thinning.cc
@@ -10,11 +10,6 @@ #include "cc/layers/scrollbar_layer_impl_base.h" #include "cc/trees/layer_tree_impl.h" -namespace { -const float kIdleThicknessScale = 0.4f; -const float kDefaultMouseMoveDistanceToTriggerAnimation = 25.f; -} - namespace cc { std::unique_ptr<ScrollbarAnimationControllerThinning> @@ -42,102 +37,52 @@ delay_before_starting, resize_delay_before_starting), opacity_(0.0f), - captured_(false), - mouse_is_over_scrollbar_(false), - mouse_is_near_scrollbar_(false), - thickness_change_(NONE), - mouse_move_distance_to_trigger_animation_( - kDefaultMouseMoveDistanceToTriggerAnimation), - fade_duration_(fade_duration), - thinning_duration_(thinning_duration), - current_animating_property_(OPACITY) { - ApplyOpacity(0.f); - ApplyThumbThicknessScale(kIdleThicknessScale); + fade_duration_(fade_duration) { + vertical_controller_ = SingleScrollbarAnimationControllerThinning::Create( + scroll_layer_id, ScrollbarOrientation::VERTICAL, client, + thinning_duration); + horizontal_controller_ = SingleScrollbarAnimationControllerThinning::Create( + scroll_layer_id, ScrollbarOrientation::HORIZONTAL, client, + thinning_duration); + ApplyOpacityToScrollbars(0.0f); } ScrollbarAnimationControllerThinning::~ScrollbarAnimationControllerThinning() {} + + +bool ScrollbarAnimationControllerThinning::ScrollbarsHidden() const { + return opacity_ == 0.0f; +} + +bool ScrollbarAnimationControllerThinning::NeedThinningAnimation() const { + return true; +} + void ScrollbarAnimationControllerThinning::RunAnimationFrame(float progress) { - if (captured_) - return; - - if (current_animating_property_ == OPACITY) - ApplyOpacity(1.f - progress); - else - ApplyThumbThicknessScale(ThumbThicknessScaleAt(progress)); - - client_->SetNeedsRedrawForScrollbarAnimation(); - if (progress == 1.f) { + ApplyOpacityToScrollbars(1.f - progress); + if (progress == 1.f) StopAnimation(); - if (current_animating_property_ == THICKNESS) { - thickness_change_ = NONE; - SetCurrentAnimatingProperty(OPACITY); - if (!mouse_is_near_scrollbar_) - PostDelayedAnimationTask(false); - } - } } const base::TimeDelta& ScrollbarAnimationControllerThinning::Duration() { - if (current_animating_property_ == OPACITY) - return fade_duration_; - else - return thinning_duration_; -} - -void ScrollbarAnimationControllerThinning::DidMouseDown() { - if (!mouse_is_over_scrollbar_ || opacity_ == 0.0f) - return; - - StopAnimation(); - captured_ = true; - ApplyOpacity(1.f); - ApplyThumbThicknessScale(1.f); -} - -void ScrollbarAnimationControllerThinning::DidMouseUp() { - if (!captured_ || opacity_ == 0.0f) - return; - - captured_ = false; - StopAnimation(); - - if (!mouse_is_near_scrollbar_) { - SetCurrentAnimatingProperty(THICKNESS); - thickness_change_ = DECREASE; - StartAnimation(); - } else { - SetCurrentAnimatingProperty(OPACITY); - } -} - -void ScrollbarAnimationControllerThinning::DidMouseLeave() { - if (!mouse_is_over_scrollbar_ && !mouse_is_near_scrollbar_) - return; - - mouse_is_over_scrollbar_ = false; - mouse_is_near_scrollbar_ = false; - - if (captured_ || opacity_ == 0.0f) - return; - - thickness_change_ = DECREASE; - SetCurrentAnimatingProperty(THICKNESS); - StartAnimation(); + return fade_duration_; } void ScrollbarAnimationControllerThinning::DidScrollUpdate(bool on_resize) { - if (captured_) + if (Captured()) return; ScrollbarAnimationController::DidScrollUpdate(on_resize); - ApplyOpacity(1.f); - ApplyThumbThicknessScale(mouse_is_near_scrollbar_ ? 1.f - : kIdleThicknessScale); - SetCurrentAnimatingProperty(OPACITY); - // Don't fade out the scrollbar when mouse is near. - if (mouse_is_near_scrollbar_) + ApplyOpacityToScrollbars(1); + vertical_controller_->UpdateThumbThicknessScale(); + horizontal_controller_->UpdateThumbThicknessScale(); + + // we started a fade out timer in + // |ScrollbarAnimationController::DidScrollUpdate| but don't want to + // fade out if the mouse is nearby. + if (mouse_is_near_any_scrollbar()) StopAnimation(); } @@ -145,70 +90,12 @@ ScrollbarAnimationController::DidScrollEnd(); // Don't fade out the scrollbar when mouse is near. - if (mouse_is_near_scrollbar_) + if (mouse_is_near_any_scrollbar()) StopAnimation(); } -void ScrollbarAnimationControllerThinning::DidMouseMoveNear(float distance) { - bool mouse_is_over_scrollbar = distance == 0.0f; - bool mouse_is_near_scrollbar = - distance < mouse_move_distance_to_trigger_animation_; - - if (captured_ || opacity_ == 0.0f) { - mouse_is_near_scrollbar_ = mouse_is_near_scrollbar; - mouse_is_over_scrollbar_ = mouse_is_over_scrollbar; - return; - } - - if (mouse_is_over_scrollbar == mouse_is_over_scrollbar_ && - mouse_is_near_scrollbar == mouse_is_near_scrollbar_) - return; - - if (mouse_is_over_scrollbar_ != mouse_is_over_scrollbar) - mouse_is_over_scrollbar_ = mouse_is_over_scrollbar; - - if (mouse_is_near_scrollbar_ != mouse_is_near_scrollbar) { - mouse_is_near_scrollbar_ = mouse_is_near_scrollbar; - thickness_change_ = mouse_is_near_scrollbar_ ? INCREASE : DECREASE; - } - - SetCurrentAnimatingProperty(THICKNESS); - StartAnimation(); -} - -bool ScrollbarAnimationControllerThinning::ScrollbarsHidden() const { - return opacity_ == 0.0f; -} - -float ScrollbarAnimationControllerThinning::ThumbThicknessScaleAt( - float progress) { - if (thickness_change_ == NONE) - return mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale; - float factor = thickness_change_ == INCREASE ? progress : (1.f - progress); - return ((1.f - kIdleThicknessScale) * factor) + kIdleThicknessScale; -} - -float ScrollbarAnimationControllerThinning::AdjustScale( - float new_value, - float current_value, - AnimationChange animation_change, - float min_value, - float max_value) { - float result; - if (animation_change == INCREASE && current_value > new_value) - result = current_value; - else if (animation_change == DECREASE && current_value < new_value) - result = current_value; - else - result = new_value; - if (result > max_value) - return max_value; - if (result < min_value) - return min_value; - return result; -} - -void ScrollbarAnimationControllerThinning::ApplyOpacity(float opacity) { +void ScrollbarAnimationControllerThinning::ApplyOpacityToScrollbars( + float opacity) { for (ScrollbarLayerImplBase* scrollbar : Scrollbars()) { if (!scrollbar->is_overlay_scrollbar()) continue; @@ -238,27 +125,4 @@ client_->DidChangeScrollbarVisibility(); } -void ScrollbarAnimationControllerThinning::ApplyThumbThicknessScale( - float thumb_thickness_scale) { - for (ScrollbarLayerImplBase* scrollbar : Scrollbars()) { - if (!scrollbar->is_overlay_scrollbar()) - continue; - - scrollbar->SetThumbThicknessScaleFactor(AdjustScale( - thumb_thickness_scale, scrollbar->thumb_thickness_scale_factor(), - thickness_change_, kIdleThicknessScale, 1)); - } -} - -void ScrollbarAnimationControllerThinning::SetCurrentAnimatingProperty( - AnimatingProperty property) { - if (current_animating_property_ == property) - return; - - StopAnimation(); - current_animating_property_ = property; - if (current_animating_property_ == THICKNESS) - ApplyOpacity(1.f); -} - } // namespace cc
diff --git a/cc/input/scrollbar_animation_controller_thinning.h b/cc/input/scrollbar_animation_controller_thinning.h index 236e595..1c53a97 100644 --- a/cc/input/scrollbar_animation_controller_thinning.h +++ b/cc/input/scrollbar_animation_controller_thinning.h
@@ -10,11 +10,17 @@ #include "base/macros.h" #include "cc/base/cc_export.h" #include "cc/input/scrollbar_animation_controller.h" +#include "cc/input/single_scrollbar_animation_controller_thinning.h" namespace cc { -// Scrollbar animation that partially fades and thins after an idle delay, -// and reacts to mouse movements. +// This class fade in scrollbars when scroll and fade out after an idle delay. +// The fade animations works on both scrollbars and is controlled in this class. + +// TODO(chaopeng) clean up the inheritance hierarchy after +// ScrollbarAnimationControllerLinearFade merge into +// ScrollbarAnimationControllerThinning so we can remove the empty overrides and +// NOTREACHED() checks. class CC_EXPORT ScrollbarAnimationControllerThinning : public ScrollbarAnimationController { public: @@ -28,22 +34,14 @@ ~ScrollbarAnimationControllerThinning() override; - void set_mouse_move_distance_for_test(float distance) { - mouse_move_distance_to_trigger_animation_ = distance; - } - bool mouse_is_over_scrollbar() const { return mouse_is_over_scrollbar_; } - bool mouse_is_near_scrollbar() const { return mouse_is_near_scrollbar_; } - void DidScrollUpdate(bool on_resize) override; void DidScrollEnd() override; - - void DidMouseDown() override; - void DidMouseUp() override; - void DidMouseLeave() override; - void DidMouseMoveNear(float distance) override; bool ScrollbarsHidden() const override; protected: + bool NeedThinningAnimation() const override; + + private: ScrollbarAnimationControllerThinning( int scroll_layer_id, ScrollbarAnimationControllerClient* client, @@ -52,38 +50,12 @@ base::TimeDelta fade_duration, base::TimeDelta thinning_duration); + void ApplyOpacityToScrollbars(float opacity) override; void RunAnimationFrame(float progress) override; const base::TimeDelta& Duration() override; - private: - // Describes whether the current animation should INCREASE (thicken) - // a bar or DECREASE it (thin). - enum AnimationChange { NONE, INCREASE, DECREASE }; - enum AnimatingProperty { OPACITY, THICKNESS }; - float ThumbThicknessScaleAt(float progress); - float AdjustScale(float new_value, - float current_value, - AnimationChange animation_change, - float min_value, - float max_value); - void ApplyOpacity(float opacity); - void ApplyThumbThicknessScale(float thumb_thickness_scale); - - void SetCurrentAnimatingProperty(AnimatingProperty property); - float opacity_; - bool captured_; - bool mouse_is_over_scrollbar_; - bool mouse_is_near_scrollbar_; - // Are we narrowing or thickening the bars. - AnimationChange thickness_change_; - // How close should the mouse be to the scrollbar before we thicken it. - float mouse_move_distance_to_trigger_animation_; - base::TimeDelta fade_duration_; - base::TimeDelta thinning_duration_; - - AnimatingProperty current_animating_property_; DISALLOW_COPY_AND_ASSIGN(ScrollbarAnimationControllerThinning); };
diff --git a/cc/input/scrollbar_animation_controller_thinning_unittest.cc b/cc/input/scrollbar_animation_controller_thinning_unittest.cc index 9d2fee7..384dbf24 100644 --- a/cc/input/scrollbar_animation_controller_thinning_unittest.cc +++ b/cc/input/scrollbar_animation_controller_thinning_unittest.cc
@@ -60,6 +60,11 @@ : host_impl_(&task_runner_provider_, &task_graph_runner_), client_(&host_impl_) {} + void ExpectScrollbarsOpacity(float opacity) { + EXPECT_FLOAT_EQ(opacity, v_scrollbar_layer_->Opacity()); + EXPECT_FLOAT_EQ(opacity, h_scrollbar_layer_->Opacity()); + } + protected: const base::TimeDelta kDelayBeforeStarting = base::TimeDelta::FromSeconds(2); const base::TimeDelta kResizeDelayBeforeStarting = @@ -71,29 +76,36 @@ std::unique_ptr<LayerImpl> scroll_layer = LayerImpl::Create(host_impl_.active_tree(), 1); std::unique_ptr<LayerImpl> clip = - LayerImpl::Create(host_impl_.active_tree(), 3); + LayerImpl::Create(host_impl_.active_tree(), 2); clip_layer_ = clip.get(); scroll_layer->SetScrollClipLayer(clip_layer_->id()); LayerImpl* scroll_layer_ptr = scroll_layer.get(); - const int kId = 2; const int kThumbThickness = 10; const int kTrackStart = 0; const bool kIsLeftSideVerticalScrollbar = false; const bool kIsOverlayScrollbar = true; - std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar = + std::unique_ptr<SolidColorScrollbarLayerImpl> h_scrollbar = SolidColorScrollbarLayerImpl::Create( - host_impl_.active_tree(), kId, HORIZONTAL, kThumbThickness, + host_impl_.active_tree(), 3, HORIZONTAL, kThumbThickness, kTrackStart, kIsLeftSideVerticalScrollbar, kIsOverlayScrollbar); - scrollbar_layer_ = scrollbar.get(); + std::unique_ptr<SolidColorScrollbarLayerImpl> v_scrollbar = + SolidColorScrollbarLayerImpl::Create( + host_impl_.active_tree(), 4, VERTICAL, kThumbThickness, kTrackStart, + kIsLeftSideVerticalScrollbar, kIsOverlayScrollbar); + v_scrollbar_layer_ = v_scrollbar.get(); + h_scrollbar_layer_ = h_scrollbar.get(); - scroll_layer->test_properties()->AddChild(std::move(scrollbar)); + scroll_layer->test_properties()->AddChild(std::move(v_scrollbar)); + scroll_layer->test_properties()->AddChild(std::move(h_scrollbar)); clip_layer_->test_properties()->AddChild(std::move(scroll_layer)); host_impl_.active_tree()->SetRootLayerForTesting(std::move(clip)); - scrollbar_layer_->SetScrollLayerId(scroll_layer_ptr->id()); - scrollbar_layer_->test_properties()->opacity_can_animate = true; + v_scrollbar_layer_->SetScrollLayerId(scroll_layer_ptr->id()); + h_scrollbar_layer_->SetScrollLayerId(scroll_layer_ptr->id()); + v_scrollbar_layer_->test_properties()->opacity_can_animate = true; + h_scrollbar_layer_->test_properties()->opacity_can_animate = true; clip_layer_->SetBounds(gfx::Size(100, 100)); scroll_layer_ptr->SetBounds(gfx::Size(200, 200)); host_impl_.active_tree()->BuildLayerListAndPropertyTreesForTesting(); @@ -108,42 +120,51 @@ FakeLayerTreeHostImpl host_impl_; std::unique_ptr<ScrollbarAnimationControllerThinning> scrollbar_controller_; LayerImpl* clip_layer_; - SolidColorScrollbarLayerImpl* scrollbar_layer_; + SolidColorScrollbarLayerImpl* v_scrollbar_layer_; + SolidColorScrollbarLayerImpl* h_scrollbar_layer_; NiceMock<MockScrollbarAnimationControllerClient> client_; }; // Check initialization of scrollbar. Should start off invisible and thin. TEST_F(ScrollbarAnimationControllerThinningTest, Idle) { - EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor()); + ExpectScrollbarsOpacity(0); + EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + v_scrollbar_layer_->thumb_thickness_scale_factor()); } // Check that scrollbar appears again when the layer becomes scrollable. TEST_F(ScrollbarAnimationControllerThinningTest, AppearOnResize) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + scrollbar_controller_->DidScrollBegin(); scrollbar_controller_->DidScrollUpdate(false); scrollbar_controller_->DidScrollEnd(); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(1); // Make the Layer non-scrollable, scrollbar disappears. clip_layer_->SetBounds(gfx::Size(200, 200)); scrollbar_controller_->DidScrollUpdate(false); - EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(0); // Make the layer scrollable, scrollbar appears again. clip_layer_->SetBounds(gfx::Size(100, 100)); scrollbar_controller_->DidScrollUpdate(false); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(1); } // Check that scrollbar disappears when the layer becomes non-scrollable. TEST_F(ScrollbarAnimationControllerThinningTest, HideOnResize) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + LayerImpl* scroll_layer = host_impl_.active_tree()->LayerById(1); ASSERT_TRUE(scroll_layer); EXPECT_EQ(gfx::Size(200, 200), scroll_layer->bounds()); - EXPECT_EQ(HORIZONTAL, scrollbar_layer_->orientation()); - // Shrink along X axis, horizontal scrollbar should appear. clip_layer_->SetBounds(gfx::Size(100, 200)); EXPECT_EQ(gfx::Size(100, 200), clip_layer_->bounds()); @@ -151,7 +172,7 @@ scrollbar_controller_->DidScrollBegin(); scrollbar_controller_->DidScrollUpdate(false); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); + EXPECT_FLOAT_EQ(1, h_scrollbar_layer_->Opacity()); scrollbar_controller_->DidScrollEnd(); @@ -163,7 +184,7 @@ scrollbar_controller_->DidScrollBegin(); scrollbar_controller_->DidScrollUpdate(false); - EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); + EXPECT_FLOAT_EQ(0.0f, h_scrollbar_layer_->Opacity()); scrollbar_controller_->DidScrollEnd(); } @@ -173,18 +194,22 @@ base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); - // Scrollbar should be invisible by default. - EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); + // Scrollbar should be invisible. + ExpectScrollbarsOpacity(0); + EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden()); // Scrollbar should appear only on scroll update. scrollbar_controller_->DidScrollBegin(); - EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(0); + EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden()); scrollbar_controller_->DidScrollUpdate(false); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(1); + EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); scrollbar_controller_->DidScrollEnd(); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(1); + EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); // An animation should have been enqueued. EXPECT_EQ(kDelayBeforeStarting, client_.delay()); @@ -196,7 +221,8 @@ time += kFadeDuration; scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(0); + EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden()); } // Scroll content. Move the mouse near the scrollbar and confirm it becomes @@ -216,18 +242,22 @@ // Now move the mouse near the scrollbar. This should cancel the currently // queued fading animation and start animating thickness. - scrollbar_controller_->DidMouseMoveNear(1); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); + scrollbar_controller_->DidMouseMoveNear(VERTICAL, 1); + ExpectScrollbarsOpacity(1); EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); EXPECT_TRUE(client_.start_fade().IsCancelled()); - // Scrollbar should become thick. + // Vertical scrollbar should become thick. scrollbar_controller_->Animate(time); time += kThinningDuration; scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); // Mouse is still near the Scrollbar. Once the thickness animation is // complete, the queued delayed fade animation should be either cancelled or @@ -253,22 +283,26 @@ // Now move the mouse over the scrollbar. This should cancel the currently // queued fading animation and start animating thickness. - scrollbar_controller_->DidMouseMoveNear(0); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); + scrollbar_controller_->DidMouseMoveNear(VERTICAL, 0); + ExpectScrollbarsOpacity(1); EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); EXPECT_TRUE(client_.start_fade().IsCancelled()); - // Scrollbar should become thick. + // Vertical scrollbar should become thick. scrollbar_controller_->Animate(time); time += kThinningDuration; scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); // Mouse is still over the Scrollbar. Once the thickness animation is - // complete, the queued delayed fade animation should be either null or - // cancelled. + // complete, the queued delayed fade animation should be either cancelled or + // null. EXPECT_TRUE(client_.start_fade().is_null() || client_.start_fade().IsCancelled()); } @@ -290,16 +324,54 @@ // Now move the mouse over the scrollbar and capture it. It should become // thick without need for an animation. - scrollbar_controller_->DidMouseMoveNear(0); + scrollbar_controller_->DidMouseMoveNear(VERTICAL, 0); scrollbar_controller_->DidMouseDown(); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); // The fade animation should have been cleared or cancelled. EXPECT_TRUE(client_.start_fade().is_null() || client_.start_fade().IsCancelled()); } +// Make sure a scrollbar captured then move mouse away doesn't try to fade out. +TEST_F(ScrollbarAnimationControllerThinningTest, + DontFadeWhileCapturedThenAway) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + + scrollbar_controller_->DidScrollBegin(); + scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollEnd(); + + // An animation should have been enqueued. + EXPECT_EQ(kDelayBeforeStarting, client_.delay()); + EXPECT_FALSE(client_.start_fade().is_null()); + + // Now move the mouse over the scrollbar and capture it. It should become + // thick without need for an animation. + scrollbar_controller_->DidMouseMoveNear(VERTICAL, 0); + scrollbar_controller_->DidMouseDown(); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); + + // The fade animation should have been cleared or cancelled. + EXPECT_TRUE(client_.start_fade().is_null() || + client_.start_fade().IsCancelled()); + + // Then move mouse away, The fade animation should have been cleared or + // cancelled. + scrollbar_controller_->DidMouseMoveNear( + VERTICAL, kDefaultMouseMoveDistanceToTriggerAnimation); + + EXPECT_TRUE(client_.start_fade().is_null() || + client_.start_fade().IsCancelled()); +} + // Make sure a scrollbar captured after a thickening animation doesn't try to // fade out. TEST_F(ScrollbarAnimationControllerThinningTest, DontFadeWhileCaptured) { @@ -316,12 +388,14 @@ EXPECT_FALSE(client_.start_fade().IsCancelled()); // Now move the mouse over the scrollbar and animate it until it's thick. - scrollbar_controller_->DidMouseMoveNear(0); + scrollbar_controller_->DidMouseMoveNear(VERTICAL, 0); scrollbar_controller_->Animate(time); time += kThinningDuration; scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); // Since the mouse is over the scrollbar, it should either clear or cancel the // queued fade. @@ -351,10 +425,12 @@ EXPECT_FALSE(client_.start_fade().IsCancelled()); // Now move the mouse over the scrollbar and capture it. - scrollbar_controller_->DidMouseMoveNear(0); + scrollbar_controller_->DidMouseMoveNear(VERTICAL, 0); scrollbar_controller_->DidMouseDown(); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); // Since the mouse is still near the scrollbar, the queued fade should be // either null or cancelled. @@ -363,17 +439,21 @@ // Now move the mouse away from the scrollbar and release it. scrollbar_controller_->DidMouseMoveNear( - kDefaultMouseMoveDistanceToTriggerAnimation + 1); + VERTICAL, kDefaultMouseMoveDistanceToTriggerAnimation); scrollbar_controller_->DidMouseUp(); scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); time += kThinningDuration; scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(1); EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); // The thickness animation is complete, a fade out must be queued. EXPECT_FALSE(client_.start_fade().is_null()); @@ -396,10 +476,12 @@ EXPECT_FALSE(client_.start_fade().IsCancelled()); // Now move the mouse over the scrollbar and capture it. - scrollbar_controller_->DidMouseMoveNear(0); + scrollbar_controller_->DidMouseMoveNear(VERTICAL, 0); scrollbar_controller_->DidMouseDown(); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); // Since the mouse is over the scrollbar, the queued fade must be either // null or cancelled. @@ -410,8 +492,10 @@ scrollbar_controller_->DidMouseUp(); EXPECT_TRUE(client_.start_fade().is_null() || client_.start_fade().IsCancelled()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); } // Make sure moving near a scrollbar while it's fading out causes it to reset @@ -430,25 +514,29 @@ client_.start_fade().Run(); scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(1); // Proceed half way through the fade out animation. time += kFadeDuration / 2; scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(0.5f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(.5f); // Now move the mouse near the scrollbar. It should reset opacity to 1 // instantly and start animating to thick. - scrollbar_controller_->DidMouseMoveNear(1); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); + scrollbar_controller_->DidMouseMoveNear(VERTICAL, 1); + ExpectScrollbarsOpacity(1); EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); scrollbar_controller_->Animate(time); time += kThinningDuration; scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); } // Make sure we can't capture scrollbar that's completely faded out. @@ -465,38 +553,41 @@ EXPECT_FALSE(client_.start_fade().IsCancelled()); client_.start_fade().Run(); scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(1); // Fade the scrollbar out completely. time += kFadeDuration; scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(0); // Move mouse over the scrollbar. It shouldn't thicken the scrollbar since // it's completely faded out. - scrollbar_controller_->DidMouseMoveNear(0); + scrollbar_controller_->DidMouseMoveNear(VERTICAL, 0); scrollbar_controller_->Animate(time); time += kThinningDuration; scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(0); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); + h_scrollbar_layer_->thumb_thickness_scale_factor()); client_.start_fade().Reset(); // Now try to capture the scrollbar. It shouldn't do anything since it's // completely faded out. scrollbar_controller_->DidMouseDown(); - EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(0); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); + h_scrollbar_layer_->thumb_thickness_scale_factor()); EXPECT_TRUE(client_.start_fade().is_null()); // Similarly, releasing the scrollbar should have no effect. scrollbar_controller_->DidMouseUp(); - EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(0); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); + h_scrollbar_layer_->thumb_thickness_scale_factor()); EXPECT_TRUE(client_.start_fade().is_null()); } @@ -506,21 +597,22 @@ base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->DidMouseMoveNear(1); + scrollbar_controller_->DidMouseMoveNear(VERTICAL, 1); scrollbar_controller_->Animate(time); time += kThinningDuration; // Since the scrollbar isn't visible yet (because we haven't scrolled), we // shouldn't have applied the thickening. scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); + h_scrollbar_layer_->thumb_thickness_scale_factor()); scrollbar_controller_->DidScrollBegin(); scrollbar_controller_->DidScrollUpdate(false); // Now that we've received a scroll, we should be thick without an animation. - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + ExpectScrollbarsOpacity(1); // An animation for the fade should be either null or cancelled, since // mouse is still near the scrollbar. @@ -530,364 +622,18 @@ client_.start_fade().IsCancelled()); scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); // Scrollbar should still be thick and visible. time += kFadeDuration; scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); -} - -// Move the pointer near the scrollbar. Confirm it gets thick and narrow when -// moved away. -TEST_F(ScrollbarAnimationControllerThinningTest, MouseNear) { - base::TimeTicks time; - time += base::TimeDelta::FromSeconds(1); - - // Scroll to make the scrollbars visible. - scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); - scrollbar_controller_->DidScrollEnd(); - - scrollbar_controller_->DidMouseMoveNear(1); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); - - // Should animate to thickened. - time += kThinningDuration; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Subsequent moves within the nearness threshold should not change anything. - scrollbar_controller_->DidMouseMoveNear(2); - scrollbar_controller_->Animate(time); - time += base::TimeDelta::FromSeconds(10); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Now move away from bar. - scrollbar_controller_->DidMouseMoveNear( - kDefaultMouseMoveDistanceToTriggerAnimation); - scrollbar_controller_->Animate(time); - time += kThinningDuration; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); -} - -// Move the pointer over the scrollbar. Make sure it gets thick that it gets -// thin when moved away. -TEST_F(ScrollbarAnimationControllerThinningTest, MouseOver) { - // Scroll to make the scrollbars visible. - scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); - scrollbar_controller_->DidScrollEnd(); - - base::TimeTicks time; - time += base::TimeDelta::FromSeconds(1); - - scrollbar_controller_->DidMouseMoveNear(0); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); - - // Should animate to thickened. - time += kThinningDuration; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Subsequent moves should not change anything. - scrollbar_controller_->DidMouseMoveNear(0); - scrollbar_controller_->Animate(time); - time += base::TimeDelta::FromSeconds(10); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Moving off the scrollbar but still withing the "near" threshold should do - // nothing. - scrollbar_controller_->DidMouseMoveNear( - kDefaultMouseMoveDistanceToTriggerAnimation - 1.f); - scrollbar_controller_->Animate(time); - time += base::TimeDelta::FromSeconds(10); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Now move away from bar. - scrollbar_controller_->DidMouseMoveNear( - kDefaultMouseMoveDistanceToTriggerAnimation); - scrollbar_controller_->Animate(time); - time += kThinningDuration; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); -} - -// First move the pointer over the scrollbar off of it. Make sure the thinning -// animation kicked off in DidMouseMoveOffScrollbar gets overridden by the -// thickening animation in the DidMouseMoveNear call. -TEST_F(ScrollbarAnimationControllerThinningTest, - MouseNearThenAwayWhileAnimating) { - // Scroll to make the scrollbars visible. - scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); - scrollbar_controller_->DidScrollEnd(); - - base::TimeTicks time; - time += base::TimeDelta::FromSeconds(1); - - scrollbar_controller_->DidMouseMoveNear(0); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); - - // Should animate to thickened. - time += kThinningDuration; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // This is tricky. The DidMouseLeave() is sent before the - // subsequent DidMouseMoveNear(), if the mouse moves in that direction. - // This results in the thumb thinning. We want to make sure that when the - // thumb starts expanding it doesn't first narrow to the idle thinness. - time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->DidMouseLeave(); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Let the animation run half of the way through the thinning animation. - time += kThinningDuration / 2; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, - scrollbar_layer_->thumb_thickness_scale_factor()); - - // Now we get a notification for the mouse moving over the scroller. The - // animation is reset to the thickening direction but we won't start - // thickening until the new animation catches up to the current thickness. - scrollbar_controller_->DidMouseMoveNear(1); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, - scrollbar_layer_->thumb_thickness_scale_factor()); - - // Until we reach the half way point, the animation will have no effect. - time += kThinningDuration / 4; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, - scrollbar_layer_->thumb_thickness_scale_factor()); - - time += kThinningDuration / 4; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, - scrollbar_layer_->thumb_thickness_scale_factor()); - - // We're now at three quarters of the way through so it should now started - // thickening again. - time += kThinningDuration / 4; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(kIdleThicknessScale + 3 * (1.0f - kIdleThicknessScale) / 4.0f, - scrollbar_layer_->thumb_thickness_scale_factor()); - - // And all the way to the end. - time += kThinningDuration / 4; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); -} - -// First move the pointer on the scrollbar, then press it, then away. -// Confirm that the bar gets thick. Then mouse up. Confirm that -// the bar gets thin. -TEST_F(ScrollbarAnimationControllerThinningTest, - MouseCaptureAndReleaseOutOfBar) { - // Scroll to make the scrollbars visible. - scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); - scrollbar_controller_->DidScrollEnd(); - - base::TimeTicks time; - time += base::TimeDelta::FromSeconds(1); - - // Move over the scrollbar. - scrollbar_controller_->DidMouseMoveNear(0); - scrollbar_controller_->Animate(time); - time += kFadeDuration; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Capture - scrollbar_controller_->DidMouseDown(); - time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Should stay thick for a while. - time += base::TimeDelta::FromSeconds(10); - scrollbar_controller_->Animate(time); - - // Move outside the "near" threshold. Because the scrollbar is captured it - // should remain thick. - scrollbar_controller_->DidMouseMoveNear( - kDefaultMouseMoveDistanceToTriggerAnimation); - time += kThinningDuration; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Release. - scrollbar_controller_->DidMouseUp(); - - // Should become thin. - time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->Animate(time); - time += kThinningDuration; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); -} - -// First move the pointer on the scrollbar, then press it, then away. Confirm -// that the bar gets thick. Then move point on the scrollbar and mouse up. -// Confirm that the bar stays thick. -TEST_F(ScrollbarAnimationControllerThinningTest, MouseCaptureAndReleaseOnBar) { - // Scroll to make the scrollbars visible. - scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); - scrollbar_controller_->DidScrollEnd(); - - base::TimeTicks time; - time += base::TimeDelta::FromSeconds(1); - - // Move over scrollbar. - scrollbar_controller_->DidMouseMoveNear(0); - scrollbar_controller_->Animate(time); - time += kThinningDuration; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Capture. Nothing should change. - scrollbar_controller_->DidMouseDown(); - time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->Animate(time); - time += base::TimeDelta::FromSeconds(10); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Move away from scrollbar. Nothing should change. - scrollbar_controller_->DidMouseMoveNear( - kDefaultMouseMoveDistanceToTriggerAnimation); - time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->Animate(time); - time += base::TimeDelta::FromSeconds(10); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Move over scrollbar and release. Since we're near the scrollbar, it should - // remain thick. - scrollbar_controller_->DidMouseMoveNear(0); - scrollbar_controller_->DidMouseUp(); - time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->Animate(time); - time += base::TimeDelta::FromSeconds(10); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); -} - -// Move mouse on scrollbar and capture then move out of window. Confirm that -// the bar stays thick. -TEST_F(ScrollbarAnimationControllerThinningTest, - MouseCapturedAndExitWindowFromScrollbar) { - // Scroll to make the scrollbars visible. - scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); - scrollbar_controller_->DidScrollEnd(); - - base::TimeTicks time; - time += base::TimeDelta::FromSeconds(1); - - // Move mouse over scrollbar. - scrollbar_controller_->DidMouseMoveNear(0); - scrollbar_controller_->Animate(time); - time += kThinningDuration; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Capture. - scrollbar_controller_->DidMouseDown(); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Move out of window. Since the scrollbar is capture, it shouldn't change in - // any way. - scrollbar_controller_->DidMouseLeave(); - scrollbar_controller_->Animate(time); - time += kThinningDuration; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); -} - -// Tests that the thickening/thinning effects are animated. -TEST_F(ScrollbarAnimationControllerThinningTest, ThicknessAnimated) { - // Scroll to make the scrollbars visible. - scrollbar_controller_->DidScrollBegin(); - scrollbar_controller_->DidScrollUpdate(false); - scrollbar_controller_->DidScrollEnd(); - - base::TimeTicks time; - time += base::TimeDelta::FromSeconds(1); - - // Move mouse near scrollbar. Test that at half the duration time, the - // thickness is half way through its animation. - scrollbar_controller_->DidMouseMoveNear(1); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); - - time += kThinningDuration / 2; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(kIdleThicknessScale + (1.0f - kIdleThicknessScale) / 2.0f, - scrollbar_layer_->thumb_thickness_scale_factor()); - - time += kThinningDuration / 2; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - // Move mouse away from scrollbar. Same check. - time += base::TimeDelta::FromSeconds(1); - scrollbar_controller_->DidMouseMoveNear( - kDefaultMouseMoveDistanceToTriggerAnimation); - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); - - time += kThinningDuration / 2; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, - scrollbar_layer_->thumb_thickness_scale_factor()); - - time += kThinningDuration / 2; - scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(kIdleThicknessScale, - scrollbar_layer_->thumb_thickness_scale_factor()); + h_scrollbar_layer_->thumb_thickness_scale_factor()); } // Tests that main thread scroll updates immediatley queue a fade animation @@ -937,33 +683,33 @@ // Tests that the fade effect is animated. TEST_F(ScrollbarAnimationControllerThinningTest, FadeAnimated) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + // Scroll to make the scrollbars visible. scrollbar_controller_->DidScrollBegin(); scrollbar_controller_->DidScrollUpdate(false); scrollbar_controller_->DidScrollEnd(); // Appearance is instant. - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(1); // An animation should have been enqueued. EXPECT_EQ(kDelayBeforeStarting, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); client_.start_fade().Run(); - base::TimeTicks time; - time += base::TimeDelta::FromSeconds(1); - // Test that at half the fade duration time, the opacity is at half. scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(1); time += kFadeDuration / 2; scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(0.5f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(.5f); time += kFadeDuration / 2; scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(0); } // Tests that the controller tells the client when the scrollbars hide/show. @@ -996,14 +742,14 @@ time += kFadeDuration / 4; EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); scrollbar_controller_->Animate(time); - EXPECT_FLOAT_EQ(0.25f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(.25f); Mock::VerifyAndClearExpectations(&client_); EXPECT_CALL(client_, DidChangeScrollbarVisibility()).Times(1); time += kFadeDuration / 4; scrollbar_controller_->Animate(time); EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden()); - EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); + ExpectScrollbarsOpacity(0); Mock::VerifyAndClearExpectations(&client_); // Calling DidScrollUpdate without a begin (i.e. update from commit) should @@ -1014,5 +760,191 @@ Mock::VerifyAndClearExpectations(&client_); } +// Move the pointer near each scrollbar. Confirm it gets thick and narrow when +// moved away. +TEST_F(ScrollbarAnimationControllerThinningTest, MouseNearEach) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + + // Scroll to make the scrollbars visible. + scrollbar_controller_->DidScrollBegin(); + scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollEnd(); + + // Near vertical scrollbar + scrollbar_controller_->DidMouseMoveNear(VERTICAL, 1); + scrollbar_controller_->Animate(time); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); + + // Should animate to thickened. + time += kThinningDuration; + scrollbar_controller_->Animate(time); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); + + // Subsequent moves within the nearness threshold should not change anything. + scrollbar_controller_->DidMouseMoveNear(VERTICAL, 2); + scrollbar_controller_->Animate(time); + time += base::TimeDelta::FromSeconds(10); + scrollbar_controller_->Animate(time); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); + + // Now move away from bar. + scrollbar_controller_->DidMouseMoveNear( + VERTICAL, kDefaultMouseMoveDistanceToTriggerAnimation); + scrollbar_controller_->Animate(time); + time += kThinningDuration; + scrollbar_controller_->Animate(time); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); + + // Near horizontal scrollbar + scrollbar_controller_->DidMouseMoveNear(HORIZONTAL, 2); + scrollbar_controller_->Animate(time); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); + + // Should animate to thickened. + time += kThinningDuration; + scrollbar_controller_->Animate(time); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(1, h_scrollbar_layer_->thumb_thickness_scale_factor()); + + // Subsequent moves within the nearness threshold should not change anything. + scrollbar_controller_->DidMouseMoveNear(HORIZONTAL, 1); + scrollbar_controller_->Animate(time); + time += base::TimeDelta::FromSeconds(10); + scrollbar_controller_->Animate(time); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(1, h_scrollbar_layer_->thumb_thickness_scale_factor()); + + // Now move away from bar. + scrollbar_controller_->DidMouseMoveNear( + HORIZONTAL, kDefaultMouseMoveDistanceToTriggerAnimation); + scrollbar_controller_->Animate(time); + time += kThinningDuration; + scrollbar_controller_->Animate(time); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); + + // An animation should have been enqueued. + EXPECT_FALSE(client_.start_fade().is_null()); + EXPECT_EQ(kDelayBeforeStarting, client_.delay()); +} + +// Move mouse near both scrollbars at the same time. +TEST_F(ScrollbarAnimationControllerThinningTest, MouseNearBoth) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + + // Scroll to make the scrollbars visible. + scrollbar_controller_->DidScrollBegin(); + scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollEnd(); + + // Near both Scrollbar + scrollbar_controller_->DidMouseMoveNear(VERTICAL, 1); + scrollbar_controller_->DidMouseMoveNear(HORIZONTAL, 1); + scrollbar_controller_->Animate(time); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); + + // Should animate to thickened. + time += kThinningDuration; + scrollbar_controller_->Animate(time); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(1, v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(1, h_scrollbar_layer_->thumb_thickness_scale_factor()); +} + +// Move mouse from one to the other scrollbar before animation is finished, then +// away before animation finished. +TEST_F(ScrollbarAnimationControllerThinningTest, + MouseNearOtherBeforeAnimationFinished) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + + // Scroll to make the scrollbars visible. + scrollbar_controller_->DidScrollBegin(); + scrollbar_controller_->DidScrollUpdate(false); + scrollbar_controller_->DidScrollEnd(); + + // Near vertical scrollbar. + scrollbar_controller_->DidMouseMoveNear(VERTICAL, 1); + scrollbar_controller_->Animate(time); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); + + // Vertical scrollbar animate to half thickened. + time += kThinningDuration / 2; + scrollbar_controller_->Animate(time); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(kIdleThicknessScale + (1.0f - kIdleThicknessScale) / 2, + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); + + // Away vertical scrollbar and near horizontal scrollbar. + scrollbar_controller_->DidMouseMoveNear( + VERTICAL, kDefaultMouseMoveDistanceToTriggerAnimation); + scrollbar_controller_->DidMouseMoveNear(HORIZONTAL, 1); + scrollbar_controller_->Animate(time); + + // Vertical scrollbar animate to thin. horizontal scrollbar animate to + // thickened. + time += kThinningDuration; + scrollbar_controller_->Animate(time); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(1, h_scrollbar_layer_->thumb_thickness_scale_factor()); + + // Away horizontal scrollbar. + scrollbar_controller_->DidMouseMoveNear( + HORIZONTAL, kDefaultMouseMoveDistanceToTriggerAnimation); + scrollbar_controller_->Animate(time); + + // Horizontal scrollbar animate to thin. + time += kThinningDuration; + scrollbar_controller_->Animate(time); + ExpectScrollbarsOpacity(1); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + v_scrollbar_layer_->thumb_thickness_scale_factor()); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + h_scrollbar_layer_->thumb_thickness_scale_factor()); + + // An animation should have been enqueued. + EXPECT_FALSE(client_.start_fade().is_null()); + EXPECT_EQ(kDelayBeforeStarting, client_.delay()); +} + } // namespace } // namespace cc
diff --git a/cc/input/single_scrollbar_animation_controller_thinning.cc b/cc/input/single_scrollbar_animation_controller_thinning.cc new file mode 100644 index 0000000..d2ba28b1 --- /dev/null +++ b/cc/input/single_scrollbar_animation_controller_thinning.cc
@@ -0,0 +1,204 @@ +// Copyright 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 "cc/input/single_scrollbar_animation_controller_thinning.h" + +#include <algorithm> + +#include "base/memory/ptr_util.h" +#include "base/time/time.h" +#include "cc/input/scrollbar_animation_controller.h" +#include "cc/layers/layer_impl.h" +#include "cc/layers/scrollbar_layer_impl_base.h" +#include "cc/trees/layer_tree_impl.h" + +namespace { +const float kIdleThicknessScale = 0.4f; +const float kDefaultMouseMoveDistanceToTriggerAnimation = 25.f; +} + +namespace cc { + +std::unique_ptr<SingleScrollbarAnimationControllerThinning> +SingleScrollbarAnimationControllerThinning::Create( + int scroll_layer_id, + ScrollbarOrientation orientation, + ScrollbarAnimationControllerClient* client, + base::TimeDelta thinning_duration) { + return base::WrapUnique(new SingleScrollbarAnimationControllerThinning( + scroll_layer_id, orientation, client, thinning_duration)); +} + +SingleScrollbarAnimationControllerThinning:: + SingleScrollbarAnimationControllerThinning( + int scroll_layer_id, + ScrollbarOrientation orientation, + ScrollbarAnimationControllerClient* client, + base::TimeDelta thinning_duration) + : client_(client), + is_animating_(false), + scroll_layer_id_(scroll_layer_id), + orientation_(orientation), + captured_(false), + mouse_is_over_scrollbar_(false), + mouse_is_near_scrollbar_(false), + thickness_change_(NONE), + mouse_move_distance_to_trigger_animation_( + kDefaultMouseMoveDistanceToTriggerAnimation), + thinning_duration_(thinning_duration) { + ApplyThumbThicknessScale(kIdleThicknessScale); +} + +bool SingleScrollbarAnimationControllerThinning::Animate(base::TimeTicks now) { + if (!is_animating_) + return false; + + if (last_awaken_time_.is_null()) + last_awaken_time_ = now; + + float progress = AnimationProgressAtTime(now); + RunAnimationFrame(progress); + + return true; +} + +float SingleScrollbarAnimationControllerThinning::AnimationProgressAtTime( + base::TimeTicks now) { + base::TimeDelta delta = now - last_awaken_time_; + float progress = delta.InSecondsF() / Duration().InSecondsF(); + return std::max(std::min(progress, 1.f), 0.f); +} + +const base::TimeDelta& SingleScrollbarAnimationControllerThinning::Duration() { + return thinning_duration_; +} + +void SingleScrollbarAnimationControllerThinning::RunAnimationFrame( + float progress) { + if (captured_) + return; + + ApplyThumbThicknessScale(ThumbThicknessScaleAt(progress)); + + client_->SetNeedsRedrawForScrollbarAnimation(); + if (progress == 1.f) { + StopAnimation(); + thickness_change_ = NONE; + } +} + +void SingleScrollbarAnimationControllerThinning::StartAnimation() { + is_animating_ = true; + last_awaken_time_ = base::TimeTicks(); + client_->SetNeedsAnimateForScrollbarAnimation(); +} + +void SingleScrollbarAnimationControllerThinning::StopAnimation() { + is_animating_ = false; +} + +void SingleScrollbarAnimationControllerThinning::DidMouseDown() { + if (!mouse_is_over_scrollbar_) + return; + + StopAnimation(); + captured_ = true; + ApplyThumbThicknessScale(1.f); +} + +void SingleScrollbarAnimationControllerThinning::DidMouseUp() { + if (!captured_) + return; + + captured_ = false; + StopAnimation(); + + if (!mouse_is_near_scrollbar_) { + thickness_change_ = DECREASE; + StartAnimation(); + } else { + thickness_change_ = NONE; + } +} + +void SingleScrollbarAnimationControllerThinning::DidMouseLeave() { + if (!mouse_is_over_scrollbar_ && !mouse_is_near_scrollbar_) + return; + + mouse_is_over_scrollbar_ = false; + mouse_is_near_scrollbar_ = false; + + if (captured_) + return; + + thickness_change_ = DECREASE; + StartAnimation(); +} + +void SingleScrollbarAnimationControllerThinning::DidMouseMoveNear( + float distance) { + bool mouse_is_over_scrollbar = distance == 0.0f; + bool mouse_is_near_scrollbar = + distance < mouse_move_distance_to_trigger_animation_; + + if (!captured_ && mouse_is_near_scrollbar != mouse_is_near_scrollbar_) { + thickness_change_ = mouse_is_near_scrollbar ? INCREASE : DECREASE; + StartAnimation(); + } + mouse_is_near_scrollbar_ = mouse_is_near_scrollbar; + mouse_is_over_scrollbar_ = mouse_is_over_scrollbar; +} + +float SingleScrollbarAnimationControllerThinning::ThumbThicknessScaleAt( + float progress) { + if (thickness_change_ == NONE) + return mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale; + float factor = thickness_change_ == INCREASE ? progress : (1.f - progress); + return ((1.f - kIdleThicknessScale) * factor) + kIdleThicknessScale; +} + +float SingleScrollbarAnimationControllerThinning::AdjustScale( + float new_value, + float current_value, + AnimationChange animation_change, + float min_value, + float max_value) { + float result; + if (animation_change == INCREASE && current_value > new_value) + result = current_value; + else if (animation_change == DECREASE && current_value < new_value) + result = current_value; + else + result = new_value; + if (result > max_value) + return max_value; + if (result < min_value) + return min_value; + return result; +} + +void SingleScrollbarAnimationControllerThinning::UpdateThumbThicknessScale() { + StopAnimation(); + ApplyThumbThicknessScale(mouse_is_near_scrollbar_ ? 1.f + : kIdleThicknessScale); +} + +void SingleScrollbarAnimationControllerThinning::ApplyThumbThicknessScale( + float thumb_thickness_scale) { + for (ScrollbarLayerImplBase* scrollbar : + client_->ScrollbarsFor(scroll_layer_id_)) { + if (scrollbar->orientation() != orientation_) + continue; + if (!scrollbar->is_overlay_scrollbar()) + continue; + + float scale = AdjustScale(thumb_thickness_scale, + scrollbar->thumb_thickness_scale_factor(), + thickness_change_, kIdleThicknessScale, 1); + + scrollbar->SetThumbThicknessScaleFactor(scale); + } +} + +} // namespace cc
diff --git a/cc/input/single_scrollbar_animation_controller_thinning.h b/cc/input/single_scrollbar_animation_controller_thinning.h new file mode 100644 index 0000000..b974387 --- /dev/null +++ b/cc/input/single_scrollbar_animation_controller_thinning.h
@@ -0,0 +1,97 @@ +// Copyright 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. + +#ifndef CC_INPUT_SINGLE_SCROLLBAR_ANIMATION_CONTROLLER_THINNING_H_ +#define CC_INPUT_SINGLE_SCROLLBAR_ANIMATION_CONTROLLER_THINNING_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/time/time.h" +#include "cc/base/cc_export.h" +#include "cc/input/scrollbar.h" +#include "cc/layers/layer_impl.h" +#include "cc/layers/scrollbar_layer_impl_base.h" +#include "ui/gfx/geometry/vector2d_f.h" + +namespace cc { + +class ScrollbarAnimationControllerClient; + +// ScrollbarAnimationControllerThinning for one scrollbar +class CC_EXPORT SingleScrollbarAnimationControllerThinning { + public: + static std::unique_ptr<SingleScrollbarAnimationControllerThinning> Create( + int scroll_layer_id, + ScrollbarOrientation orientation, + ScrollbarAnimationControllerClient* client, + base::TimeDelta thinning_duration); + + ~SingleScrollbarAnimationControllerThinning() {} + + void set_mouse_move_distance_for_test(float distance) { + mouse_move_distance_to_trigger_animation_ = distance; + } + bool mouse_is_over_scrollbar() const { return mouse_is_over_scrollbar_; } + bool mouse_is_near_scrollbar() const { return mouse_is_near_scrollbar_; } + bool captured() const { return captured_; } + + bool Animate(base::TimeTicks now); + void StartAnimation(); + void StopAnimation(); + + void UpdateThumbThicknessScale(); + + void DidMouseDown(); + void DidMouseUp(); + void DidMouseLeave(); + void DidMouseMoveNear(float distance); + + private: + SingleScrollbarAnimationControllerThinning( + int scroll_layer_id, + ScrollbarOrientation orientation, + ScrollbarAnimationControllerClient* client, + base::TimeDelta thinning_duration); + + float AnimationProgressAtTime(base::TimeTicks now); + void RunAnimationFrame(float progress); + const base::TimeDelta& Duration(); + + // Describes whether the current animation should INCREASE (thicken) + // a bar or DECREASE it (thin). + enum AnimationChange { NONE, INCREASE, DECREASE }; + float ThumbThicknessScaleAt(float progress); + + float AdjustScale(float new_value, + float current_value, + AnimationChange animation_change, + float min_value, + float max_value); + void ApplyThumbThicknessScale(float thumb_thickness_scale); + + ScrollbarAnimationControllerClient* client_; + + base::TimeTicks last_awaken_time_; + bool is_animating_; + + int scroll_layer_id_; + + ScrollbarOrientation orientation_; + bool captured_; + bool mouse_is_over_scrollbar_; + bool mouse_is_near_scrollbar_; + // Are we narrowing or thickening the bars. + AnimationChange thickness_change_; + // How close should the mouse be to the scrollbar before we thicken it. + float mouse_move_distance_to_trigger_animation_; + + base::TimeDelta thinning_duration_; + + DISALLOW_COPY_AND_ASSIGN(SingleScrollbarAnimationControllerThinning); +}; + +} // namespace cc + +#endif // CC_INPUT_SINGLE_SCROLLBAR_ANIMATION_CONTROLLER_THINNING_H_
diff --git a/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc b/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc new file mode 100644 index 0000000..4486a87c --- /dev/null +++ b/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc
@@ -0,0 +1,381 @@ +// Copyright 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 "cc/input/single_scrollbar_animation_controller_thinning.h" + +#include "cc/layers/solid_color_scrollbar_layer_impl.h" +#include "cc/test/fake_impl_task_runner_provider.h" +#include "cc/test/fake_layer_tree_host_impl.h" +#include "cc/test/geometry_test_utils.h" +#include "cc/test/test_task_graph_runner.h" +#include "cc/trees/layer_tree_impl.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::AtLeast; +using testing::Mock; +using testing::NiceMock; +using testing::_; + +namespace cc { +namespace { + +// These constants are hard-coded and should match the values in +// single_scrollbar_animation_controller_thinning.cc. +const float kIdleThicknessScale = 0.4f; +const float kDefaultMouseMoveDistanceToTriggerAnimation = 25.f; + +class MockSingleScrollbarAnimationControllerClient + : public ScrollbarAnimationControllerClient { + public: + explicit MockSingleScrollbarAnimationControllerClient( + LayerTreeHostImpl* host_impl) + : host_impl_(host_impl) {} + virtual ~MockSingleScrollbarAnimationControllerClient() {} + + ScrollbarSet ScrollbarsFor(int scroll_layer_id) const override { + return host_impl_->ScrollbarsFor(scroll_layer_id); + } + + MOCK_METHOD2(PostDelayedScrollbarAnimationTask, + void(const base::Closure& start_fade, base::TimeDelta delay)); + MOCK_METHOD0(SetNeedsRedrawForScrollbarAnimation, void()); + MOCK_METHOD0(SetNeedsAnimateForScrollbarAnimation, void()); + MOCK_METHOD0(DidChangeScrollbarVisibility, void()); + MOCK_METHOD0(start_fade, base::Closure()); + MOCK_METHOD0(delay, base::TimeDelta()); + + private: + LayerTreeHostImpl* host_impl_; +}; + +class SingleScrollbarAnimationControllerThinningTest : public testing::Test { + public: + SingleScrollbarAnimationControllerThinningTest() + : host_impl_(&task_runner_provider_, &task_graph_runner_), + client_(&host_impl_) {} + + protected: + const base::TimeDelta kThinningDuration = base::TimeDelta::FromSeconds(2); + + void SetUp() override { + std::unique_ptr<LayerImpl> scroll_layer = + LayerImpl::Create(host_impl_.active_tree(), 1); + std::unique_ptr<LayerImpl> clip = + LayerImpl::Create(host_impl_.active_tree(), 3); + clip_layer_ = clip.get(); + scroll_layer->SetScrollClipLayer(clip_layer_->id()); + LayerImpl* scroll_layer_ptr = scroll_layer.get(); + + const int kId = 2; + const int kThumbThickness = 10; + const int kTrackStart = 0; + const bool kIsLeftSideVerticalScrollbar = false; + const bool kIsOverlayScrollbar = true; + + std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar = + SolidColorScrollbarLayerImpl::Create( + host_impl_.active_tree(), kId, HORIZONTAL, kThumbThickness, + kTrackStart, kIsLeftSideVerticalScrollbar, kIsOverlayScrollbar); + scrollbar_layer_ = scrollbar.get(); + + scroll_layer->test_properties()->AddChild(std::move(scrollbar)); + clip_layer_->test_properties()->AddChild(std::move(scroll_layer)); + host_impl_.active_tree()->SetRootLayerForTesting(std::move(clip)); + + scrollbar_layer_->SetScrollLayerId(scroll_layer_ptr->id()); + scrollbar_layer_->test_properties()->opacity_can_animate = true; + clip_layer_->SetBounds(gfx::Size(100, 100)); + scroll_layer_ptr->SetBounds(gfx::Size(200, 200)); + host_impl_.active_tree()->BuildLayerListAndPropertyTreesForTesting(); + + scrollbar_controller_ = SingleScrollbarAnimationControllerThinning::Create( + scroll_layer_ptr->id(), HORIZONTAL, &client_, kThinningDuration); + } + + FakeImplTaskRunnerProvider task_runner_provider_; + TestTaskGraphRunner task_graph_runner_; + FakeLayerTreeHostImpl host_impl_; + std::unique_ptr<SingleScrollbarAnimationControllerThinning> + scrollbar_controller_; + LayerImpl* clip_layer_; + SolidColorScrollbarLayerImpl* scrollbar_layer_; + NiceMock<MockSingleScrollbarAnimationControllerClient> client_; +}; + +// Check initialization of scrollbar. Should start thin. +TEST_F(SingleScrollbarAnimationControllerThinningTest, Idle) { + EXPECT_FLOAT_EQ(kIdleThicknessScale, + scrollbar_layer_->thumb_thickness_scale_factor()); +} + +// Move the pointer near the scrollbar. Confirm it gets thick and narrow when +// moved away. +TEST_F(SingleScrollbarAnimationControllerThinningTest, MouseNear) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + + scrollbar_controller_->DidMouseMoveNear(1); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + scrollbar_layer_->thumb_thickness_scale_factor()); + + // Should animate to thickened. + time += kThinningDuration; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Subsequent moves within the nearness threshold should not change anything. + scrollbar_controller_->DidMouseMoveNear(2); + scrollbar_controller_->Animate(time); + time += base::TimeDelta::FromSeconds(10); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Now move away from bar. + scrollbar_controller_->DidMouseMoveNear( + kDefaultMouseMoveDistanceToTriggerAnimation); + scrollbar_controller_->Animate(time); + time += kThinningDuration; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + scrollbar_layer_->thumb_thickness_scale_factor()); +} + +// Move the pointer over the scrollbar. Make sure it gets thick that it gets +// thin when moved away. +TEST_F(SingleScrollbarAnimationControllerThinningTest, MouseOver) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + + scrollbar_controller_->DidMouseMoveNear(0); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + scrollbar_layer_->thumb_thickness_scale_factor()); + + // Should animate to thickened. + time += kThinningDuration; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Subsequent moves should not change anything. + scrollbar_controller_->DidMouseMoveNear(0); + scrollbar_controller_->Animate(time); + time += base::TimeDelta::FromSeconds(10); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Moving off the scrollbar but still withing the "near" threshold should do + // nothing. + scrollbar_controller_->DidMouseMoveNear( + kDefaultMouseMoveDistanceToTriggerAnimation - 1.f); + scrollbar_controller_->Animate(time); + time += base::TimeDelta::FromSeconds(10); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Now move away from bar. + scrollbar_controller_->DidMouseMoveNear( + kDefaultMouseMoveDistanceToTriggerAnimation); + scrollbar_controller_->Animate(time); + time += kThinningDuration; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + scrollbar_layer_->thumb_thickness_scale_factor()); +} + +// First move the pointer over the scrollbar off of it. Make sure the thinning +// animation kicked off in DidMouseMoveOffScrollbar gets overridden by the +// thickening animation in the DidMouseMoveNear call. +TEST_F(SingleScrollbarAnimationControllerThinningTest, + MouseNearThenAwayWhileAnimating) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + + scrollbar_controller_->DidMouseMoveNear(0); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + scrollbar_layer_->thumb_thickness_scale_factor()); + + // Should animate to thickened. + time += kThinningDuration; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // This is tricky. The DidMouseLeave() is sent before the + // subsequent DidMouseMoveNear(), if the mouse moves in that direction. + // This results in the thumb thinning. We want to make sure that when the + // thumb starts expanding it doesn't first narrow to the idle thinness. + time += base::TimeDelta::FromSeconds(1); + scrollbar_controller_->DidMouseLeave(); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Let the animation run half of the way through the thinning animation. + time += kThinningDuration / 2; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, + scrollbar_layer_->thumb_thickness_scale_factor()); + + // Now we get a notification for the mouse moving over the scroller. The + // animation is reset to the thickening direction but we won't start + // thickening until the new animation catches up to the current thickness. + scrollbar_controller_->DidMouseMoveNear(1); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, + scrollbar_layer_->thumb_thickness_scale_factor()); + + // Until we reach the half way point, the animation will have no effect. + time += kThinningDuration / 4; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, + scrollbar_layer_->thumb_thickness_scale_factor()); + + time += kThinningDuration / 4; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, + scrollbar_layer_->thumb_thickness_scale_factor()); + + // We're now at three quarters of the way through so it should now started + // thickening again. + time += kThinningDuration / 4; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(kIdleThicknessScale + 3 * (1.0f - kIdleThicknessScale) / 4.0f, + scrollbar_layer_->thumb_thickness_scale_factor()); + + // And all the way to the end. + time += kThinningDuration / 4; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); +} + +// First move the pointer on the scrollbar, then press it, then away. +// Confirm that the bar gets thick. Then mouse up. Confirm that +// the bar gets thin. +TEST_F(SingleScrollbarAnimationControllerThinningTest, + MouseCaptureAndReleaseOutOfBar) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + + // Move over the scrollbar. + scrollbar_controller_->DidMouseMoveNear(0); + scrollbar_controller_->Animate(time); + time += kThinningDuration; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Capture + scrollbar_controller_->DidMouseDown(); + time += base::TimeDelta::FromSeconds(1); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Should stay thick for a while. + time += base::TimeDelta::FromSeconds(10); + scrollbar_controller_->Animate(time); + + // Move outside the "near" threshold. Because the scrollbar is captured it + // should remain thick. + scrollbar_controller_->DidMouseMoveNear( + kDefaultMouseMoveDistanceToTriggerAnimation); + time += kThinningDuration; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Release. + scrollbar_controller_->DidMouseUp(); + + // Should become thin. + time += base::TimeDelta::FromSeconds(1); + scrollbar_controller_->Animate(time); + time += kThinningDuration; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + scrollbar_layer_->thumb_thickness_scale_factor()); +} + +// First move the pointer on the scrollbar, then press it, then away. Confirm +// that the bar gets thick. Then move point on the scrollbar and mouse up. +// Confirm that the bar stays thick. +TEST_F(SingleScrollbarAnimationControllerThinningTest, + MouseCaptureAndReleaseOnBar) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + + // Move over scrollbar. + scrollbar_controller_->DidMouseMoveNear(0); + scrollbar_controller_->Animate(time); + time += kThinningDuration; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Capture. Nothing should change. + scrollbar_controller_->DidMouseDown(); + time += base::TimeDelta::FromSeconds(1); + scrollbar_controller_->Animate(time); + time += base::TimeDelta::FromSeconds(10); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Move away from scrollbar. Nothing should change. + scrollbar_controller_->DidMouseMoveNear( + kDefaultMouseMoveDistanceToTriggerAnimation); + time += base::TimeDelta::FromSeconds(1); + scrollbar_controller_->Animate(time); + time += base::TimeDelta::FromSeconds(10); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Move over scrollbar and release. Since we're near the scrollbar, it should + // remain thick. + scrollbar_controller_->DidMouseMoveNear(0); + scrollbar_controller_->DidMouseUp(); + time += base::TimeDelta::FromSeconds(1); + scrollbar_controller_->Animate(time); + time += base::TimeDelta::FromSeconds(10); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); +} + +// Tests that the thickening/thinning effects are animated. +TEST_F(SingleScrollbarAnimationControllerThinningTest, ThicknessAnimated) { + base::TimeTicks time; + time += base::TimeDelta::FromSeconds(1); + + // Move mouse near scrollbar. Test that at half the duration time, the + // thickness is half way through its animation. + scrollbar_controller_->DidMouseMoveNear(1); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + scrollbar_layer_->thumb_thickness_scale_factor()); + + time += kThinningDuration / 2; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(kIdleThicknessScale + (1.0f - kIdleThicknessScale) / 2.0f, + scrollbar_layer_->thumb_thickness_scale_factor()); + + time += kThinningDuration / 2; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + // Move mouse away from scrollbar. Same check. + time += base::TimeDelta::FromSeconds(1); + scrollbar_controller_->DidMouseMoveNear( + kDefaultMouseMoveDistanceToTriggerAnimation); + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor()); + + time += kThinningDuration / 2; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(1.0f - (1.0f - kIdleThicknessScale) / 2.0f, + scrollbar_layer_->thumb_thickness_scale_factor()); + + time += kThinningDuration / 2; + scrollbar_controller_->Animate(time); + EXPECT_FLOAT_EQ(kIdleThicknessScale, + scrollbar_layer_->thumb_thickness_scale_factor()); +} + +} // namespace +} // namespace cc
diff --git a/cc/test/ordered_simple_task_runner.cc b/cc/test/ordered_simple_task_runner.cc index 161704f..98b943b 100644 --- a/cc/test/ordered_simple_task_runner.cc +++ b/cc/test/ordered_simple_task_runner.cc
@@ -43,6 +43,12 @@ task_id_(TestOrderablePendingTask::task_id_counter++) { } +TestOrderablePendingTask::TestOrderablePendingTask(TestOrderablePendingTask&&) = + default; + +TestOrderablePendingTask& TestOrderablePendingTask::operator=( + TestOrderablePendingTask&&) = default; + size_t TestOrderablePendingTask::task_id_counter = 0; TestOrderablePendingTask::~TestOrderablePendingTask() { @@ -106,7 +112,7 @@ base::TestPendingTask::NESTABLE); TRACE_TASK("OrderedSimpleTaskRunner::PostDelayedTask", pt); - pending_tasks_.insert(pt); + pending_tasks_.insert(std::move(pt)); return true; } @@ -119,7 +125,7 @@ base::TestPendingTask::NON_NESTABLE); TRACE_TASK("OrderedSimpleTaskRunner::PostNonNestableDelayedTask", pt); - pending_tasks_.insert(pt); + pending_tasks_.insert(std::move(pt)); return true; } @@ -230,7 +236,11 @@ "OrderedSimpleTaskRunner::RunPendingTasks running", "task", task_to_run->AsValue()); - task_to_run->task.Run(); + // It's safe to remove const and consume |task| here, since |task| is not + // used for ordering the item. + base::OnceClosure& task = + const_cast<base::OnceClosure&>(task_to_run->task); + std::move(task).Run(); } pending_tasks_.erase(task_to_run); @@ -318,15 +328,18 @@ } base::Callback<bool(void)> OrderedSimpleTaskRunner::TaskExistedInitially() { - // base::Bind takes a copy of pending_tasks_ + std::set<size_t> task_ids; + for (const auto& task : pending_tasks_) + task_ids.insert(task.task_id()); + return base::Bind(&OrderedSimpleTaskRunner::TaskExistedInitiallyCallback, - base::Unretained(this), - pending_tasks_); + base::Unretained(this), std::move(task_ids)); } bool OrderedSimpleTaskRunner::TaskExistedInitiallyCallback( - const std::set<TestOrderablePendingTask>& existing_tasks) { - return existing_tasks.find(*pending_tasks_.begin()) != existing_tasks.end(); + const std::set<size_t>& existing_tasks) { + return existing_tasks.find(pending_tasks_.begin()->task_id()) != + existing_tasks.end(); } base::Callback<bool(void)> OrderedSimpleTaskRunner::NowBefore(
diff --git a/cc/test/ordered_simple_task_runner.h b/cc/test/ordered_simple_task_runner.h index 1ba8e95..f4d1076d 100644 --- a/cc/test/ordered_simple_task_runner.h +++ b/cc/test/ordered_simple_task_runner.h
@@ -32,8 +32,11 @@ base::TimeTicks post_time, base::TimeDelta delay, TestNestability nestability); + TestOrderablePendingTask(TestOrderablePendingTask&&); ~TestOrderablePendingTask(); + TestOrderablePendingTask& operator=(TestOrderablePendingTask&&); + // operators needed by std::set and comparison bool operator==(const TestOrderablePendingTask& other) const; bool operator<(const TestOrderablePendingTask& other) const; @@ -42,9 +45,13 @@ std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue() const; void AsValueInto(base::trace_event::TracedValue* state) const; + size_t task_id() const { return task_id_; } + private: static size_t task_id_counter; - const size_t task_id_; + size_t task_id_; + + DISALLOW_COPY_AND_ASSIGN(TestOrderablePendingTask); }; // This runs pending tasks based on task's post_time + delay. @@ -135,8 +142,7 @@ protected: static bool TaskRunCountBelowCallback(size_t max_tasks, size_t* task_run); - bool TaskExistedInitiallyCallback( - const std::set<TestOrderablePendingTask>& existing_tasks); + bool TaskExistedInitiallyCallback(const std::set<size_t>& existing_tasks); bool NowBeforeCallback(base::TimeTicks stop_at); bool AdvanceNowCallback();
diff --git a/cc/test/ordered_simple_task_runner_unittest.cc b/cc/test/ordered_simple_task_runner_unittest.cc index df6975b..6e3c03f 100644 --- a/cc/test/ordered_simple_task_runner_unittest.cc +++ b/cc/test/ordered_simple_task_runner_unittest.cc
@@ -48,8 +48,7 @@ EXPECT_LT(b, c); EXPECT_LT(a, c); - TestOrderablePendingTask a2 = a; - EXPECT_EQ(a, a2); + TestOrderablePendingTask a2 = std::move(a); EXPECT_LT(a2, b); EXPECT_LT(b, c); EXPECT_LT(a2, c);
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 00fa09fd..45ea42e 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -3248,7 +3248,6 @@ } void LayerTreeHostImpl::MouseMoveAt(const gfx::Point& viewport_point) { - float distance_to_scrollbar = std::numeric_limits<float>::max(); gfx::PointF device_viewport_point = gfx::ScalePoint( gfx::PointF(viewport_point), active_tree_->device_scale_factor()); LayerImpl* layer_impl = @@ -3261,10 +3260,7 @@ int new_id = Layer::INVALID_ID; if (layer_impl && layer_impl->ToScrollbarLayer()) new_id = layer_impl->ToScrollbarLayer()->ScrollLayerId(); - if (new_id != Layer::INVALID_ID) { - // Mouse over a scrollbar. - distance_to_scrollbar = 0; - } else { + if (new_id == Layer::INVALID_ID) { bool scroll_on_main_thread = false; uint32_t main_thread_scrolling_reasons; LayerImpl* scroll_layer_impl = FindScrollLayerForDeviceViewportPoint( @@ -3293,12 +3289,12 @@ if (!new_animation_controller) return; - for (ScrollbarLayerImplBase* scrollbar : ScrollbarsFor(new_id)) - distance_to_scrollbar = - std::min(distance_to_scrollbar, - DeviceSpaceDistanceToLayer(device_viewport_point, scrollbar)); - new_animation_controller->DidMouseMoveNear( - distance_to_scrollbar / active_tree_->device_scale_factor()); + for (ScrollbarLayerImplBase* scrollbar : ScrollbarsFor(new_id)) { + new_animation_controller->DidMouseMoveNear( + scrollbar->orientation(), + DeviceSpaceDistanceToLayer(device_viewport_point, scrollbar) / + active_tree_->device_scale_factor()); + } } void LayerTreeHostImpl::MouseLeave() {
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 0da0a662..200c19e2 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -2944,7 +2944,7 @@ if (expecting_animations) { host_impl_->ScrollbarAnimationControllerForId(scroll->id()) - ->DidMouseMoveNear(0); + ->DidMouseMoveNear(VERTICAL, 0); } else { EXPECT_EQ(nullptr, host_impl_->ScrollbarAnimationControllerForId(scroll->id())); @@ -3204,26 +3204,34 @@ scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f); host_impl_->MouseMoveAt(gfx::Point(200, 1)); - EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar()); + EXPECT_FALSE( + scrollbar_animation_controller->mouse_is_near_scrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(100, 50)); - EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar()); + EXPECT_TRUE( + scrollbar_animation_controller->mouse_is_near_scrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(116, 100)); - EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar()); + EXPECT_FALSE( + scrollbar_animation_controller->mouse_is_near_scrollbar(VERTICAL)); scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f); host_impl_->MouseMoveAt(gfx::Point(116, 100)); - EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar()); + EXPECT_TRUE( + scrollbar_animation_controller->mouse_is_near_scrollbar(VERTICAL)); did_request_redraw_ = false; - EXPECT_FALSE(scrollbar_animation_controller->mouse_is_over_scrollbar()); + EXPECT_FALSE( + scrollbar_animation_controller->mouse_is_over_scrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 100)); - EXPECT_TRUE(scrollbar_animation_controller->mouse_is_over_scrollbar()); + EXPECT_TRUE( + scrollbar_animation_controller->mouse_is_over_scrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 120)); - EXPECT_TRUE(scrollbar_animation_controller->mouse_is_over_scrollbar()); + EXPECT_TRUE( + scrollbar_animation_controller->mouse_is_over_scrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(150, 120)); - EXPECT_FALSE(scrollbar_animation_controller->mouse_is_over_scrollbar()); + EXPECT_FALSE( + scrollbar_animation_controller->mouse_is_over_scrollbar(VERTICAL)); } TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) { @@ -11604,20 +11612,30 @@ // Mouse moves close to the scrollbar, goes over the scrollbar, and // moves back to where it was. host_impl_->MouseMoveAt(gfx::Point(100, 150)); - EXPECT_FALSE(scrollbar_1_animation_controller->mouse_is_near_scrollbar()); - EXPECT_FALSE(scrollbar_1_animation_controller->mouse_is_over_scrollbar()); + EXPECT_FALSE( + scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_FALSE( + scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(40, 150)); - EXPECT_TRUE(scrollbar_1_animation_controller->mouse_is_near_scrollbar()); - EXPECT_FALSE(scrollbar_1_animation_controller->mouse_is_over_scrollbar()); + EXPECT_TRUE( + scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_FALSE( + scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 150)); - EXPECT_TRUE(scrollbar_1_animation_controller->mouse_is_near_scrollbar()); - EXPECT_TRUE(scrollbar_1_animation_controller->mouse_is_over_scrollbar()); + EXPECT_TRUE( + scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_TRUE( + scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(40, 150)); - EXPECT_TRUE(scrollbar_1_animation_controller->mouse_is_near_scrollbar()); - EXPECT_FALSE(scrollbar_1_animation_controller->mouse_is_over_scrollbar()); + EXPECT_TRUE( + scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_FALSE( + scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(100, 150)); - EXPECT_FALSE(scrollbar_1_animation_controller->mouse_is_near_scrollbar()); - EXPECT_FALSE(scrollbar_1_animation_controller->mouse_is_over_scrollbar()); + EXPECT_FALSE( + scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_FALSE( + scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); // scrollbar_2 on child. std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar_2 = @@ -11658,25 +11676,41 @@ // Mouse goes over scrollbar_2, moves close to scrollbar_2, moves close to // scrollbar_1, goes over scrollbar_1. host_impl_->MouseMoveAt(gfx::Point(60, 150)); - EXPECT_FALSE(scrollbar_1_animation_controller->mouse_is_near_scrollbar()); - EXPECT_FALSE(scrollbar_1_animation_controller->mouse_is_over_scrollbar()); - EXPECT_TRUE(scrollbar_2_animation_controller->mouse_is_near_scrollbar()); - EXPECT_TRUE(scrollbar_2_animation_controller->mouse_is_over_scrollbar()); + EXPECT_FALSE( + scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_FALSE( + scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_TRUE( + scrollbar_2_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_TRUE( + scrollbar_2_animation_controller->mouse_is_over_scrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(100, 150)); - EXPECT_FALSE(scrollbar_1_animation_controller->mouse_is_near_scrollbar()); - EXPECT_FALSE(scrollbar_1_animation_controller->mouse_is_over_scrollbar()); - EXPECT_TRUE(scrollbar_2_animation_controller->mouse_is_near_scrollbar()); - EXPECT_FALSE(scrollbar_2_animation_controller->mouse_is_over_scrollbar()); + EXPECT_FALSE( + scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_FALSE( + scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_TRUE( + scrollbar_2_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_FALSE( + scrollbar_2_animation_controller->mouse_is_over_scrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(40, 150)); - EXPECT_TRUE(scrollbar_1_animation_controller->mouse_is_near_scrollbar()); - EXPECT_FALSE(scrollbar_1_animation_controller->mouse_is_over_scrollbar()); - EXPECT_FALSE(scrollbar_2_animation_controller->mouse_is_near_scrollbar()); - EXPECT_FALSE(scrollbar_2_animation_controller->mouse_is_over_scrollbar()); + EXPECT_TRUE( + scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_FALSE( + scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_FALSE( + scrollbar_2_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_FALSE( + scrollbar_2_animation_controller->mouse_is_over_scrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 150)); - EXPECT_TRUE(scrollbar_1_animation_controller->mouse_is_near_scrollbar()); - EXPECT_TRUE(scrollbar_1_animation_controller->mouse_is_over_scrollbar()); - EXPECT_FALSE(scrollbar_2_animation_controller->mouse_is_near_scrollbar()); - EXPECT_FALSE(scrollbar_2_animation_controller->mouse_is_over_scrollbar()); + EXPECT_TRUE( + scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_TRUE( + scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_FALSE( + scrollbar_2_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_FALSE( + scrollbar_2_animation_controller->mouse_is_over_scrollbar(VERTICAL)); } TEST_F(LayerTreeHostImplTest,
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index d1cc0a0..481a370 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -1793,34 +1793,20 @@ const ClipTree& clip_tree = property_trees->clip_tree; const TransformTree& transform_tree = property_trees->transform_tree; const ClipNode* clip_node = clip_tree.Node(1); - gfx::Rect combined_clip_in_target_space = - gfx::ToEnclosingRect(clip_node->combined_clip_in_target_space); - if (!PointHitsRect(screen_space_point, gfx::Transform(), - combined_clip_in_target_space, NULL)) + gfx::Rect clip = gfx::ToEnclosingRect(clip_node->clip); + if (!PointHitsRect(screen_space_point, gfx::Transform(), clip, NULL)) return true; for (const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index()); clip_node->id > ClipTree::kViewportNodeId; clip_node = clip_tree.parent(clip_node)) { if (clip_node->clip_type == ClipNode::ClipType::APPLIES_LOCAL_CLIP) { - const TransformNode* transform_node = - transform_tree.Node(clip_node->target_transform_id); - gfx::Rect combined_clip_in_target_space = - gfx::ToEnclosingRect(clip_node->combined_clip_in_target_space); + gfx::Rect clip = gfx::ToEnclosingRect(clip_node->clip); - const LayerImpl* target_layer = - layer->layer_tree_impl()->LayerById(transform_node->owning_layer_id); - DCHECK(transform_node->id == TransformTree::kRootNodeId || - target_layer->render_surface() || - layer->layer_tree_impl()->is_in_resourceless_software_draw_mode()); - gfx::Transform surface_screen_space_transform = - transform_node->id == TransformTree::kRootNodeId || - (layer->layer_tree_impl() - ->is_in_resourceless_software_draw_mode()) - ? gfx::Transform() - : SurfaceScreenSpaceTransform(target_layer); - if (!PointHitsRect(screen_space_point, surface_screen_space_transform, - combined_clip_in_target_space, NULL)) { + gfx::Transform screen_space_transform = + transform_tree.ToScreen(clip_node->transform_id); + if (!PointHitsRect(screen_space_point, screen_space_transform, clip, + NULL)) { return true; } }
diff --git a/chrome/VERSION b/chrome/VERSION index 3b0661d..81d27e2 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=58 MINOR=0 -BUILD=2994 +BUILD=2995 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContext.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContext.java index 26f5e00..a2565b85 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContext.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContext.java
@@ -15,16 +15,6 @@ long getNativeGvrContext(); /** - * Must be called when activity resumes. - */ - void resume(); - - /** - * Must be called when activity pauses. - */ - void pause(); - - /** * Shutdown the native gvr context. */ void shutdown();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContextImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContextImpl.java index 4a47640..c70bea44 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContextImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContextImpl.java
@@ -24,19 +24,6 @@ } @Override - public void resume() { - mGvrLayout.getGvrApi().resumeTracking(); - } - - @Override - public void pause() { - // We can't pause/resume the GvrLayout, because doing so will force us to enter VR. However, - // we should be safe not pausing it as we never add it to the view hierarchy, or give it a - // presentation view, so there's nothing to pause but the tracking. - mGvrLayout.getGvrApi().pauseTracking(); - } - - @Override public void shutdown() { mGvrLayout.shutdown(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java index 835a3c63..8f0b7f14 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -7,12 +7,16 @@ import android.app.Activity; import android.app.PendingIntent; import android.content.ComponentName; +import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.os.Handler; import android.os.StrictMode; import android.os.SystemClock; import android.support.annotation.IntDef; +import android.view.Choreographer; +import android.view.Choreographer.FrameCallback; +import android.view.Display; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; @@ -170,6 +174,16 @@ public void onNativeLibraryReady() { if (mVrSupportLevel == VR_NOT_AVAILABLE) return; mNativeVrShellDelegate = nativeInit(); + Choreographer choreographer = Choreographer.getInstance(); + choreographer.postFrameCallback(new FrameCallback() { + @Override + public void doFrame(long frameTimeNanos) { + Display display = ((WindowManager) mActivity.getSystemService( + Context.WINDOW_SERVICE)).getDefaultDisplay(); + nativeUpdateVSyncInterval(mNativeVrShellDelegate, frameTimeNanos, + 1.0d / display.getRefreshRate()); + } + }); } @SuppressWarnings("unchecked") @@ -403,20 +417,16 @@ // TODO(bshe): Ideally, we do not need two gvr context exist at the same time. We can // probably shutdown non presenting gvr when presenting and create a new one after exit // presenting. See crbug.com/655242 - if (mNonPresentingGvrContext != null) { - StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); - try { - mNonPresentingGvrContext.resume(); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Unable to resume mNonPresentingGvrContext", e); - } finally { - StrictMode.setThreadPolicy(oldPolicy); - } + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + nativeOnResume(mNativeVrShellDelegate); + } finally { + StrictMode.setThreadPolicy(oldPolicy); } if (mInVr) { setupVrModeWindowFlags(); - StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + oldPolicy = StrictMode.allowThreadDiskWrites(); try { mVrShell.resume(); } catch (IllegalArgumentException e) { @@ -448,9 +458,7 @@ // vrdisplayactivate event should be dispatched in enterVRFromIntent. mListeningForWebVrActivateBeforePause = mListeningForWebVrActivate; } - if (mNonPresentingGvrContext != null) { - mNonPresentingGvrContext.pause(); - } + nativeOnPause(mNativeVrShellDelegate); // TODO(mthiesse): When VR Shell lives in its own activity, and integrates with Daydream // home, pause instead of exiting VR here. For now, because VR Apps shouldn't show up in the @@ -656,4 +664,8 @@ private native long nativeInit(); private native void nativeSetPresentResult(long nativeVrShellDelegate, boolean result); private native void nativeDisplayActivate(long nativeVrShellDelegate); + private native void nativeUpdateVSyncInterval(long nativeVrShellDelegate, long timebaseNanos, + double intervalSeconds); + private native void nativeOnPause(long nativeVrShellDelegate); + private native void nativeOnResume(long nativeVrShellDelegate); }
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index 7524657..a9c54355 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -1010,7 +1010,7 @@ } #elif defined(OS_POSIX) && !defined(OS_ANDROID) void ChromeMainDelegate::ZygoteStarting( - ScopedVector<content::ZygoteForkDelegate>* delegates) { + std::vector<std::unique_ptr<content::ZygoteForkDelegate>>* delegates) { #if defined(OS_CHROMEOS) chromeos::ReloadElfTextInHugePages(); #endif
diff --git a/chrome/app/chrome_main_delegate.h b/chrome/app/chrome_main_delegate.h index 278858c..5af397be 100644 --- a/chrome/app/chrome_main_delegate.h +++ b/chrome/app/chrome_main_delegate.h
@@ -6,6 +6,7 @@ #define CHROME_APP_CHROME_MAIN_DELEGATE_H_ #include <memory> +#include <vector> #include "base/macros.h" #include "base/time/time.h" @@ -13,9 +14,6 @@ #include "chrome/common/chrome_content_client.h" #include "content/public/app/content_main_delegate.h" -template <typename> -class ScopedVector; - namespace base { class CommandLine; } @@ -45,8 +43,8 @@ bool ShouldSendMachPort(const std::string& process_type) override; bool DelaySandboxInitialization(const std::string& process_type) override; #elif defined(OS_POSIX) && !defined(OS_ANDROID) - void ZygoteStarting( - ScopedVector<content::ZygoteForkDelegate>* delegates) override; + void ZygoteStarting(std::vector<std::unique_ptr<content::ZygoteForkDelegate>>* + delegates) override; void ZygoteForked() override; #endif bool ShouldEnableProfilerRecording() override;
diff --git a/chrome/browser/android/vr_shell/BUILD.gn b/chrome/browser/android/vr_shell/BUILD.gn index c25fb064..4e06340 100644 --- a/chrome/browser/android/vr_shell/BUILD.gn +++ b/chrome/browser/android/vr_shell/BUILD.gn
@@ -17,6 +17,8 @@ "animation.h", "easing.cc", "easing.h", + "non_presenting_gvr_delegate.cc", + "non_presenting_gvr_delegate.h", "ui_elements.cc", "ui_elements.h", "ui_interface.cc", @@ -28,6 +30,8 @@ "vr_controller.cc", "vr_controller.h", "vr_gesture.h", + "vr_gl_thread.cc", + "vr_gl_thread.h", "vr_gl_util.cc", "vr_gl_util.h", "vr_input_manager.cc",
diff --git a/chrome/browser/android/vr_shell/non_presenting_gvr_delegate.cc b/chrome/browser/android/vr_shell/non_presenting_gvr_delegate.cc new file mode 100644 index 0000000..a13bc7e8 --- /dev/null +++ b/chrome/browser/android/vr_shell/non_presenting_gvr_delegate.cc
@@ -0,0 +1,148 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/vr_shell/non_presenting_gvr_delegate.h" + +#include "chrome/browser/android/vr_shell/vr_shell.h" + +namespace vr_shell { + +namespace { +static constexpr long kPredictionTimeWithoutVsyncNanos = 50000000; +} // namespace + +NonPresentingGvrDelegate::NonPresentingGvrDelegate(long context) + : task_runner_(base::ThreadTaskRunnerHandle::Get()), + binding_(this), + weak_ptr_factory_(this) { + gvr_api_ = gvr::GvrApi::WrapNonOwned(reinterpret_cast<gvr_context*>(context)); +} + +NonPresentingGvrDelegate::~NonPresentingGvrDelegate() { + StopVSyncLoop(); +} + +gvr::Sizei NonPresentingGvrDelegate::GetWebVRCompositorSurfaceSize() { + return device::kInvalidRenderTargetSize; +} + +gvr::GvrApi* NonPresentingGvrDelegate::gvr_api() { + return gvr_api_.get(); +} + +void NonPresentingGvrDelegate::OnVRVsyncProviderRequest( + device::mojom::VRVSyncProviderRequest request) { + binding_.Close(); + binding_.Bind(std::move(request)); + binding_.set_connection_error_handler( + base::Bind(&NonPresentingGvrDelegate::StopVSyncLoop, + weak_ptr_factory_.GetWeakPtr())); + StartVSyncLoop(); +} + +void NonPresentingGvrDelegate::Pause() { + vsync_task_.Cancel(); + vsync_paused_ = true; + gvr_api_->PauseTracking(); +} + +void NonPresentingGvrDelegate::Resume() { + if (!vsync_paused_) + return; + vsync_paused_ = false; + StartVSyncLoop(); +} + +device::mojom::VRVSyncProviderRequest +NonPresentingGvrDelegate::OnSwitchToPresentingDelegate() { + StopVSyncLoop(); + if (binding_.is_bound()) + return binding_.Unbind(); + return nullptr; +} + +void NonPresentingGvrDelegate::StopVSyncLoop() { + vsync_task_.Cancel(); + if (!callback_.is_null()) + callback_.Run(nullptr, base::TimeDelta()); + callback_.Reset(); + gvr_api_->PauseTracking(); + // If the loop is stopped, it's not considered to be paused. + vsync_paused_ = false; +} + +void NonPresentingGvrDelegate::StartVSyncLoop() { + vsync_task_.Reset( + base::Bind(&NonPresentingGvrDelegate::OnVSync, base::Unretained(this))); + gvr_api_->RefreshViewerProfile(); + gvr_api_->ResumeTracking(); + OnVSync(); +} + +void NonPresentingGvrDelegate::OnVSync() { + base::TimeTicks now = base::TimeTicks::Now(); + base::TimeTicks target; + + // Don't run the VSync loop if we're not bound. + if (!binding_.is_bound()) { + return; + } + + // Don't send VSyncs until we have a timebase/interval. + if (vsync_interval_.is_zero()) + return; + target = now + vsync_interval_; + int64_t intervals = (target - vsync_timebase_) / vsync_interval_; + target = vsync_timebase_ + intervals * vsync_interval_; + if (!vsync_task_.IsCancelled()) { + task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(), + target - now); + } + + base::TimeDelta time = intervals * vsync_interval_; + if (!callback_.is_null()) { + callback_.Run(GetPose(), time); + callback_.Reset(); + } else { + pending_vsync_ = true; + pending_time_ = time; + } +} + +void NonPresentingGvrDelegate::GetVSync(const GetVSyncCallback& callback) { + if (!pending_vsync_) { + if (!callback_.is_null()) { + mojo::ReportBadMessage("Requested VSync before waiting for response to " + "previous request."); + return; + } + callback_ = callback; + return; + } + pending_vsync_ = false; + callback.Run(GetPose(), pending_time_); +} + +void NonPresentingGvrDelegate::UpdateVSyncInterval(long timebase_nanos, + double interval_seconds) { + vsync_timebase_ = base::TimeTicks(); + vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000); + vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds); + StartVSyncLoop(); +} + +device::mojom::VRPosePtr NonPresentingGvrDelegate::GetPose() { + gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); + target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; + + gvr::Mat4f head_mat = + gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); + head_mat = gvr_api_->ApplyNeckModel(head_mat, 1.0f); + + uint32_t pose_index = pose_index_++; + + return VrShell::VRPosePtrFromGvrPose(head_mat, pose_index); +} + +} // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/non_presenting_gvr_delegate.h b/chrome/browser/android/vr_shell/non_presenting_gvr_delegate.h new file mode 100644 index 0000000..7e40607 --- /dev/null +++ b/chrome/browser/android/vr_shell/non_presenting_gvr_delegate.h
@@ -0,0 +1,72 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ANDROID_VR_SHELL_NON_PRESENTING_GVR_DELEGATE_H_ +#define CHROME_BROWSER_ANDROID_VR_SHELL_NON_PRESENTING_GVR_DELEGATE_H_ + +#include <jni.h> + +#include "base/cancelable_callback.h" +#include "base/macros.h" +#include "device/vr/android/gvr/gvr_delegate.h" +#include "device/vr/vr_service.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" + +namespace vr_shell { + +// A non presenting delegate for magic window mode. +class NonPresentingGvrDelegate : public device::GvrDelegate, + public device::mojom::VRVSyncProvider { + public: + explicit NonPresentingGvrDelegate(long context); + + ~NonPresentingGvrDelegate() override; + + // GvrDelegate implementation + void SetWebVRSecureOrigin(bool secure_origin) override {} + void SubmitWebVRFrame() override {} + void UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds, + const gvr::Rectf& right_bounds) override {} + void SetWebVRRenderSurfaceSize(int width, int height) override {} + gvr::Sizei GetWebVRCompositorSurfaceSize() override; + gvr::GvrApi* gvr_api() override; + void OnVRVsyncProviderRequest( + device::mojom::VRVSyncProviderRequest request) override; + void UpdateVSyncInterval(long timebase_nanos, + double interval_seconds) override; + + void Pause(); + void Resume(); + device::mojom::VRVSyncProviderRequest OnSwitchToPresentingDelegate(); + + private: + void StopVSyncLoop(); + void StartVSyncLoop(); + void OnVSync(); + device::mojom::VRPosePtr GetPose(); + + // VRVSyncProvider + void GetVSync(const GetVSyncCallback& callback) override; + + std::unique_ptr<gvr::GvrApi> gvr_api_; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + base::CancelableClosure vsync_task_; + base::TimeTicks vsync_timebase_; + base::TimeDelta vsync_interval_; + + // Whether the vsync loop is paused, but not stopped. + bool vsync_paused_ = false; + base::TimeDelta pending_time_; + bool pending_vsync_ = false; + GetVSyncCallback callback_; + uint32_t pose_index_ = 1; + mojo::Binding<device::mojom::VRVSyncProvider> binding_; + base::WeakPtrFactory<NonPresentingGvrDelegate> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(NonPresentingGvrDelegate); +}; + +} // namespace vr_shell + +#endif // CHROME_BROWSER_ANDROID_VR_SHELL_NON_PRESENTING_GVR_DELEGATE_H_
diff --git a/chrome/browser/android/vr_shell/vr_gl_thread.cc b/chrome/browser/android/vr_shell/vr_gl_thread.cc new file mode 100644 index 0000000..ff4aa92 --- /dev/null +++ b/chrome/browser/android/vr_shell/vr_gl_thread.cc
@@ -0,0 +1,47 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/vr_shell/vr_gl_thread.h" + +#include "chrome/browser/android/vr_shell/vr_input_manager.h" +#include "chrome/browser/android/vr_shell/vr_shell.h" +#include "chrome/browser/android/vr_shell/vr_shell_gl.h" + +namespace vr_shell { + +VrGLThread::VrGLThread( + const base::WeakPtr<VrShell>& weak_vr_shell, + const base::WeakPtr<VrShellDelegate>& delegate_provider, + scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, + gvr_context* gvr_api, + bool initially_web_vr, + bool reprojected_rendering) + : base::Thread("VrShellGL"), + weak_vr_shell_(weak_vr_shell), + delegate_provider_(delegate_provider), + main_thread_task_runner_(std::move(main_thread_task_runner)), + gvr_api_(gvr_api), + initially_web_vr_(initially_web_vr), + reprojected_rendering_(reprojected_rendering) {} + +VrGLThread::~VrGLThread() { + Stop(); +} + +void VrGLThread::Init() { + vr_shell_gl_.reset(new VrShellGl(std::move(weak_vr_shell_), + std::move(delegate_provider_), + std::move(main_thread_task_runner_), + gvr_api_, + initially_web_vr_, + reprojected_rendering_)); + weak_vr_shell_gl_ = vr_shell_gl_->GetWeakPtr(); + vr_shell_gl_->Initialize(); +} + +void VrGLThread::CleanUp() { + vr_shell_gl_.reset(); +} + +} // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/vr_gl_thread.h b/chrome/browser/android/vr_shell/vr_gl_thread.h new file mode 100644 index 0000000..0fcb754 --- /dev/null +++ b/chrome/browser/android/vr_shell/vr_gl_thread.h
@@ -0,0 +1,58 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ANDROID_VR_SHELL_VR_GL_THREAD_H_ +#define CHROME_BROWSER_ANDROID_VR_SHELL_VR_GL_THREAD_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread.h" +#include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_types.h" + +namespace vr_shell { + +class VrShell; +class VrShellDelegate; +class VrShellGl; + +class VrGLThread : public base::Thread { + public: + VrGLThread( + const base::WeakPtr<VrShell>& weak_vr_shell, + const base::WeakPtr<VrShellDelegate>& delegate_provider, + scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, + gvr_context* gvr_api, + bool initially_web_vr, + bool reprojected_rendering); + + ~VrGLThread() override; + base::WeakPtr<VrShellGl> GetVrShellGl() { return weak_vr_shell_gl_; } + VrShellGl* GetVrShellGlUnsafe() { return vr_shell_gl_.get(); } + + protected: + void Init() override; + void CleanUp() override; + + private: + // Created on GL thread. + std::unique_ptr<VrShellGl> vr_shell_gl_; + base::WeakPtr<VrShellGl> weak_vr_shell_gl_; + + // This state is used for initializing vr_shell_gl_. + base::WeakPtr<VrShell> weak_vr_shell_; + base::WeakPtr<VrShellDelegate> delegate_provider_; + scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; + gvr_context* gvr_api_; + bool initially_web_vr_; + bool reprojected_rendering_; + + DISALLOW_COPY_AND_ASSIGN(VrGLThread); +}; + +} // namespace vr_shell + +#endif // CHROME_BROWSER_ANDROID_VR_SHELL_VR_GL_THREAD_H_
diff --git a/chrome/browser/android/vr_shell/vr_shell.cc b/chrome/browser/android/vr_shell/vr_shell.cc index 4cba25a..515ca6c3 100644 --- a/chrome/browser/android/vr_shell/vr_shell.cc +++ b/chrome/browser/android/vr_shell/vr_shell.cc
@@ -6,6 +6,7 @@ #include <android/native_window_jni.h> +#include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/threading/platform_thread.h" #include "base/threading/thread.h" @@ -14,6 +15,7 @@ #include "base/values.h" #include "chrome/browser/android/vr_shell/ui_interface.h" #include "chrome/browser/android/vr_shell/vr_compositor.h" +#include "chrome/browser/android/vr_shell/vr_gl_thread.h" #include "chrome/browser/android/vr_shell/vr_input_manager.h" #include "chrome/browser/android/vr_shell/vr_shell_delegate.h" #include "chrome/browser/android/vr_shell/vr_shell_gl.h" @@ -33,6 +35,8 @@ #include "ui/base/page_transition_types.h" #include "ui/display/display.h" #include "ui/display/screen.h" +#include "ui/gfx/transform.h" +#include "ui/gfx/transform_util.h" using base::android::JavaParamRef; using base::android::JavaRef; @@ -44,52 +48,6 @@ static const char kVrShellUIURL[] = "chrome://vr-shell-ui"; -class GLThread : public base::Thread { - public: - GLThread(const base::WeakPtr<VrShell>& weak_vr_shell, - scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, - gvr_context* gvr_api, - bool initially_web_vr, - bool reprojected_rendering) - : base::Thread("VrShellGL"), - weak_vr_shell_(weak_vr_shell), - main_thread_task_runner_(std::move(main_thread_task_runner)), - gvr_api_(gvr_api), - initially_web_vr_(initially_web_vr), - reprojected_rendering_(reprojected_rendering) {} - - ~GLThread() override { - Stop(); - } - base::WeakPtr<VrShellGl> GetVrShellGl() { return weak_vr_shell_gl_; } - VrShellGl* GetVrShellGlUnsafe() { return vr_shell_gl_.get(); } - - protected: - void Init() override { - vr_shell_gl_.reset(new VrShellGl(std::move(weak_vr_shell_), - std::move(main_thread_task_runner_), - gvr_api_, - initially_web_vr_, - reprojected_rendering_)); - weak_vr_shell_gl_ = vr_shell_gl_->GetWeakPtr(); - vr_shell_gl_->Initialize(); - } - void CleanUp() override { - vr_shell_gl_.reset(); - } - - private: - // Created on GL thread. - std::unique_ptr<VrShellGl> vr_shell_gl_; - base::WeakPtr<VrShellGl> weak_vr_shell_gl_; - - base::WeakPtr<VrShell> weak_vr_shell_; - scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; - gvr_context* gvr_api_; - bool initially_web_vr_; - bool reprojected_rendering_; -}; - void SetIsInVR(content::WebContents* contents, bool is_in_vr) { if (contents->GetRenderWidgetHostView()) contents->GetRenderWidgetHostView()->SetIsInVR(is_in_vr); @@ -113,7 +71,7 @@ base::MakeUnique<VrCompositor>(content_window, false)), ui_contents_(ui_contents), ui_compositor_(base::MakeUnique<VrCompositor>(ui_window, true)), - delegate_(delegate), + delegate_provider_(delegate), metrics_helper_(base::MakeUnique<VrMetricsHelper>(main_contents_)), main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), reprojected_rendering_(reprojected_rendering), @@ -128,9 +86,9 @@ content_compositor_->SetLayer(main_contents_); ui_compositor_->SetLayer(ui_contents_); - gl_thread_ = base::MakeUnique<GLThread>(weak_ptr_factory_.GetWeakPtr(), - main_thread_task_runner_, gvr_api, - for_web_vr, reprojected_rendering_); + gl_thread_ = base::MakeUnique<VrGLThread>( + weak_ptr_factory_.GetWeakPtr(), delegate_provider_->GetWeakPtr(), + main_thread_task_runner_, gvr_api, for_web_vr, reprojected_rendering_); base::Thread::Options options(base::MessageLoop::TYPE_DEFAULT, 0); options.priority = base::ThreadPriority::DISPLAY; @@ -198,7 +156,7 @@ base::ThreadRestrictions::ScopedAllowIO allow_io; gl_thread_.reset(); } - delegate_->RemoveDelegate(); + delegate_provider_->RemoveDelegate(); g_instance = nullptr; } @@ -211,16 +169,14 @@ void VrShell::OnTriggerEvent(JNIEnv* env, const JavaParamRef<jobject>& obj) { - GLThread* thread = static_cast<GLThread*>(gl_thread_.get()); - thread->task_runner()->PostTask(FROM_HERE, - base::Bind(&VrShellGl::OnTriggerEvent, - thread->GetVrShellGl())); + gl_thread_->task_runner()->PostTask( + FROM_HERE, + base::Bind(&VrShellGl::OnTriggerEvent, gl_thread_->GetVrShellGl())); } void VrShell::OnPause(JNIEnv* env, const JavaParamRef<jobject>& obj) { - GLThread* thread = static_cast<GLThread*>(gl_thread_.get()); - thread->task_runner()->PostTask( - FROM_HERE, base::Bind(&VrShellGl::OnPause, thread->GetVrShellGl())); + gl_thread_->task_runner()->PostTask( + FROM_HERE, base::Bind(&VrShellGl::OnPause, gl_thread_->GetVrShellGl())); // exit vr session metrics_helper_->SetVRActive(false); @@ -228,9 +184,8 @@ } void VrShell::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) { - GLThread* thread = static_cast<GLThread*>(gl_thread_.get()); - thread->task_runner()->PostTask( - FROM_HERE, base::Bind(&VrShellGl::OnResume, thread->GetVrShellGl())); + gl_thread_->task_runner()->PostTask( + FROM_HERE, base::Bind(&VrShellGl::OnResume, gl_thread_->GetVrShellGl())); metrics_helper_->SetVRActive(true); SetIsInVR(main_contents_, true); @@ -240,11 +195,10 @@ const JavaParamRef<jobject>& obj, const JavaParamRef<jobject>& surface) { CHECK(!reprojected_rendering_); - GLThread* thread = static_cast<GLThread*>(gl_thread_.get()); gfx::AcceleratedWidget window = ANativeWindow_fromSurface(base::android::AttachCurrentThread(), surface); PostToGlThreadWhenReady(base::Bind(&VrShellGl::InitializeGl, - thread->GetVrShellGl(), + gl_thread_->GetVrShellGl(), base::Unretained(window))); } @@ -267,9 +221,8 @@ const base::android::JavaParamRef<jobject>& obj, bool enabled) { metrics_helper_->SetWebVREnabled(enabled); - GLThread* thread = static_cast<GLThread*>(gl_thread_.get()); - PostToGlThreadWhenReady( - base::Bind(&VrShellGl::SetWebVrMode, thread->GetVrShellGl(), enabled)); + PostToGlThreadWhenReady(base::Bind(&VrShellGl::SetWebVrMode, + gl_thread_->GetVrShellGl(), enabled)); if (enabled) { html_interface_->SetMode(UiInterface::Mode::WEB_VR); } else { @@ -284,15 +237,6 @@ html_interface_->SetLoadProgress(progress); } -void VrShell::SetGvrPoseForWebVr(const gvr::Mat4f& pose, uint32_t pose_num) { - GLThread* thread = static_cast<GLThread*>(gl_thread_.get()); - if (thread->IsRunning()) { - thread->task_runner()->PostTask( - FROM_HERE, base::Bind(&VrShellGl::SetGvrPoseForWebVr, - thread->GetVrShellGl(), pose, pose_num)); - } -} - void VrShell::SetWebVRRenderSurfaceSize(int width, int height) { // TODO(klausw,crbug.com/655722): Change the GVR render size and set the WebVR // render surface size. @@ -312,18 +256,16 @@ void VrShell::UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds, const gvr::Rectf& right_bounds) { - GLThread* thread = static_cast<GLThread*>(gl_thread_.get()); PostToGlThreadWhenReady(base::Bind(&VrShellGl::UpdateWebVRTextureBounds, - thread->GetVrShellGl(), left_bounds, + gl_thread_->GetVrShellGl(), left_bounds, right_bounds)); } // TODO(mthiesse): Do not expose GVR API outside of GL thread. // It's not thread-safe. gvr::GvrApi* VrShell::gvr_api() { - GLThread* thread = static_cast<GLThread*>(gl_thread_.get()); - if (thread->GetVrShellGlUnsafe()) { - return thread->GetVrShellGlUnsafe()->gvr_api(); + if (gl_thread_->GetVrShellGlUnsafe()) { + return gl_thread_->GetVrShellGlUnsafe()->gvr_api(); } CHECK(false); return nullptr; @@ -335,7 +277,7 @@ } void VrShell::GvrDelegateReady() { - delegate_->SetDelegate(this); + delegate_provider_->SetDelegate(this); } void VrShell::AppButtonPressed() { @@ -345,11 +287,11 @@ // TODO(mthiesse): The page is no longer visible when in menu mode. We // should unfocus or otherwise let it know it's hidden. if (html_interface_->GetMode() == UiInterface::Mode::WEB_VR) { - if (delegate_->device_provider()) { + if (delegate_provider_->device_provider()) { if (html_interface_->GetMenuMode()) { - delegate_->device_provider()->OnDisplayBlur(); + delegate_provider_->device_provider()->OnDisplayBlur(); } else { - delegate_->device_provider()->OnDisplayFocus(); + delegate_provider_->device_provider()->OnDisplayFocus(); } } } @@ -361,18 +303,18 @@ jint width, jint height, jfloat dpr) { TRACE_EVENT0("gpu", "VrShell::ContentPhysicalBoundsChanged"); - GLThread* thread = static_cast<GLThread*>(gl_thread_.get()); PostToGlThreadWhenReady(base::Bind(&VrShellGl::ContentPhysicalBoundsChanged, - thread->GetVrShellGl(), width, height)); + gl_thread_->GetVrShellGl(), width, + height)); content_compositor_->SetWindowBounds(gfx::Size(width, height)); } void VrShell::UIPhysicalBoundsChanged(JNIEnv* env, const JavaParamRef<jobject>& object, jint width, jint height, jfloat dpr) { - GLThread* thread = static_cast<GLThread*>(gl_thread_.get()); PostToGlThreadWhenReady(base::Bind(&VrShellGl::UIPhysicalBoundsChanged, - thread->GetVrShellGl(), width, height)); + gl_thread_->GetVrShellGl(), width, + height)); ui_compositor_->SetWindowBounds(gfx::Size(width, height)); } @@ -381,9 +323,8 @@ } void VrShell::UpdateScene(const base::ListValue* args) { - GLThread* thread = static_cast<GLThread*>(gl_thread_.get()); PostToGlThreadWhenReady(base::Bind(&VrShellGl::UpdateScene, - thread->GetVrShellGl(), + gl_thread_->GetVrShellGl(), base::Passed(args->CreateDeepCopy()))); } @@ -428,18 +369,16 @@ void VrShell::MainFrameWasResized(bool width_changed) { display::Display display = display::Screen::GetScreen() ->GetDisplayNearestWindow(ui_contents_->GetNativeView()); - GLThread* thread = static_cast<GLThread*>(gl_thread_.get()); PostToGlThreadWhenReady( - base::Bind(&VrShellGl::UIBoundsChanged, thread->GetVrShellGl(), + base::Bind(&VrShellGl::UIBoundsChanged, gl_thread_->GetVrShellGl(), display.size().width(), display.size().height())); } void VrShell::ContentFrameWasResized(bool width_changed) { display::Display display = display::Screen::GetScreen() ->GetDisplayNearestWindow(main_contents_->GetNativeView()); - GLThread* thread = static_cast<GLThread*>(gl_thread_.get()); PostToGlThreadWhenReady( - base::Bind(&VrShellGl::ContentBoundsChanged, thread->GetVrShellGl(), + base::Bind(&VrShellGl::ContentBoundsChanged, gl_thread_->GetVrShellGl(), display.size().width(), display.size().height())); } @@ -467,7 +406,21 @@ } void VrShell::ForceExitVr() { - delegate_->ForceExitVr(); + delegate_provider_->ForceExitVr(); +} + +void VrShell::OnVRVsyncProviderRequest( + device::mojom::VRVSyncProviderRequest request) { + PostToGlThreadWhenReady(base::Bind(&VrShellGl::OnRequest, + gl_thread_->GetVrShellGl(), + base::Passed(&request))); +} + +void VrShell::UpdateVSyncInterval(long timebase_nanos, + double interval_seconds) { + PostToGlThreadWhenReady( + base::Bind(&VrShellGl::UpdateVSyncInterval, + gl_thread_->GetVrShellGl(), timebase_nanos, interval_seconds)); } void VrShell::SetContentCssSize(float width, float height, float dpr) { @@ -495,6 +448,39 @@ } } +device::mojom::VRPosePtr VrShell::VRPosePtrFromGvrPose(gvr::Mat4f head_mat, + uint32_t pose_index) { + device::mojom::VRPosePtr pose = device::mojom::VRPose::New(); + + pose->timestamp = base::Time::Now().ToJsTime(); + + pose->poseIndex = pose_index; + pose->orientation.emplace(4); + + gfx::Transform inv_transform( + head_mat.m[0][0], head_mat.m[0][1], head_mat.m[0][2], head_mat.m[0][3], + head_mat.m[1][0], head_mat.m[1][1], head_mat.m[1][2], head_mat.m[1][3], + head_mat.m[2][0], head_mat.m[2][1], head_mat.m[2][2], head_mat.m[2][3], + head_mat.m[3][0], head_mat.m[3][1], head_mat.m[3][2], head_mat.m[3][3]); + + gfx::Transform transform; + if (inv_transform.GetInverse(&transform)) { + gfx::DecomposedTransform decomposed_transform; + gfx::DecomposeTransform(&decomposed_transform, transform); + + pose->orientation.value()[0] = decomposed_transform.quaternion[0]; + pose->orientation.value()[1] = decomposed_transform.quaternion[1]; + pose->orientation.value()[2] = decomposed_transform.quaternion[2]; + pose->orientation.value()[3] = decomposed_transform.quaternion[3]; + + pose->position.emplace(3); + pose->position.value()[0] = decomposed_transform.translate[0]; + pose->position.value()[1] = decomposed_transform.translate[1]; + pose->position.value()[2] = decomposed_transform.translate[2]; + } + + return pose; +} // ---------------------------------------------------------------------------- // Native JNI methods
diff --git a/chrome/browser/android/vr_shell/vr_shell.h b/chrome/browser/android/vr_shell/vr_shell.h index f0e83ec..66b0f53a 100644 --- a/chrome/browser/android/vr_shell/vr_shell.h +++ b/chrome/browser/android/vr_shell/vr_shell.h
@@ -16,12 +16,12 @@ #include "base/single_thread_task_runner.h" #include "content/public/browser/web_contents_observer.h" #include "device/vr/android/gvr/gvr_delegate.h" +#include "device/vr/vr_service.mojom.h" #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr.h" #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_types.h" namespace base { class ListValue; -class Thread; } namespace blink { @@ -40,6 +40,7 @@ class UiInterface; class VrCompositor; +class VrGLThread; class VrInputManager; class VrMetricsHelper; class VrShellDelegate; @@ -101,22 +102,9 @@ static base::WeakPtr<VrShell> GetWeakPtr( const content::WebContents* web_contents); - // TODO(mthiesse): Clean up threading around UiInterface. UiInterface* GetUiInterface(); void OnDomContentsLoaded(); - // device::GvrDelegate implementation - // TODO(mthiesse): Clean up threading around GVR API. These functions are - // called on the UI thread, but use GL thread objects in a non-threadsafe way. - void SetWebVRSecureOrigin(bool secure_origin) override; - void SubmitWebVRFrame() override; - void UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds, - const gvr::Rectf& right_bounds) override; - gvr::GvrApi* gvr_api() override; - void SetGvrPoseForWebVr(const gvr::Mat4f& pose, uint32_t pose_num) override; - void SetWebVRRenderSurfaceSize(int width, int height) override; - gvr::Sizei GetWebVRCompositorSurfaceSize() override; - void SurfacesChanged(jobject content_surface, jobject ui_surface); void GvrDelegateReady(); void AppButtonPressed(); @@ -146,16 +134,32 @@ void ProcessUIGesture(std::unique_ptr<blink::WebInputEvent> event); void ProcessContentGesture(std::unique_ptr<blink::WebInputEvent> event); + static device::mojom::VRPosePtr VRPosePtrFromGvrPose(gvr::Mat4f head_mat, + uint32_t pose_index); + private: ~VrShell() override; void PostToGlThreadWhenReady(const base::Closure& task); - // content::WebContentsObserver implementation. All called on UI thread. + // content::WebContentsObserver implementation. void RenderViewHostChanged(content::RenderViewHost* old_host, content::RenderViewHost* new_host) override; void MainFrameWasResized(bool width_changed) override; void WebContentsDestroyed() override; + // device::GvrDelegate implementation + void SetWebVRSecureOrigin(bool secure_origin) override; + void SubmitWebVRFrame() override; + void UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds, + const gvr::Rectf& right_bounds) override; + gvr::GvrApi* gvr_api() override; + void SetWebVRRenderSurfaceSize(int width, int height) override; + gvr::Sizei GetWebVRCompositorSurfaceSize() override; + void OnVRVsyncProviderRequest( + device::mojom::VRVSyncProviderRequest request) override; + void UpdateVSyncInterval(long timebase_nanos, + double interval_seconds) override; + std::unique_ptr<UiInterface> html_interface_; content::WebContents* main_contents_; @@ -165,7 +169,7 @@ std::unique_ptr<VrWebContentsObserver> vr_web_contents_observer_; - VrShellDelegate* delegate_ = nullptr; + VrShellDelegate* delegate_provider_ = nullptr; base::android::ScopedJavaGlobalRef<jobject> j_vr_shell_; std::unique_ptr<VrInputManager> content_input_manager_; @@ -173,7 +177,7 @@ std::unique_ptr<VrMetricsHelper> metrics_helper_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; - std::unique_ptr<base::Thread> gl_thread_; + std::unique_ptr<VrGLThread> gl_thread_; bool reprojected_rendering_; base::WeakPtrFactory<VrShell> weak_ptr_factory_;
diff --git a/chrome/browser/android/vr_shell/vr_shell_delegate.cc b/chrome/browser/android/vr_shell/vr_shell_delegate.cc index 9a3dd57..2d1a5088 100644 --- a/chrome/browser/android/vr_shell/vr_shell_delegate.cc +++ b/chrome/browser/android/vr_shell/vr_shell_delegate.cc
@@ -5,7 +5,7 @@ #include "chrome/browser/android/vr_shell/vr_shell_delegate.h" #include "base/android/jni_android.h" -#include "chrome/browser/android/vr_shell/vr_shell.h" +#include "chrome/browser/android/vr_shell/non_presenting_gvr_delegate.h" #include "device/vr/android/gvr/gvr_device_provider.h" #include "jni/VrShellDelegate_jni.h" @@ -14,32 +14,8 @@ namespace vr_shell { -// A non presenting delegate for magic window mode. -class GvrNonPresentingDelegate : public device::GvrDelegate { - public: - explicit GvrNonPresentingDelegate(jlong context) { - gvr_api_ = - gvr::GvrApi::WrapNonOwned(reinterpret_cast<gvr_context*>(context)); - } - - virtual ~GvrNonPresentingDelegate() = default; - - // GvrDelegate implementation - void SetWebVRSecureOrigin(bool secure_origin) override {} - void SubmitWebVRFrame() override {} - void UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds, - const gvr::Rectf& right_bounds) override {} - void SetGvrPoseForWebVr(const gvr::Mat4f& pose, - uint32_t pose_index) override {} - void SetWebVRRenderSurfaceSize(int width, int height) override {} - gvr::Sizei GetWebVRCompositorSurfaceSize() override { - return device::kInvalidRenderTargetSize; } - gvr::GvrApi* gvr_api() override { return gvr_api_.get(); } - private: - std::unique_ptr<gvr::GvrApi> gvr_api_; -}; - -VrShellDelegate::VrShellDelegate(JNIEnv* env, jobject obj) { +VrShellDelegate::VrShellDelegate(JNIEnv* env, jobject obj) + : weak_ptr_factory_(this) { j_vr_shell_delegate_.Reset(env, obj); GvrDelegateProvider::SetInstance(this); } @@ -58,12 +34,17 @@ } void VrShellDelegate::SetDelegate(device::GvrDelegate* delegate) { - // TODO(mthiesse): There's no reason for this delegate to be a WeakPtr - // anymore. delegate_ = delegate; + if (non_presenting_delegate_) { + device::mojom::VRVSyncProviderRequest request = + non_presenting_delegate_->OnSwitchToPresentingDelegate(); + if (request.is_pending()) + delegate->OnVRVsyncProviderRequest(std::move(request)); + } if (device_provider_) { device_provider_->OnGvrDelegateReady(delegate_); } + delegate_->UpdateVSyncInterval(timebase_nanos_, interval_seconds_); } void VrShellDelegate::RemoveDelegate() { @@ -73,19 +54,51 @@ delegate_ = nullptr; } -void VrShellDelegate::SetPresentResult(JNIEnv* env, jobject obj, +void VrShellDelegate::SetPresentResult(JNIEnv* env, + const JavaParamRef<jobject>& obj, jboolean result) { CHECK(!present_callback_.is_null()); present_callback_.Run(result); present_callback_.Reset(); } -void VrShellDelegate::DisplayActivate(JNIEnv* env, jobject obj) { +void VrShellDelegate::DisplayActivate(JNIEnv* env, + const JavaParamRef<jobject>& obj) { if (device_provider_) { device_provider_->OnDisplayActivate(); } } +void VrShellDelegate::UpdateVSyncInterval(JNIEnv* env, + const JavaParamRef<jobject>& obj, + jlong timebase_nanos, + jdouble interval_seconds) { + timebase_nanos_ = timebase_nanos; + interval_seconds_ = interval_seconds; + if (delegate_) { + delegate_->UpdateVSyncInterval(timebase_nanos_, + interval_seconds_); + } + if (non_presenting_delegate_) { + non_presenting_delegate_->UpdateVSyncInterval(timebase_nanos_, + interval_seconds_); + } +} + +void VrShellDelegate::OnPause(JNIEnv* env, + const JavaParamRef<jobject>& obj) { + if (non_presenting_delegate_) { + non_presenting_delegate_->Pause(); + } +} + +void VrShellDelegate::OnResume(JNIEnv* env, + const JavaParamRef<jobject>& obj) { + if (non_presenting_delegate_) { + non_presenting_delegate_->Resume(); + } +} + void VrShellDelegate::SetDeviceProvider( device::GvrDeviceProvider* device_provider) { device_provider_ = device_provider; @@ -122,6 +135,15 @@ Java_VrShellDelegate_forceExitVr(env, j_vr_shell_delegate_.obj()); } +base::WeakPtr<VrShellDelegate> VrShellDelegate::GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); +} + +void VrShellDelegate::OnVRVsyncProviderRequest( + device::mojom::VRVSyncProviderRequest request) { + GetNonPresentingDelegate()->OnVRVsyncProviderRequest(std::move(request)); +} + device::GvrDelegate* VrShellDelegate::GetNonPresentingDelegate() { if (!non_presenting_delegate_) { JNIEnv* env = AttachCurrentThread(); @@ -130,9 +152,11 @@ if (!context) return nullptr; - non_presenting_delegate_.reset(new GvrNonPresentingDelegate(context)); + non_presenting_delegate_.reset(new NonPresentingGvrDelegate(context)); + non_presenting_delegate_->UpdateVSyncInterval(timebase_nanos_, + interval_seconds_); } - return static_cast<GvrNonPresentingDelegate*>(non_presenting_delegate_.get()); + return non_presenting_delegate_.get(); } void VrShellDelegate::DestroyNonPresentingDelegate() {
diff --git a/chrome/browser/android/vr_shell/vr_shell_delegate.h b/chrome/browser/android/vr_shell/vr_shell_delegate.h index 3731bb2..8067a41 100644 --- a/chrome/browser/android/vr_shell/vr_shell_delegate.h +++ b/chrome/browser/android/vr_shell/vr_shell_delegate.h
@@ -8,6 +8,7 @@ #include <jni.h> #include "base/android/jni_weak_ref.h" +#include "base/callback.h" #include "base/macros.h" #include "device/vr/android/gvr/gvr_delegate.h" @@ -17,22 +18,35 @@ namespace vr_shell { +class NonPresentingGvrDelegate; + class VrShellDelegate : public device::GvrDelegateProvider { public: VrShellDelegate(JNIEnv* env, jobject obj); - virtual ~VrShellDelegate(); + ~VrShellDelegate() override; static VrShellDelegate* GetNativeDelegate(JNIEnv* env, jobject jdelegate); void SetDelegate(device::GvrDelegate* delegate); void RemoveDelegate(); - void SetPresentResult(JNIEnv* env, jobject obj, jboolean result); - void DisplayActivate(JNIEnv* env, jobject obj); + void SetPresentResult(JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + jboolean result); + void DisplayActivate(JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj); + void UpdateVSyncInterval(JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + jlong timebase_nanos, jdouble interval_seconds); + void OnPause(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); + void OnResume(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); void ForceExitVr(); device::GvrDeviceProvider* device_provider() { return device_provider_; } + void OnVRVsyncProviderRequest(device::mojom::VRVSyncProviderRequest request); + base::WeakPtr<VrShellDelegate> GetWeakPtr(); + private: // device::GvrDelegateProvider implementation void SetDeviceProvider(device::GvrDeviceProvider* device_provider) override; void RequestWebVRPresent(const base::Callback<void(bool)>& callback) override; @@ -41,12 +55,15 @@ void DestroyNonPresentingDelegate() override; void SetListeningForActivate(bool listening) override; - private: - std::unique_ptr<device::GvrDelegate> non_presenting_delegate_; + std::unique_ptr<NonPresentingGvrDelegate> non_presenting_delegate_; base::android::ScopedJavaGlobalRef<jobject> j_vr_shell_delegate_; device::GvrDeviceProvider* device_provider_ = nullptr; device::GvrDelegate* delegate_ = nullptr; base::Callback<void(bool)> present_callback_; + long timebase_nanos_ = 0; + double interval_seconds_ = 0; + + base::WeakPtrFactory<VrShellDelegate> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(VrShellDelegate); };
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.cc b/chrome/browser/android/vr_shell/vr_shell_gl.cc index f9a0af1..501a811 100644 --- a/chrome/browser/android/vr_shell/vr_shell_gl.cc +++ b/chrome/browser/android/vr_shell/vr_shell_gl.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/android/vr_shell/vr_shell_gl.h" +#include <utility> + #include "base/android/jni_android.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" @@ -14,10 +16,11 @@ #include "chrome/browser/android/vr_shell/vr_gl_util.h" #include "chrome/browser/android/vr_shell/vr_math.h" #include "chrome/browser/android/vr_shell/vr_shell.h" +#include "chrome/browser/android/vr_shell/vr_shell_delegate.h" #include "chrome/browser/android/vr_shell/vr_shell_renderer.h" +#include "device/vr/android/gvr/gvr_device.h" #include "third_party/WebKit/public/platform/WebInputEvent.h" #include "third_party/WebKit/public/platform/WebMouseEvent.h" -#include "ui/gfx/vsync_provider.h" #include "ui/gl/android/scoped_java_surface.h" #include "ui/gl/android/surface_texture.h" #include "ui/gl/gl_bindings.h" @@ -28,7 +31,8 @@ namespace vr_shell { namespace { -// Constant taken from treasure_hunt demo. +// TODO(mthiesse): If gvr::PlatformInfo().GetPosePredictionTime() is ever +// exposed, use that instead (it defaults to 50ms on most platforms). static constexpr long kPredictionTimeWithoutVsyncNanos = 50000000; static constexpr float kZNear = 0.1f; @@ -140,46 +144,16 @@ VIEWER_TYPE_MAX, }; -int GetPixelEncodedPoseIndexByte() { - TRACE_EVENT0("gpu", "VrShellGl::GetPixelEncodedPoseIndex"); - // Read the pose index encoded in a bottom left pixel as color values. - // See also third_party/WebKit/Source/modules/vr/VRDisplay.cpp which - // encodes the pose index, and device/vr/android/gvr/gvr_device.cc - // which tracks poses. Returns the low byte (0..255) if valid, or -1 - // if not valid due to bad magic number. - uint8_t pixels[4]; - // Assume we're reading from the framebuffer we just wrote to. - // That's true currently, we may need to use glReadBuffer(GL_BACK) - // or equivalent if the rendering setup changes in the future. - glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Check for the magic number written by VRDevice.cpp on submit. - // This helps avoid glitches from garbage data in the render - // buffer that can appear during initialization or resizing. These - // often appear as flashes of all-black or all-white pixels. - if (pixels[1] == kWebVrPosePixelMagicNumbers[0] && - pixels[2] == kWebVrPosePixelMagicNumbers[1]) { - // Pose is good. - return pixels[0]; - } - VLOG(1) << "WebVR: reject decoded pose index " << (int)pixels[0] << - ", bad magic number " << (int)pixels[1] << ", " << (int)pixels[2]; - return -1; -} - int64_t TimeInMicroseconds() { return std::chrono::duration_cast<std::chrono::microseconds>( std::chrono::steady_clock::now().time_since_epoch()).count(); } -void WaitForSwapAck(const base::Closure& callback, gfx::SwapResult result) { - callback.Run(); -} - } // namespace VrShellGl::VrShellGl( const base::WeakPtr<VrShell>& weak_vr_shell, + const base::WeakPtr<VrShellDelegate>& delegate_provider, scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, gvr_context* gvr_api, bool initially_web_vr, @@ -187,22 +161,26 @@ : web_vr_mode_(initially_web_vr), surfaceless_rendering_(reprojected_rendering), task_runner_(base::ThreadTaskRunnerHandle::Get()), + binding_(this), weak_vr_shell_(weak_vr_shell), + delegate_provider_(delegate_provider), main_thread_task_runner_(std::move(main_thread_task_runner)), weak_ptr_factory_(this) { GvrInit(gvr_api); } VrShellGl::~VrShellGl() { - draw_task_.Cancel(); + vsync_task_.Cancel(); + if (!callback_.is_null()) + callback_.Run(nullptr, base::TimeDelta()); + if (binding_.is_bound()) { + main_thread_task_runner_->PostTask(FROM_HERE, base::Bind( + &VrShellDelegate::OnVRVsyncProviderRequest, delegate_provider_, + base::Passed(binding_.Unbind()))); + } } void VrShellGl::Initialize() { - gvr::Mat4f identity; - SetIdentityM(identity); - webvr_head_pose_.resize(kPoseRingBufferSize, identity); - webvr_head_pose_valid_.resize(kPoseRingBufferSize, false); - scene_.reset(new UiScene); if (surfaceless_rendering_) { @@ -245,16 +223,6 @@ return; } - // TODO(mthiesse): We don't appear to have a VSync provider ever here. This is - // sort of okay, because the GVR swap chain will block if we render too fast, - // but we should address this properly. - if (surface_->GetVSyncProvider()) { - surface_->GetVSyncProvider()->GetVSyncParameters(base::Bind( - &VrShellGl::UpdateVSyncParameters, weak_ptr_factory_.GetWeakPtr())); - } else { - LOG(ERROR) << "No VSync Provider"; - } - unsigned int textures[2]; glGenTextures(2, textures); ui_texture_id_ = textures[0]; @@ -281,8 +249,8 @@ InitializeRenderer(); - draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this))); - ScheduleNextDrawFrame(); + vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this))); + OnVSync(); ready_to_draw_ = true; } @@ -293,6 +261,43 @@ void VrShellGl::OnContentFrameAvailable() { content_surface_texture_->UpdateTexImage(); + received_frame_ = true; +} + +bool VrShellGl::GetPixelEncodedPoseIndexByte(int* pose_index) { + TRACE_EVENT0("gpu", "VrShellGl::GetPixelEncodedPoseIndex"); + if (!received_frame_) { + *pose_index = last_pose_; + return true; + } + received_frame_ = false; + + // Read the pose index encoded in a bottom left pixel as color values. + // See also third_party/WebKit/Source/modules/vr/VRDisplay.cpp which + // encodes the pose index, and device/vr/android/gvr/gvr_device.cc + // which tracks poses. Returns the low byte (0..255) if valid, or -1 + // if not valid due to bad magic number. + uint8_t pixels[4]; + // Assume we're reading from the framebuffer we just wrote to. + // That's true currently, we may need to use glReadBuffer(GL_BACK) + // or equivalent if the rendering setup changes in the future. + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Check for the magic number written by VRDevice.cpp on submit. + // This helps avoid glitches from garbage data in the render + // buffer that can appear during initialization or resizing. These + // often appear as flashes of all-black or all-white pixels. + if (pixels[1] == kWebVrPosePixelMagicNumbers[0] && + pixels[2] == kWebVrPosePixelMagicNumbers[1]) { + // Pose is good. + *pose_index = pixels[0]; + last_pose_ = pixels[0]; + return true; + } + VLOG(1) << "WebVR: reject decoded pose index " << (int)pixels[0] + << ", bad magic number " << (int)pixels[1] << ", " + << (int)pixels[2]; + return false; } void VrShellGl::GvrInit(gvr_context* gvr_api) { @@ -322,12 +327,12 @@ // surface, but store it separately to avoid future confusion. // TODO(klausw,crbug.com/655722): remove this. webvr_texture_id_ = content_texture_id_; - // Out of paranoia, explicitly reset the "pose valid" flags to false - // from the GL thread. The constructor ran in the UI thread. - // TODO(klausw,crbug.com/655722): remove this. - webvr_head_pose_valid_.assign(kPoseRingBufferSize, false); gvr_api_->InitializeGl(); + webvr_head_pose_.assign(kPoseRingBufferSize, + gvr_api_->GetHeadSpaceFromStartSpaceRotation( + gvr::GvrApi::GetTimePointNow())); + std::vector<gvr::BufferSpec> specs; // For kFramePrimaryBuffer (primary VrShell and WebVR content) specs.push_back(gvr_api_->CreateBufferSpec()); @@ -584,36 +589,41 @@ base::Bind(target, weak_vr_shell_, base::Passed(std::move(event)))); } -void VrShellGl::SetGvrPoseForWebVr(const gvr::Mat4f& pose, uint32_t pose_num) { - webvr_head_pose_[pose_num % kPoseRingBufferSize] = pose; - webvr_head_pose_valid_[pose_num % kPoseRingBufferSize] = true; -} - -bool VrShellGl::WebVrPoseByteIsValid(int pose_index_byte) { - if (pose_index_byte < 0) { - return false; - } - if (!webvr_head_pose_valid_[pose_index_byte % kPoseRingBufferSize]) { - VLOG(1) << "WebVR: reject decoded pose index " << pose_index_byte << - ", not a valid pose"; - return false; - } - return true; -} - void VrShellGl::DrawFrame() { TRACE_EVENT0("gpu", "VrShellGl::DrawFrame"); + // Reset the viewport list to just the pair of viewports for the // primary buffer each frame. Head-locked viewports get added by // DrawVrShell if needed. buffer_viewport_list_->SetToRecommendedBufferViewports(); gvr::Frame frame = swap_chain_->AcquireFrame(); - gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); - target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; + if (!frame.is_valid()) { + return; + } + frame.BindBuffer(kFramePrimaryBuffer); + if (web_vr_mode_) { + DrawWebVr(); + } - gvr::Mat4f head_pose = - gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); + int pose_index; + gvr::Mat4f head_pose; + + // When using async reprojection, we need to know which pose was used in + // the WebVR app for drawing this frame. Due to unknown amounts of + // buffering in the compositor and SurfaceTexture, we read the pose number + // from a corner pixel. There's no point in doing this for legacy + // distortion rendering since that doesn't need a pose, and reading back + // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop + // doing this once we have working no-compositor rendering for WebVR. + if (web_vr_mode_ && gvr_api_->GetAsyncReprojectionEnabled() && + GetPixelEncodedPoseIndexByte(&pose_index)) { + head_pose = webvr_head_pose_[pose_index % kPoseRingBufferSize]; + } else { + gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); + target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; + head_pose = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); + } gvr::Vec3f position = GetTranslation(head_pose); if (position.x == 0.0f && position.y == 0.0f && position.z == 0.0f) { @@ -625,64 +635,21 @@ gvr_api_->ApplyNeckModel(head_pose, 1.0f); } - frame.BindBuffer(kFramePrimaryBuffer); - // Update the render position of all UI elements (including desktop). const float screen_tilt = kDesktopScreenTiltDefault * M_PI / 180.0f; scene_->UpdateTransforms(screen_tilt, TimeInMicroseconds()); UpdateController(GetForwardVector(head_pose)); - if (web_vr_mode_) { - DrawWebVr(); - - // When using async reprojection, we need to know which pose was used in - // the WebVR app for drawing this frame. Due to unknown amounts of - // buffering in the compositor and SurfaceTexture, we read the pose number - // from a corner pixel. There's no point in doing this for legacy - // distortion rendering since that doesn't need a pose, and reading back - // pixels is an expensive operation. TODO(klausw,crbug.com/655722): stop - // doing this once we have working no-compositor rendering for WebVR. - if (gvr_api_->GetAsyncReprojectionEnabled()) { - int pose_index_byte = GetPixelEncodedPoseIndexByte(); - if (WebVrPoseByteIsValid(pose_index_byte)) { - // We have a valid pose, use it for reprojection. - webvr_left_viewport_->SetReprojection(GVR_REPROJECTION_FULL); - webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_FULL); - head_pose = webvr_head_pose_[pose_index_byte % kPoseRingBufferSize]; - // We can't mark the used pose as invalid since unfortunately - // we have to reuse them. The compositor will re-submit stale - // frames on vsync, and we can't tell that this has happened - // until we've read the pose index from it, and at that point - // it's too late to skip rendering. - } else { - // If we don't get a valid frame ID back we shouldn't attempt - // to reproject by an invalid matrix, so turn off reprojection - // instead. Invalid poses can permanently break reprojection - // for this GVR instance: http://crbug.com/667327 - webvr_left_viewport_->SetReprojection(GVR_REPROJECTION_NONE); - webvr_right_viewport_->SetReprojection(GVR_REPROJECTION_NONE); - } - } - } - DrawVrShell(head_pose, frame); frame.Unbind(); frame.Submit(*buffer_viewport_list_, head_pose); // No need to swap buffers for surfaceless rendering. - if (surfaceless_rendering_) { - ScheduleNextDrawFrame(); - return; - } - - if (surface_->SupportsAsyncSwap()) { - surface_->SwapBuffersAsync(base::Bind(&WaitForSwapAck, base::Bind( - &VrShellGl::ScheduleNextDrawFrame, weak_ptr_factory_.GetWeakPtr()))); - } else { + if (!surfaceless_rendering_) { + // TODO(mthiesse): Support asynchronous SwapBuffers. surface_->SwapBuffers(); - ScheduleNextDrawFrame(); } } @@ -915,7 +882,7 @@ } void VrShellGl::OnPause() { - draw_task_.Cancel(); + vsync_task_.Cancel(); controller_->OnPause(); gvr_api_->PauseTracking(); } @@ -925,8 +892,8 @@ gvr_api_->ResumeTracking(); controller_->OnResume(); if (ready_to_draw_) { - draw_task_.Reset(base::Bind(&VrShellGl::DrawFrame, base::Unretained(this))); - ScheduleNextDrawFrame(); + vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this))); + OnVSync(); } } @@ -973,25 +940,56 @@ return weak_ptr_factory_.GetWeakPtr(); } -void VrShellGl::UpdateVSyncParameters(const base::TimeTicks timebase, - const base::TimeDelta interval) { - vsync_timebase_ = timebase; - vsync_interval_ = interval; -} - -void VrShellGl::ScheduleNextDrawFrame() { +void VrShellGl::OnVSync() { base::TimeTicks now = base::TimeTicks::Now(); base::TimeTicks target; - if (vsync_interval_.is_zero()) { - target = now; - } else { - target = now + vsync_interval_; - int64_t intervals = (target - vsync_timebase_) / vsync_interval_; - target = vsync_timebase_ + intervals * vsync_interval_; - } + // Don't send VSyncs until we have a timebase/interval. + if (vsync_interval_.is_zero()) + return; + target = now + vsync_interval_; + int64_t intervals = (target - vsync_timebase_) / vsync_interval_; + target = vsync_timebase_ + intervals * vsync_interval_; + task_runner_->PostDelayedTask(FROM_HERE, vsync_task_.callback(), + target - now); - task_runner_->PostDelayedTask(FROM_HERE, draw_task_.callback(), target - now); + base::TimeDelta time = intervals * vsync_interval_; + if (!callback_.is_null()) { + callback_.Run(GetPose(), time); + callback_.Reset(); + } else { + pending_vsync_ = true; + pending_time_ = time; + } + DrawFrame(); +} + +void VrShellGl::OnRequest(device::mojom::VRVSyncProviderRequest request) { + binding_.Close(); + binding_.Bind(std::move(request)); +} + +void VrShellGl::GetVSync(const GetVSyncCallback& callback) { + if (!pending_vsync_) { + if (!callback_.is_null()) { + mojo::ReportBadMessage("Requested VSync before waiting for response to " + "previous request."); + return; + } + callback_ = callback; + return; + } + pending_vsync_ = false; + callback.Run(GetPose(), pending_time_); +} + +void VrShellGl::UpdateVSyncInterval(long timebase_nanos, + double interval_seconds) { + vsync_timebase_ = base::TimeTicks(); + vsync_timebase_ += base::TimeDelta::FromMicroseconds(timebase_nanos / 1000); + vsync_interval_ = base::TimeDelta::FromSecondsD(interval_seconds); + vsync_task_.Reset(base::Bind(&VrShellGl::OnVSync, base::Unretained(this))); + OnVSync(); } void VrShellGl::ForceExitVr() { @@ -1003,4 +1001,20 @@ scene_->HandleCommands(std::move(commands), TimeInMicroseconds()); } +device::mojom::VRPosePtr VrShellGl::GetPose() { + TRACE_EVENT0("input", "VrShellGl::GetPose"); + + gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); + target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; + + gvr::Mat4f head_mat = + gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); + head_mat = gvr_api_->ApplyNeckModel(head_mat, 1.0f); + + uint32_t pose_index = pose_index_++; + webvr_head_pose_[pose_index % kPoseRingBufferSize] = head_mat; + + return VrShell::VRPosePtrFromGvrPose(head_mat, pose_index); +} + } // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.h b/chrome/browser/android/vr_shell/vr_shell_gl.h index f38164b..25151e99 100644 --- a/chrome/browser/android/vr_shell/vr_shell_gl.h +++ b/chrome/browser/android/vr_shell/vr_shell_gl.h
@@ -13,6 +13,8 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "device/vr/android/gvr/gvr_delegate.h" +#include "device/vr/vr_service.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr.h" #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_types.h" #include "ui/gfx/native_widget_types.h" @@ -37,12 +39,13 @@ class UiScene; class VrController; class VrShell; +class VrShellDelegate; class VrShellRenderer; struct ContentRectangle; // This class manages all GLThread owned objects and GL rendering for VrShell. // It is not threadsafe and must only be used on the GL thread. -class VrShellGl { +class VrShellGl : public device::mojom::VRVSyncProvider { public: enum class InputTarget { NONE = 0, @@ -52,17 +55,16 @@ VrShellGl( const base::WeakPtr<VrShell>& weak_vr_shell, + const base::WeakPtr<VrShellDelegate>& delegate_provider, scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, gvr_context* gvr_api, bool initially_web_vr, bool reprojected_rendering); - ~VrShellGl(); + ~VrShellGl() override; void Initialize(); void InitializeGl(gfx::AcceleratedWidget window); - void DrawFrame(); - void OnTriggerEvent(); void OnPause(); void OnResume(); @@ -82,9 +84,14 @@ void UpdateScene(std::unique_ptr<base::ListValue> commands); + void UpdateVSyncInterval(long timebase_nanos, double interval_seconds); + + void OnRequest(device::mojom::VRVSyncProviderRequest request); + private: void GvrInit(gvr_context* gvr_api); void InitializeRenderer(); + void DrawFrame(); void DrawVrShell(const gvr::Mat4f& head_pose, gvr::Frame &frame); void DrawUiView(const gvr::Mat4f* head_pose, const std::vector<const ContentRectangle*>& elements, @@ -104,13 +111,17 @@ void OnUIFrameAvailable(); void OnContentFrameAvailable(); + bool GetPixelEncodedPoseIndexByte(int* pose_index); - void UpdateVSyncParameters(const base::TimeTicks timebase, - const base::TimeDelta interval); - void ScheduleNextDrawFrame(); + void OnVSync(); + + // VRVSyncProvider + void GetVSync(const GetVSyncCallback& callback) override; void ForceExitVr(); + device::mojom::VRPosePtr GetPose(); + // samplerExternalOES texture data for UI content image. int ui_texture_id_ = 0; // samplerExternalOES texture data for main content image. @@ -159,7 +170,6 @@ // current backlog of poses which is 2-3 frames. static constexpr int kPoseRingBufferSize = 8; std::vector<gvr::Mat4f> webvr_head_pose_; - std::vector<bool> webvr_head_pose_valid_; int webvr_texture_id_ = 0; bool web_vr_mode_; bool ready_to_draw_ = false; @@ -168,13 +178,23 @@ std::unique_ptr<VrController> controller_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - base::CancelableClosure draw_task_; + base::CancelableClosure vsync_task_; base::TimeTicks vsync_timebase_; base::TimeDelta vsync_interval_; + base::TimeDelta pending_time_; + bool pending_vsync_ = false; + GetVSyncCallback callback_; + bool received_frame_ = false; + mojo::Binding<device::mojom::VRVSyncProvider> binding_; + base::WeakPtr<VrShell> weak_vr_shell_; + base::WeakPtr<VrShellDelegate> delegate_provider_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; + uint32_t pose_index_ = 1; + int last_pose_ = 0; + base::WeakPtrFactory<VrShellGl> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(VrShellGl);
diff --git a/chrome/browser/resources/bluetooth_internals/characteristic_list.js b/chrome/browser/resources/bluetooth_internals/characteristic_list.js index 7fb7708e..17f4ebab 100644 --- a/chrome/browser/resources/bluetooth_internals/characteristic_list.js +++ b/chrome/browser/resources/bluetooth_internals/characteristic_list.js
@@ -113,7 +113,13 @@ /** @private {!value_control.ValueControl} */ this.valueControl_ = new value_control.ValueControl(); - this.valueControl_.load(this.deviceAddress_, this.serviceId_, this.info); + + this.valueControl_.load({ + deviceAddress: this.deviceAddress_, + serviceId: this.serviceId_, + characteristicId: this.info.id, + properties: this.info.properties, + }); this.valueControl_.setValue(this.info.last_known_value); /** @private {!descriptor_list.DescriptorList} */
diff --git a/chrome/browser/resources/bluetooth_internals/descriptor_list.js b/chrome/browser/resources/bluetooth_internals/descriptor_list.js index 3b026c30..13d646b1 100644 --- a/chrome/browser/resources/bluetooth_internals/descriptor_list.js +++ b/chrome/browser/resources/bluetooth_internals/descriptor_list.js
@@ -26,13 +26,23 @@ * properties, 'id' and 'uuid' within the DescriptorInfo object. * @constructor * @param {!interfaces.BluetoothDevice.DescriptorInfo} descriptorInfo + * @param {string} deviceAddress + * @param {string} serviceId + * @param {string} characteristicId */ - function DescriptorListItem(descriptorInfo) { + function DescriptorListItem( + descriptorInfo, deviceAddress, serviceId, characteristicId) { var listItem = new ExpandableListItem(); listItem.__proto__ = DescriptorListItem.prototype; /** @type {!interfaces.BluetoothDevice.DescriptorInfo} */ listItem.info = descriptorInfo; + /** @private {string} */ + listItem.deviceAddress_ = deviceAddress; + /** @private {string} */ + listItem.serviceId_ = serviceId; + /** @private {string} */ + listItem.characteristicId_ = characteristicId; listItem.decorate(); return listItem; @@ -57,6 +67,15 @@ 'uuid.uuid': this.info.uuid.uuid, }); + /** @private {!value_control.ValueControl} */ + this.valueControl_ = new value_control.ValueControl(); + this.valueControl_.load({ + deviceAddress: this.deviceAddress_, + serviceId: this.serviceId_, + characteristicId: this.characteristicId_, + descriptorId: this.info.id, + }); + // Create content for display in brief content container. var descriptorHeaderText = document.createElement('div'); descriptorHeaderText.textContent = 'Descriptor:'; @@ -77,10 +96,15 @@ descriptorDiv.classList.add('flex'); descriptorDiv.appendChild(this.descriptorFieldSet_); + var valueHeader = document.createElement('h4'); + valueHeader.textContent = 'Value'; + var infoDiv = document.createElement('div'); infoDiv.classList.add('info-container'); infoDiv.appendChild(descriptorInfoHeader); infoDiv.appendChild(descriptorDiv); + infoDiv.appendChild(valueHeader); + infoDiv.appendChild(this.valueControl_); this.expandedContent_.appendChild(infoDiv); }, @@ -99,6 +123,12 @@ decorate: function() { ExpandableList.prototype.decorate.call(this); + /** @private {?string} */ + this.deviceAddress_ = null; + /** @private {?string} */ + this.serviceId_ = null; + /** @private {?string} */ + this.characteristicId_ = null; /** @private {boolean} */ this.descriptorsRequested_ = false; @@ -108,7 +138,8 @@ /** @override */ createItem: function(data) { - return new DescriptorListItem(data); + return new DescriptorListItem( + data, this.deviceAddress_, this.serviceId_, this.characteristicId_); }, /** @@ -124,6 +155,9 @@ if (this.descriptorsRequested_ || !this.isSpinnerShowing()) return; + this.deviceAddress_ = deviceAddress; + this.serviceId_ = serviceId; + this.characteristicId_ = characteristicId; this.descriptorsRequested_ = true; device_broker.connectToDevice(deviceAddress)
diff --git a/chrome/browser/resources/bluetooth_internals/value_control.js b/chrome/browser/resources/bluetooth_internals/value_control.js index 2fccbb8..bd5673f 100644 --- a/chrome/browser/resources/bluetooth_internals/value_control.js +++ b/chrome/browser/resources/bluetooth_internals/value_control.js
@@ -10,6 +10,16 @@ /** @const */ var Snackbar = snackbar.Snackbar; /** @const */ var SnackbarType = snackbar.SnackbarType; + /** @typedef {{ + * deviceAddress: string, + * serviceId: string, + * characteristicId: string, + * descriptorId: (string|undefined) + * properties: (number|undefined) + * }} + */ + var ValueLoadOptions; + /** @enum {string} */ var ValueDataType = { HEXADECIMAL: 'Hexadecimal', @@ -207,8 +217,12 @@ this.deviceAddress_ = null; /** @private {?string} */ this.serviceId_ = null; - /** @private {?interfaces.BluetoothDevice.CharacteristicInfo} */ - this.characteristicInfo_ = null; + /** @private {?string} */ + this.characteristicId_ = null; + /** @private {?string} */ + this.descriptorId_ = null; + /** @private {number} */ + this.properties_ = Number.MAX_SAFE_INTEGER; this.unavailableMessage_ = document.createElement('h3'); this.unavailableMessage_.textContent = 'Value cannot be read or written.'; @@ -257,17 +271,18 @@ /** * Sets the settings used by the value control and redraws the control to - * match the read/write settings provided in - * |characteristicInfo.properties|. - * @param {string} deviceAddress - * @param {string} serviceId - * @param {!interfaces.BluetoothDevice.CharacteristicInfo} - * characteristicInfo + * match the read/write settings in |options.properties|. If properties + * are not provided, no restrictions on reading/writing are applied. + * @param {!ValueLoadOptions} options */ - load: function(deviceAddress, serviceId, characteristicInfo) { - this.deviceAddress_ = deviceAddress; - this.serviceId_ = serviceId; - this.characteristicInfo_ = characteristicInfo; + load: function(options) { + this.deviceAddress_ = options.deviceAddress; + this.serviceId_ = options.serviceId; + this.characteristicId_ = options.characteristicId; + this.descriptorId_ = options.descriptorId; + + if (options.properties) + this.properties_ = options.properties; this.redraw(); }, @@ -277,10 +292,10 @@ * availability of reads and writes and the current cached value. */ redraw: function() { - this.readBtn_.hidden = (this.characteristicInfo_.properties & - interfaces.BluetoothDevice.Property.READ) === 0; - this.writeBtn_.hidden = (this.characteristicInfo_.properties & - interfaces.BluetoothDevice.Property.WRITE) === 0; + this.readBtn_.hidden = + (this.properties_ & interfaces.BluetoothDevice.Property.READ) === 0; + this.writeBtn_.hidden = + (this.properties_ & interfaces.BluetoothDevice.Property.WRITE) === 0; var isAvailable = !this.readBtn_.hidden || !this.writeBtn_.hidden; this.unavailableMessage_.hidden = isAvailable; @@ -319,15 +334,21 @@ /** * Called when the read button is pressed. Connects to the device and * retrieves the current value of the characteristic in the |service_id| - * with id |characteristic_id| + * with id |characteristic_id|. If |descriptor_id| is defined, the + * descriptor value with |descriptor_id| is read instead. * @private */ readValue_: function() { this.readBtn_.disabled = true; device_broker.connectToDevice(this.deviceAddress_).then(function(device) { + if (this.descriptorId_) { + return device.readValueForDescriptor( + this.serviceId_, this.characteristicId_, this.descriptorId_); + } + return device.readValueForCharacteristic( - this.serviceId_, this.characteristicInfo_.id); + this.serviceId_, this.characteristicId_); }.bind(this)).then(function(response) { this.readBtn_.disabled = false; @@ -347,17 +368,23 @@ /** * Called when the write button is pressed. Connects to the device and - * retrieves the current value of the characteristic in the |service_id| - * with id |characteristic_id| + * retrieves the current value of the characteristic in the + * |service_id| with id |characteristic_id|. If |descriptor_id| is defined, + * the descriptor value with |descriptor_id| is written instead. * @private */ writeValue_: function() { this.writeBtn_.disabled = true; device_broker.connectToDevice(this.deviceAddress_).then(function(device) { + if (this.descriptorId_) { + return device.writeValueForDescriptor( + this.serviceId_, this.characteristicId_, this.descriptorId_, + this.value_.getArray()); + } + return device.writeValueForCharacteristic( - this.serviceId_, this.characteristicInfo_.id, - this.value_.getArray()); + this.serviceId_, this.characteristicId_, this.value_.getArray()); }.bind(this)).then(function(response) { this.writeBtn_.disabled = false;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 9cba78d..9e6ae1f 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1514,6 +1514,8 @@ "views/sync/bubble_sync_promo_view.h", "views/task_manager_view.cc", "views/task_manager_view.h", + "views/update_recommended_message_box.cc", + "views/update_recommended_message_box.h", "views/website_settings/chosen_object_row.cc", "views/website_settings/chosen_object_row.h", "views/website_settings/chosen_object_row_observer.h", @@ -1889,8 +1891,6 @@ "views/translate/translate_bubble_view.h", "views/translate/translate_icon_view.cc", "views/translate/translate_icon_view.h", - "views/update_recommended_message_box.cc", - "views/update_recommended_message_box.h", "views/validation_message_bubble_view.cc", "views/validation_message_bubble_view.h", "views/website_settings/chooser_bubble_ui_view.cc",
diff --git a/chrome/browser/ui/browser_dialogs.h b/chrome/browser/ui/browser_dialogs.h index 58befd4..66d37aa 100644 --- a/chrome/browser/ui/browser_dialogs.h +++ b/chrome/browser/ui/browser_dialogs.h
@@ -137,6 +137,9 @@ task_manager::TaskManagerTableModel* ShowTaskManagerViews(Browser* browser); void HideTaskManagerViews(); +// Show the Views "Chrome Update" dialog. +void ShowUpdateChromeDialogViews(gfx::NativeWindow parent); + #endif // OS_MACOSX #if defined(TOOLKIT_VIEWS)
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm index b539d82..751979ed 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
@@ -24,6 +24,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_command_controller.h" #include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window_state.h" #import "chrome/browser/ui/cocoa/autofill/save_card_bubble_view_bridge.h" @@ -66,6 +67,7 @@ #include "extensions/browser/extension_system.h" #include "extensions/common/constants.h" #include "ui/base/l10n/l10n_util_mac.h" +#include "ui/base/material_design/material_design_controller.h" #include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/geometry/rect.h" @@ -525,7 +527,11 @@ } void BrowserWindowCocoa::ShowUpdateChromeDialog() { - restart_browser::RequestRestart(window()); + if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { + chrome::ShowUpdateChromeDialogViews(GetNativeWindow()); + } else { + restart_browser::RequestRestart(window()); + } } void BrowserWindowCocoa::ShowBookmarkBubble(const GURL& url,
diff --git a/chrome/browser/ui/update_chrome_dialog_browsertest.cc b/chrome/browser/ui/update_chrome_dialog_browsertest.cc new file mode 100644 index 0000000..eb57550b --- /dev/null +++ b/chrome/browser/ui/update_chrome_dialog_browsertest.cc
@@ -0,0 +1,41 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/test/test_browser_dialog.h" +#include "ui/base/ui_base_switches.h" + +class UpdateRecommendedDialogTest : public DialogBrowserTest { + public: + UpdateRecommendedDialogTest() {} + + // DialogBrowserTest: + void ShowDialog(const std::string& name) override { + InProcessBrowserTest::browser()->window()->ShowUpdateChromeDialog(); + } + + // content::BrowserTestBase: + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitch(switches::kExtendMdToSecondaryUi); + } + + private: + DISALLOW_COPY_AND_ASSIGN(UpdateRecommendedDialogTest); +}; + +#if !defined(OS_MACOSX) +// Initially disabled except on Mac due to http://crbug.com/683808. +#define MAYBE_InvokeDialog_default DISABLED_InvokeDialog_default +#else +#define MAYBE_InvokeDialog_default InvokeDialog_default +#endif + +// Test that calls ShowDialog("default"). Interactive when run via +// browser_tests --gtest_filter=BrowserDialogTest.Invoke --interactive +// --dialog=UpdateRecommendedDialogTest.InvokeDialog_default +IN_PROC_BROWSER_TEST_F(UpdateRecommendedDialogTest, + MAYBE_InvokeDialog_default) { + RunDialog(); +}
diff --git a/chrome/browser/ui/views/browser_dialogs_views_mac.cc b/chrome/browser/ui/views/browser_dialogs_views_mac.cc index 276b2fa..984f41ce 100644 --- a/chrome/browser/ui/views/browser_dialogs_views_mac.cc +++ b/chrome/browser/ui/views/browser_dialogs_views_mac.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h" #include "chrome/browser/ui/views/content_setting_bubble_contents.h" #include "chrome/browser/ui/views/task_manager_view.h" +#include "chrome/browser/ui/views/update_recommended_message_box.h" #include "chrome/browser/ui/views/website_settings/website_settings_popup_view.h" // This file provides definitions of desktop browser dialog-creation methods for @@ -78,4 +79,8 @@ views::BubbleDialogDelegateView::CreateBubble(contents)->Show(); } +void ShowUpdateChromeDialogViews(gfx::NativeWindow parent) { + UpdateRecommendedMessageBox::Show(parent); +} + } // namespace chrome
diff --git a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc b/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc index 237cb79..fcd76e36 100644 --- a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc +++ b/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc
@@ -40,6 +40,7 @@ #include "chromeos/network/network_state_handler_observer.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/url_data_source.h" #include "content/public/browser/web_contents.h" @@ -628,26 +629,20 @@ content::WebContentsObserver::Observe(web_ui->GetWebContents()); } -void MobileSetupUI::DidCommitProvisionalLoadForFrame( - content::RenderFrameHost* render_frame_host, - const GURL& url, - ui::PageTransition transition_type) { - if (render_frame_host->GetFrameName() != "paymentForm") +void MobileSetupUI::DidFinishNavigation( + content::NavigationHandle* navigation_handle) { + if (!navigation_handle->HasCommitted() || + navigation_handle->GetRenderFrameHost()->GetFrameName() != + "paymentForm") { return; + } + + if (navigation_handle->IsErrorPage()) { + base::FundamentalValue result_value(-navigation_handle->GetNetErrorCode()); + web_ui()->CallJavascriptFunctionUnsafe(kJsPortalFrameLoadFailedCallback, + result_value); + return; + } web_ui()->CallJavascriptFunctionUnsafe(kJsPortalFrameLoadCompletedCallback); } - -void MobileSetupUI::DidFailProvisionalLoad( - content::RenderFrameHost* render_frame_host, - const GURL& validated_url, - int error_code, - const base::string16& error_description, - bool was_ignored_by_handler) { - if (render_frame_host->GetFrameName() != "paymentForm") - return; - - base::FundamentalValue result_value(-error_code); - web_ui()->CallJavascriptFunctionUnsafe(kJsPortalFrameLoadFailedCallback, - result_value); -}
diff --git a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.h b/chrome/browser/ui/webui/chromeos/mobile_setup_ui.h index 048cf794..0fd9d741 100644 --- a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.h +++ b/chrome/browser/ui/webui/chromeos/mobile_setup_ui.h
@@ -20,15 +20,8 @@ private: // content::WebContentsObserver overrides. - void DidCommitProvisionalLoadForFrame( - content::RenderFrameHost* render_frame_host, - const GURL& url, - ui::PageTransition transition_type) override; - void DidFailProvisionalLoad(content::RenderFrameHost* render_frame_host, - const GURL& validated_url, - int error_code, - const base::string16& error_description, - bool was_ignored_by_handler) override; + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override; DISALLOW_COPY_AND_ASSIGN(MobileSetupUI); };
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 737292eb..cc813b6 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1802,6 +1802,7 @@ "../browser/ui/toolbar/component_toolbar_actions_browsertest.cc", "../browser/ui/toolbar/mock_component_toolbar_actions_factory.cc", "../browser/ui/toolbar/mock_component_toolbar_actions_factory.h", + "../browser/ui/update_chrome_dialog_browsertest.cc", "../browser/ui/website_settings/mock_permission_prompt.cc", "../browser/ui/website_settings/mock_permission_prompt.h", "../browser/ui/website_settings/mock_permission_prompt_factory.cc",
diff --git a/chromecast/renderer/cast_content_renderer_client.cc b/chromecast/renderer/cast_content_renderer_client.cc index 69e3e87c..63489470 100644 --- a/chromecast/renderer/cast_content_renderer_client.cc +++ b/chromecast/renderer/cast_content_renderer_client.cc
@@ -182,6 +182,10 @@ } } +bool CastContentRendererClient::AllowMediaSuspend() { + return false; +} + void ExecuteJavaScript(content::RenderFrame* render_frame, int resource_id) { const std::string& js_string = ui::ResourceBundle::GetSharedInstance() .GetRawDataResource(resource_id)
diff --git a/chromecast/renderer/cast_content_renderer_client.h b/chromecast/renderer/cast_content_renderer_client.h index d4b78d82..edc1182 100644 --- a/chromecast/renderer/cast_content_renderer_client.h +++ b/chromecast/renderer/cast_content_renderer_client.h
@@ -43,6 +43,7 @@ bool render_frame_has_played_media_before, const base::Closure& closure) override; void RunScriptsAtDocumentStart(content::RenderFrame* render_frame) override; + bool AllowMediaSuspend() override; protected: CastContentRendererClient();
diff --git a/components/nacl/zygote/nacl_fork_delegate_linux.cc b/components/nacl/zygote/nacl_fork_delegate_linux.cc index b1b39ecc..40e3a53 100644 --- a/components/nacl/zygote/nacl_fork_delegate_linux.cc +++ b/components/nacl/zygote/nacl_fork_delegate_linux.cc
@@ -10,7 +10,6 @@ #include <sys/resource.h> #include <sys/socket.h> -#include <memory> #include <set> #include "base/command_line.h" @@ -19,7 +18,7 @@ #include "base/files/scoped_file.h" #include "base/logging.h" #include "base/macros.h" -#include "base/memory/scoped_vector.h" +#include "base/memory/ptr_util.h" #include "base/path_service.h" #include "base/pickle.h" #include "base/posix/eintr_wrapper.h" @@ -131,9 +130,11 @@ namespace nacl { void AddNaClZygoteForkDelegates( - ScopedVector<content::ZygoteForkDelegate>* delegates) { - delegates->push_back(new NaClForkDelegate(false /* nonsfi_mode */)); - delegates->push_back(new NaClForkDelegate(true /* nonsfi_mode */)); + std::vector<std::unique_ptr<content::ZygoteForkDelegate>>* delegates) { + delegates->push_back( + base::MakeUnique<NaClForkDelegate>(false /* nonsfi_mode */)); + delegates->push_back( + base::MakeUnique<NaClForkDelegate>(true /* nonsfi_mode */)); } NaClForkDelegate::NaClForkDelegate(bool nonsfi_mode)
diff --git a/components/nacl/zygote/nacl_fork_delegate_linux.h b/components/nacl/zygote/nacl_fork_delegate_linux.h index 4dd5366..e64fb14 100644 --- a/components/nacl/zygote/nacl_fork_delegate_linux.h +++ b/components/nacl/zygote/nacl_fork_delegate_linux.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_NACL_ZYGOTE_NACL_FORK_DELEGATE_LINUX_H_ #define COMPONENTS_NACL_ZYGOTE_NACL_FORK_DELEGATE_LINUX_H_ +#include <memory> #include <string> #include <vector> @@ -17,14 +18,11 @@ struct LaunchOptions; } -template <typename> -class ScopedVector; - namespace nacl { // Appends any ZygoteForkDelegate instances needed by NaCl to |*delegates|. void AddNaClZygoteForkDelegates( - ScopedVector<content::ZygoteForkDelegate>* delegates); + std::vector<std::unique_ptr<content::ZygoteForkDelegate>>* delegates); // The NaClForkDelegate is created during Chrome linux zygote // initialization, and provides "fork()" functionality with
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc index a48d5b6d..b236b99c 100644 --- a/content/app/content_main_runner.cc +++ b/content/app/content_main_runner.cc
@@ -11,6 +11,7 @@ #include <memory> #include <string> #include <utility> +#include <vector> #include "base/allocator/allocator_check.h" #include "base/allocator/allocator_extension.h" @@ -318,7 +319,7 @@ { switches::kUtilityProcess, UtilityMain }, }; - ScopedVector<ZygoteForkDelegate> zygote_fork_delegates; + std::vector<std::unique_ptr<ZygoteForkDelegate>> zygote_fork_delegates; if (delegate) { delegate->ZygoteStarting(&zygote_fork_delegates); media::InitializeMediaLibrary();
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index a90666d3..69a67af 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -2005,7 +2005,7 @@ if (enable_webvr) { deps += [ "//device/vr" ] } else { - deps += [ "//device/vr:mojo_bindings" ] + deps += [ "//device/vr:mojo_only" ] } if (enable_ipc_fuzzer) {
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h index 87e47f6..3153002 100644 --- a/content/browser/bad_message.h +++ b/content/browser/bad_message.h
@@ -182,6 +182,7 @@ BDH_INVALID_OPTIONS = 158, RFH_DID_ADD_CONSOLE_MESSAGE_BAD_SEVERITY = 159, AIRH_VOLUME_OUT_OF_RANGE = 160, + BDH_INVALID_DESCRIPTOR_ID = 161, // Please add new elements here. The naming convention is abbreviated class // name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/content/browser/bluetooth/bluetooth_metrics.cc b/content/browser/bluetooth/bluetooth_metrics.cc index c32c9cf0..d33f130 100644 --- a/content/browser/bluetooth/bluetooth_metrics.cc +++ b/content/browser/bluetooth/bluetooth_metrics.cc
@@ -243,6 +243,7 @@ UMAGetCharacteristicOutcome::NO_SERVICE); return; case CacheQueryOutcome::NO_CHARACTERISTIC: + case CacheQueryOutcome::NO_DESCRIPTOR: NOTREACHED(); return; } @@ -279,6 +280,9 @@ case UMAGATTOperation::START_NOTIFICATIONS: RecordStartNotificationsOutcome(outcome); return; + case UMAGATTOperation::DESCRIPTOR_READ: + // TODO(667319) Add reporting to descriptors + return; case UMAGATTOperation::COUNT: NOTREACHED(); return; @@ -300,6 +304,8 @@ return UMAGATTOperationOutcome::NO_SERVICE; case CacheQueryOutcome::NO_CHARACTERISTIC: return UMAGATTOperationOutcome::NO_CHARACTERISTIC; + case CacheQueryOutcome::NO_DESCRIPTOR: + return UMAGATTOperationOutcome::NO_DESCRIPTOR; } NOTREACHED() << "No need to record success or renderer crash"; return UMAGATTOperationOutcome::NOT_SUPPORTED;
diff --git a/content/browser/bluetooth/bluetooth_metrics.h b/content/browser/bluetooth/bluetooth_metrics.h index b15bb35..37b54af 100644 --- a/content/browser/bluetooth/bluetooth_metrics.h +++ b/content/browser/bluetooth/bluetooth_metrics.h
@@ -51,6 +51,7 @@ NO_DEVICE = 2, NO_SERVICE = 3, NO_CHARACTERISTIC = 4, + NO_DESCRIPTOR = 5, }; // requestDevice() Metrics @@ -236,6 +237,7 @@ CHARACTERISTIC_READ, CHARACTERISTIC_WRITE, START_NOTIFICATIONS, + DESCRIPTOR_READ, // Note: Add new GATT Operations immediately above this line. COUNT };
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.cc b/content/browser/bluetooth/web_bluetooth_service_impl.cc index 9f35101..15238442 100644 --- a/content/browser/bluetooth/web_bluetooth_service_impl.cc +++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -152,6 +152,8 @@ case CacheQueryOutcome::NO_CHARACTERISTIC: return blink::mojom::WebBluetoothResult:: CHARACTERISTIC_NO_LONGER_EXISTS; + case CacheQueryOutcome::NO_DESCRIPTOR: + return blink::mojom::WebBluetoothResult::DESCRIPTOR_NO_LONGER_EXISTS; } NOTREACHED(); return blink::mojom::WebBluetoothResult::DEVICE_NO_LONGER_IN_RANGE; @@ -160,6 +162,7 @@ device::BluetoothDevice* device = nullptr; device::BluetoothRemoteGattService* service = nullptr; device::BluetoothRemoteGattCharacteristic* characteristic = nullptr; + device::BluetoothRemoteGattDescriptor* descriptor = nullptr; CacheQueryOutcome outcome; }; @@ -737,6 +740,37 @@ weak_ptr_factory_.GetWeakPtr(), characteristic_instance_id, callback)); } +void WebBluetoothServiceImpl::RemoteDescriptorReadValue( + const std::string& descriptor_instance_id, + const RemoteDescriptorReadValueCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + const CacheQueryResult query_result = + QueryCacheForDescriptor(descriptor_instance_id); + + if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { + return; + } + + if (query_result.outcome != CacheQueryOutcome::SUCCESS) { + callback.Run(query_result.GetWebResult(), base::nullopt /* value */); + return; + } + + if (BluetoothBlocklist::Get().IsExcludedFromReads( + query_result.descriptor->GetUUID())) { + callback.Run(blink::mojom::WebBluetoothResult::BLOCKLISTED_READ, + base::nullopt /* value */); + return; + } + + query_result.descriptor->ReadRemoteDescriptor( + base::Bind(&WebBluetoothServiceImpl::OnDescriptorReadValueSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&WebBluetoothServiceImpl::OnDescriptorReadValueFailed, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + void WebBluetoothServiceImpl::RequestDeviceImpl( blink::mojom::WebBluetoothRequestDeviceOptionsPtr options, const RequestDeviceCallback& callback, @@ -938,6 +972,23 @@ callback.Run(); } +void WebBluetoothServiceImpl::OnDescriptorReadValueSuccess( + const RemoteDescriptorReadValueCallback& callback, + const std::vector<uint8_t>& value) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + callback.Run(blink::mojom::WebBluetoothResult::SUCCESS, value); +} + +void WebBluetoothServiceImpl::OnDescriptorReadValueFailed( + const RemoteDescriptorReadValueCallback& callback, + device::BluetoothRemoteGattService::GattErrorCode error_code) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + // TODO(667319) We are reporting failures to UMA but not reporting successes. + callback.Run(TranslateGATTErrorAndRecord(error_code, + UMAGATTOperation::DESCRIPTOR_READ), + base::nullopt /* value */); +} + CacheQueryResult WebBluetoothServiceImpl::QueryCacheForDevice( const WebBluetoothDeviceId& device_id) { const std::string& device_address = @@ -1020,6 +1071,34 @@ return result; } +CacheQueryResult WebBluetoothServiceImpl::QueryCacheForDescriptor( + const std::string& descriptor_instance_id) { + auto descriptor_iter = + descriptor_id_to_characteristic_id_.find(descriptor_instance_id); + + // Kill the render, see "ID Not in Map Note" above. + if (descriptor_iter == descriptor_id_to_characteristic_id_.end()) { + CrashRendererAndClosePipe(bad_message::BDH_INVALID_DESCRIPTOR_ID); + return CacheQueryResult(CacheQueryOutcome::BAD_RENDERER); + } + + CacheQueryResult result = + QueryCacheForCharacteristic(descriptor_iter->second); + + if (result.outcome != CacheQueryOutcome::SUCCESS) { + return result; + } + + result.descriptor = + result.characteristic->GetDescriptor(descriptor_instance_id); + + if (result.descriptor == nullptr) { + result.outcome = CacheQueryOutcome::NO_DESCRIPTOR; + } + + return result; +} + RenderProcessHost* WebBluetoothServiceImpl::GetRenderProcessHost() { return render_frame_host_->GetProcess(); }
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.h b/content/browser/bluetooth/web_bluetooth_service_impl.h index 01b3da6..c8a4c59 100644 --- a/content/browser/bluetooth/web_bluetooth_service_impl.h +++ b/content/browser/bluetooth/web_bluetooth_service_impl.h
@@ -133,6 +133,9 @@ blink::mojom::WebBluetoothGATTQueryQuantity quantity, const base::Optional<device::BluetoothUUID>& characteristics_uuid, const RemoteCharacteristicGetDescriptorsCallback& callback) override; + void RemoteDescriptorReadValue( + const std::string& characteristic_instance_id, + const RemoteDescriptorReadValueCallback& callback) override; void RequestDeviceImpl( blink::mojom::WebBluetoothRequestDeviceOptionsPtr options, @@ -195,6 +198,14 @@ const std::string& characteristic_instance_id, const RemoteCharacteristicStopNotificationsCallback& callback); + // Callbacks for BluetoothRemoteGattDescriptor::ReadRemoteDescriptor. + void OnDescriptorReadValueSuccess( + const RemoteDescriptorReadValueCallback& callback, + const std::vector<uint8_t>& value); + void OnDescriptorReadValueFailed( + const RemoteDescriptorReadValueCallback& callback, + device::BluetoothRemoteGattService::GattErrorCode error_code); + // Functions to query the platform cache for the bluetooth object. // result.outcome == CacheQueryOutcome::SUCCESS if the object was found in the // cache. Otherwise result.outcome that can used to record the outcome and @@ -217,6 +228,12 @@ CacheQueryResult QueryCacheForCharacteristic( const std::string& characteristic_instance_id); + // Queries the platform cache for a descriptor with |descriptor_instance_id|. + // Fills in the |outcome| field, and |device|, |service|, |characteristic|, + // |descriptor| fields if successful. + CacheQueryResult QueryCacheForDescriptor( + const std::string& descriptor_instance_id); + RenderProcessHost* GetRenderProcessHost(); device::BluetoothAdapter* GetAdapter(); url::Origin GetOrigin();
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc index 15ca6b6..56e37ac 100644 --- a/content/browser/devtools/protocol/network_handler.cc +++ b/content/browser/devtools/protocol/network_handler.cc
@@ -631,12 +631,22 @@ head.load_timing.request_start_time) .Build()); if (head.devtools_info) { - response->SetStatus(head.devtools_info->http_status_code); - response->SetStatusText(head.devtools_info->http_status_text); - response->SetRequestHeaders( - getHeaders(head.devtools_info->request_headers)); - response->SetHeaders(getHeaders(head.devtools_info->response_headers)); - response->SetHeadersText(head.devtools_info->response_headers_text); + if (head.devtools_info->http_status_code) { + response->SetStatus(head.devtools_info->http_status_code); + response->SetStatusText(head.devtools_info->http_status_text); + } + if (head.devtools_info->request_headers.size()) { + response->SetRequestHeaders( + getHeaders(head.devtools_info->request_headers)); + } + if (!head.devtools_info->request_headers_text.empty()) { + response->SetRequestHeadersText( + head.devtools_info->request_headers_text); + } + if (head.devtools_info->response_headers.size()) + response->SetHeaders(getHeaders(head.devtools_info->response_headers)); + if (!head.devtools_info->response_headers_text.empty()) + response->SetHeadersText(head.devtools_info->response_headers_text); } response->SetProtocol(getProtocol(url, head)); response->SetRemoteIPAddress(head.socket_address.HostForURL());
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 7424a5b..01653b00 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -124,7 +124,11 @@ #include "content/browser/frame_host/popup_menu_helper_mac.h" #endif +#if defined(ENABLE_WEBVR) #include "device/vr/vr_service_impl.h" // nogncheck +#else +#include "device/vr/vr_service.mojom.h" // nogncheck +#endif using base::TimeDelta;
diff --git a/content/child/indexed_db/webidbdatabase_impl_unittest.cc b/content/child/indexed_db/webidbdatabase_impl_unittest.cc index 114737b..5bbd1e3 100644 --- a/content/child/indexed_db/webidbdatabase_impl_unittest.cc +++ b/content/child/indexed_db/webidbdatabase_impl_unittest.cc
@@ -76,8 +76,8 @@ const std::vector<char> data(kMaxValueSizeForTesting - kKeySize); const WebData value(&data.front(), data.size()); const WebVector<WebBlobInfo> web_blob_info; - const WebIDBKey key = WebIDBKey::createString( - base::string16(kKeySize / sizeof(base::string16::value_type), 'x')); + const WebIDBKey key = WebIDBKey::createString(blink::WebString::fromUTF16( + base::string16(kKeySize / sizeof(base::string16::value_type), 'x'))); const int64_t transaction_id = 1; const int64_t object_store_id = 2;
diff --git a/content/child/webmessageportchannel_impl.cc b/content/child/webmessageportchannel_impl.cc index 2b4d265a..26de409 100644 --- a/content/child/webmessageportchannel_impl.cc +++ b/content/child/webmessageportchannel_impl.cc
@@ -173,10 +173,10 @@ // from two threads, which is a data race. main_thread_task_runner_->PostTask( FROM_HERE, base::Bind(&WebMessagePortChannelImpl::SendPostMessage, this, - base::Passed(base::string16(message)), + base::Passed(message.utf16()), base::Passed(std::move(channels)))); } else { - SendPostMessage(message, std::move(channels)); + SendPostMessage(message.utf16(), std::move(channels)); } } @@ -195,7 +195,7 @@ if (message_queue_.empty()) return false; - *message = message_queue_.front().message; + *message = WebString::fromUTF16(message_queue_.front().message); channels = message_queue_.front().ports; message_queue_.pop(); return true;
diff --git a/content/public/app/content_main_delegate.cc b/content/public/app/content_main_delegate.cc index d833cb0..e46f80a 100644 --- a/content/public/app/content_main_delegate.cc +++ b/content/public/app/content_main_delegate.cc
@@ -45,8 +45,7 @@ #elif defined(OS_POSIX) && !defined(OS_ANDROID) void ContentMainDelegate::ZygoteStarting( - ScopedVector<ZygoteForkDelegate>* delegates) { -} + std::vector<std::unique_ptr<ZygoteForkDelegate>>* delegates) {} #endif
diff --git a/content/public/app/content_main_delegate.h b/content/public/app/content_main_delegate.h index 1dcb57f..a94502f 100644 --- a/content/public/app/content_main_delegate.h +++ b/content/public/app/content_main_delegate.h
@@ -5,14 +5,13 @@ #ifndef CONTENT_PUBLIC_APP_CONTENT_MAIN_DELEGATE_H_ #define CONTENT_PUBLIC_APP_CONTENT_MAIN_DELEGATE_H_ +#include <memory> #include <string> +#include <vector> #include "build/build_config.h" #include "content/common/content_export.h" -template <typename> -class ScopedVector; - namespace content { class ContentBrowserClient; @@ -70,7 +69,8 @@ // Tells the embedder that the zygote process is starting, and allows it to // specify one or more zygote delegates if it wishes by storing them in // |*delegates|. - virtual void ZygoteStarting(ScopedVector<ZygoteForkDelegate>* delegates); + virtual void ZygoteStarting( + std::vector<std::unique_ptr<ZygoteForkDelegate>>* delegates); // Called every time the zygote process forks. virtual void ZygoteForked() {}
diff --git a/content/public/common/color_suggestion.cc b/content/public/common/color_suggestion.cc index 0d36538..457ddd46 100644 --- a/content/public/common/color_suggestion.cc +++ b/content/public/common/color_suggestion.cc
@@ -9,8 +9,6 @@ namespace content { ColorSuggestion::ColorSuggestion(const blink::WebColorSuggestion& suggestion) - : color(suggestion.color), - label(suggestion.label) { -} + : color(suggestion.color), label(suggestion.label.utf16()) {} } // namespace content
diff --git a/content/public/common/window_container_type.cc b/content/public/common/window_container_type.cc index 57291bb..265e371 100644 --- a/content/public/common/window_container_type.cc +++ b/content/public/common/window_container_type.cc
@@ -31,11 +31,14 @@ bool persistent = false; for (size_t i = 0; i < window_features.additionalFeatures.size(); ++i) { - base::string16 feature = window_features.additionalFeatures[i]; - if (base::LowerCaseEqualsASCII(feature, kBackground)) - background = true; - else if (base::LowerCaseEqualsASCII(feature, kPersistent)) - persistent = true; + blink::WebString feature = window_features.additionalFeatures[i]; + if (feature.containsOnlyASCII()) { + std::string featureASCII = feature.ascii(); + if (base::LowerCaseEqualsASCII(featureASCII, kBackground)) + background = true; + else if (base::LowerCaseEqualsASCII(featureASCII, kPersistent)) + persistent = true; + } } if (background) {
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc index cc1d049a..fb40b4de 100644 --- a/content/public/renderer/content_renderer_client.cc +++ b/content/public/renderer/content_renderer_client.cc
@@ -224,4 +224,8 @@ return GURL(); } +bool ContentRendererClient::AllowMediaSuspend() { + return true; +} + } // namespace content
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h index 9895206..718db99 100644 --- a/content/public/renderer/content_renderer_client.h +++ b/content/public/renderer/content_renderer_client.h
@@ -362,6 +362,9 @@ std::vector<base::SchedulerWorkerPoolParams>* params_vector, base::TaskScheduler::WorkerPoolIndexForTraitsCallback* index_to_traits_callback) {} + + // Returns true if the media pipeline can be suspended, or false otherwise. + virtual bool AllowMediaSuspend(); }; } // namespace content
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 06535765..59e4884e 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -282,6 +282,8 @@ "origin_trials/web_trial_token_validator_impl.h", "peripheral_content_heuristic.cc", "peripheral_content_heuristic.h", + "presentation/presentation_connection_proxy.cc", + "presentation/presentation_connection_proxy.h", "presentation/presentation_dispatcher.cc", "presentation/presentation_dispatcher.h", "push_messaging/push_messaging_dispatcher.cc",
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc index a76de5e6..c4c2723f 100644 --- a/content/renderer/accessibility/render_accessibility_impl.cc +++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -504,7 +504,7 @@ target.setSequentialFocusNavigationStartingPoint(); break; case ui::AX_ACTION_SET_VALUE: - target.setValue(data.value); + target.setValue(blink::WebString::fromUTF16(data.value)); HandleAXEvent(target, ui::AX_EVENT_VALUE_CHANGED); break; case ui::AX_ACTION_SHOW_CONTEXT_MENU:
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc index 2c9c1f87..b6ad4ae 100644 --- a/content/renderer/browser_plugin/browser_plugin.cc +++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -142,9 +142,8 @@ return; blink::WebElement element = container()->element(); - blink::WebString web_attribute_name = - blink::WebString::fromUTF8(attribute_name); - element.setAttribute(web_attribute_name, attribute_value); + element.setAttribute(blink::WebString::fromUTF8(attribute_name), + blink::WebString::fromUTF16(attribute_value)); } void BrowserPlugin::Attach() {
diff --git a/content/renderer/context_menu_params_builder.cc b/content/renderer/context_menu_params_builder.cc index 2a0f66d..a344777 100644 --- a/content/renderer/context_menu_params_builder.cc +++ b/content/renderer/context_menu_params_builder.cc
@@ -28,9 +28,9 @@ params.keyword_url = data.keywordURL; params.frame_url = data.frameURL; params.media_flags = data.mediaFlags; - params.selection_text = data.selectedText; - params.title_text = data.titleText; - params.misspelled_word = data.misspelledWord; + params.selection_text = data.selectedText.utf16(); + params.title_text = data.titleText.utf16(); + params.misspelled_word = data.misspelledWord.utf16(); params.misspelling_hash = data.misspellingHash; params.spellcheck_enabled = data.isSpellCheckingEnabled; params.is_editable = data.isEditable; @@ -40,7 +40,7 @@ params.edit_flags = data.editFlags; params.frame_charset = data.frameEncoding.utf8(); params.referrer_policy = data.referrerPolicy; - params.suggested_filename = data.suggestedFilename; + params.suggested_filename = data.suggestedFilename.utf16(); params.input_field_type = data.inputFieldType; if (!data.imageResponse.isNull()) { @@ -49,7 +49,8 @@ } for (size_t i = 0; i < data.dictionarySuggestions.size(); ++i) - params.dictionary_suggestions.push_back(data.dictionarySuggestions[i]); + params.dictionary_suggestions.push_back( + data.dictionarySuggestions[i].utf16()); params.custom_context.is_pepper_menu = false; for (size_t i = 0; i < data.customItems.size(); ++i) @@ -60,7 +61,7 @@ SingleHistoryItemToPageState(data.frameHistoryItem); } - params.link_text = data.linkText; + params.link_text = data.linkText.utf16(); return params; }
diff --git a/content/renderer/devtools/devtools_agent.cc b/content/renderer/devtools/devtools_agent.cc index 789805f2..7e6f708 100644 --- a/content/renderer/devtools/devtools_agent.cc +++ b/content/renderer/devtools/devtools_agent.cc
@@ -330,7 +330,7 @@ } WebString url = frame_->GetWebFrame()->document().manifestURL().string(); - result->SetString("url", url); + result->SetString("url", url.utf16()); if (!failed) result->SetString("data", debug_info.raw_data); result->Set("errors", errors.release());
diff --git a/content/renderer/dom_serializer_browsertest.cc b/content/renderer/dom_serializer_browsertest.cc index edd3542..bcda843 100644 --- a/content/renderer/dom_serializer_browsertest.cc +++ b/content/renderer/dom_serializer_browsertest.cc
@@ -192,8 +192,7 @@ // Find corresponding WebFrame according to frame_url. WebFrame* web_frame = FindSubFrameByURL(frame_url); ASSERT_TRUE(web_frame != NULL); - WebString file_path = - base::FilePath(FILE_PATH_LITERAL("c:\\dummy.htm")).AsUTF16Unsafe(); + WebString file_path = WebString::fromUTF8("c:\\dummy.htm"); SingleLinkRewritingDelegate delegate(frame_url, file_path); // Start serializing DOM. bool result = WebFrameSerializer::serialize(web_frame->toWebLocalFrame(), @@ -474,8 +473,8 @@ }; WebString value = body_element.getAttribute("title"); WebString content = doc.contentAsTextForTesting(); - ASSERT_TRUE(base::UTF16ToWide(value) == parsed_value); - ASSERT_TRUE(base::UTF16ToWide(content) == parsed_value); + ASSERT_TRUE(base::UTF16ToWide(value.utf16()) == parsed_value); + ASSERT_TRUE(base::UTF16ToWide(content.utf16()) == parsed_value); // Do serialization. SerializeDomForURL(file_url);
diff --git a/content/renderer/history_serialization.cc b/content/renderer/history_serialization.cc index c9a7b200..b1fae6a7 100644 --- a/content/renderer/history_serialization.cc +++ b/content/renderer/history_serialization.cc
@@ -34,17 +34,19 @@ std::vector<base::NullableString16>* output) { output->reserve(output->size() + input.size()); for (size_t i = 0; i < input.size(); ++i) - output->push_back(input[i]); + output->push_back(WebString::toNullableString16(input[i])); } void GenerateFrameStateFromItem(const WebHistoryItem& item, ExplodedFrameState* state) { - state->url_string = item.urlString(); - state->referrer = item.referrer(); + state->url_string = WebString::toNullableString16(item.urlString()); + state->referrer = WebString::toNullableString16(item.referrer()); state->referrer_policy = item.getReferrerPolicy(); - state->target = item.target(); - if (!item.stateObject().isNull()) - state->state_object = item.stateObject().toString(); + state->target = WebString::toNullableString16(item.target()); + if (!item.stateObject().isNull()) { + state->state_object = + WebString::toNullableString16(item.stateObject().toString()); + } state->scroll_restoration_type = item.scrollRestorationType(); state->visual_viewport_scroll_offset = item.visualViewportScrollOffset(); state->scroll_offset = item.getScrollOffset(); @@ -54,7 +56,8 @@ state->page_scale_factor = item.pageScaleFactor(); ToNullableString16Vector(item.getDocumentState(), &state->document_state); - state->http_body.http_content_type = item.httpContentType(); + state->http_body.http_content_type = + WebString::toNullableString16(item.httpContentType()); const WebHTTPBody& http_body = item.httpBody(); if (!http_body.isNull()) { state->http_body.request_body = GetRequestBodyForWebHTTPBody(http_body); @@ -82,14 +85,19 @@ HistoryEntry::HistoryNode* node) { WebHistoryItem item; item.initialize(); - item.setURLString(state.url_string); - item.setReferrer(state.referrer, state.referrer_policy); - item.setTarget(state.target); + item.setURLString(WebString::fromUTF16(state.url_string)); + item.setReferrer(WebString::fromUTF16(state.referrer), state.referrer_policy); + item.setTarget(WebString::fromUTF16(state.target)); if (!state.state_object.is_null()) { - item.setStateObject( - WebSerializedScriptValue::fromString(state.state_object)); + item.setStateObject(WebSerializedScriptValue::fromString( + WebString::fromUTF16(state.state_object))); } - item.setDocumentState(state.document_state); + WebVector<WebString> document_state(state.document_state.size()); + std::transform(state.document_state.begin(), state.document_state.end(), + document_state.begin(), [](const base::NullableString16& s) { + return WebString::fromUTF16(s); + }); + item.setDocumentState(document_state); item.setScrollRestorationType(state.scroll_restoration_type); item.setVisualViewportScrollOffset(state.visual_viewport_scroll_offset); item.setScrollOffset(state.scroll_offset); @@ -103,7 +111,8 @@ if (state.document_sequence_number) item.setDocumentSequenceNumber(state.document_sequence_number); - item.setHTTPContentType(state.http_body.http_content_type); + item.setHTTPContentType( + WebString::fromUTF16(state.http_body.http_content_type)); if (state.http_body.request_body != nullptr) { item.setHTTPBody( GetWebHTTPBodyForRequestBody(state.http_body.request_body));
diff --git a/content/renderer/manifest/manifest_parser.cc b/content/renderer/manifest/manifest_parser.cc index 4d3f7f79..fb957a8 100644 --- a/content/renderer/manifest/manifest_parser.cc +++ b/content/renderer/manifest/manifest_parser.cc
@@ -137,7 +137,8 @@ return Manifest::kInvalidOrMissingColor; blink::WebColor color; - if (!blink::WebCSSParser::parseColor(&color, parsed_color.string())) { + if (!blink::WebCSSParser::parseColor( + &color, blink::WebString::fromUTF16(parsed_color.string()))) { AddErrorInfo("property '" + key + "' ignored, '" + base::UTF16ToUTF8(parsed_color.string()) + "' is not a " + "valid color."); @@ -267,7 +268,8 @@ return sizes; blink::WebVector<blink::WebSize> web_sizes = - blink::WebIconSizesParser::parseIconSizes(sizes_str.string()); + blink::WebIconSizesParser::parseIconSizes( + blink::WebString::fromUTF16(sizes_str.string())); sizes.resize(web_sizes.size()); for (size_t i = 0; i < web_sizes.size(); ++i) sizes[i] = web_sizes[i];
diff --git a/content/renderer/menu_item_builder.cc b/content/renderer/menu_item_builder.cc index d6507d86..a23624d7 100644 --- a/content/renderer/menu_item_builder.cc +++ b/content/renderer/menu_item_builder.cc
@@ -13,9 +13,9 @@ MenuItem MenuItemBuilder::Build(const blink::WebMenuItemInfo& item) { MenuItem result; - result.label = item.label; - result.icon = item.icon; - result.tool_tip = item.toolTip; + result.label = item.label.utf16(); + result.icon = item.icon.utf16(); + result.tool_tip = item.toolTip.utf16(); result.type = static_cast<MenuItem::Type>(item.type); result.action = item.action; result.rtl = (item.textDirection == blink::WebTextDirectionRightToLeft);
diff --git a/content/renderer/presentation/presentation_connection_proxy.cc b/content/renderer/presentation/presentation_connection_proxy.cc new file mode 100644 index 0000000..93129af --- /dev/null +++ b/content/renderer/presentation/presentation_connection_proxy.cc
@@ -0,0 +1,114 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/presentation/presentation_connection_proxy.h" + +#include "base/logging.h" +#include "content/renderer/presentation/presentation_dispatcher.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationConnection.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationSessionInfo.h" + +namespace content { + +PresentationConnectionProxy::PresentationConnectionProxy( + blink::WebPresentationConnection* source_connection) + : binding_(this), + target_connection_ptr_(nullptr), + source_connection_(source_connection) { + DCHECK(source_connection_); +} + +PresentationConnectionProxy::~PresentationConnectionProxy() = default; + +void PresentationConnectionProxy::SendConnectionMessage( + blink::mojom::ConnectionMessagePtr connection_message, + const OnMessageCallback& callback) const { + DCHECK(target_connection_ptr_); + target_connection_ptr_->OnMessage(std::move(connection_message), callback); +} + +void PresentationConnectionProxy::OnMessage( + blink::mojom::ConnectionMessagePtr message, + const OnMessageCallback& callback) { + DCHECK(!callback.is_null()); + + switch (message->type) { + case blink::mojom::PresentationMessageType::TEXT: { + DCHECK(message->message); + source_connection_->didReceiveTextMessage( + blink::WebString::fromUTF8(message->message.value())); + break; + } + case blink::mojom::PresentationMessageType::BINARY: { + DCHECK(message->data); + source_connection_->didReceiveBinaryMessage(&(message->data->front()), + message->data->size()); + break; + } + default: { + callback.Run(false); + NOTREACHED(); + return; + } + } + + callback.Run(true); +} + +// TODO(crbug.com/588874): Ensure legal PresentationConnection state transitions +// in a single place. +void PresentationConnectionProxy::DidChangeState( + blink::mojom::PresentationConnectionState state) { + if (state != blink::mojom::PresentationConnectionState::CONNECTED) { + // |DidChangeState| should only handle state transition from connecting -> + // connected. PresentationService and MRP handles other state transitions. + NOTREACHED(); + return; + } + + source_connection_->didChangeState( + blink::WebPresentationConnectionState::Connected); +} + +ControllerConnectionProxy::ControllerConnectionProxy( + blink::WebPresentationConnection* controller_connection) + : PresentationConnectionProxy(controller_connection) {} + +ControllerConnectionProxy::~ControllerConnectionProxy() = default; + +blink::mojom::PresentationConnectionPtr ControllerConnectionProxy::Bind() { + return binding_.CreateInterfacePtrAndBind(); +} + +blink::mojom::PresentationConnectionRequest +ControllerConnectionProxy::MakeRemoteRequest() { + DCHECK(!target_connection_ptr_) + << "target_connection_ptr_ should only be bound once."; + return mojo::MakeRequest(&target_connection_ptr_); +} + +ReceiverConnectionProxy::ReceiverConnectionProxy( + blink::WebPresentationConnection* receiver_connection) + : PresentationConnectionProxy(receiver_connection) {} + +ReceiverConnectionProxy::~ReceiverConnectionProxy() = default; + +void ReceiverConnectionProxy::Bind( + blink::mojom::PresentationConnectionRequest receiver_connection_request) { + binding_.Bind(std::move(receiver_connection_request)); +} + +void ReceiverConnectionProxy::BindControllerConnection( + blink::mojom::PresentationConnectionPtr controller_connection_ptr) { + DCHECK(!target_connection_ptr_); + target_connection_ptr_ = std::move(controller_connection_ptr); + target_connection_ptr_->DidChangeState( + blink::mojom::PresentationConnectionState::CONNECTED); + + DidChangeState(blink::mojom::PresentationConnectionState::CONNECTED); +} + +} // namespace content
diff --git a/content/renderer/presentation/presentation_connection_proxy.h b/content/renderer/presentation/presentation_connection_proxy.h new file mode 100644 index 0000000..fa828496 --- /dev/null +++ b/content/renderer/presentation/presentation_connection_proxy.h
@@ -0,0 +1,130 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_PRESENTATION_PRESENTATION_CONNECTION_PROXY_H_ +#define CONTENT_RENDERER_PRESENTATION_PRESENTATION_CONNECTION_PROXY_H_ + +#include "base/callback.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationConnectionProxy.h" +#include "third_party/WebKit/public/platform/modules/presentation/presentation.mojom.h" + +namespace blink { +class WebPresentationConnection; +} // namespace blink + +namespace content { + +// This class connects PresentationConnection owned by one frame with +// PresentationConnection owned by a different frame. +// +// PresentationConnectionProxy's ctor sets |source_connection_| to +// PresentationConnection object owned by one frame. +// +// To connect |controller_connection_proxy| on controlling frame with +// |receiver_connection_proxy| on receiver frame: +// 1. On controlling frame, create PresentationConnection object and +// ControllerConnectionProxy object |controller_connection_proxy|; +// 2. Create |target_connection_request|, an interface request of +// controller proxy's |target_connection_| by invoking: +// ControllerConnectionProxy::MakeRemoteRequest() { +// return mojo::MakeRequest(&target_connection_); +// } +// 3. Pass |controller_connection_proxy|'s interface pointer and +// |target_connection_request| to browser; +// 4. Browser passes |controller_connection_proxy|'s interface pointer and +// |target_connection_request| to receiver frame; +// 5. On receiver frame, create PresentationConnection object and +// ReceiverConnectionProxy object |receiver_connection_proxy|; +// 6. Bind |target_connection_request| with |receiver_connection_proxy| by +// invoking: +// ReceiverConnectionProxy::Bind(target_connection_request); +// 7. Set receiver proxy's |target_connection_| to +// |controller_connection_proxy|'s interface pointer: +// ReceiverConnectionProxy::BindTargetConnection( +// blink::mojom::PresentationConnectionPtr connection) { +// target_connection_ = std::move(connection); +// ... +// } +// +// When both |source_connection_| and |target_connection_| are set, +// we can send message or notify state changes between controller and receiver. +// +// To send message from controlling frame to receiver frame: +// 1. Controlling frame invokes connection.sendMessage(); +// 2. This call is delegated to controller presentation connection proxy's +// SendConnectionMessage(). +// ControllerConnectionProxy::SendConnectionMessage() { +// target_connection_->OnMessage(); +// } +// 3. ReceiverConnectionProxy::OnMessage() is invoked. +// 4. connection.onmessage event on receiver frame is fired. +// +// Sending message from receiver frame to controlling frame and notifying state +// changes works the same. +// +// Instance of this class is created for both offscreen and non offscreen +// presentations. +class CONTENT_EXPORT PresentationConnectionProxy + : public NON_EXPORTED_BASE(blink::WebPresentationConnectionProxy), + public NON_EXPORTED_BASE(blink::mojom::PresentationConnection) { + public: + using OnMessageCallback = base::Callback<void(bool)>; + + ~PresentationConnectionProxy() override; + + virtual void SendConnectionMessage( + blink::mojom::ConnectionMessagePtr connection_message, + const OnMessageCallback& callback) const; + + // blink::mojom::PresentationConnection implementation + void OnMessage(blink::mojom::ConnectionMessagePtr message, + const OnMessageCallback& callback) override; + void DidChangeState(blink::mojom::PresentationConnectionState state) override; + + protected: + explicit PresentationConnectionProxy( + blink::WebPresentationConnection* source_connection); + mojo::Binding<blink::mojom::PresentationConnection> binding_; + mojo::InterfacePtr<blink::mojom::PresentationConnection> + target_connection_ptr_; + + private: + // Raw pointer to Blink connection object owning this proxy object. Does not + // take ownership. + blink::WebPresentationConnection* const source_connection_; +}; + +// Represents PresentationConnectionProxy object on controlling frame. +class CONTENT_EXPORT ControllerConnectionProxy + : public PresentationConnectionProxy { + public: + explicit ControllerConnectionProxy( + blink::WebPresentationConnection* controller_connection); + ~ControllerConnectionProxy() override; + + blink::mojom::PresentationConnectionPtr Bind(); + blink::mojom::PresentationConnectionRequest MakeRemoteRequest(); +}; + +// Represents PresentationConnectionProxy object on receiver frame. +class CONTENT_EXPORT ReceiverConnectionProxy + : public PresentationConnectionProxy { + public: + explicit ReceiverConnectionProxy( + blink::WebPresentationConnection* receiver_connection); + ~ReceiverConnectionProxy() override; + + void Bind( + blink::mojom::PresentationConnectionRequest receiver_connection_request); + + // Sets |target_connection_ptr_| to |controller_connection_ptr|. Should be + // called only once. + void BindControllerConnection( + blink::mojom::PresentationConnectionPtr controller_connection_ptr); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_PRESENTATION_PRESENTATION_CONNECTION_PROXY_H_
diff --git a/content/renderer/presentation/presentation_connection_proxy_unittest.cc b/content/renderer/presentation/presentation_connection_proxy_unittest.cc new file mode 100644 index 0000000..03f0bcc5 --- /dev/null +++ b/content/renderer/presentation/presentation_connection_proxy_unittest.cc
@@ -0,0 +1,114 @@ +// 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 <memory> +#include <utility> + +#include "base/run_loop.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "content/renderer/presentation/presentation_connection_proxy.h" +#include "content/renderer/presentation/test_presentation_connection.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationConnection.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h" + +using ::testing::_; + +namespace content { + +class PresentationConnectionProxyTest : public ::testing::Test { + public: + PresentationConnectionProxyTest() = default; + ~PresentationConnectionProxyTest() override = default; + + void SetUp() override { + // Set up test connections and test connection proxies. + controller_connection_ = base::MakeUnique<TestPresentationConnection>(); + receiver_connection_ = base::MakeUnique<TestPresentationConnection>(); + + controller_connection_proxy_ = + new ControllerConnectionProxy(controller_connection_.get()); + controller_connection_->bindProxy( + base::WrapUnique(controller_connection_proxy_)); + receiver_connection_proxy_ = + new ReceiverConnectionProxy(receiver_connection_.get()); + receiver_connection_->bindProxy( + base::WrapUnique(receiver_connection_proxy_)); + + EXPECT_CALL( + *controller_connection_, + didChangeState(blink::WebPresentationConnectionState::Connected)); + EXPECT_CALL( + *receiver_connection_, + didChangeState(blink::WebPresentationConnectionState::Connected)); + + receiver_connection_proxy_->Bind( + controller_connection_proxy_->MakeRemoteRequest()); + receiver_connection_proxy_->BindControllerConnection( + controller_connection_proxy_->Bind()); + } + + void TearDown() override { + controller_connection_.reset(); + receiver_connection_.reset(); + } + + void ExpectSendConnectionMessageCallback(bool success) { + EXPECT_TRUE(success); + } + + protected: + std::unique_ptr<TestPresentationConnection> controller_connection_; + std::unique_ptr<TestPresentationConnection> receiver_connection_; + ControllerConnectionProxy* controller_connection_proxy_; + ReceiverConnectionProxy* receiver_connection_proxy_; + + private: + content::TestBrowserThreadBundle thread_bundle_; +}; + +TEST_F(PresentationConnectionProxyTest, TestSendString) { + blink::WebString message = blink::WebString::fromUTF8("test message"); + blink::mojom::ConnectionMessagePtr session_message = + blink::mojom::ConnectionMessage::New(); + session_message->type = blink::mojom::PresentationMessageType::TEXT; + session_message->message = message.utf8(); + + base::RunLoop run_loop; + EXPECT_CALL(*receiver_connection_, didReceiveTextMessage(message)); + controller_connection_proxy_->SendConnectionMessage( + std::move(session_message), + base::Bind( + &PresentationConnectionProxyTest::ExpectSendConnectionMessageCallback, + base::Unretained(this))); + run_loop.RunUntilIdle(); +} + +TEST_F(PresentationConnectionProxyTest, TestSendArrayBuffer) { + std::vector<uint8_t> expected_data; + expected_data.push_back(42); + expected_data.push_back(36); + + blink::mojom::ConnectionMessagePtr session_message = + blink::mojom::ConnectionMessage::New(); + session_message->type = blink::mojom::PresentationMessageType::BINARY; + session_message->data = expected_data; + + base::RunLoop run_loop; + EXPECT_CALL(*receiver_connection_, didReceiveBinaryMessage(_, _)) + .WillOnce(::testing::Invoke( + [this, &expected_data](const uint8_t* data, size_t length) { + std::vector<uint8_t> message_data(data, data + length); + EXPECT_EQ(expected_data, message_data); + })); + + controller_connection_proxy_->SendConnectionMessage( + std::move(session_message), + base::Bind( + &PresentationConnectionProxyTest::ExpectSendConnectionMessageCallback, + base::Unretained(this))); + run_loop.RunUntilIdle(); +} + +} // namespace content
diff --git a/content/renderer/presentation/presentation_dispatcher.cc b/content/renderer/presentation/presentation_dispatcher.cc index 594fdde..15753c3e 100644 --- a/content/renderer/presentation/presentation_dispatcher.cc +++ b/content/renderer/presentation/presentation_dispatcher.cc
@@ -14,12 +14,15 @@ #include "base/threading/thread_task_runner_handle.h" #include "content/public/common/presentation_constants.h" #include "content/public/renderer/render_frame.h" +#include "content/renderer/presentation/presentation_connection_proxy.h" #include "mojo/public/cpp/bindings/type_converter.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/platform/WebVector.h" #include "third_party/WebKit/public/platform/modules/presentation/WebPresentationAvailabilityObserver.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationConnection.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationConnectionCallbacks.h" #include "third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h" #include "third_party/WebKit/public/platform/modules/presentation/WebPresentationError.h" #include "third_party/WebKit/public/platform/modules/presentation/WebPresentationReceiver.h" @@ -101,8 +104,8 @@ PresentationDispatcher::PresentationDispatcher(RenderFrame* render_frame) : RenderFrameObserver(render_frame), controller_(nullptr), - binding_(this) { -} + receiver_(nullptr), + binding_(this) {} PresentationDispatcher::~PresentationDispatcher() { // Controller should be destroyed before the dispatcher when frame is @@ -122,7 +125,7 @@ void PresentationDispatcher::startSession( const blink::WebVector<blink::WebURL>& presentationUrls, - std::unique_ptr<blink::WebPresentationConnectionCallback> callback) { + std::unique_ptr<blink::WebPresentationConnectionCallbacks> callback) { DCHECK(callback); ConnectToPresentationServiceIfNeeded(); @@ -141,7 +144,7 @@ void PresentationDispatcher::joinSession( const blink::WebVector<blink::WebURL>& presentationUrls, const blink::WebString& presentationId, - std::unique_ptr<blink::WebPresentationConnectionCallback> callback) { + std::unique_ptr<blink::WebPresentationConnectionCallbacks> callback) { DCHECK(callback); ConnectToPresentationServiceIfNeeded(); @@ -158,9 +161,11 @@ base::Unretained(this), base::Passed(&callback))); } -void PresentationDispatcher::sendString(const blink::WebURL& presentationUrl, - const blink::WebString& presentationId, - const blink::WebString& message) { +void PresentationDispatcher::sendString( + const blink::WebURL& presentationUrl, + const blink::WebString& presentationId, + const blink::WebString& message, + const blink::WebPresentationConnectionProxy* connection_proxy) { if (message.utf8().size() > kMaxPresentationConnectionMessageSize) { // TODO(crbug.com/459008): Limit the size of individual messages to 64k // for now. Consider throwing DOMException or splitting bigger messages @@ -169,8 +174,8 @@ return; } - message_request_queue_.push(base::WrapUnique( - CreateSendTextMessageRequest(presentationUrl, presentationId, message))); + message_request_queue_.push(base::WrapUnique(CreateSendTextMessageRequest( + presentationUrl, presentationId, message, connection_proxy))); // Start processing request if only one in the queue. if (message_request_queue_.size() == 1) DoSendMessage(message_request_queue_.front().get()); @@ -180,7 +185,8 @@ const blink::WebURL& presentationUrl, const blink::WebString& presentationId, const uint8_t* data, - size_t length) { + size_t length, + const blink::WebPresentationConnectionProxy* connection_proxy) { DCHECK(data); if (length > kMaxPresentationConnectionMessageSize) { // TODO(crbug.com/459008): Same as in sendString(). @@ -190,7 +196,8 @@ message_request_queue_.push(base::WrapUnique(CreateSendBinaryMessageRequest( presentationUrl, presentationId, - blink::mojom::PresentationMessageType::BINARY, data, length))); + blink::mojom::PresentationMessageType::BINARY, data, length, + connection_proxy))); // Start processing request if only one in the queue. if (message_request_queue_.size() == 1) DoSendMessage(message_request_queue_.front().get()); @@ -200,7 +207,8 @@ const blink::WebURL& presentationUrl, const blink::WebString& presentationId, const uint8_t* data, - size_t length) { + size_t length, + const blink::WebPresentationConnectionProxy* connection_proxy) { DCHECK(data); if (length > kMaxPresentationConnectionMessageSize) { // TODO(crbug.com/459008): Same as in sendString(). @@ -210,7 +218,8 @@ message_request_queue_.push(base::WrapUnique(CreateSendBinaryMessageRequest( presentationUrl, presentationId, - blink::mojom::PresentationMessageType::BINARY, data, length))); + blink::mojom::PresentationMessageType::BINARY, data, length, + connection_proxy))); // Start processing request if only one in the queue. if (message_request_queue_.size() == 1) DoSendMessage(message_request_queue_.front().get()); @@ -479,13 +488,15 @@ if (!session_info.is_null()) { presentation_service_->ListenForConnectionMessages(session_info.Clone()); - controller_->didStartDefaultSession( + auto* connection = controller_->didStartDefaultSession( mojo::ConvertTo<blink::WebPresentationSessionInfo>(session_info)); + connection->bindProxy( + base::MakeUnique<ControllerConnectionProxy>(connection)); } } void PresentationDispatcher::OnSessionCreated( - std::unique_ptr<blink::WebPresentationConnectionCallback> callback, + std::unique_ptr<blink::WebPresentationConnectionCallbacks> callback, blink::mojom::PresentationSessionInfoPtr session_info, blink::mojom::PresentationErrorPtr error) { DCHECK(callback); @@ -501,16 +512,27 @@ presentation_service_->ListenForConnectionMessages(session_info.Clone()); callback->onSuccess( mojo::ConvertTo<blink::WebPresentationSessionInfo>(session_info)); + + auto* connection = callback->getConnection(); + connection->bindProxy( + base::MakeUnique<ControllerConnectionProxy>(connection)); } void PresentationDispatcher::OnReceiverConnectionAvailable( blink::mojom::PresentationSessionInfoPtr session_info, - blink::mojom::PresentationConnectionPtr, - blink::mojom::PresentationConnectionRequest) { - if (receiver_) { - receiver_->onReceiverConnectionAvailable( - mojo::ConvertTo<blink::WebPresentationSessionInfo>(session_info)); - } + blink::mojom::PresentationConnectionPtr controller_connection_ptr, + blink::mojom::PresentationConnectionRequest receiver_connection_request) { + DCHECK(receiver_); + // Bind receiver_connection_proxy with PresentationConnection in receiver + // page. + auto* connection = receiver_->onReceiverConnectionAvailable( + mojo::ConvertTo<blink::WebPresentationSessionInfo>(session_info)); + auto* receiver_connection_proxy = new ReceiverConnectionProxy(connection); + connection->bindProxy(base::WrapUnique(receiver_connection_proxy)); + + receiver_connection_proxy->Bind(std::move(receiver_connection_request)); + receiver_connection_proxy->BindControllerConnection( + std::move(controller_connection_ptr)); } void PresentationDispatcher::OnConnectionStateChanged( @@ -680,8 +702,11 @@ PresentationDispatcher::SendMessageRequest::SendMessageRequest( blink::mojom::PresentationSessionInfoPtr session_info, - blink::mojom::ConnectionMessagePtr message) - : session_info(std::move(session_info)), message(std::move(message)) {} + blink::mojom::ConnectionMessagePtr message, + const blink::WebPresentationConnectionProxy* connection_proxy) + : session_info(std::move(session_info)), + message(std::move(message)), + connection_proxy(connection_proxy) {} PresentationDispatcher::SendMessageRequest::~SendMessageRequest() {} @@ -690,7 +715,8 @@ PresentationDispatcher::CreateSendTextMessageRequest( const blink::WebURL& presentationUrl, const blink::WebString& presentationId, - const blink::WebString& message) { + const blink::WebString& message, + const blink::WebPresentationConnectionProxy* connection_proxy) { blink::mojom::PresentationSessionInfoPtr session_info = blink::mojom::PresentationSessionInfo::New(); session_info->url = presentationUrl; @@ -701,7 +727,7 @@ session_message->type = blink::mojom::PresentationMessageType::TEXT; session_message->message = message.utf8(); return new SendMessageRequest(std::move(session_info), - std::move(session_message)); + std::move(session_message), connection_proxy); } // static @@ -711,7 +737,8 @@ const blink::WebString& presentationId, blink::mojom::PresentationMessageType type, const uint8_t* data, - size_t length) { + size_t length, + const blink::WebPresentationConnectionProxy* connection_proxy) { blink::mojom::PresentationSessionInfoPtr session_info = blink::mojom::PresentationSessionInfo::New(); session_info->url = presentationUrl; @@ -722,7 +749,7 @@ session_message->type = type; session_message->data = std::vector<uint8_t>(data, data + length); return new SendMessageRequest(std::move(session_info), - std::move(session_message)); + std::move(session_message), connection_proxy); } PresentationDispatcher::AvailabilityListener::AvailabilityListener(
diff --git a/content/renderer/presentation/presentation_dispatcher.h b/content/renderer/presentation/presentation_dispatcher.h index a1c987a..d8462f8 100644 --- a/content/renderer/presentation/presentation_dispatcher.h +++ b/content/renderer/presentation/presentation_dispatcher.h
@@ -49,6 +49,9 @@ ~PresentationDispatcher() override; private: + // TODO(crbug.com/684116): remove friend class after moving message queue + // logic from PresentationDispatcher to PresentationConnectionProxy. + friend class PresentationConnectionProxy; friend class TestPresentationDispatcher; friend class PresentationDispatcherTest; FRIEND_TEST_ALL_PREFIXES(PresentationDispatcherTest, TestStartSession); @@ -66,47 +69,61 @@ TestSetDefaultPresentationUrls); struct SendMessageRequest { - SendMessageRequest(blink::mojom::PresentationSessionInfoPtr session_info, - blink::mojom::ConnectionMessagePtr message); + SendMessageRequest( + blink::mojom::PresentationSessionInfoPtr session_info, + blink::mojom::ConnectionMessagePtr message, + const blink::WebPresentationConnectionProxy* connection_proxy); ~SendMessageRequest(); blink::mojom::PresentationSessionInfoPtr session_info; blink::mojom::ConnectionMessagePtr message; + // Proxy of Blink connection object |connection| calling connection.send(). + // It does not take ownership of proxy object. Proxy object is owned by + // Blink connection. Blink connection is destroyed after + // PresentationDispatcher so |connection_proxy| should always be valid. + const blink::WebPresentationConnectionProxy* connection_proxy; }; static SendMessageRequest* CreateSendTextMessageRequest( const blink::WebURL& presentationUrl, const blink::WebString& presentationId, - const blink::WebString& message); + const blink::WebString& message, + const blink::WebPresentationConnectionProxy* connection_proxy); static SendMessageRequest* CreateSendBinaryMessageRequest( const blink::WebURL& presentationUrl, const blink::WebString& presentationId, blink::mojom::PresentationMessageType type, const uint8_t* data, - size_t length); + size_t length, + const blink::WebPresentationConnectionProxy* connection_proxy); // WebPresentationClient implementation. void setController(blink::WebPresentationController* controller) override; void setReceiver(blink::WebPresentationReceiver*) override; - void startSession(const blink::WebVector<blink::WebURL>& presentationUrls, - std::unique_ptr<blink::WebPresentationConnectionCallback> + std::unique_ptr<blink::WebPresentationConnectionCallbacks> callback) override; void joinSession(const blink::WebVector<blink::WebURL>& presentationUrls, const blink::WebString& presentationId, - std::unique_ptr<blink::WebPresentationConnectionCallback> + std::unique_ptr<blink::WebPresentationConnectionCallbacks> callback) override; - void sendString(const blink::WebURL& presentationUrl, - const blink::WebString& presentationId, - const blink::WebString& message) override; - void sendArrayBuffer(const blink::WebURL& presentationUrl, - const blink::WebString& presentationId, - const uint8_t* data, - size_t length) override; - void sendBlobData(const blink::WebURL& presentationUrl, - const blink::WebString& presentationId, - const uint8_t* data, - size_t length) override; + void sendString( + const blink::WebURL& presentationUrl, + const blink::WebString& presentationId, + const blink::WebString& message, + const blink::WebPresentationConnectionProxy* connection_proxy) override; + void sendArrayBuffer( + const blink::WebURL& presentationUrl, + const blink::WebString& presentationId, + const uint8_t* data, + size_t length, + const blink::WebPresentationConnectionProxy* connection_proxy) override; + void sendBlobData( + const blink::WebURL& presentationUrl, + const blink::WebString& presentationId, + const uint8_t* data, + size_t length, + const blink::WebPresentationConnectionProxy* connection_proxy) override; void closeSession(const blink::WebURL& presentationUrl, const blink::WebString& presentationId) override; void terminateSession(const blink::WebURL& presentationUrl, @@ -143,7 +160,7 @@ blink::mojom::PresentationSessionInfoPtr session_info) override; void OnSessionCreated( - std::unique_ptr<blink::WebPresentationConnectionCallback> callback, + std::unique_ptr<blink::WebPresentationConnectionCallbacks> callback, blink::mojom::PresentationSessionInfoPtr session_info, blink::mojom::PresentationErrorPtr error); void OnReceiverConnectionAvailable(
diff --git a/content/renderer/presentation/presentation_dispatcher_unittest.cc b/content/renderer/presentation/presentation_dispatcher_unittest.cc index 6ab2c6ceb..4fb461e 100644 --- a/content/renderer/presentation/presentation_dispatcher_unittest.cc +++ b/content/renderer/presentation/presentation_dispatcher_unittest.cc
@@ -7,9 +7,14 @@ #include "base/run_loop.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "content/renderer/presentation/presentation_connection_proxy.h" #include "content/renderer/presentation/presentation_dispatcher.h" +#include "content/renderer/presentation/test_presentation_connection.h" #include "testing/gmock/include/gmock/gmock.h" #include "third_party/WebKit/public/platform/modules/presentation/WebPresentationAvailabilityObserver.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationConnection.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationConnectionCallbacks.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h" #include "third_party/WebKit/public/platform/modules/presentation/WebPresentationError.h" #include "third_party/WebKit/public/platform/modules/presentation/WebPresentationSessionInfo.h" #include "third_party/WebKit/public/web/WebArrayBuffer.h" @@ -19,7 +24,7 @@ using blink::WebArrayBuffer; using blink::WebPresentationAvailabilityCallbacks; using blink::WebPresentationAvailabilityObserver; -using blink::WebPresentationConnectionCallback; +using blink::WebPresentationConnectionCallbacks; using blink::WebPresentationError; using blink::WebPresentationSessionInfo; using blink::WebString; @@ -125,7 +130,7 @@ }; class TestWebPresentationConnectionCallback - : public WebPresentationConnectionCallback { + : public WebPresentationConnectionCallbacks { public: TestWebPresentationConnectionCallback(WebURL url, WebString id) : url_(url), id_(id), callback_called_(false) {} @@ -139,14 +144,19 @@ EXPECT_EQ(info.id, id_); } + blink::WebPresentationConnection* getConnection() override { + return &connection_; + } + private: const WebURL url_; const WebString id_; bool callback_called_; + TestPresentationConnection connection_; }; class TestWebPresentationConnectionErrorCallback - : public WebPresentationConnectionCallback { + : public WebPresentationConnectionCallbacks { public: TestWebPresentationConnectionErrorCallback( WebPresentationError::ErrorType error_type, @@ -162,6 +172,8 @@ EXPECT_EQ(error.message, message_); } + blink::WebPresentationConnection* getConnection() override { return nullptr; } + private: const WebPresentationError::ErrorType error_type_; const WebString message_; @@ -390,7 +402,7 @@ EXPECT_EQ(message.utf8(), message_request->message.value()); callback.Run(true); })); - dispatcher_.sendString(url1_, presentation_id_, message); + dispatcher_.sendString(url1_, presentation_id_, message, nullptr); run_loop.RunUntilIdle(); } @@ -411,7 +423,7 @@ callback.Run(true); })); dispatcher_.sendArrayBuffer(url1_, presentation_id_, array_buffer_data(), - array_buffer_.byteLength()); + array_buffer_.byteLength(), nullptr); run_loop.RunUntilIdle(); } @@ -432,7 +444,7 @@ callback.Run(true); })); dispatcher_.sendBlobData(url1_, presentation_id_, array_buffer_data(), - array_buffer_.byteLength()); + array_buffer_.byteLength(), nullptr); run_loop.RunUntilIdle(); }
diff --git a/content/renderer/presentation/test_presentation_connection.cc b/content/renderer/presentation/test_presentation_connection.cc new file mode 100644 index 0000000..39350bd --- /dev/null +++ b/content/renderer/presentation/test_presentation_connection.cc
@@ -0,0 +1,22 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/presentation/test_presentation_connection.h" + +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationConnectionProxy.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h" + +namespace content { + +TestPresentationConnection::TestPresentationConnection() = default; + +TestPresentationConnection::~TestPresentationConnection() = default; + +void TestPresentationConnection::bindProxy( + std::unique_ptr<blink::WebPresentationConnectionProxy> proxy) { + proxy_ = std::move(proxy); +} + +} // namespace content
diff --git a/content/renderer/presentation/test_presentation_connection.h b/content/renderer/presentation/test_presentation_connection.h new file mode 100644 index 0000000..16ba3cdd --- /dev/null +++ b/content/renderer/presentation/test_presentation_connection.h
@@ -0,0 +1,34 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_PRESENTATION_PRESENTATION_CONNECTION_TEST_HELPER_H_ +#define CONTENT_RENDERER_PRESENTATION_PRESENTATION_CONNECTION_TEST_HELPER_H_ + +#include <memory> + +#include "testing/gmock/include/gmock/gmock.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationConnection.h" + +namespace content { + +class TestPresentationConnection : public blink::WebPresentationConnection { + public: + TestPresentationConnection(); + ~TestPresentationConnection(); + + void bindProxy( + std::unique_ptr<blink::WebPresentationConnectionProxy> proxy) override; + + MOCK_METHOD1(didReceiveTextMessage, void(const blink::WebString& message)); + MOCK_METHOD2(didReceiveBinaryMessage, + void(const uint8_t* data, size_t length)); + MOCK_METHOD1(didChangeState, void(blink::WebPresentationConnectionState)); + + private: + std::unique_ptr<blink::WebPresentationConnectionProxy> proxy_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_PRESENTATION_PRESENTATION_CONNECTION_TEST_HELPER_H_
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index f30efe8..71213fc 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -1852,7 +1852,7 @@ // Since the find pasteboard supports only plain text, this can be simpler // than the |OnCopy()| case. if (frame_->hasSelection()) { - base::string16 selection = frame_->selectionAsText(); + base::string16 selection = frame_->selectionAsText().utf16(); RenderThread::Get()->Send( new ClipboardHostMsg_FindPboardWriteStringAsync(selection)); } @@ -1917,7 +1917,7 @@ if (!frame_->hasSelection()) frame_->selectWordAroundCaret(); - frame_->replaceSelection(text); + frame_->replaceSelection(WebString::fromUTF16(text)); SyncSelectionIfRequired(); } @@ -1925,7 +1925,7 @@ if (!frame_->hasSelection()) return; - frame_->replaceMisspelledRange(text); + frame_->replaceMisspelledRange(WebString::fromUTF16(text)); } void RenderFrameImpl::OnCopyImageAt(int x, int y) { @@ -1953,8 +1953,8 @@ TRACE_EVENT_SCOPE_THREAD); v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); - v8::Local<v8::Value> result = - frame_->executeScriptAndReturnValue(WebScriptSource(jscript)); + v8::Local<v8::Value> result = frame_->executeScriptAndReturnValue( + WebScriptSource(WebString::fromUTF16(jscript))); HandleJavascriptExecutionResult(jscript, id, notify_result, result); } @@ -1972,8 +1972,8 @@ std::unique_ptr<blink::WebScopedUserGesture> gesture( has_user_gesture ? new blink::WebScopedUserGesture(frame_) : nullptr); v8::HandleScope handle_scope(blink::mainThreadIsolate()); - v8::Local<v8::Value> result = - frame_->executeScriptAndReturnValue(WebScriptSource(jscript)); + v8::Local<v8::Value> result = frame_->executeScriptAndReturnValue( + WebScriptSource(WebString::fromUTF16(jscript))); HandleJavascriptExecutionResult(jscript, id, notify_result, result); } @@ -1996,7 +1996,7 @@ } v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); - WebScriptSource script = WebScriptSource(jscript); + WebScriptSource script = WebScriptSource(WebString::fromUTF16(jscript)); JavaScriptIsolatedWorldRequest* request = new JavaScriptIsolatedWorldRequest( id, notify_result, routing_id_, weak_factory_.GetWeakPtr()); frame_->requestExecuteScriptInIsolatedWorld(world_id, &script, 1, false, @@ -2232,22 +2232,21 @@ context); serialized_script_value = WebSerializedScriptValue::serialize(result_value); } else { - serialized_script_value = WebSerializedScriptValue::fromString(params.data); + serialized_script_value = + WebSerializedScriptValue::fromString(WebString::fromUTF16(params.data)); } // We must pass in the target_origin to do the security check on this side, // since it may have changed since the original postMessage call was made. WebSecurityOrigin target_origin; if (!params.target_origin.empty()) { - target_origin = - WebSecurityOrigin::createFromString(WebString(params.target_origin)); + target_origin = WebSecurityOrigin::createFromString( + WebString::fromUTF16(params.target_origin)); } WebDOMMessageEvent msg_event(serialized_script_value, - params.source_origin, - source_frame, - frame_->document(), - channels); + WebString::fromUTF16(params.source_origin), + source_frame, frame_->document(), channels); frame_->dispatchMessageEventWithOriginCheck(target_origin, msg_event); } @@ -2275,8 +2274,7 @@ } Send(new FrameHostMsg_TextSurroundingSelectionResponse( - routing_id_, - surroundingText.textContent(), + routing_id_, surroundingText.textContent().utf16(), surroundingText.startOffsetInTextContent(), surroundingText.endOffsetInTextContent())); } @@ -2737,8 +2735,8 @@ return plugin; } - if (base::UTF16ToUTF8(base::StringPiece16(params.mimeType)) == - kBrowserPluginMimeType) { + if (params.mimeType.containsOnlyASCII() && + params.mimeType.ascii() == kBrowserPluginMimeType) { return BrowserPluginManager::Get()->CreateBrowserPlugin( this, GetContentClient() ->renderer() @@ -2837,7 +2835,8 @@ initial_cdm, media_surface_manager_, media_observer, // TODO(avayvod, asvitkine): Query the value directly when it is available // in the renderer process. See https://crbug.com/681160. - GetWebkitPreferences().max_keyframe_distance_to_disable_background_video); + GetWebkitPreferences().max_keyframe_distance_to_disable_background_video, + GetContentClient()->renderer()->AllowMediaSuspend()); bool use_fallback_path = false; #if defined(OS_ANDROID) @@ -3025,9 +3024,8 @@ FrameHostMsg_CreateChildFrame_Params params; params.parent_routing_id = routing_id_; params.scope = scope; - params.frame_name = base::UTF16ToUTF8(base::StringPiece16(name)); - params.frame_unique_name = - base::UTF16ToUTF8(base::StringPiece16(unique_name)); + params.frame_name = name.utf8(); + params.frame_unique_name = unique_name.utf8(); params.sandbox_flags = sandbox_flags; params.frame_owner_properties = FrameOwnerProperties(frame_owner_properties); Send(new FrameHostMsg_CreateChildFrame(params, &child_routing_id)); @@ -3163,8 +3161,7 @@ void RenderFrameImpl::didChangeName(const blink::WebString& name, const blink::WebString& unique_name) { Send(new FrameHostMsg_DidChangeName( - routing_id_, base::UTF16ToUTF8(base::StringPiece16(name)), - base::UTF16ToUTF8(base::StringPiece16(unique_name)))); + routing_id_, name.utf8(), unique_name.utf8())); if (!committed_first_load_) name_changed_before_first_commit_ = true; @@ -3201,7 +3198,7 @@ return; ContentSecurityPolicyHeader header; - header.header_value = base::UTF16ToUTF8(base::StringPiece16(header_value)); + header.header_value = header_value.utf8(); header.type = type; header.source = source; Send(new FrameHostMsg_DidAddContentSecurityPolicy(routing_id_, header)); @@ -3232,7 +3229,7 @@ bool RenderFrameImpl::shouldReportDetailedMessageForSource( const blink::WebString& source) { return GetContentClient()->renderer()->ShouldReportDetailedMessageForSource( - source); + source.utf16()); } void RenderFrameImpl::didAddMessageToConsole( @@ -3260,15 +3257,15 @@ if (shouldReportDetailedMessageForSource(source_name)) { for (auto& observer : observers_) { - observer.DetailedConsoleMessageAdded(message.text, source_name, - stack_trace, source_line, - static_cast<uint32_t>(log_severity)); + observer.DetailedConsoleMessageAdded( + message.text.utf16(), source_name.utf16(), stack_trace.utf16(), + source_line, static_cast<uint32_t>(log_severity)); } } Send(new FrameHostMsg_DidAddMessageToConsole( - routing_id_, static_cast<int32_t>(log_severity), message.text, - static_cast<int32_t>(source_line), source_name)); + routing_id_, static_cast<int32_t>(log_severity), message.text.utf16(), + static_cast<int32_t>(source_line), source_name.utf16())); } void RenderFrameImpl::loadURLExternally(const blink::WebURLRequest& request, @@ -3283,7 +3280,7 @@ params.url = request.url(); params.referrer = referrer; params.initiator_origin = request.requestorOrigin(); - params.suggested_name = suggested_name; + params.suggested_name = suggested_name.utf16(); Send(new FrameHostMsg_DownloadUrl(params)); } else { @@ -3768,10 +3765,10 @@ DCHECK_EQ(frame_, frame); // Ignore all but top level navigations. if (!frame->parent()) { - base::string16 title16 = title; base::trace_event::TraceLog::GetInstance()->UpdateProcessLabel( - routing_id_, base::UTF16ToUTF8(title16)); + routing_id_, title.utf8()); + base::string16 title16 = title.utf16(); base::string16 shortened_title = title16.substr(0, kMaxTitleChars); Send(new FrameHostMsg_UpdateTitle(routing_id_, shortened_title, direction)); @@ -4062,19 +4059,13 @@ } void RenderFrameImpl::runModalAlertDialog(const blink::WebString& message) { - RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_ALERT, - message, - base::string16(), - frame_->document().url(), - NULL); + RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_ALERT, message.utf16(), + base::string16(), frame_->document().url(), NULL); } bool RenderFrameImpl::runModalConfirmDialog(const blink::WebString& message) { - return RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_CONFIRM, - message, - base::string16(), - frame_->document().url(), - NULL); + return RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_CONFIRM, message.utf16(), + base::string16(), frame_->document().url(), NULL); } bool RenderFrameImpl::runModalPromptDialog( @@ -4083,12 +4074,10 @@ blink::WebString* actual_value) { base::string16 result; bool ok = RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_PROMPT, - message, - default_value, - frame_->document().url(), - &result); + message.utf16(), default_value.utf16(), + frame_->document().url(), &result); if (ok) - actual_value->assign(result); + actual_value->assign(WebString::fromUTF16(result)); return ok; } @@ -4121,10 +4110,10 @@ ipc_params.mode = FileChooserParams::Save; else ipc_params.mode = FileChooserParams::Open; - ipc_params.title = params.title; + ipc_params.title = params.title.utf16(); ipc_params.accept_types.reserve(params.acceptTypes.size()); for (const auto& type : params.acceptTypes) - ipc_params.accept_types.push_back(type); + ipc_params.accept_types.push_back(type.utf16()); ipc_params.need_local_path = params.needLocalPath; #if defined(OS_ANDROID) ipc_params.capture = params.useMediaCapture; @@ -4697,22 +4686,15 @@ const WebURL& url, const WebString& title) { bool user_gesture = WebUserGestureIndicator::isProcessingUserGesture(); - Send(new FrameHostMsg_RegisterProtocolHandler( - routing_id_, - base::UTF16ToUTF8(base::StringPiece16(scheme)), - url, - title, - user_gesture)); + Send(new FrameHostMsg_RegisterProtocolHandler(routing_id_, scheme.utf8(), url, + title.utf16(), user_gesture)); } void RenderFrameImpl::unregisterProtocolHandler(const WebString& scheme, const WebURL& url) { bool user_gesture = WebUserGestureIndicator::isProcessingUserGesture(); - Send(new FrameHostMsg_UnregisterProtocolHandler( - routing_id_, - base::UTF16ToUTF8(base::StringPiece16(scheme)), - url, - user_gesture)); + Send(new FrameHostMsg_UnregisterProtocolHandler(routing_id_, scheme.utf8(), + url, user_gesture)); } void RenderFrameImpl::didSerializeDataForFrame( @@ -5597,7 +5579,8 @@ // Just navigate back/forward. plugin->selectFindResult(options.forward, request_id); } else { - if (!plugin->startFind(search_text, options.matchCase, request_id)) { + if (!plugin->startFind(WebString::fromUTF16(search_text), + options.matchCase, request_id)) { // Send "no results". SendFindReply(request_id, 0 /* match_count */, 0 /* ordinal */, gfx::Rect(), true /* final_status_update */); @@ -5606,7 +5589,7 @@ return; } - frame_->requestFind(request_id, search_text, options); + frame_->requestFind(request_id, WebString::fromUTF16(search_text), options); } void RenderFrameImpl::OnClearActiveFindMatch() { @@ -5655,9 +5638,9 @@ files.size()); for (size_t i = 0; i < files.size(); ++i) { blink::WebFileChooserCompletion::SelectedFileInfo selected_file; - selected_file.path = files[i].file_path.AsUTF16Unsafe(); + selected_file.path = blink::FilePathToWebString(files[i].file_path); selected_file.displayName = - base::FilePath(files[i].display_name).AsUTF16Unsafe(); + blink::FilePathToWebString(base::FilePath(files[i].display_name)); if (files[i].file_system_url.is_valid()) { selected_file.fileSystemURL = files[i].file_system_url; selected_file.length = files[i].length; @@ -6072,10 +6055,10 @@ offset = 0; size_t length = selection.endOffset() - offset + kExtraCharsBeforeAndAfterSelection; - text = frame_->rangeAsText(WebRange(offset, length)); + text = frame_->rangeAsText(WebRange(offset, length)).utf16(); } else { offset = selection.startOffset(); - text = frame_->selectionAsText(); + text = frame_->selectionAsText().utf16(); // http://crbug.com/101435 // In some case, frame->selectionAsText() returned text's length is not // equal to the length returned from @@ -6346,7 +6329,7 @@ blink::WebLocalFrame* frame) { bool show_repost_interstitial = (error.reason == net::ERR_CACHE_MISS && - base::EqualsASCII(base::StringPiece16(request.httpMethod()), "POST")); + base::EqualsASCII(request.httpMethod().utf16(), "POST")); FrameHostMsg_DidFailProvisionalLoadWithError_Params params; params.error_code = error.reason;
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index 843f030..c080cefc 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -459,10 +459,10 @@ FrameMsg_PostMessage_Params params; params.is_data_raw_string = false; - params.data = event.data().toString(); - params.source_origin = event.origin(); + params.data = event.data().toString().utf16(); + params.source_origin = event.origin().utf16(); if (!target_origin.isNull()) - params.target_origin = target_origin.toString(); + params.target_origin = target_origin.toString().utf16(); params.message_ports = WebMessagePortChannelImpl::ExtractMessagePortIDs(event.releaseChannels());
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 0d23fcdd..e90b015 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -188,9 +188,8 @@ FrameReplicationState result; // can't recover result.scope - no way to get WebTreeScopeType via public // blink API... - result.name = base::UTF16ToUTF8(base::StringPiece16(frame->assignedName())); - result.unique_name = - base::UTF16ToUTF8(base::StringPiece16(frame->uniqueName())); + result.name = frame->assignedName().utf8(); + result.unique_name = frame->uniqueName().utf8(); result.sandbox_flags = frame->effectiveSandboxFlags(); // result.should_enforce_strict_mixed_content_checking is calculated in the // browser... @@ -1276,7 +1275,8 @@ // result. const int kMaxOutputCharacters = 128; base::string16 output = WebFrameContentDumper::dumpWebViewAsText( - view()->GetWebView(), kMaxOutputCharacters); + view()->GetWebView(), kMaxOutputCharacters) + .utf16(); EXPECT_EQ(base::WideToUTF16(ime_message->result), output); } } @@ -1325,7 +1325,8 @@ // expected result. const int kMaxOutputCharacters = 16; base::string16 output = WebFrameContentDumper::dumpWebViewAsText( - view()->GetWebView(), kMaxOutputCharacters); + view()->GetWebView(), kMaxOutputCharacters) + .utf16(); EXPECT_EQ(base::WideToUTF16(kTextDirection[i].expected_result), output); } } @@ -1693,9 +1694,9 @@ // Copy the document content to std::wstring and compare with the // expected result. const int kMaxOutputCharacters = 256; - std::string output = base::UTF16ToUTF8( - base::StringPiece16(WebFrameContentDumper::dumpWebViewAsText( - view()->GetWebView(), kMaxOutputCharacters))); + std::string output = WebFrameContentDumper::dumpWebViewAsText( + view()->GetWebView(), kMaxOutputCharacters) + .utf8(); EXPECT_EQ(output, "hello \n\nworld"); } @@ -1835,9 +1836,9 @@ FrameLoadWaiter(main_frame).Wait(); const int kMaxOutputCharacters = 22; EXPECT_EQ("A suffusion of yellow.", - base::UTF16ToASCII( - base::StringPiece16(WebFrameContentDumper::dumpWebViewAsText( - view()->GetWebView(), kMaxOutputCharacters)))); + WebFrameContentDumper::dumpWebViewAsText(view()->GetWebView(), + kMaxOutputCharacters) + .ascii()); } #if defined(OS_ANDROID) @@ -1870,9 +1871,9 @@ FrameLoadWaiter(main_frame).Wait(); const int kMaxOutputCharacters = 22; EXPECT_EQ("A suffusion of yellow.", - base::UTF16ToASCII( - base::StringPiece16(WebFrameContentDumper::dumpWebViewAsText( - view()->GetWebView(), kMaxOutputCharacters)))); + WebFrameContentDumper::dumpWebViewAsText(view()->GetWebView(), + kMaxOutputCharacters) + .ascii()); } // Ensure the render view sends favicon url update events correctly.
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index a4ddccb4..fc848215 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -382,43 +382,43 @@ void SetStandardFontFamilyWrapper(WebSettings* settings, const base::string16& font, UScriptCode script) { - settings->setStandardFontFamily(font, script); + settings->setStandardFontFamily(WebString::fromUTF16(font), script); } void SetFixedFontFamilyWrapper(WebSettings* settings, const base::string16& font, UScriptCode script) { - settings->setFixedFontFamily(font, script); + settings->setFixedFontFamily(WebString::fromUTF16(font), script); } void SetSerifFontFamilyWrapper(WebSettings* settings, const base::string16& font, UScriptCode script) { - settings->setSerifFontFamily(font, script); + settings->setSerifFontFamily(WebString::fromUTF16(font), script); } void SetSansSerifFontFamilyWrapper(WebSettings* settings, const base::string16& font, UScriptCode script) { - settings->setSansSerifFontFamily(font, script); + settings->setSansSerifFontFamily(WebString::fromUTF16(font), script); } void SetCursiveFontFamilyWrapper(WebSettings* settings, const base::string16& font, UScriptCode script) { - settings->setCursiveFontFamily(font, script); + settings->setCursiveFontFamily(WebString::fromUTF16(font), script); } void SetFantasyFontFamilyWrapper(WebSettings* settings, const base::string16& font, UScriptCode script) { - settings->setFantasyFontFamily(font, script); + settings->setFantasyFontFamily(WebString::fromUTF16(font), script); } void SetPictographFontFamilyWrapper(WebSettings* settings, const base::string16& font, UScriptCode script) { - settings->setPictographFontFamily(font, script); + settings->setPictographFontFamily(WebString::fromUTF16(font), script); } // If |scriptCode| is a member of a family of "similar" script codes, returns @@ -1395,7 +1395,8 @@ params->window_container_type = WindowFeaturesToContainerType(features); params->session_storage_namespace_id = session_storage_namespace_id_; if (frame_name != "_blank") - params->frame_name = base::UTF16ToUTF8(base::StringPiece16(frame_name)); + params->frame_name = frame_name.utf8( + WebString::UTF8ConversionMode::kStrictReplacingErrorsWithFFFD); params->opener_url = creator->document().url(); // The browser process uses the top frame's URL for a content settings check @@ -1603,8 +1604,8 @@ blink::WebTextDirection main_text_hint, const blink::WebString& sub_text, blink::WebTextDirection sub_text_hint) { - base::string16 wrapped_main_text = main_text; - base::string16 wrapped_sub_text = sub_text; + base::string16 wrapped_main_text = main_text.utf16(); + base::string16 wrapped_sub_text = sub_text.utf16(); SetValidationMessageDirection( &wrapped_main_text, main_text_hint, &wrapped_sub_text, sub_text_hint); @@ -2071,7 +2072,7 @@ WebVector<WebString> ws_file_names(paths.size()); for (size_t i = 0; i < paths.size(); ++i) - ws_file_names[i] = paths[i].AsUTF16Unsafe(); + ws_file_names[i] = blink::FilePathToWebString(paths[i]); enumeration_completions_[id]->didChooseFile(ws_file_names); enumeration_completions_.erase(id);
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 3d64c0d..d251ad7 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -64,6 +64,7 @@ #include "ipc/ipc_sync_message.h" #include "ppapi/features/features.h" #include "skia/ext/platform_canvas.h" +#include "third_party/WebKit/public/platform/FilePathConversion.h" #include "third_party/WebKit/public/platform/WebCursorInfo.h" #include "third_party/WebKit/public/platform/WebDragData.h" #include "third_party/WebKit/public/platform/WebDragOperation.h" @@ -187,7 +188,7 @@ if (meta_data_item.kind == DropData::Kind::STRING) { WebDragData::Item item; item.storageType = WebDragData::Item::StorageTypeString; - item.stringType = meta_data_item.mime_type; + item.stringType = WebString::fromUTF16(meta_data_item.mime_type); // Have to pass a dummy URL here instead of an empty URL because the // DropData received by browser_plugins goes through a round trip: // DropData::MetaData --> WebDragData-->DropData. In the end, DropData @@ -208,7 +209,7 @@ !meta_data_item.filename.empty()) { WebDragData::Item item; item.storageType = WebDragData::Item::StorageTypeFilename; - item.filenameData = meta_data_item.filename.AsUTF16Unsafe(); + item.filenameData = blink::FilePathToWebString(meta_data_item.filename); item_list.push_back(item); continue; } @@ -240,7 +241,7 @@ WebDragData::Item item; item.storageType = WebDragData::Item::StorageTypeString; item.stringType = WebString::fromUTF8(ui::Clipboard::kMimeTypeText); - item.stringData = drop_data.text.string(); + item.stringData = WebString::fromUTF16(drop_data.text.string()); item_list.push_back(item); } @@ -249,7 +250,7 @@ item.storageType = WebDragData::Item::StorageTypeString; item.stringType = WebString::fromUTF8(ui::Clipboard::kMimeTypeURIList); item.stringData = WebString::fromUTF8(drop_data.url.spec()); - item.title = drop_data.url_title; + item.title = WebString::fromUTF16(drop_data.url_title); item_list.push_back(item); } @@ -257,7 +258,7 @@ WebDragData::Item item; item.storageType = WebDragData::Item::StorageTypeString; item.stringType = WebString::fromUTF8(ui::Clipboard::kMimeTypeHTML); - item.stringData = drop_data.html.string(); + item.stringData = WebString::fromUTF16(drop_data.html.string()); item.baseURL = drop_data.html_base_url; item_list.push_back(item); } @@ -268,8 +269,9 @@ ++it) { WebDragData::Item item; item.storageType = WebDragData::Item::StorageTypeFilename; - item.filenameData = it->path.AsUTF16Unsafe(); - item.displayNameData = it->display_name.AsUTF16Unsafe(); + item.filenameData = blink::FilePathToWebString(it->path); + item.displayNameData = + blink::FilePathToWebString(base::FilePath(it->display_name)); item_list.push_back(item); } @@ -291,15 +293,15 @@ ++it) { WebDragData::Item item; item.storageType = WebDragData::Item::StorageTypeString; - item.stringType = it->first; - item.stringData = it->second; + item.stringType = WebString::fromUTF16(it->first); + item.stringData = WebString::fromUTF16(it->second); item_list.push_back(item); } WebDragData result; result.initialize(); result.setItems(item_list); - result.setFilesystemId(drop_data.filesystem_id); + result.setFilesystemId(WebString::fromUTF16(drop_data.filesystem_id)); return result; } @@ -1495,7 +1497,7 @@ void RenderWidget::setToolTipText(const blink::WebString& text, WebTextDirection hint) { - Send(new ViewHostMsg_SetTooltipText(routing_id_, text, hint)); + Send(new ViewHostMsg_SetTooltipText(routing_id_, text.utf16(), hint)); } void RenderWidget::setWindowRect(const WebRect& rect_in_screen) { @@ -1552,7 +1554,8 @@ blink::WebInputMethodController* controller = GetInputMethodController(); if (!controller || !controller->setComposition( - text, WebVector<WebCompositionUnderline>(underlines), selection_start, + WebString::fromUTF16(text), + WebVector<WebCompositionUnderline>(underlines), selection_start, selection_end)) { // If we failed to set the composition text, then we need to let the browser // process to cancel the input method's ongoing composition session, to make @@ -1587,7 +1590,8 @@ ImeEventGuard guard(this); input_handler_->set_handling_input_event(true); if (auto* controller = GetInputMethodController()) - controller->commitText(text, WebVector<WebCompositionUnderline>(underlines), + controller->commitText(WebString::fromUTF16(text), + WebVector<WebCompositionUnderline>(underlines), relative_cursor_pos); input_handler_->set_handling_input_event(false); UpdateCompositionInfo(false /* not an immediate request */);
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index 1da9e4d..ac5c05a3 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -709,8 +709,7 @@ int session_id = 0; if (input_device_id.isNull() || - !base::StringToInt(base::UTF16ToUTF8( - base::StringPiece16(input_device_id)), &session_id)) { + !base::StringToInt(input_device_id.utf8(), &session_id)) { if (input_channels > 0) DLOG(WARNING) << "createAudioDevice(): request for audio input ignored"; @@ -759,13 +758,14 @@ RenderThread::Get()->Send( new FrameHostMsg_GetPlugins(refresh, mainFrameOrigin, &plugins)); for (const WebPluginInfo& plugin : plugins) { - builder->addPlugin( - plugin.name, plugin.desc, - plugin.path.BaseName().AsUTF16Unsafe()); + builder->addPlugin(WebString::fromUTF16(plugin.name), + WebString::fromUTF16(plugin.desc), + blink::FilePathToWebString(plugin.path.BaseName())); for (const WebPluginMimeType& mime_type : plugin.mime_types) { builder->addMediaTypeToLastPlugin( - WebString::fromUTF8(mime_type.mime_type), mime_type.description); + WebString::fromUTF8(mime_type.mime_type), + WebString::fromUTF16(mime_type.description)); for (const auto& extension : mime_type.file_extensions) { builder->addFileExtensionToLastMediaType( @@ -1107,7 +1107,7 @@ blink::WebString RendererBlinkPlatformImpl::convertIDNToUnicode( const blink::WebString& host) { - return url_formatter::IDNToUnicode(host.utf8()); + return WebString::fromUTF16(url_formatter::IDNToUnicode(host.utf8())); } //------------------------------------------------------------------------------
diff --git a/content/renderer/renderer_webcookiejar_impl.cc b/content/renderer/renderer_webcookiejar_impl.cc index b3f6e26..8ed110f 100644 --- a/content/renderer/renderer_webcookiejar_impl.cc +++ b/content/renderer/renderer_webcookiejar_impl.cc
@@ -18,7 +18,8 @@ void RendererWebCookieJarImpl::setCookie( const WebURL& url, const WebURL& first_party_for_cookies, const WebString& value) { - std::string value_utf8 = base::UTF16ToUTF8(base::StringPiece16(value)); + std::string value_utf8 = value.utf8( + WebString::UTF8ConversionMode::kStrictReplacingErrorsWithFFFD); RenderThreadImpl::current()->render_frame_message_filter()->SetCookie( sender_->GetRoutingID(), url, first_party_for_cookies, value_utf8); }
diff --git a/content/renderer/savable_resources.cc b/content/renderer/savable_resources.cc index cb2116147..395b1f7 100644 --- a/content/renderer/savable_resources.cc +++ b/content/renderer/savable_resources.cc
@@ -150,10 +150,12 @@ attribute_name = "data"; } else if (element.hasHTMLTagName("link")) { // If the link element is not linked to css, ignore it. - if (base::LowerCaseEqualsASCII( - base::StringPiece16(element.getAttribute("type")), "text/css") || - base::LowerCaseEqualsASCII( - base::StringPiece16(element.getAttribute("rel")), "stylesheet")) { + WebString type = element.getAttribute("type"); + WebString rel = element.getAttribute("rel"); + if ((type.containsOnlyASCII() && + base::LowerCaseEqualsASCII(type.ascii(), "text/css")) || + (rel.containsOnlyASCII() && + base::LowerCaseEqualsASCII(rel.ascii(), "stylesheet"))) { // TODO(jnd): Add support for extracting links of sub-resources which // are inside style-sheet such as @import, url(), etc. // See bug: http://b/issue?id=1111667.
diff --git a/content/renderer/speech_recognition_dispatcher.cc b/content/renderer/speech_recognition_dispatcher.cc index a9574cd..637b97b 100644 --- a/content/renderer/speech_recognition_dispatcher.cc +++ b/content/renderer/speech_recognition_dispatcher.cc
@@ -108,8 +108,7 @@ SpeechRecognitionGrammar(grammar.src().string().utf8(), grammar.weight())); } - msg_params.language = - base::UTF16ToUTF8(base::StringPiece16(params.language())); + msg_params.language = params.language().utf8(); msg_params.max_hypotheses = static_cast<uint32_t>(params.maxAlternatives()); msg_params.continuous = params.continuous(); msg_params.interim_results = params.interimResults(); @@ -253,7 +252,7 @@ WebVector<WebString> transcripts(num_hypotheses); WebVector<float> confidences(num_hypotheses); for (size_t i = 0; i < num_hypotheses; ++i) { - transcripts[i] = result.hypotheses[i].utterance; + transcripts[i] = WebString::fromUTF16(result.hypotheses[i].utterance); confidences[i] = static_cast<float>(result.hypotheses[i].confidence); } webkit_result->assign(transcripts, confidences, !result.is_provisional);
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc index 4fa8f075..9dd447ef 100644 --- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc +++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
@@ -97,6 +97,10 @@ // Blocklisted descriptor const char kBlocklistedDescriptorUUID[] = "bad2ddcf-60db-45cd-bef9-fd72b153cf7c"; +const char kBlocklistedReadDescriptorUUID[] = + "bad3ec61-3cc3-4954-9702-7977df514114"; +const char kCharacteristicUserDescription[] = + "gatt.characteristic_user_description"; // Invokes Run() on the k-th argument of the function with no arguments. ACTION_TEMPLATE(RunCallback, @@ -160,7 +164,7 @@ observer.DeviceChanged(adapter, device); } -void PerformReadValue( +void PerformCharacteristicReadValue( MockBluetoothAdapter* adapter, MockBluetoothGattCharacteristic* characteristic, const BluetoothRemoteGattCharacteristic::ValueCallback& callback, @@ -171,6 +175,17 @@ callback.Run(value); } +void PerformDescriptorReadValue( + MockBluetoothAdapter* adapter, + MockBluetoothGattDescriptor* descriptor, + const BluetoothRemoteGattDescriptor::ValueCallback& callback, + const std::vector<uint8_t>& value) { + for (auto& observer : adapter->GetObservers()) { + observer.GattDescriptorValueChanged(adapter, descriptor, value); + } + callback.Run(value); +} + } // namespace namespace content { @@ -216,7 +231,10 @@ if (fake_adapter_name == "DisconnectingHeartRateAdapter") return GetDisconnectingHeartRateAdapter(); if (fake_adapter_name == "DisconnectingHealthThermometerAdapter") - return GetDisconnectingHealthThermometer(); + return GetDisconnectingHealthThermometer(true); + if (fake_adapter_name == + "MissingDescriptorsDisconnectingHealthThermometerAdapter") + return GetDisconnectingHealthThermometer(false); if (fake_adapter_name == "DisconnectingDuringServiceRetrievalAdapter") return GetServicesDiscoveredAfterReconnectionAdapter(true /* disconnect */); if (fake_adapter_name == "ServicesDiscoveredAfterReconnectionAdapter") @@ -679,7 +697,8 @@ // static scoped_refptr<NiceMockBluetoothAdapter> -LayoutTestBluetoothAdapterProvider::GetDisconnectingHealthThermometer() { +LayoutTestBluetoothAdapterProvider::GetDisconnectingHealthThermometer( + bool add_descriptors) { scoped_refptr<NiceMockBluetoothAdapter> adapter(GetEmptyAdapter()); NiceMockBluetoothAdapter* adapter_ptr = adapter.get(); @@ -724,30 +743,62 @@ return GetBaseGATTNotifySession(measurement_ptr->GetWeakPtr()); })); - auto user_description = base::MakeUnique<NiceMockBluetoothGattDescriptor>( - measurement_interval.get(), "gatt.characteristic_user_description", - BluetoothUUID(kUserDescriptionUUID), false, - device::BluetoothRemoteGattCharacteristic::PROPERTY_READ); + if (add_descriptors) { + const std::string descriptorName = kCharacteristicUserDescription; + auto user_description = base::MakeUnique<NiceMockBluetoothGattDescriptor>( + measurement_interval.get(), descriptorName, + BluetoothUUID(kUserDescriptionUUID), false /* is_local */, + device::BluetoothRemoteGattCharacteristic::PROPERTY_READ); - auto client_config = base::MakeUnique<NiceMockBluetoothGattDescriptor>( - measurement_interval.get(), "gatt.client_characteristic_configuration", - BluetoothUUID(kClientConfigUUID), false, - device::BluetoothRemoteGattCharacteristic::PROPERTY_READ | - device::BluetoothRemoteGattCharacteristic::PROPERTY_WRITE); + ON_CALL(*user_description, ReadRemoteDescriptor(_, _)) + .WillByDefault(Invoke([descriptorName]( + const BluetoothRemoteGattDescriptor::ValueCallback& callback, + const BluetoothRemoteGattDescriptor::ErrorCallback&) { + std::vector<uint8_t> value(descriptorName.begin(), + descriptorName.end()); + callback.Run(value); + })); - // Add it here with full permission as the blocklist should prevent us from - // accessing this descriptor - auto blocklisted_descriptor = - base::MakeUnique<NiceMockBluetoothGattDescriptor>( - measurement_interval.get(), "bad2ddcf-60db-45cd-bef9-fd72b153cf7c", - BluetoothUUID(kBlocklistedDescriptorUUID), false, - device::BluetoothRemoteGattCharacteristic::PROPERTY_READ | - device::BluetoothRemoteGattCharacteristic::PROPERTY_WRITE); + auto client_config = base::MakeUnique<NiceMockBluetoothGattDescriptor>( + measurement_interval.get(), "gatt.client_characteristic_configuration", + BluetoothUUID(kClientConfigUUID), false /* is_local */, + device::BluetoothRemoteGattCharacteristic::PROPERTY_READ | + device::BluetoothRemoteGattCharacteristic::PROPERTY_WRITE); - measurement_interval->AddMockDescriptor(std::move(user_description)); - measurement_interval->AddMockDescriptor(std::move(client_config)); - measurement_interval->AddMockDescriptor(std::move(blocklisted_descriptor)); + auto no_read_descriptor = base::MakeUnique<NiceMockBluetoothGattDescriptor>( + measurement_interval.get(), kBlocklistedReadDescriptorUUID, + BluetoothUUID(kBlocklistedReadDescriptorUUID), false, + device::BluetoothRemoteGattCharacteristic::PROPERTY_READ | + device::BluetoothRemoteGattCharacteristic::PROPERTY_WRITE); + std::vector<uint8_t> value(1); + value[0] = false; + + // Crash if ReadRemoteDescriptor called. Not using GoogleMock's Expect + // because this is used in layout tests that may not report a mock + // expectation + // error correctly as a layout test failure. + ON_CALL(*no_read_descriptor, ReadRemoteDescriptor(_, _)) + .WillByDefault( + Invoke([](const BluetoothRemoteGattDescriptor::ValueCallback&, + const BluetoothRemoteGattDescriptor::ErrorCallback&) { + NOTREACHED(); + })); + + // Add it here with full permission as the blocklist should prevent us from + // accessing this descriptor + auto blocklisted_descriptor = + base::MakeUnique<NiceMockBluetoothGattDescriptor>( + measurement_interval.get(), kBlocklistedDescriptorUUID, + BluetoothUUID(kBlocklistedDescriptorUUID), false, + device::BluetoothRemoteGattCharacteristic::PROPERTY_READ | + device::BluetoothRemoteGattCharacteristic::PROPERTY_WRITE); + + measurement_interval->AddMockDescriptor(std::move(user_description)); + measurement_interval->AddMockDescriptor(std::move(client_config)); + measurement_interval->AddMockDescriptor(std::move(blocklisted_descriptor)); + measurement_interval->AddMockDescriptor(std::move(no_read_descriptor)); + } health_thermometer->AddMockCharacteristic(std::move(measurement_interval)); device->AddMockService(std::move(health_thermometer)); @@ -987,9 +1038,9 @@ error_callback) { base::Closure pending; if (succeeds) { - pending = - base::Bind(&PerformReadValue, base::RetainedRef(adapter_ptr), - measurement_ptr, callback, std::vector<uint8_t>({1})); + pending = base::Bind(&PerformCharacteristicReadValue, + base::RetainedRef(adapter_ptr), measurement_ptr, + callback, std::vector<uint8_t>({1})); } else { pending = base::Bind(error_callback, BluetoothRemoteGattService::GATT_ERROR_FAILED); @@ -1051,6 +1102,38 @@ } })); + auto user_descriptor = base::MakeUnique<NiceMockBluetoothGattDescriptor>( + measurement_interval.get(), kCharacteristicUserDescription, + BluetoothUUID(kUserDescriptionUUID), false, + device::BluetoothRemoteGattCharacteristic::PROPERTY_READ); + + NiceMockBluetoothGattDescriptor* user_descriptor_ptr = user_descriptor.get(); + ON_CALL(*user_descriptor, ReadRemoteDescriptor(_, _)) + .WillByDefault(Invoke([adapter_ptr, device_ptr, user_descriptor_ptr, + disconnect, succeeds]( + const BluetoothRemoteGattDescriptor::ValueCallback& callback, + const BluetoothRemoteGattDescriptor::ErrorCallback& error_callback) { + base::Closure pending; + if (succeeds) { + pending = base::Bind( + &PerformDescriptorReadValue, base::RetainedRef(adapter_ptr), + user_descriptor_ptr, callback, std::vector<uint8_t>({1})); + } else { + pending = base::Bind(error_callback, + BluetoothRemoteGattService::GATT_ERROR_FAILED); + } + device_ptr->PushPendingCallback(pending); + if (disconnect) { + device_ptr->SetConnected(false); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&NotifyDeviceChanged, base::RetainedRef(adapter_ptr), + device_ptr)); + } + })); + + measurement_interval->AddMockDescriptor(std::move(user_descriptor)); + health_thermometer->AddMockCharacteristic(std::move(measurement_interval)); device->AddMockService(std::move(health_thermometer)); adapter->AddMockDevice(std::move(device)); @@ -1639,6 +1722,17 @@ ON_CALL(*characteristic, StartNotifySession(_, _)) .WillByDefault(RunCallback<1 /* error_callback */>(error_code)); + // Add error descriptor to |characteristic| + auto error_descriptor = base::MakeUnique<NiceMockBluetoothGattDescriptor>( + characteristic.get(), kCharacteristicUserDescription, + BluetoothUUID(kUserDescriptionUUID), false, + device::BluetoothRemoteGattCharacteristic::PROPERTY_READ); + + ON_CALL(*error_descriptor, ReadRemoteDescriptor(_, _)) + .WillByDefault(RunCallback<1 /* error_callback */>(error_code)); + + characteristic->AddMockDescriptor(std::move(error_descriptor)); + return characteristic; } @@ -1719,4 +1813,4 @@ base::StringPrintf("%012" PRIx64, addr)); } -} // namespace content +} // namespace content \ No newline at end of file
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h index 1b4f4fd8..9eb85ef 100644 --- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h +++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
@@ -341,15 +341,17 @@ // - StartNotifySession: Run success callback. // - GetProperties: Returns // BluetoothRemoteGattCharacteristic::PROPERTY_READ - // - Descriptors + // - Descriptors (if |addDescriptors| input is true) // - User Description (2901) // - Client Characteristic Configuration (2902) // Note: This descriptor is blocklisted for writes. // - bad2ddcf-60db-45cd-bef9-fd72b153cf7c // A test descriptor that is blocklisted. + // - bad3ec61-3cc3-4954-9702-7977df514114 + // A test descriptor that is exclude read.. static scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> - GetDisconnectingHealthThermometer(); + GetDisconnectingHealthThermometer(bool add_descriptors); // |ServicesDiscoveredAfterReconnectionAdapter|(disconnect) // Inherits from |HeartRateAdapter|
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 75250780..05e0baa7 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1367,7 +1367,10 @@ "../renderer/media/video_capture_impl_unittest.cc", "../renderer/media/webmediaplayer_ms_unittest.cc", "../renderer/peripheral_content_heuristic_unittest.cc", + "../renderer/presentation/presentation_connection_proxy_unittest.cc", "../renderer/presentation/presentation_dispatcher_unittest.cc", + "../renderer/presentation/test_presentation_connection.cc", + "../renderer/presentation/test_presentation_connection.h", "../renderer/render_thread_impl_unittest.cc", "../renderer/render_widget_unittest.cc", "../renderer/scheduler/resource_dispatch_throttler_unittest.cc",
diff --git a/content/zygote/zygote_linux.cc b/content/zygote/zygote_linux.cc index 900463e4..37dcac9 100644 --- a/content/zygote/zygote_linux.cc +++ b/content/zygote/zygote_linux.cc
@@ -91,7 +91,7 @@ } // namespace Zygote::Zygote(int sandbox_flags, - ScopedVector<ZygoteForkDelegate> helpers, + std::vector<std::unique_ptr<ZygoteForkDelegate>> helpers, const std::vector<base::ProcessHandle>& extra_children, const std::vector<int>& extra_fds) : sandbox_flags_(sandbox_flags), @@ -418,11 +418,9 @@ int* uma_sample, int* uma_boundary_value) { ZygoteForkDelegate* helper = NULL; - for (ScopedVector<ZygoteForkDelegate>::iterator i = helpers_.begin(); - i != helpers_.end(); - ++i) { + for (auto i = helpers_.begin(); i != helpers_.end(); ++i) { if ((*i)->CanHelp(process_type, uma_name, uma_sample, uma_boundary_value)) { - helper = *i; + helper = i->get(); break; } }
diff --git a/content/zygote/zygote_linux.h b/content/zygote/zygote_linux.h index af2c100..79a06eb 100644 --- a/content/zygote/zygote_linux.h +++ b/content/zygote/zygote_linux.h
@@ -7,12 +7,12 @@ #include <stddef.h> +#include <memory> #include <string> #include <vector> #include "base/containers/small_map.h" #include "base/files/scoped_file.h" -#include "base/memory/scoped_vector.h" #include "base/posix/global_descriptors.h" #include "base/process/kill.h" #include "base/process/process.h" @@ -32,7 +32,8 @@ // runs it. class Zygote { public: - Zygote(int sandbox_flags, ScopedVector<ZygoteForkDelegate> helpers, + Zygote(int sandbox_flags, + std::vector<std::unique_ptr<ZygoteForkDelegate>> helpers, const std::vector<base::ProcessHandle>& extra_children, const std::vector<int>& extra_fds); ~Zygote(); @@ -135,7 +136,7 @@ ZygoteProcessMap process_info_map_; const int sandbox_flags_; - ScopedVector<ZygoteForkDelegate> helpers_; + std::vector<std::unique_ptr<ZygoteForkDelegate>> helpers_; // Count of how many fork delegates for which we've invoked InitialUMA(). size_t initial_uma_index_;
diff --git a/content/zygote/zygote_main.h b/content/zygote/zygote_main.h index 119210f..f5a9a850 100644 --- a/content/zygote/zygote_main.h +++ b/content/zygote/zygote_main.h
@@ -5,16 +5,17 @@ #ifndef CONTENT_ZYGOTE_ZYGOTE_MAIN_H_ #define CONTENT_ZYGOTE_ZYGOTE_MAIN_H_ -template <typename> -class ScopedVector; +#include <memory> +#include <vector> namespace content { struct MainFunctionParams; class ZygoteForkDelegate; -bool ZygoteMain(const MainFunctionParams& params, - ScopedVector<ZygoteForkDelegate> fork_delegates); +bool ZygoteMain( + const MainFunctionParams& params, + std::vector<std::unique_ptr<ZygoteForkDelegate>> fork_delegates); } // namespace content
diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc index e1b5489..b16ea54 100644 --- a/content/zygote/zygote_main_linux.cc +++ b/content/zygote/zygote_main_linux.cc
@@ -15,16 +15,13 @@ #include <sys/types.h> #include <unistd.h> -#include <memory> #include <set> #include <utility> -#include <vector> #include "base/bind.h" #include "base/command_line.h" #include "base/compiler_specific.h" #include "base/lazy_instance.h" -#include "base/memory/scoped_vector.h" #include "base/native_library.h" #include "base/pickle.h" #include "base/posix/eintr_wrapper.h" @@ -574,8 +571,9 @@ } } -bool ZygoteMain(const MainFunctionParams& params, - ScopedVector<ZygoteForkDelegate> fork_delegates) { +bool ZygoteMain( + const MainFunctionParams& params, + std::vector<std::unique_ptr<ZygoteForkDelegate>> fork_delegates) { g_am_zygote_or_renderer = true; std::vector<int> fds_to_close_post_fork; @@ -628,7 +626,7 @@ VLOG(1) << "ZygoteMain: initializing " << fork_delegates.size() << " fork delegates"; - for (ZygoteForkDelegate* fork_delegate : fork_delegates) { + for (const auto& fork_delegate : fork_delegates) { fork_delegate->Init(GetSandboxFD(), using_layer1_sandbox); }
diff --git a/device/bluetooth/device.cc b/device/bluetooth/device.cc index 873d277..acba3d2 100644 --- a/device/bluetooth/device.cc +++ b/device/bluetooth/device.cc
@@ -213,12 +213,90 @@ descriptor_info->id = descriptor->GetIdentifier(); descriptor_info->uuid = descriptor->GetUUID(); + descriptor_info->last_known_value = descriptor->GetValue(); + descriptors.push_back(std::move(descriptor_info)); } callback.Run(std::move(descriptors)); } +void Device::ReadValueForDescriptor( + const std::string& service_id, + const std::string& characteristic_id, + const std::string& descriptor_id, + const ReadValueForDescriptorCallback& callback) { + device::BluetoothDevice* device = adapter_->GetDevice(GetAddress()); + DCHECK(device); + + device::BluetoothRemoteGattService* service = + device->GetGattService(service_id); + if (!service) { + callback.Run(mojom::GattResult::SERVICE_NOT_FOUND, + base::nullopt /* value */); + return; + } + + device::BluetoothRemoteGattCharacteristic* characteristic = + service->GetCharacteristic(characteristic_id); + if (!characteristic) { + callback.Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND, + base::nullopt /* value */); + return; + } + + device::BluetoothRemoteGattDescriptor* descriptor = + characteristic->GetDescriptor(descriptor_id); + if (!descriptor) { + callback.Run(mojom::GattResult::DESCRIPTOR_NOT_FOUND, + base::nullopt /* value */); + return; + } + + descriptor->ReadRemoteDescriptor( + base::Bind(&Device::OnReadRemoteDescriptor, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&Device::OnReadRemoteDescriptorError, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + +void Device::WriteValueForDescriptor( + const std::string& service_id, + const std::string& characteristic_id, + const std::string& descriptor_id, + const std::vector<uint8_t>& value, + const WriteValueForDescriptorCallback& callback) { + device::BluetoothDevice* device = adapter_->GetDevice(GetAddress()); + DCHECK(device); + + device::BluetoothRemoteGattService* service = + device->GetGattService(service_id); + if (!service) { + callback.Run(mojom::GattResult::SERVICE_NOT_FOUND); + return; + } + + device::BluetoothRemoteGattCharacteristic* characteristic = + service->GetCharacteristic(characteristic_id); + if (!characteristic) { + callback.Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND); + return; + } + + device::BluetoothRemoteGattDescriptor* descriptor = + characteristic->GetDescriptor(descriptor_id); + if (!descriptor) { + callback.Run(mojom::GattResult::DESCRIPTOR_NOT_FOUND); + return; + } + + descriptor->WriteRemoteDescriptor( + value, base::Bind(&Device::OnWriteRemoteDescriptor, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&Device::OnWriteRemoteDescriptorError, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + Device::Device(scoped_refptr<device::BluetoothAdapter> adapter, std::unique_ptr<device::BluetoothGattConnection> connection) : adapter_(std::move(adapter)), @@ -276,6 +354,30 @@ callback.Run(mojo::ConvertTo<mojom::GattResult>(error_code)); } +void Device::OnReadRemoteDescriptor( + const ReadValueForDescriptorCallback& callback, + const std::vector<uint8_t>& value) { + callback.Run(mojom::GattResult::SUCCESS, std::move(value)); +} + +void Device::OnReadRemoteDescriptorError( + const ReadValueForDescriptorCallback& callback, + device::BluetoothGattService::GattErrorCode error_code) { + callback.Run(mojo::ConvertTo<mojom::GattResult>(error_code), + base::nullopt /* value */); +} + +void Device::OnWriteRemoteDescriptor( + const WriteValueForDescriptorCallback& callback) { + callback.Run(mojom::GattResult::SUCCESS); +} + +void Device::OnWriteRemoteDescriptorError( + const WriteValueForDescriptorCallback& callback, + device::BluetoothGattService::GattErrorCode error_code) { + callback.Run(mojo::ConvertTo<mojom::GattResult>(error_code)); +} + const std::string& Device::GetAddress() { return connection_->GetDeviceAddress(); }
diff --git a/device/bluetooth/device.h b/device/bluetooth/device.h index 953b80b..223f19d 100644 --- a/device/bluetooth/device.h +++ b/device/bluetooth/device.h
@@ -67,6 +67,17 @@ void GetDescriptors(const std::string& service_id, const std::string& characteristic_id, const GetDescriptorsCallback& callback) override; + void ReadValueForDescriptor( + const std::string& service_id, + const std::string& characteristic_id, + const std::string& descriptor_id, + const ReadValueForDescriptorCallback& callback) override; + void WriteValueForDescriptor( + const std::string& service_id, + const std::string& characteristic_id, + const std::string& descriptor_id, + const std::vector<uint8_t>& value, + const WriteValueForDescriptorCallback& callback) override; private: Device(scoped_refptr<device::BluetoothAdapter> adapter, @@ -92,6 +103,19 @@ const WriteValueForCharacteristicCallback& callback, device::BluetoothGattService::GattErrorCode error_code); + void OnReadRemoteDescriptor(const ReadValueForDescriptorCallback& callback, + const std::vector<uint8_t>& value); + + void OnReadRemoteDescriptorError( + const ReadValueForDescriptorCallback& callback, + device::BluetoothGattService::GattErrorCode error_code); + + void OnWriteRemoteDescriptor(const WriteValueForDescriptorCallback& callback); + + void OnWriteRemoteDescriptorError( + const WriteValueForDescriptorCallback& callback, + device::BluetoothGattService::GattErrorCode error_code); + const std::string& GetAddress(); // The current BluetoothAdapter.
diff --git a/device/bluetooth/public/interfaces/device.mojom b/device/bluetooth/public/interfaces/device.mojom index baa36115..9388e655 100644 --- a/device/bluetooth/public/interfaces/device.mojom +++ b/device/bluetooth/public/interfaces/device.mojom
@@ -45,7 +45,8 @@ NOT_PAIRED, NOT_SUPPORTED, SERVICE_NOT_FOUND, - CHARACTERISTIC_NOT_FOUND + CHARACTERISTIC_NOT_FOUND, + DESCRIPTOR_NOT_FOUND }; // TODO(crbug.com/657632): Remove when numerical values can be optional. @@ -77,6 +78,7 @@ struct DescriptorInfo { string id; UUID uuid; + array<uint8> last_known_value; }; interface Device { @@ -114,4 +116,16 @@ // means that no descriptors were found. GetDescriptors(string service_id, string characteristic_id) => (array<DescriptorInfo>? descriptors); + + // Reads the value for the GATT Descriptor with |descriptor_id| in the GATT + // Characteristic with |characteristic_id| in the GATT Service with + // |service_id|. + ReadValueForDescriptor(string service_id, string characteristic_id, + string descriptor_id) => (GattResult result, array<uint8>? value); + + // Writes the |value| for the GATT Descriptor with |descriptor_id| in the GATT + // Characteristic with |characteristic_id| in the GATT Service with + // |service_id|. + WriteValueForDescriptor(string service_id, string characteristic_id, + string descriptor_id, array<uint8> value) => (GattResult result); };
diff --git a/device/bluetooth/test/bluetooth_test_win.cc b/device/bluetooth/test/bluetooth_test_win.cc index 5bbdebfc..63c2ad0 100644 --- a/device/bluetooth/test/bluetooth_test_win.cc +++ b/device/bluetooth/test/bluetooth_test_win.cc
@@ -18,6 +18,10 @@ namespace { +void RunOnceClosure(base::OnceClosure closure) { + std::move(closure).Run(); +} + BLUETOOTH_ADDRESS CanonicalStringToBLUETOOTH_ADDRESS( std::string device_address) { BLUETOOTH_ADDRESS win_addr; @@ -476,20 +480,24 @@ int original_callback_count = callback_count_; int original_error_callback_count = error_callback_count_; do { - base::TestPendingTask task = tasks.front(); + base::TestPendingTask task = std::move(tasks.front()); tasks.pop_front(); - task.task.Run(); + std::move(task.task).Run(); base::RunLoop().RunUntilIdle(); } while (tasks.size() && callback_count_ == original_callback_count && error_callback_count_ == original_error_callback_count); // Put the rest of pending tasks back to Bluetooth task runner. - for (const auto& task : tasks) { + for (auto& task : tasks) { + // TODO(tzik): Remove RunOnceClosure once TaskRunner migrates from Closure + // to OnceClosure. if (task.delay.is_zero()) { - bluetooth_task_runner_->PostTask(task.location, task.task); + bluetooth_task_runner_->PostTask( + task.location, base::Bind(&RunOnceClosure, base::Passed(&task.task))); } else { - bluetooth_task_runner_->PostDelayedTask(task.location, task.task, - task.delay); + bluetooth_task_runner_->PostDelayedTask( + task.location, base::Bind(&RunOnceClosure, base::Passed(&task.task)), + task.delay); } } }
diff --git a/device/vr/BUILD.gn b/device/vr/BUILD.gn index 5e321fd6..1420d6e 100644 --- a/device/vr/BUILD.gn +++ b/device/vr/BUILD.gn
@@ -9,7 +9,7 @@ import("//build/config/android/rules.gni") # For generate_jni(). } -if (current_cpu == "arm" || current_cpu == "arm64") { +if (enable_webvr) { component("vr") { output_name = "device_vr" @@ -21,6 +21,7 @@ "vr_device_provider.h", "vr_display_impl.cc", "vr_display_impl.h", + "vr_export.h", "vr_service_impl.cc", "vr_service_impl.h", ] @@ -33,8 +34,7 @@ ] defines = [ "DEVICE_VR_IMPLEMENTATION" ] - - if (is_android) { + if (is_android && (current_cpu == "arm" || current_cpu == "arm64")) { sources += [ "android/gvr/gvr_delegate.cc", "android/gvr/gvr_delegate.h", @@ -77,10 +77,31 @@ "//mojo/public/cpp/bindings", ] } +} else { + component("mojo_only") { + sources = [ + # We need to include an empty .cc file so that mac and windows don't fall over when trying to + # compile this. + "empty.cc", + "vr_export.h", + ] + defines = [ "DEVICE_VR_IMPLEMENTATION" ] + public_deps = [ + ":mojo_bindings", + ] + } } mojom("mojo_bindings") { sources = [ "vr_service.mojom", ] + + public_deps = [ + "//mojo/common:common_custom_types", + ] + + export_class_attribute = "DEVICE_VR_EXPORT" + export_define = "DEVICE_VR_IMPLEMENTATION=1" + export_header = "device/vr/vr_export.h" }
diff --git a/device/vr/android/gvr/gvr_delegate.h b/device/vr/android/gvr/gvr_delegate.h index c5e22a0..b96e366 100644 --- a/device/vr/android/gvr/gvr_delegate.h +++ b/device/vr/android/gvr/gvr_delegate.h
@@ -7,6 +7,7 @@ #include "device/vr/android/gvr/gvr_device_provider.h" #include "device/vr/vr_export.h" +#include "device/vr/vr_service.mojom.h" #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_types.h" namespace gvr { @@ -23,12 +24,17 @@ virtual void SubmitWebVRFrame() = 0; virtual void UpdateWebVRTextureBounds(const gvr::Rectf& left_bounds, const gvr::Rectf& right_bounds) = 0; - - virtual void SetGvrPoseForWebVr(const gvr::Mat4f& pose, - uint32_t pose_index) = 0; virtual gvr::Sizei GetWebVRCompositorSurfaceSize() = 0; virtual void SetWebVRRenderSurfaceSize(int width, int height) = 0; + // TODO(mthiesse): This function is not threadsafe. crbug.com/674594 virtual gvr::GvrApi* gvr_api() = 0; + virtual void OnVRVsyncProviderRequest( + mojom::VRVSyncProviderRequest request) = 0; + virtual void UpdateVSyncInterval(long timebase_nanos, + double interval_seconds) = 0; + + protected: + virtual ~GvrDelegate() {} }; class DEVICE_VR_EXPORT GvrDelegateProvider { @@ -44,6 +50,9 @@ virtual void DestroyNonPresentingDelegate() = 0; virtual void SetListeningForActivate(bool listening) = 0; + protected: + virtual ~GvrDelegateProvider() {} + private: static GvrDelegateProvider* delegate_provider_; };
diff --git a/device/vr/android/gvr/gvr_device.cc b/device/vr/android/gvr/gvr_device.cc index 9dc6b39..18b5cfd 100644 --- a/device/vr/android/gvr/gvr_device.cc +++ b/device/vr/android/gvr/gvr_device.cc
@@ -19,12 +19,6 @@ namespace device { -namespace { - -static const uint64_t kPredictionTimeWithoutVsyncNanos = 50000000; - -} // namespace - GvrDevice::GvrDevice(GvrDeviceProvider* provider, GvrDelegate* delegate) : VRDevice(), delegate_(delegate), gvr_provider_(provider) {} @@ -150,68 +144,6 @@ return device; } -mojom::VRPosePtr GvrDevice::GetPose() { - TRACE_EVENT0("input", "GvrDevice::GetSensorState"); - - mojom::VRPosePtr pose = mojom::VRPose::New(); - - pose->timestamp = base::Time::Now().ToJsTime(); - - // Increment pose frame counter always, even if it's a faked pose. - pose->poseIndex = ++pose_index_; - - pose->orientation.emplace(4); - - gvr::GvrApi* gvr_api = GetGvrApi(); - if (!gvr_api) { - // If we don't have a GvrApi instance return a static forward orientation. - pose->orientation.value()[0] = 0.0; - pose->orientation.value()[1] = 0.0; - pose->orientation.value()[2] = 0.0; - pose->orientation.value()[3] = 1.0; - - return pose; - } - - if (!delegate_) - return nullptr; - - gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); - target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; - - gvr::Mat4f head_mat = - gvr_api->GetHeadSpaceFromStartSpaceRotation(target_time); - head_mat = gvr_api->ApplyNeckModel(head_mat, 1.0f); - - gfx::Transform inv_transform( - head_mat.m[0][0], head_mat.m[0][1], head_mat.m[0][2], head_mat.m[0][3], - head_mat.m[1][0], head_mat.m[1][1], head_mat.m[1][2], head_mat.m[1][3], - head_mat.m[2][0], head_mat.m[2][1], head_mat.m[2][2], head_mat.m[2][3], - head_mat.m[3][0], head_mat.m[3][1], head_mat.m[3][2], head_mat.m[3][3]); - - gfx::Transform transform; - if (inv_transform.GetInverse(&transform)) { - gfx::DecomposedTransform decomposed_transform; - gfx::DecomposeTransform(&decomposed_transform, transform); - - pose->orientation.value()[0] = decomposed_transform.quaternion[0]; - pose->orientation.value()[1] = decomposed_transform.quaternion[1]; - pose->orientation.value()[2] = decomposed_transform.quaternion[2]; - pose->orientation.value()[3] = decomposed_transform.quaternion[3]; - - pose->position.emplace(3); - pose->position.value()[0] = decomposed_transform.translate[0]; - pose->position.value()[1] = decomposed_transform.translate[1]; - pose->position.value()[2] = decomposed_transform.translate[2]; - } - - // Save the underlying GVR pose for use by rendering. It can't use a - // VRPosePtr since that's a different data type. - delegate_->SetGvrPoseForWebVr(head_mat, pose_index_); - - return pose; -} - void GvrDevice::ResetPose() { gvr::GvrApi* gvr_api = GetGvrApi(); @@ -261,6 +193,11 @@ delegate_->UpdateWebVRTextureBounds(left_gvr_bounds, right_gvr_bounds); } +void GvrDevice::GetVRVSyncProvider(mojom::VRVSyncProviderRequest request) { + if (delegate_) + delegate_->OnVRVsyncProviderRequest(std::move(request)); +} + void GvrDevice::SetDelegate(GvrDelegate* delegate) { delegate_ = delegate;
diff --git a/device/vr/android/gvr/gvr_device.h b/device/vr/android/gvr/gvr_device.h index 4d57f58..20db1172 100644 --- a/device/vr/android/gvr/gvr_device.h +++ b/device/vr/android/gvr/gvr_device.h
@@ -24,7 +24,6 @@ // VRDevice mojom::VRDisplayInfoPtr GetVRDevice() override; - mojom::VRPosePtr GetPose() override; void ResetPose() override; void RequestPresent(const base::Callback<void(bool)>& callback) override; @@ -34,6 +33,7 @@ void SubmitFrame(mojom::VRPosePtr pose) override; void UpdateLayerBounds(mojom::VRLayerBoundsPtr left_bounds, mojom::VRLayerBoundsPtr right_bounds) override; + void GetVRVSyncProvider(mojom::VRVSyncProviderRequest request) override; void SetDelegate(GvrDelegate* delegate); @@ -43,7 +43,6 @@ GvrDelegate* delegate_; GvrDeviceProvider* gvr_provider_; bool secure_origin_ = false; - uint32_t pose_index_ = 1; DISALLOW_COPY_AND_ASSIGN(GvrDevice); };
diff --git a/device/vr/empty.cc b/device/vr/empty.cc new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/device/vr/empty.cc
diff --git a/device/vr/test/fake_vr_device.cc b/device/vr/test/fake_vr_device.cc index b828a5fe..cd478b2 100644 --- a/device/vr/test/fake_vr_device.cc +++ b/device/vr/test/fake_vr_device.cc
@@ -8,7 +8,6 @@ FakeVRDevice::FakeVRDevice() { device_ = mojom::VRDisplayInfo::New(); - pose_ = mojom::VRPose::New(); InitBasicDevice(); } @@ -55,19 +54,11 @@ device_ = device.Clone(); } -void FakeVRDevice::SetPose(const mojom::VRPosePtr& pose) { - pose_ = pose.Clone(); -} - mojom::VRDisplayInfoPtr FakeVRDevice::GetVRDevice() { mojom::VRDisplayInfoPtr display = device_.Clone(); return display.Clone(); } -mojom::VRPosePtr FakeVRDevice::GetPose() { - return pose_.Clone(); -} - void FakeVRDevice::ResetPose() {} void FakeVRDevice::RequestPresent(const base::Callback<void(bool)>& callback) { @@ -85,4 +76,6 @@ void FakeVRDevice::UpdateLayerBounds(mojom::VRLayerBoundsPtr leftBounds, mojom::VRLayerBoundsPtr rightBounds) {} +void FakeVRDevice::GetVRVSyncProvider(mojom::VRVSyncProviderRequest request) {} + } // namespace device
diff --git a/device/vr/test/fake_vr_device.h b/device/vr/test/fake_vr_device.h index 64101704..6d6acb3 100644 --- a/device/vr/test/fake_vr_device.h +++ b/device/vr/test/fake_vr_device.h
@@ -21,10 +21,8 @@ void InitBasicDevice(); void SetVRDevice(const mojom::VRDisplayInfoPtr& device); - void SetPose(const mojom::VRPosePtr& state); mojom::VRDisplayInfoPtr GetVRDevice() override; - mojom::VRPosePtr GetPose() override; void ResetPose() override; void RequestPresent(const base::Callback<void(bool)>& callback) override; @@ -33,12 +31,12 @@ void SubmitFrame(mojom::VRPosePtr pose) override; void UpdateLayerBounds(mojom::VRLayerBoundsPtr leftBounds, mojom::VRLayerBoundsPtr rightBounds) override; + void GetVRVSyncProvider(mojom::VRVSyncProviderRequest request) override; private: mojom::VREyeParametersPtr InitEye(float fov, float offset, uint32_t size); mojom::VRDisplayInfoPtr device_; - mojom::VRPosePtr pose_; DISALLOW_COPY_AND_ASSIGN(FakeVRDevice); };
diff --git a/device/vr/vr_device.h b/device/vr/vr_device.h index 93c9aa0..165bee0 100644 --- a/device/vr/vr_device.h +++ b/device/vr/vr_device.h
@@ -24,7 +24,6 @@ unsigned int id() const { return id_; } virtual mojom::VRDisplayInfoPtr GetVRDevice() = 0; - virtual mojom::VRPosePtr GetPose() = 0; virtual void ResetPose() = 0; virtual void RequestPresent(const base::Callback<void(bool)>& callback) = 0; @@ -33,6 +32,7 @@ virtual void SubmitFrame(mojom::VRPosePtr pose) = 0; virtual void UpdateLayerBounds(mojom::VRLayerBoundsPtr left_bounds, mojom::VRLayerBoundsPtr right_bounds) = 0; + virtual void GetVRVSyncProvider(mojom::VRVSyncProviderRequest request) = 0; virtual void AddDisplay(VRDisplayImpl* display); virtual void RemoveDisplay(VRDisplayImpl* display);
diff --git a/device/vr/vr_display_impl.cc b/device/vr/vr_display_impl.cc index b4025dd80..db268c9 100644 --- a/device/vr/vr_display_impl.cc +++ b/device/vr/vr_display_impl.cc
@@ -27,15 +27,6 @@ device_->RemoveDisplay(this); } -void VRDisplayImpl::GetPose(const GetPoseCallback& callback) { - if (!device_->IsAccessAllowed(this)) { - callback.Run(nullptr); - return; - } - - callback.Run(device_->GetPose()); -} - void VRDisplayImpl::ResetPose() { if (!device_->IsAccessAllowed(this)) return; @@ -83,4 +74,11 @@ device_->UpdateLayerBounds(std::move(left_bounds), std::move(right_bounds)); } + +void VRDisplayImpl::GetVRVSyncProvider(mojom::VRVSyncProviderRequest request) { + if (!device_->IsAccessAllowed(this)) { + return; + } + device_->GetVRVSyncProvider(std::move(request)); +} }
diff --git a/device/vr/vr_display_impl.h b/device/vr/vr_display_impl.h index 951c591..1e52a6e 100644 --- a/device/vr/vr_display_impl.h +++ b/device/vr/vr_display_impl.h
@@ -29,7 +29,6 @@ friend class VRDisplayImplTest; friend class VRServiceImpl; - void GetPose(const GetPoseCallback& callback) override; void ResetPose() override; void RequestPresent(bool secure_origin, @@ -39,6 +38,7 @@ void UpdateLayerBounds(mojom::VRLayerBoundsPtr left_bounds, mojom::VRLayerBoundsPtr right_bounds) override; + void GetVRVSyncProvider(mojom::VRVSyncProviderRequest request) override; void RequestPresentResult(const RequestPresentCallback& callback, bool secure_origin,
diff --git a/device/vr/vr_service.mojom b/device/vr/vr_service.mojom index d41b1a9..b7d85158 100644 --- a/device/vr/vr_service.mojom +++ b/device/vr/vr_service.mojom
@@ -3,6 +3,8 @@ module device.mojom; +import "mojo/common/time.mojom"; + // A field of view, given by 4 degrees describing the view from a center point. struct VRFieldOfView { float upDegrees; @@ -84,14 +86,17 @@ }; interface VRDisplay { - [Sync] - GetPose() => (VRPose? pose); ResetPose(); RequestPresent(bool secureOrigin) => (bool success); ExitPresent(); SubmitFrame(VRPose? pose); UpdateLayerBounds(VRLayerBounds leftBounds, VRLayerBounds rightBounds); + GetVRVSyncProvider(VRVSyncProvider& request); +}; + +interface VRVSyncProvider { + GetVSync() => (VRPose? pose, mojo.common.mojom.TimeDelta time); }; interface VRDisplayClient {
diff --git a/extensions/browser/api/audio/audio_api.cc b/extensions/browser/api/audio/audio_api.cc index 53bd0da1..dabb853b 100644 --- a/extensions/browser/api/audio/audio_api.cc +++ b/extensions/browser/api/audio/audio_api.cc
@@ -59,14 +59,21 @@ } void AudioAPI::OnMuteChanged(bool is_input, bool is_muted) { - if (EventRouter::Get(browser_context_)) { - std::unique_ptr<base::ListValue> args = - audio::OnMuteChanged::Create(is_input, is_muted); - std::unique_ptr<Event> event(new Event(events::AUDIO_ON_MUTE_CHANGED, - audio::OnMuteChanged::kEventName, - std::move(args))); - EventRouter::Get(browser_context_)->BroadcastEvent(std::move(event)); - } + EventRouter* event_router = EventRouter::Get(browser_context_); + if (!event_router) + return; + + // Dispatch onMuteChanged event. + audio::MuteChangedEvent raw_event; + raw_event.stream_type = + is_input ? audio::STREAM_TYPE_INPUT : audio::STREAM_TYPE_OUTPUT; + raw_event.is_muted = is_muted; + std::unique_ptr<base::ListValue> event_args = + audio::OnMuteChanged::Create(raw_event); + std::unique_ptr<Event> event(new Event(events::AUDIO_ON_MUTE_CHANGED, + audio::OnMuteChanged::kEventName, + std::move(event_args))); + event_router->BroadcastEvent(std::move(event)); } void AudioAPI::OnDevicesChanged(const DeviceInfoList& devices) { @@ -140,13 +147,52 @@ int gain_value = params->properties.gain.get() ? *params->properties.gain : -1; - if (!service->SetDeviceProperties(params->id, params->properties.is_muted, - volume_value, gain_value)) { - return RespondNow(Error("Could not set properties")); + if (!service->SetDeviceSoundLevel(params->id, volume_value, gain_value)) + return RespondNow(Error("Could not set volume/gain properties")); + + if (params->properties.is_muted.get() && + !service->SetMuteForDevice(params->id, *params->properties.is_muted)) { + return RespondNow(Error("Could not set mute property.")); + } + + return RespondNow(NoArguments()); +} + +/////////////////////////////////////////////////////////////////////////////// + +ExtensionFunction::ResponseAction AudioSetMuteFunction::Run() { + std::unique_ptr<audio::SetMute::Params> params( + audio::SetMute::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params.get()); + + AudioService* service = + AudioAPI::GetFactoryInstance()->Get(browser_context())->GetService(); + DCHECK(service); + + if (!service->SetMute(params->stream_type == audio::STREAM_TYPE_INPUT, + params->is_muted)) { + return RespondNow(Error("Could not set mute state.")); } return RespondNow(NoArguments()); } /////////////////////////////////////////////////////////////////////////////// +ExtensionFunction::ResponseAction AudioGetMuteFunction::Run() { + std::unique_ptr<audio::GetMute::Params> params( + audio::GetMute::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params.get()); + + AudioService* service = + AudioAPI::GetFactoryInstance()->Get(browser_context())->GetService(); + DCHECK(service); + + bool value = false; + if (!service->GetMute(params->stream_type == audio::STREAM_TYPE_INPUT, + &value)) { + return RespondNow(Error("Could not get mute state.")); + } + return RespondNow(ArgumentList(audio::GetMute::Results::Create(value))); +} + } // namespace extensions
diff --git a/extensions/browser/api/audio/audio_api.h b/extensions/browser/api/audio/audio_api.h index ee4ce3b..f4d09ed 100644 --- a/extensions/browser/api/audio/audio_api.h +++ b/extensions/browser/api/audio/audio_api.h
@@ -68,6 +68,24 @@ ResponseAction Run() override; }; +class AudioSetMuteFunction : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("audio.setMute", AUDIO_SETMUTE); + + protected: + ~AudioSetMuteFunction() override {} + ResponseAction Run() override; +}; + +class AudioGetMuteFunction : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("audio.getMute", AUDIO_GETMUTE); + + protected: + ~AudioGetMuteFunction() override {} + ResponseAction Run() override; +}; + } // namespace extensions #endif // EXTENSIONS_BROWSER_API_AUDIO_AUDIO_API_H_
diff --git a/extensions/browser/api/audio/audio_service.cc b/extensions/browser/api/audio/audio_service.cc index 8c0ab27..bdc1ea6 100644 --- a/extensions/browser/api/audio/audio_service.cc +++ b/extensions/browser/api/audio/audio_service.cc
@@ -21,10 +21,12 @@ bool SetActiveDeviceLists( const std::unique_ptr<DeviceIdList>& input_devices, const std::unique_ptr<DeviceIdList>& output_devives) override; - bool SetDeviceProperties(const std::string& device_id, - bool muted, + bool SetDeviceSoundLevel(const std::string& device_id, int volume, int gain) override; + bool SetMuteForDevice(const std::string& device_id, bool value) override; + bool SetMute(bool is_input, bool value) override; + bool GetMute(bool is_input, bool* value) override; }; void AudioServiceImpl::AddObserver(Observer* observer) { @@ -54,11 +56,23 @@ void AudioServiceImpl::SetActiveDevices(const DeviceIdList& device_list) { } -bool AudioServiceImpl::SetDeviceProperties(const std::string& device_id, - bool muted, +bool AudioServiceImpl::SetDeviceSoundLevel(const std::string& device_id, int volume, int gain) { return false; } +bool AudioServiceImpl::SetMuteForDevice(const std::string& device_id, + bool value) { + return false; +} + +bool AudioServiceImpl::SetMute(bool is_input, bool value) { + return false; +} + +bool AudioServiceImpl::GetMute(bool is_input, bool* value) { + return false; +} + } // namespace extensions
diff --git a/extensions/browser/api/audio/audio_service.h b/extensions/browser/api/audio/audio_service.h index 6ad8d96..e44c3a5 100644 --- a/extensions/browser/api/audio/audio_service.h +++ b/extensions/browser/api/audio/audio_service.h
@@ -80,12 +80,24 @@ // before we activate the new devices with the same type(input/output). virtual void SetActiveDevices(const DeviceIdList& device_list) = 0; - // Set the muted and volume/gain properties of a device. - virtual bool SetDeviceProperties(const std::string& device_id, - bool muted, + // Set the sound level properties (volume or gain) of a device. + virtual bool SetDeviceSoundLevel(const std::string& device_id, int volume, int gain) = 0; + // Sets the mute property of a device. + virtual bool SetMuteForDevice(const std::string& device_id, bool value) = 0; + + // Sets mute property for audio input (if |is_input| is true) or output (if + // |is_input| is false). + virtual bool SetMute(bool is_input, bool value) = 0; + + // Gets mute property for audio input (if |is_input| is true) or output (if + // |is_input| is false). + // The mute value is returned via |mute| argument. + // The method returns whether the value was successfully fetched. + virtual bool GetMute(bool is_input, bool* mute) = 0; + protected: AudioService() {}
diff --git a/extensions/browser/api/audio/audio_service_chromeos.cc b/extensions/browser/api/audio/audio_service_chromeos.cc index 524fefa..a50c9a7 100644 --- a/extensions/browser/api/audio/audio_service_chromeos.cc +++ b/extensions/browser/api/audio/audio_service_chromeos.cc
@@ -39,10 +39,12 @@ bool SetActiveDeviceLists( const std::unique_ptr<DeviceIdList>& input_devices, const std::unique_ptr<DeviceIdList>& output_devives) override; - bool SetDeviceProperties(const std::string& device_id, - bool muted, + bool SetDeviceSoundLevel(const std::string& device_id, int volume, int gain) override; + bool SetMuteForDevice(const std::string& device_id, bool value) override; + bool SetMute(bool is_input, bool value) override; + bool GetMute(bool is_input, bool* value) override; protected: // chromeos::CrasAudioHandler::AudioObserver overrides. @@ -182,8 +184,7 @@ return success; } -bool AudioServiceImpl::SetDeviceProperties(const std::string& device_id, - bool muted, +bool AudioServiceImpl::SetDeviceSoundLevel(const std::string& device_id, int volume, int gain) { DCHECK(cras_audio_handler_); @@ -195,8 +196,6 @@ if (!device) return false; - cras_audio_handler_->SetMuteForDevice(device->id, muted); - if (!device->is_input && volume != -1) { cras_audio_handler_->SetVolumeGainPercentForDevice(device->id, volume); return true; @@ -208,6 +207,45 @@ return false; } +bool AudioServiceImpl::SetMuteForDevice(const std::string& device_id, + bool value) { + DCHECK(cras_audio_handler_); + if (!cras_audio_handler_) + return false; + + const chromeos::AudioDevice* device = + cras_audio_handler_->GetDeviceFromId(GetIdFromStr(device_id)); + if (!device) + return false; + + cras_audio_handler_->SetMuteForDevice(device->id, value); + return true; +} + +bool AudioServiceImpl::SetMute(bool is_input, bool value) { + DCHECK(cras_audio_handler_); + if (!cras_audio_handler_) + return false; + + if (is_input) + cras_audio_handler_->SetInputMute(value); + else + cras_audio_handler_->SetOutputMute(value); + return true; +} + +bool AudioServiceImpl::GetMute(bool is_input, bool* value) { + DCHECK(cras_audio_handler_); + if (!cras_audio_handler_) + return false; + + if (is_input) + *value = cras_audio_handler_->IsInputMuted(); + else + *value = cras_audio_handler_->IsOutputMuted(); + return true; +} + uint64_t AudioServiceImpl::GetIdFromStr(const std::string& id_str) { uint64_t device_id; if (!base::StringToUint64(id_str, &device_id)) @@ -293,6 +331,9 @@ for (size_t i = 0; i < devices.size(); ++i) { AudioDeviceInfo info; info.id = base::Uint64ToString(devices[i].id); + info.stream_type = devices[i].is_input + ? extensions::api::audio::STREAM_TYPE_INPUT + : extensions::api::audio::STREAM_TYPE_OUTPUT; info.is_input = devices[i].is_input; info.device_type = chromeos::AudioDevice::GetTypeString(devices[i].type); info.display_name = devices[i].display_name;
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index b26969f..c8518e1 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1218,6 +1218,8 @@ NETWORKINGPRIVATE_GETGLOBALPOLICY, DIAL_FETCHDEVICEDESCRIPTION, SYSTEM_DISPLAY_STARTCUSTOMTOUCHCALIBRATION, + AUDIO_GETMUTE, + AUDIO_SETMUTE, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/common/api/audio.idl b/extensions/common/api/audio.idl index 2d68b5d..401949c 100644 --- a/extensions/common/api/audio.idl +++ b/extensions/common/api/audio.idl
@@ -7,6 +7,12 @@ // system. This API is currently only implemented for ChromeOS. namespace audio { + // Type of stream an audio device provides. + enum StreamType { + INPUT, + OUTPUT + }; + dictionary OutputDeviceInfo { // The unique identifier of the audio output device. DOMString id; @@ -36,8 +42,10 @@ dictionary AudioDeviceInfo { // The unique identifier of the audio device. DOMString id; + // Stream type associated with this device. + StreamType streamType; // True for input device; false for output device. - boolean isInput; + [deprecated="Use |streamType|."] boolean isInput; // Type of the device, including "INTERNAL_SPEAKER", "INTERNAL_MIC", // "HEADPHONE", "USB", "BLUETOOTH", "HDMI", "MIC", "KEYBOARD_MIC", // "AOKR", and "OTHER". @@ -58,7 +66,7 @@ dictionary DeviceProperties { // True if this is muted. - boolean isMuted; + [deprecated="Use $(ref:setMute) to set mute state."] boolean? isMuted; // If this is an output device then this field indicates the output volume. // If this is an input device then this field is ignored. double? volume; @@ -79,9 +87,19 @@ DOMString[]? output; }; + dictionary MuteChangedEvent { + // The type of the stream for which the mute value changed. The updated mute + // value applies to all devices with this stream type. + StreamType streamType; + + // Whether or not the stream is now muted. + boolean isMuted; + }; + callback GetInfoCallback = void(OutputDeviceInfo[] outputInfo, InputDeviceInfo[] inputInfo); callback EmptyCallback = void(); + callback GetMuteCallback = void(boolean value); interface Functions { // Gets the information of all audio output and input devices. @@ -105,6 +123,20 @@ static void setProperties(DOMString id, DeviceProperties properties, EmptyCallback callback); + + // Gets the system-wide mute state for the specified stream type. + // |streamType|: Stream type for which mute state should be fetched. + // |callback|: Callback reporting whether mute is set or not for specified + // stream type. + static void getMute(StreamType streamType, GetMuteCallback callback); + + // Sets mute state for a stream type. The mute state will apply to all audio + // devices with the specified audio stream type. + // |streamType|: Stream type for which mute state should be set. + // |isMuted|: New mute value. + static void setMute(StreamType streamType, + boolean isMuted, + optional EmptyCallback callback); }; interface Events { @@ -117,9 +149,9 @@ static void OnLevelChanged(DOMString id, long level); // Fired when the mute state of the audio input or output changes. - // |isInput|: true indicating audio input; false indicating audio output. - // |isMuted|: new value of mute state. - static void OnMuteChanged(boolean isInput, boolean isMuted); + // Note that mute state is system-wide and the new value applies to every + // audio device with specified stream type. + static void onMuteChanged(MuteChangedEvent event); // Fired when audio devices change, either new devices being added, or // existing devices being removed.
diff --git a/extensions/shell/app/shell_main_delegate.cc b/extensions/shell/app/shell_main_delegate.cc index d275927..997b91b 100644 --- a/extensions/shell/app/shell_main_delegate.cc +++ b/extensions/shell/app/shell_main_delegate.cc
@@ -124,7 +124,7 @@ #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) void ShellMainDelegate::ZygoteStarting( - ScopedVector<content::ZygoteForkDelegate>* delegates) { + std::vector<std::unique_ptr<content::ZygoteForkDelegate>>* delegates) { #if !defined(DISABLE_NACL) nacl::AddNaClZygoteForkDelegates(delegates); #endif // DISABLE_NACL
diff --git a/extensions/shell/app/shell_main_delegate.h b/extensions/shell/app/shell_main_delegate.h index 7b52b22f..45ab287c 100644 --- a/extensions/shell/app/shell_main_delegate.h +++ b/extensions/shell/app/shell_main_delegate.h
@@ -6,10 +6,10 @@ #define EXTENSIONS_SHELL_APP_SHELL_MAIN_DELEGATE_H_ #include <memory> +#include <vector> #include "base/compiler_specific.h" #include "base/macros.h" -#include "base/memory/scoped_vector.h" #include "build/build_config.h" #include "content/public/app/content_main_delegate.h" @@ -33,8 +33,8 @@ content::ContentRendererClient* CreateContentRendererClient() override; content::ContentUtilityClient* CreateContentUtilityClient() override; #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) - void ZygoteStarting( - ScopedVector<content::ZygoteForkDelegate>* delegates) override; + void ZygoteStarting(std::vector<std::unique_ptr<content::ZygoteForkDelegate>>* + delegates) override; #endif protected:
diff --git a/extensions/test/data/api_test/audio/input_mute_change/background.js b/extensions/test/data/api_test/audio/input_mute_change/background.js index 39fbc86..d02eae29 100644 --- a/extensions/test/data/api_test/audio/input_mute_change/background.js +++ b/extensions/test/data/api_test/audio/input_mute_change/background.js
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -chrome.test.runTests([ - function waitForMuteChangedEventTests() { - chrome.test.listenOnce( - chrome.audio.OnMuteChanged, - function(isInput, isMuted) { - chrome.test.assertTrue(isInput); - chrome.test.assertTrue(isMuted); - }); - } -]); +chrome.test.runTests([function waitForMuteChangedEventTests() { + chrome.test.listenOnce(chrome.audio.onMuteChanged, function(evt) { + chrome.test.assertEq('INPUT', evt.streamType); + chrome.test.assertTrue(evt.isMuted); + }); +}]); chrome.test.sendMessage('loaded');
diff --git a/extensions/test/data/api_test/audio/output_mute_change/background.js b/extensions/test/data/api_test/audio/output_mute_change/background.js index 73b1357..4f5b748 100644 --- a/extensions/test/data/api_test/audio/output_mute_change/background.js +++ b/extensions/test/data/api_test/audio/output_mute_change/background.js
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -chrome.test.runTests([ - function waitForMuteChangedEventTests() { - chrome.test.listenOnce( - chrome.audio.OnMuteChanged, - function(isInput, isMuted) { - chrome.test.assertFalse(isInput); - chrome.test.assertFalse(isMuted); - }); - } -]); +chrome.test.runTests([function waitForMuteChangedEventTests() { + chrome.test.listenOnce(chrome.audio.onMuteChanged, function(evt) { + chrome.test.assertEq('OUTPUT', evt.streamType); + chrome.test.assertFalse(evt.isMuted); + }); +}]); chrome.test.sendMessage('loaded');
diff --git a/extensions/test/data/api_test/audio/test.js b/extensions/test/data/api_test/audio/test.js index 8aa3e47..10af90c 100644 --- a/extensions/test/data/api_test/audio/test.js +++ b/extensions/test/data/api_test/audio/test.js
@@ -167,11 +167,9 @@ var updatedOutput = expectedOutput['30001']; chrome.test.assertFalse(updatedOutput.isMuted); chrome.test.assertFalse(updatedOutput.volume === 35); - updatedOutput.isMuted = true; updatedOutput.volume = 35; chrome.audio.setProperties('30001', { - isMuted: true, volume: 35 }, chrome.test.callbackPass(function() { chrome.audio.setProperties('40002', { @@ -188,28 +186,61 @@ }); }, + function inputMuteTest() { + var getMute = function(callback) { + chrome.audio.getMute('INPUT', chrome.test.callbackPass(callback)); + }; + getMute(function(originalValue) { + chrome.audio.setMute( + 'INPUT', !originalValue, chrome.test.callbackPass(function() { + getMute(function(value) { + chrome.test.assertEq(!originalValue, value); + }); + })); + }); + }, + + function outputMuteTest() { + var getMute = function(callback) { + chrome.audio.getMute('OUTPUT', chrome.test.callbackPass(callback)); + }; + getMute(function(originalValue) { + chrome.audio.setMute( + 'OUTPUT', !originalValue, chrome.test.callbackPass(function() { + getMute(function(value) { + chrome.test.assertEq(!originalValue, value); + }); + })); + }); + }, + function setPropertiesInvalidValuesTest() { getDevices(function(originalOutputInfo, originalInputInfo) { var expectedInput = deviceListToExpectedDevicesMap(originalInputInfo); var expectedOutput = deviceListToExpectedDevicesMap(originalOutputInfo); + var expectedError = 'Could not set volume/gain properties'; - chrome.audio.setProperties('30001', { - isMuted: true, - // Output device - should have volume set. - gain: 55 - }, chrome.test.callbackFail('Could not set properties', function() { - chrome.audio.setProperties('40002', { - isMuted: true, - // Input device - should have gain set. - volume:55 - }, chrome.test.callbackFail('Could not set properties', function() { - // Assert that device properties haven't changed. - getDevices(function(outputInfo, inputInfo) { - assertDevicesMatch(expectedOutput, outputInfo); - assertDevicesMatch(expectedInput, inputInfo); - }); - })); - })); + chrome.audio.setProperties( + '30001', { + isMuted: true, + // Output device - should have volume set. + gain: 55 + }, + chrome.test.callbackFail(expectedError, function() { + chrome.audio.setProperties( + '40002', { + isMuted: true, + // Input device - should have gain set. + volume: 55 + }, + chrome.test.callbackFail(expectedError, function() { + // Assert that device properties haven't changed. + getDevices(function(outputInfo, inputInfo) { + assertDevicesMatch(expectedOutput, outputInfo); + assertDevicesMatch(expectedInput, inputInfo); + }); + })); + })); }); },
diff --git a/google_apis/drive/drive_api_parser.cc b/google_apis/drive/drive_api_parser.cc index 5f511645..5cdff35 100644 --- a/google_apis/drive/drive_api_parser.cc +++ b/google_apis/drive/drive_api_parser.cc
@@ -164,6 +164,25 @@ const char kDriveFolderMimeType[] = "application/vnd.google-apps.folder"; +// Team Drive +const char kTeamDriveKind[] = "drive#teamDrive"; +const char kCapabilities[] = "capabilities"; + +// Team Drive capabilities. +const char kCanAddChildren[] = "canAddChildren"; +const char kCanComment[] = "canComment"; +const char kCanCopy[] = "canCopy"; +const char kCanDeleteTeamDrive[] = "canDeleteTeamDrive"; +const char kCanDownload[] = "canDownload"; +const char kCanEdit[] = "canEdit"; +const char kCanListChildren[] = "canListChildren"; +const char kCanManageMembers[] = "canManageMembers"; +const char kCanReadRevisions[] = "canReadRevisions"; +const char kCanRemoveChildren[] = "canRemoveChildren"; +const char kCanRename[] = "canRename"; +const char kCanRenameTeamDrive[] = "canRenameTeamDrive"; +const char kCanShare[] = "canShare"; + // Files List // https://developers.google.com/drive/v2/reference/files/list const char kFileListKind[] = "drive#fileList"; @@ -392,6 +411,91 @@ } //////////////////////////////////////////////////////////////////////////////// +// TeamDriveCapabilities implementation + +TeamDriveCapabilities::TeamDriveCapabilities() + : can_add_children_(false), + can_comment_(false), + can_copy_(false), + can_delete_team_drive_(false), + can_download_(false), + can_edit_(false), + can_list_children_(false), + can_manage_members_(false), + can_read_revisions_(false), + can_remove_children_(false), + can_rename_(false), + can_rename_team_drive_(false), + can_share_(false) { +} + +TeamDriveCapabilities::~TeamDriveCapabilities(){} + +// static +void TeamDriveCapabilities::RegisterJSONConverter( + base::JSONValueConverter<TeamDriveCapabilities>* converter) { + converter->RegisterBoolField(kCanAddChildren, + &TeamDriveCapabilities::can_add_children_); + converter->RegisterBoolField(kCanComment, + &TeamDriveCapabilities::can_comment_); + converter->RegisterBoolField(kCanCopy, &TeamDriveCapabilities::can_copy_); + converter->RegisterBoolField(kCanDeleteTeamDrive, + &TeamDriveCapabilities::can_delete_team_drive_); + converter->RegisterBoolField(kCanDownload, + &TeamDriveCapabilities::can_download_); + converter->RegisterBoolField(kCanEdit, &TeamDriveCapabilities::can_edit_); + converter->RegisterBoolField(kCanListChildren, + &TeamDriveCapabilities::can_list_children_); + converter->RegisterBoolField(kCanManageMembers, + &TeamDriveCapabilities::can_manage_members_); + converter->RegisterBoolField(kCanReadRevisions, + &TeamDriveCapabilities::can_read_revisions_); + converter->RegisterBoolField(kCanRemoveChildren, + &TeamDriveCapabilities::can_remove_children_); + converter->RegisterBoolField(kCanRename, &TeamDriveCapabilities::can_rename_); + converter->RegisterBoolField(kCanRenameTeamDrive, + &TeamDriveCapabilities::can_rename_team_drive_); + converter->RegisterBoolField(kCanShare, &TeamDriveCapabilities::can_share_); +} + +//////////////////////////////////////////////////////////////////////////////// +// TeamDriveResource implementation + +TeamDriveResource::TeamDriveResource() {} + +TeamDriveResource::~TeamDriveResource() {} + +// static +std::unique_ptr<TeamDriveResource> TeamDriveResource::CreateFrom( + const base::Value& value) { + std::unique_ptr<TeamDriveResource> resource(new TeamDriveResource()); + if (!IsResourceKindExpected(value, kTeamDriveKind) || + !resource->Parse(value)) { + LOG(ERROR) << "Unable to create: Invalid Team Drive resource JSON!"; + return std::unique_ptr<TeamDriveResource>(); + } + return resource; +} + +// static +void TeamDriveResource::RegisterJSONConverter( + base::JSONValueConverter<TeamDriveResource>* converter) { + converter->RegisterStringField(kId, &TeamDriveResource::id_); + converter->RegisterStringField(kName, &TeamDriveResource::name_); + converter->RegisterNestedField(kCapabilities, + &TeamDriveResource::capabilities_); +} + +bool TeamDriveResource::Parse(const base::Value& value) { + base::JSONValueConverter<TeamDriveResource> converter; + if (!converter.Convert(value, this)) { + LOG(ERROR) << "Unable to parse: Invalid Team Drive resource JSON!"; + return false; + } + return true; +} + +//////////////////////////////////////////////////////////////////////////////// // ParentReference implementation ParentReference::ParentReference() {}
diff --git a/google_apis/drive/drive_api_parser.h b/google_apis/drive/drive_api_parser.h index 43fa4f1..7f8c3ce 100644 --- a/google_apis/drive/drive_api_parser.h +++ b/google_apis/drive/drive_api_parser.h
@@ -326,6 +326,109 @@ DISALLOW_COPY_AND_ASSIGN(AppList); }; +// Capabilities of a Team Drive indicate the permissions granted to the user +// for the Team Drive and items within the Team Drive. +class TeamDriveCapabilities { + public: + TeamDriveCapabilities(); + ~TeamDriveCapabilities(); + + // Registers the mapping between JSON field names and the members in this + // class. + static void RegisterJSONConverter( + base::JSONValueConverter<TeamDriveCapabilities>* converter); + + // Creates Team Drive resource from parsed JSON. + static std::unique_ptr<TeamDriveCapabilities> + CreateFrom(const base::Value& value); + + // Whether the current user can add children to folders in this Team Drive. + bool can_add_children() const { return can_add_children_; } + // Whether the current user can comment on files in this Team Drive. + bool can_comment() const { return can_comment_; } + // Whether files in this Team Drive can be copied by the current user. + bool can_copy() const { return can_copy_; } + // Whether this Team Drive can be deleted by the current user. + bool can_delete_team_drive() const { return can_delete_team_drive_; } + // Whether files in this Team Drive can be edited by the current user. + bool can_download() const { return can_download_; } + // Whether files in this Team Drive can be edited by current user. + bool can_edit() const { return can_edit_; } + // Whether the current user can list the children of folders in this Team + // Drive. + bool can_list_children() const { return can_list_children_; } + // Whether the current user can add members to this Team Drive or remove them + // or change their role. + bool can_manage_members() const { return can_manage_members_; } + // Whether the current user has read access to the Revisions resource of files + // in this Team Drive. + bool can_read_revisions() const { return can_read_revisions_; } + // Whether the current user can remove children from folders in this Team + // Drive. + bool can_remove_children() const { return can_remove_children_; } + // Whether files or folders in this Team Drive can be renamed by the current + // user. + bool can_rename() const { return can_rename_; } + // Whether this Team Drive can be renamed by the current user. + bool can_rename_team_drive() const { return can_rename_team_drive_; } + // Whether files or folders in this Team Drive can be shared by the current + // user. + bool can_share() const { return can_share_; } + + private: + bool can_add_children_; + bool can_comment_; + bool can_copy_; + bool can_delete_team_drive_; + bool can_download_; + bool can_edit_; + bool can_list_children_; + bool can_manage_members_; + bool can_read_revisions_; + bool can_remove_children_; + bool can_rename_; + bool can_rename_team_drive_; + bool can_share_; +}; + +// Team Drive resource represents the metadata about Team Drive itself, such as +// the name. +class TeamDriveResource { + public: + TeamDriveResource(); + ~TeamDriveResource(); + + // Registers the mapping between JSON field names and the members in this + // class. + static void RegisterJSONConverter( + base::JSONValueConverter<TeamDriveResource>* converter); + + // Creates Team Drive resource from parsed JSON. + static std::unique_ptr<TeamDriveResource> + CreateFrom(const base::Value& value); + + // The ID of this Team Drive. The ID is the same as the top-level folder for + // this Team Drive. + const std::string& id() const { return id_; } + // The name of this Team Drive. + const std::string& name() const { return name_; } + // Capabilities the current user has on this Team Drive. + const TeamDriveCapabilities& capabilities() const { return capabilities_; } + + private: + friend class DriveAPIParserTest; + FRIEND_TEST_ALL_PREFIXES(DriveAPIParserTest, TeamDriveResourceParser); + + // Parses and initializes data members from content of |value|. + // Return false if parsing fails. + bool Parse(const base::Value& value); + + std::string id_; + std::string name_; + TeamDriveCapabilities capabilities_; +}; + + // ParentReference represents a directory. // https://developers.google.com/drive/v2/reference/parents class ParentReference {
diff --git a/google_apis/drive/drive_api_parser_unittest.cc b/google_apis/drive/drive_api_parser_unittest.cc index 01f930c..77579bc 100644 --- a/google_apis/drive/drive_api_parser_unittest.cc +++ b/google_apis/drive/drive_api_parser_unittest.cc
@@ -107,6 +107,34 @@ EXPECT_EQ("https://www.example.com/createForApp2", app2.create_url().spec()); } +// Test Team Drive resource parsing. +TEST(DriveAPIParserTest, TeamDriveResourceParser) { + std::unique_ptr<base::Value> document = + test_util::LoadJSONFile("drive/team_drive.json"); + ASSERT_TRUE(document.get()); + + ASSERT_EQ(base::Value::Type::DICTIONARY, document->GetType()); + std::unique_ptr<TeamDriveResource> resource(new TeamDriveResource()); + EXPECT_TRUE(resource->Parse(*document)); + + EXPECT_EQ("TestTeamDriveId", resource->id()); + EXPECT_EQ("My Team", resource->name()); + const TeamDriveCapabilities& capabilities = resource->capabilities(); + EXPECT_TRUE(capabilities.can_add_children()); + EXPECT_TRUE(capabilities.can_comment()); + EXPECT_TRUE(capabilities.can_copy()); + EXPECT_TRUE(capabilities.can_delete_team_drive()); + EXPECT_TRUE(capabilities.can_download()); + EXPECT_TRUE(capabilities.can_edit()); + EXPECT_TRUE(capabilities.can_list_children()); + EXPECT_TRUE(capabilities.can_manage_members()); + EXPECT_TRUE(capabilities.can_read_revisions()); + EXPECT_TRUE(capabilities.can_remove_children()); + EXPECT_TRUE(capabilities.can_rename()); + EXPECT_TRUE(capabilities.can_rename_team_drive()); + EXPECT_TRUE(capabilities.can_share()); +} + // Test file list parsing. TEST(DriveAPIParserTest, FileListParser) { std::string error;
diff --git a/google_apis/test/data/drive/team_drive.json b/google_apis/test/data/drive/team_drive.json new file mode 100644 index 0000000..b93b0a8 --- /dev/null +++ b/google_apis/test/data/drive/team_drive.json
@@ -0,0 +1,20 @@ +{ + "kind": "drive#teamDrive", + "id": "TestTeamDriveId", + "name": "My Team", + "capabilities": { + "canAddChildren": true, + "canComment": true, + "canCopy": true, + "canDeleteTeamDrive": true, + "canDownload": true, + "canEdit": true, + "canListChildren": true, + "canManageMembers": true, + "canReadRevisions": true, + "canRemoveChildren": true, + "canRename": true, + "canRenameTeamDrive": true, + "canShare": true + } +}
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 0ab7b54d..f61c35b 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -238,7 +238,7 @@ surface_manager_(params.surface_manager()), overlay_surface_id_(SurfaceManager::kNoSurfaceID), suppress_destruction_errors_(false), - can_suspend_state_(CanSuspendState::UNKNOWN), + suspend_enabled_(params.allow_suspend()), use_fallback_path_(false), is_encrypted_(false), underflow_count_(0), @@ -1867,31 +1867,17 @@ void WebMediaPlayerImpl::SetSuspendState(bool is_suspended) { DCHECK(main_task_runner_->BelongsToCurrentThread()); + if (!suspend_enabled_) { + DCHECK(!pipeline_controller_.IsSuspended()); + return; + } // Do not change the state after an error has occurred. // TODO(sandersd): Update PipelineController to remove the need for this. if (IsNetworkStateError(network_state_)) return; -#if defined(OS_LINUX) - // TODO(sandersd): idle suspend is disabled if decoder owns video frame. - // Used on Chromecast. Since GetCurrentFrameFromCompositor is a synchronous - // cross-thread post, avoid the cost on platforms that always allow suspend. - // Need to find a better mechanism for this. See http://crbug.com/602708 - if (can_suspend_state_ == CanSuspendState::UNKNOWN) { - scoped_refptr<VideoFrame> frame = GetCurrentFrameFromCompositor(); - if (frame) { - can_suspend_state_ = - frame->metadata()->IsTrue(VideoFrameMetadata::DECODER_OWNS_FRAME) - ? CanSuspendState::NO - : CanSuspendState::YES; - } - } -#else - can_suspend_state_ = CanSuspendState::YES; -#endif - - if (is_suspended && can_suspend_state_ != CanSuspendState::NO) { + if (is_suspended) { // If we were not resumed for long enough to satisfy the preroll attempt, // reset the clock. if (!preroll_attempt_pending_ && IsPrerollAttemptNeeded()) {
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h index 0942929..a20739f 100644 --- a/media/blink/webmediaplayer_impl.h +++ b/media/blink/webmediaplayer_impl.h
@@ -635,12 +635,8 @@ // unimportant. bool suppress_destruction_errors_; - // State indicating if it's okay to suspend or not. Updated on the first time - // OnSuspendRequested() is called. If the state is UNKNOWN, the current frame - // from the compositor will be queried to see if suspend is supported; the - // state will be set to YES or NO respectively if a frame is available. - enum class CanSuspendState { UNKNOWN, YES, NO }; - CanSuspendState can_suspend_state_; + // If true, the media pipeline can be suspended. + const bool suspend_enabled_; // Used for HLS playback and in certain fallback paths (e.g. on older devices // that can't support the unified media pipeline).
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc index 7e293fac..4f97436 100644 --- a/media/blink/webmediaplayer_impl_unittest.cc +++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -197,8 +197,8 @@ media_thread_.StartAndWaitForTesting(); } - void InitializeWebMediaPlayerImpl() { - wmpi_.reset(new WebMediaPlayerImpl( + void InitializeWebMediaPlayerImpl(bool allow_suspend) { + wmpi_ = base::MakeUnique<WebMediaPlayerImpl>( web_local_frame_, &client_, nullptr, &delegate_, base::MakeUnique<DefaultRendererFactory>( media_log_, nullptr, DefaultRendererFactory::GetGpuFactoriesCB()), @@ -209,7 +209,7 @@ media_thread_.task_runner(), message_loop_.task_runner(), message_loop_.task_runner(), WebMediaPlayerParams::Context3DCB(), base::Bind(&OnAdjustAllocatedMemory), nullptr, nullptr, nullptr, - base::TimeDelta::FromSeconds(10)))); + base::TimeDelta::FromSeconds(10), allow_suspend)); } ~WebMediaPlayerImplTest() override { @@ -330,16 +330,17 @@ // The WebMediaPlayerImpl instance under test. std::unique_ptr<WebMediaPlayerImpl> wmpi_; + private: DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImplTest); }; TEST_F(WebMediaPlayerImplTest, ConstructAndDestroy) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); EXPECT_FALSE(IsSuspended()); } TEST_F(WebMediaPlayerImplTest, IdleSuspendIsEnabledBeforeLoadingBegins) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); EXPECT_TRUE(delegate_.ExpireForTesting()); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(IsSuspended()); @@ -347,7 +348,7 @@ TEST_F(WebMediaPlayerImplTest, IdleSuspendIsDisabledIfLoadingProgressedRecently) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); base::SimpleTestTickClock* clock = new base::SimpleTestTickClock(); clock->Advance(base::TimeDelta::FromSeconds(1)); SetTickClock(clock); @@ -361,7 +362,7 @@ } TEST_F(WebMediaPlayerImplTest, IdleSuspendIsEnabledIfLoadingHasStalled) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); base::SimpleTestTickClock* clock = new base::SimpleTestTickClock(); clock->Advance(base::TimeDelta::FromSeconds(1)); SetTickClock(clock); @@ -374,9 +375,16 @@ EXPECT_TRUE(IsSuspended()); } +TEST_F(WebMediaPlayerImplTest, DisableSuspend) { + InitializeWebMediaPlayerImpl(false); + EXPECT_TRUE(delegate_.ExpireForTesting()); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(IsSuspended()); +} + TEST_F(WebMediaPlayerImplTest, DidLoadingProgressTriggersResume) { // Same setup as IdleSuspendIsEnabledBeforeLoadingBegins. - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); EXPECT_TRUE(delegate_.ExpireForTesting()); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(IsSuspended()); @@ -391,7 +399,7 @@ } TEST_F(WebMediaPlayerImplTest, ComputePlayState_Constructed) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); WebMediaPlayerImpl::PlayState state = ComputePlayState(); EXPECT_EQ(WebMediaPlayerImpl::DelegateState::GONE, state.delegate_state); EXPECT_TRUE(state.is_idle); @@ -400,7 +408,7 @@ } TEST_F(WebMediaPlayerImplTest, ComputePlayState_HaveMetadata) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); WebMediaPlayerImpl::PlayState state = ComputePlayState(); EXPECT_EQ(WebMediaPlayerImpl::DelegateState::GONE, state.delegate_state); @@ -410,7 +418,7 @@ } TEST_F(WebMediaPlayerImplTest, ComputePlayState_HaveFutureData) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); WebMediaPlayerImpl::PlayState state = ComputePlayState(); @@ -421,7 +429,7 @@ } TEST_F(WebMediaPlayerImplTest, ComputePlayState_Playing) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); SetPaused(false); @@ -433,7 +441,7 @@ } TEST_F(WebMediaPlayerImplTest, ComputePlayState_Underflow) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); SetPaused(false); @@ -446,7 +454,7 @@ } TEST_F(WebMediaPlayerImplTest, ComputePlayState_FrameHidden) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); SetPaused(false); @@ -475,7 +483,7 @@ } TEST_F(WebMediaPlayerImplTest, ComputePlayState_FrameClosed) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); SetPaused(false); @@ -488,7 +496,7 @@ } TEST_F(WebMediaPlayerImplTest, ComputePlayState_PausedSeek) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); SetSeeking(true); @@ -500,7 +508,7 @@ } TEST_F(WebMediaPlayerImplTest, ComputePlayState_Ended) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); SetPaused(false); @@ -524,7 +532,7 @@ } TEST_F(WebMediaPlayerImplTest, ComputePlayState_StaysSuspended) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); @@ -537,7 +545,7 @@ } TEST_F(WebMediaPlayerImplTest, ComputePlayState_Remote) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); @@ -550,7 +558,7 @@ } TEST_F(WebMediaPlayerImplTest, ComputePlayState_Fullscreen) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); SetFullscreen(true); @@ -566,7 +574,7 @@ } TEST_F(WebMediaPlayerImplTest, ComputePlayState_Streaming) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); SetPaused(true); @@ -594,7 +602,7 @@ base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeature(kResumeBackgroundVideo); - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); SetPaused(false); @@ -609,7 +617,7 @@ } TEST_F(WebMediaPlayerImplTest, ComputePlayState_AudioOnly) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, false); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); SetPaused(false); @@ -623,7 +631,7 @@ } TEST_F(WebMediaPlayerImplTest, AutoplayMuted_StartsAndStops) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); SetPaused(false); @@ -638,7 +646,7 @@ } TEST_F(WebMediaPlayerImplTest, AutoplayMuted_SetVolume) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetMetadata(true, true); SetReadyState(blink::WebMediaPlayer::ReadyStateHaveFutureData); SetPaused(false); @@ -653,7 +661,7 @@ } TEST_F(WebMediaPlayerImplTest, NaturalSizeChange) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); PipelineMetadata metadata; metadata.has_video = true; metadata.natural_size = gfx::Size(320, 240); @@ -667,7 +675,7 @@ } TEST_F(WebMediaPlayerImplTest, NaturalSizeChange_Rotated) { - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); PipelineMetadata metadata; metadata.has_video = true; metadata.natural_size = gfx::Size(320, 240); @@ -684,7 +692,7 @@ TEST_F(WebMediaPlayerImplTest, BackgroundOptimizationsFeatureEnabled) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeature(kBackgroundVideoTrackOptimization); - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetVideoKeyframeDistanceAverage(base::TimeDelta::FromSeconds(5)); SetDuration(base::TimeDelta::FromSeconds(300)); @@ -725,7 +733,7 @@ base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndDisableFeature(kBackgroundVideoTrackOptimization); - InitializeWebMediaPlayerImpl(); + InitializeWebMediaPlayerImpl(true); SetVideoKeyframeDistanceAverage(base::TimeDelta::FromSeconds(5)); SetDuration(base::TimeDelta::FromSeconds(300));
diff --git a/media/blink/webmediaplayer_params.cc b/media/blink/webmediaplayer_params.cc index 917261f..ac83ceb1 100644 --- a/media/blink/webmediaplayer_params.cc +++ b/media/blink/webmediaplayer_params.cc
@@ -23,7 +23,8 @@ blink::WebContentDecryptionModule* initial_cdm, SurfaceManager* surface_manager, base::WeakPtr<MediaObserver> media_observer, - base::TimeDelta max_keyframe_distance_to_disable_background_video) + base::TimeDelta max_keyframe_distance_to_disable_background_video, + bool allow_suspend) : defer_load_cb_(defer_load_cb), audio_renderer_sink_(audio_renderer_sink), media_log_(media_log), @@ -36,7 +37,8 @@ surface_manager_(surface_manager), media_observer_(media_observer), max_keyframe_distance_to_disable_background_video_( - max_keyframe_distance_to_disable_background_video) {} + max_keyframe_distance_to_disable_background_video), + allow_suspend_(allow_suspend) {} WebMediaPlayerParams::~WebMediaPlayerParams() {}
diff --git a/media/blink/webmediaplayer_params.h b/media/blink/webmediaplayer_params.h index 54ab539d..a39b6a6 100644 --- a/media/blink/webmediaplayer_params.h +++ b/media/blink/webmediaplayer_params.h
@@ -59,7 +59,8 @@ blink::WebContentDecryptionModule* initial_cdm, SurfaceManager* surface_manager, base::WeakPtr<MediaObserver> media_observer, - base::TimeDelta max_keyframe_distance_to_disable_background_video); + base::TimeDelta max_keyframe_distance_to_disable_background_video, + bool allow_suspend); ~WebMediaPlayerParams(); @@ -107,6 +108,8 @@ return max_keyframe_distance_to_disable_background_video_; } + bool allow_suspend() const { return allow_suspend_; } + private: DeferLoadCB defer_load_cb_; scoped_refptr<SwitchableAudioRendererSink> audio_renderer_sink_; @@ -121,6 +124,7 @@ SurfaceManager* surface_manager_; base::WeakPtr<MediaObserver> media_observer_; base::TimeDelta max_keyframe_distance_to_disable_background_video_; + const bool allow_suspend_; DISALLOW_IMPLICIT_CONSTRUCTORS(WebMediaPlayerParams); };
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn index 6450f6a9..8b12761 100644 --- a/media/mojo/services/BUILD.gn +++ b/media/mojo/services/BUILD.gn
@@ -196,12 +196,13 @@ source = "test_manifest.json" } -test("media_pipeline_integration_unittests") { +service_test("media_pipeline_integration_unittests") { testonly = true + catalog = ":media_pipeline_integration_unittests_catalog" + deps = [ "//media/test:mojo_pipeline_integration_tests", - "//services/service_manager/public/cpp/test:run_all_service_tests", ] data_deps = [ @@ -218,3 +219,8 @@ embedded_services = [ ":test_manifest" ] standalone_services = [ ":media_manifest" ] } + +catalog("media_pipeline_integration_unittests_catalog") { + embedded_services = [ ":pipeline_test_manifest" ] + standalone_services = [ ":media_manifest" ] +}
diff --git a/net/quic/test_tools/test_task_runner.cc b/net/quic/test_tools/test_task_runner.cc index 5e6e647d..aed7b8fc 100644 --- a/net/quic/test_tools/test_task_runner.cc +++ b/net/quic/test_tools/test_task_runner.cc
@@ -40,9 +40,9 @@ DCHECK(next != tasks_.end()); clock_->AdvanceTime(QuicTime::Delta::FromMicroseconds( (next->GetTimeToRun() - clock_->NowInTicks()).InMicroseconds())); - PostedTask task = *next; + PostedTask task = std::move(*next); tasks_.erase(next); - task.task.Run(); + std::move(task.task).Run(); } namespace {
diff --git a/remoting/protocol/connection_unittest.cc b/remoting/protocol/connection_unittest.cc index f2a48ef7..5fcdc50 100644 --- a/remoting/protocol/connection_unittest.cc +++ b/remoting/protocol/connection_unittest.cc
@@ -619,7 +619,8 @@ EXPECT_LE(stats.client_stats.time_rendered, finish_time); } -TEST_P(ConnectionTest, Audio) { +// Disabling due to failures after WebRTC roll http://crbug.com/685910 +TEST_P(ConnectionTest, DISABLED_Audio) { Connect(); std::unique_ptr<AudioStream> audio_stream =
diff --git a/services/BUILD.gn b/services/BUILD.gn index 5cb1983..6153cdf 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn
@@ -12,6 +12,6 @@ test("service_unittests") { deps = [ "//services/image_decoder:tests", - "//services/service_manager/public/cpp/test:run_all_service_tests", + "//services/test:run_all_unittests", ] }
diff --git a/services/navigation/BUILD.gn b/services/navigation/BUILD.gn index 411829a..e30fe16 100644 --- a/services/navigation/BUILD.gn +++ b/services/navigation/BUILD.gn
@@ -4,6 +4,7 @@ import("//services/service_manager/public/cpp/service.gni") import("//services/service_manager/public/service_manifest.gni") +import("//services/service_manager/public/tools/test/service_test.gni") import("//testing/test.gni") import("//tools/grit/repack.gni") @@ -43,23 +44,24 @@ ] } -test("navigation_unittests") { +service_test("navigation_unittests") { sources = [ "navigation_unittest.cc", ] + catalog = ":navigation_unittests_catalog" + deps = [ "//base", - "//base/test:test_support", + "//mojo/public/cpp/bindings", "//services/navigation/public/interfaces", "//services/service_manager/public/cpp", "//services/service_manager/public/cpp:service_test_support", - "//services/service_manager/public/cpp/test:run_all_service_tests", + "//services/service_manager/public/interfaces", "//testing/gtest", ] data_deps = [ - ":unittest_manifest", "//content/shell:content_shell", "//services/ui/test_wm", ] @@ -74,3 +76,12 @@ name = "navigation_unittests" source = "unittest_manifest.json" } + +catalog("navigation_unittests_catalog") { + embedded_services = [ ":unittest_manifest" ] + standalone_services = [ + ":manifest", + "//services/ui:manifest", + "//services/ui/test_wm:manifest", + ] +}
diff --git a/services/service_manager/background/BUILD.gn b/services/service_manager/background/BUILD.gn index 8e734e6d..156dc47 100644 --- a/services/service_manager/background/BUILD.gn +++ b/services/service_manager/background/BUILD.gn
@@ -6,7 +6,6 @@ testonly = true deps = [ ":lib", - ":main", ] } @@ -25,19 +24,3 @@ "//services/service_manager/standalone", ] } - -source_set("main") { - sources = [ - "background_service_manager_main.cc", - "background_service_manager_main.h", - ] - deps = [ - "//base", - "//services/service_manager", - "//services/service_manager/public/cpp:sources", - "//services/service_manager/runner:init", - "//services/service_manager/runner/common", - "//services/service_manager/runner/host:lib", - "//services/service_manager/standalone", - ] -}
diff --git a/services/service_manager/background/background_service_manager_main.cc b/services/service_manager/background/background_service_manager_main.cc deleted file mode 100644 index 6902ee4..0000000 --- a/services/service_manager/background/background_service_manager_main.cc +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/service_manager/background/background_service_manager_main.h" - -#include "base/at_exit.h" -#include "base/command_line.h" -#include "base/debug/debugger.h" -#include "base/process/launch.h" -#include "services/service_manager/runner/common/switches.h" -#include "services/service_manager/runner/init.h" - -int main(int argc, char** argv) { - return MasterProcessMain(argc, argv); -}
diff --git a/services/service_manager/background/background_service_manager_main.h b/services/service_manager/background/background_service_manager_main.h deleted file mode 100644 index e25ef4a..0000000 --- a/services/service_manager/background/background_service_manager_main.h +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_SERVICE_MANAGER_BACKGROUND_BACKGROUND_SERVICE_MANAGER_MAIN_H_ -#define SERVICES_SERVICE_MANAGER_BACKGROUND_BACKGROUND_SERVICE_MANAGER_MAIN_H_ - -// The "main" gn target supplies a file with a main() that calls to the child -// process as necessary. For the main process this function is called. -int MasterProcessMain(int argc, char** argv); - -#endif // SERVICES_SERVICE_MANAGER_BACKGROUND_BACKGROUND_SERVICE_MANAGER_MAIN_H_
diff --git a/services/service_manager/public/cpp/test/BUILD.gn b/services/service_manager/public/cpp/test/BUILD.gn index 569aac0..c1adadf 100644 --- a/services/service_manager/public/cpp/test/BUILD.gn +++ b/services/service_manager/public/cpp/test/BUILD.gn
@@ -4,36 +4,13 @@ import("//testing/test.gni") -group("test") { - testonly = true - deps = [ - ":run_all_service_tests", - ] -} - +# NOTE: Don't depend on this target directly. Instead use the service_test +# template from //services/service_manager/public/tools/test/service_test.gni. source_set("run_all_service_tests") { testonly = true sources = [ "run_all_service_tests.cc", - ] - - deps = [ - "//base", - "//base/test:test_support", - "//mojo/edk/system", - "//services/service_manager/background:lib", - "//services/service_manager/background:main", - ] -} - -# TODO(rockot): Remove this when all consumers of :run_all_service_tests are -# ported to service_test targets. -source_set("run_all_service_tests_with_catalog") { - testonly = true - - sources = [ - "run_all_service_tests_with_catalog.cc", "service_test_catalog.h", ]
diff --git a/services/service_manager/public/cpp/test/DEPS b/services/service_manager/public/cpp/test/DEPS index 11f060e9..c5e51f22 100644 --- a/services/service_manager/public/cpp/test/DEPS +++ b/services/service_manager/public/cpp/test/DEPS
@@ -1,5 +1,5 @@ specific_include_rules = { - "run_all_service_tests_with_catalog.cc": [ + "run_all_service_tests.cc": [ "+services/catalog", ] }
diff --git a/services/service_manager/public/cpp/test/run_all_service_tests.cc b/services/service_manager/public/cpp/test/run_all_service_tests.cc index 20e1a92..8d02f3f 100644 --- a/services/service_manager/public/cpp/test/run_all_service_tests.cc +++ b/services/service_manager/public/cpp/test/run_all_service_tests.cc
@@ -2,14 +2,30 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/message_loop/message_loop.h" #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" +#include "base/threading/thread.h" #include "mojo/edk/embedder/embedder.h" -#include "services/service_manager/background/background_service_manager_main.h" +#include "mojo/edk/embedder/scoped_ipc_support.h" +#include "services/catalog/catalog.h" +#include "services/service_manager/public/cpp/test/service_test_catalog.h" -int MasterProcessMain(int argc, char** argv) { +int main(int argc, char** argv) { base::TestSuite test_suite(argc, argv); + + catalog::Catalog::SetDefaultCatalogManifest( + service_manager::test::CreateTestCatalog()); + mojo::edk::Init(); + + base::Thread ipc_thread("IPC thread"); + ipc_thread.StartWithOptions( + base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); + mojo::edk::ScopedIPCSupport ipc_support( + ipc_thread.task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); + return base::LaunchUnitTests( argc, argv, base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
diff --git a/services/service_manager/public/tools/test/service_test.gni b/services/service_manager/public/tools/test/service_test.gni index ad7e358..dd361358 100644 --- a/services/service_manager/public/tools/test/service_test.gni +++ b/services/service_manager/public/tools/test/service_test.gni
@@ -26,7 +26,7 @@ } deps += [ ":$catalog_source_target", - "//services/service_manager/public/cpp/test:run_all_service_tests_with_catalog", + "//services/service_manager/public/cpp/test:run_all_service_tests", ] }
diff --git a/services/service_manager/tests/BUILD.gn b/services/service_manager/tests/BUILD.gn index c5bbd22..9c0a718 100644 --- a/services/service_manager/tests/BUILD.gn +++ b/services/service_manager/tests/BUILD.gn
@@ -4,6 +4,7 @@ import("//services/catalog/public/tools/catalog.gni") import("//services/service_manager/public/cpp/service.gni") +import("//services/service_manager/public/tools/test/service_test.gni") import("//mojo/public/tools/bindings/mojom.gni") import("//testing/test.gni") @@ -14,10 +15,8 @@ ] } -test("service_manager_unittests") { - sources = [ - "run_all_unittests.cc", - ] +service_test("service_manager_unittests") { + catalog = ":service_manager_unittests_catalog" deps = [ ":interfaces", @@ -40,10 +39,6 @@ "//services/service_manager/tests/shutdown", "//testing/gtest", ] - - data_deps = [ - ":catalog", - ] } mojom("interfaces") { @@ -76,13 +71,3 @@ "//services/service_manager/tests/shutdown:catalog", ] } - -copy("catalog") { - sources = get_target_outputs(":service_manager_unittests_catalog") - outputs = [ - "${root_out_dir}/service_manager_unittests_catalog.json", - ] - deps = [ - ":service_manager_unittests_catalog", - ] -}
diff --git a/services/service_manager/tests/run_all_unittests.cc b/services/service_manager/tests/run_all_unittests.cc deleted file mode 100644 index d8ebb57..0000000 --- a/services/service_manager/tests/run_all_unittests.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/test/launcher/unit_test_launcher.h" -#include "base/test/test_suite.h" -#include "base/threading/thread.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/scoped_ipc_support.h" -#include "services/catalog/catalog.h" - -namespace { - -const base::FilePath::CharType kCatalogFilename[] = - FILE_PATH_LITERAL("service_manager_unittests_catalog.json"); - -} // namespace - -int main(int argc, char** argv) { - base::TestSuite test_suite(argc, argv); - - catalog::Catalog::LoadDefaultCatalogManifest( - base::FilePath(kCatalogFilename)); - - mojo::edk::Init(); - base::Thread ipc_thread("IPC thread"); - ipc_thread.StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); - mojo::edk::ScopedIPCSupport ipc_support( - ipc_thread.task_runner(), - mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST); - - return base::LaunchUnitTests( - argc, argv, - base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite))); -}
diff --git a/services/service_manager/tests/shutdown/BUILD.gn b/services/service_manager/tests/shutdown/BUILD.gn index c07d1ff92..e5decbd 100644 --- a/services/service_manager/tests/shutdown/BUILD.gn +++ b/services/service_manager/tests/shutdown/BUILD.gn
@@ -28,7 +28,6 @@ data_deps = [ ":shutdown_client", ":shutdown_service", - ":shutdown_unittest_manifest", ] } @@ -59,9 +58,6 @@ "//services/service_manager/public/cpp:sources", "//services/service_manager/public/interfaces", ] - data_deps = [ - ":shutdown_service_manifest", - ] } service_manifest("shutdown_client_manifest") { @@ -80,9 +76,6 @@ "//services/service_manager/public/cpp:sources", "//services/service_manager/public/interfaces", ] - data_deps = [ - ":shutdown_client_manifest", - ] } catalog("catalog") {
diff --git a/services/test/BUILD.gn b/services/test/BUILD.gn new file mode 100644 index 0000000..bd22d3a --- /dev/null +++ b/services/test/BUILD.gn
@@ -0,0 +1,17 @@ +# 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. + +source_set("run_all_unittests") { + testonly = true + + sources = [ + "run_all_unittests.cc", + ] + + deps = [ + "//base", + "//base/test:test_support", + "//mojo/edk/system", + ] +}
diff --git a/services/service_manager/public/cpp/test/run_all_service_tests_with_catalog.cc b/services/test/run_all_unittests.cc similarity index 80% rename from services/service_manager/public/cpp/test/run_all_service_tests_with_catalog.cc rename to services/test/run_all_unittests.cc index 8d02f3f..9822c38 100644 --- a/services/service_manager/public/cpp/test/run_all_service_tests_with_catalog.cc +++ b/services/test/run_all_unittests.cc
@@ -8,15 +8,10 @@ #include "base/threading/thread.h" #include "mojo/edk/embedder/embedder.h" #include "mojo/edk/embedder/scoped_ipc_support.h" -#include "services/catalog/catalog.h" -#include "services/service_manager/public/cpp/test/service_test_catalog.h" int main(int argc, char** argv) { base::TestSuite test_suite(argc, argv); - catalog::Catalog::SetDefaultCatalogManifest( - service_manager::test::CreateTestCatalog()); - mojo::edk::Init(); base::Thread ipc_thread("IPC thread");
diff --git a/services/ui/common/BUILD.gn b/services/ui/common/BUILD.gn index cc7dea5..96ea1354 100644 --- a/services/ui/common/BUILD.gn +++ b/services/ui/common/BUILD.gn
@@ -67,7 +67,6 @@ deps = [ "//base/test:test_support", "//mojo/edk/system", - "//services/service_manager/background:main", ] if (use_ozone) {
diff --git a/services/ui/common/run_all_service_tests.cc b/services/ui/common/run_all_service_tests.cc index 1bdba53e..673812f 100644 --- a/services/ui/common/run_all_service_tests.cc +++ b/services/ui/common/run_all_service_tests.cc
@@ -6,7 +6,6 @@ #include "base/test/test_suite.h" #include "build/build_config.h" #include "mojo/edk/embedder/embedder.h" -#include "services/service_manager/background/background_service_manager_main.h" #if defined(USE_OZONE) #include "ui/ozone/public/ozone_platform.h" @@ -27,7 +26,7 @@ } }; -int MasterProcessMain(int argc, char** argv) { +int main(int argc, char** argv) { MusGpuTestSuite test_suite(argc, argv); mojo::edk::Init(); return base::LaunchUnitTests(
diff --git a/services/video_capture/BUILD.gn b/services/video_capture/BUILD.gn index eeb080e..c6a60f8 100644 --- a/services/video_capture/BUILD.gn +++ b/services/video_capture/BUILD.gn
@@ -4,6 +4,7 @@ import("//services/service_manager/public/cpp/service.gni") import("//services/service_manager/public/service_manifest.gni") +import("//services/service_manager/public/tools/test/service_test.gni") import("//testing/test.gni") service("video_capture") { @@ -46,7 +47,7 @@ ] } -test("video_capture_unittests") { +service_test("video_capture_unittests") { sources = [ "test/fake_device_descriptor_test.cc", "test/fake_device_descriptor_test.h", @@ -66,6 +67,8 @@ "test/service_unittest.cc", ] + catalog = ":video_capture_unittests_catalog" + deps = [ ":lib", ":video_capture", @@ -73,7 +76,6 @@ "//media/capture/mojo:capture_types", "//services/service_manager/public/cpp", "//services/service_manager/public/cpp:service_test_support", - "//services/service_manager/public/cpp/test:run_all_service_tests", "//testing/gmock", "//testing/gtest", "//ui/gfx:test_support", @@ -84,3 +86,8 @@ name = "video_capture_unittests" source = "test/service_unittest_manifest.json" } + +catalog("video_capture_unittests_catalog") { + embedded_services = [ ":unittest_manifest" ] + standalone_services = [ ":manifest" ] +}
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index a8a36f28..878c791 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -768,52 +768,52 @@ crbug.com/659123 [ Mac ] fast/css/text-overflow-ellipsis-button.html [ Pass Failure ] -crbug.com/35697 [ Win7 ] fast/table/backgr_border-table-cell-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_border-table-cell.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_border-table-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_border-table-column-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_border-table-column-group-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_border-table-column-group.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_border-table-column.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_border-table-quirks-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_border-table-quirks.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_border-table-row-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_border-table-row-group-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_border-table-row-group.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_border-table-row.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_border-table.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_layers-hide-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_layers-hide.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_layers-opacity-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_layers-opacity.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_layers-show-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_layers-show.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_position-table-cell-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_position-table-cell.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_position-table-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_position-table-column-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_position-table-column-group-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_position-table-column-group.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_position-table-column.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_position-table-row-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_position-table-row-group-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_position-table-row-group.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_position-table-row.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_position-table.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_simple-table-cell-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_simple-table-cell.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_simple-table-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_simple-table-column-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_simple-table-column-group-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_simple-table-column-group.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_simple-table-column.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_simple-table-row-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_simple-table-row-group-collapsed-border.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_simple-table-row-group.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_simple-table-row.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/backgr_simple-table.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] fast/table/tbody-background-image.html [ NeedsRebaseline ] -crbug.com/35697 [ Win7 ] tables/mozilla_expected_failures/marvin/backgr_fixed-bg.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_border-table-cell-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_border-table-cell.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_border-table-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_border-table-column-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_border-table-column-group-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_border-table-column-group.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_border-table-column.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_border-table-quirks-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_border-table-quirks.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_border-table-row-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_border-table-row-group-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_border-table-row-group.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_border-table-row.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_border-table.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_layers-hide-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_layers-hide.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_layers-opacity-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_layers-opacity.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_layers-show-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_layers-show.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_position-table-cell-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_position-table-cell.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_position-table-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_position-table-column-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_position-table-column-group-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_position-table-column-group.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_position-table-column.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_position-table-row-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_position-table-row-group-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_position-table-row-group.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_position-table-row.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_position-table.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_simple-table-cell-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_simple-table-cell.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_simple-table-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_simple-table-column-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_simple-table-column-group-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_simple-table-column-group.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_simple-table-column.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_simple-table-row-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_simple-table-row-group-collapsed-border.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_simple-table-row-group.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_simple-table-row.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/backgr_simple-table.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] fast/table/tbody-background-image.html [ NeedsRebaseline ] +crbug.com/685851 [ Win7 ] tables/mozilla_expected_failures/marvin/backgr_fixed-bg.html [ NeedsRebaseline ] # TODO(oshima): Mac Android are currently not supported. crbug.com/567837 [ Mac Android ] virtual/scalefactor200withzoom/fast/hidpi/static [ Skip ] @@ -1800,50 +1800,60 @@ # This test fails with the stable release mode. crbug.com/490015 virtual/stable/http/tests/navigation/same-and-different-back.html [ Skip ] +# These tests have console error messages whose order is not deterministic. +crbug.com/685778 http/tests/dom/promise-rejection-events.html [ Pass Failure ] +crbug.com/685778 virtual/mojo-loading/http/tests/dom/promise-rejection-events.html [ Pass Failure ] + # ====== New tests from w3c-test-autoroller added here ====== +crbug.com/626703 external/csswg-test/css-flexbox-1/layout-algorithm_algo-cross-line-001.html [ Failure ] +crbug.com/626703 external/wpt/dom/nodes/Document-characterSet-normalization.html [ Timeout ] +crbug.com/626703 external/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-2.html [ Timeout ] +crbug.com/626703 external/wpt/html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html [ Timeout ] +crbug.com/626703 external/wpt/html/semantics/scripting-1/the-script-element/async_007.htm [ Timeout ] +crbug.com/626703 external/wpt/html/semantics/scripting-1/the-script-element/async_010.htm [ Timeout ] crbug.com/626703 [ Win ] external/csswg-test/css-flexbox-1/flex-minimum-width-flex-items-001.xht [ Failure ] crbug.com/626703 [ Win ] external/csswg-test/css-flexbox-1/flex-minimum-width-flex-items-003.xht [ Failure ] crbug.com/626703 [ Win10 ] external/csswg-test/css-flexbox-1/flexbox_flex-natural-mixed-basis-auto.html [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/wpt/selection/dir-manual.html [ Timeout ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/wpt/html/semantics/forms/constraints/tooShort-input-email-add-manual.html [ Timeout ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/wpt/html/semantics/forms/constraints/tooShort-input-search-add-manual.html [ Timeout ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/wpt/html/semantics/forms/constraints/tooShort-input-url-add-manual.html [ Timeout ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/wpt/html/semantics/forms/constraints/tooShort-input-text-add-manual.html [ Timeout ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/wpt/html/semantics/forms/constraints/tooShort-textarea-add-manual.html [ Timeout ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/wpt/html/semantics/forms/constraints/tooShort-input-password-add-manual.html [ Timeout ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/wpt/html/semantics/forms/constraints/tooShort-input-tel-add-manual.html [ Timeout ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/wpt/pointerevents/compat/pointerevent_touch-action_two-finger_interaction-manual.html [ Timeout ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vrl-002.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vrl-020.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-vlr-in-htb-020.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vrl-001.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vlr-001.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vrl-001.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vrl-004.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-vlr-in-htb-001.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vrl-008.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-vlr-in-htb-008.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-prct-vrl-in-htb-002.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vrl-006.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-vrl-in-htb-004.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vlr-016.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-vrl-in-htb-020.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vlr-006.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vrl-013.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vlr-001.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vlr-008.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vlr-020.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-prct-vlr-in-htb-002.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-vrl-in-htb-001.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vrl-005.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-vrl-in-htb-008.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vlr-004.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-prct-vlr-in-htb-001.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vrl-016.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vlr-005.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-vlr-in-htb-004.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-prct-vrl-in-htb-001.xht [ Failure ] -crbug.com/626703 [ Trusty Mac10.11 Mac10.10 Retina Win7 Win10 Mac10.9 ] external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vlr-002.xht [ Failure ] +crbug.com/626703 external/wpt/selection/dir-manual.html [ Timeout ] +crbug.com/626703 external/wpt/html/semantics/forms/constraints/tooShort-input-email-add-manual.html [ Timeout ] +crbug.com/626703 external/wpt/html/semantics/forms/constraints/tooShort-input-search-add-manual.html [ Timeout ] +crbug.com/626703 external/wpt/html/semantics/forms/constraints/tooShort-input-url-add-manual.html [ Timeout ] +crbug.com/626703 external/wpt/html/semantics/forms/constraints/tooShort-input-text-add-manual.html [ Timeout ] +crbug.com/626703 external/wpt/html/semantics/forms/constraints/tooShort-textarea-add-manual.html [ Timeout ] +crbug.com/626703 external/wpt/html/semantics/forms/constraints/tooShort-input-password-add-manual.html [ Timeout ] +crbug.com/626703 external/wpt/html/semantics/forms/constraints/tooShort-input-tel-add-manual.html [ Timeout ] +crbug.com/626703 external/wpt/pointerevents/compat/pointerevent_touch-action_two-finger_interaction-manual.html [ Timeout ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vrl-002.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vrl-020.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-vlr-in-htb-020.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vrl-001.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vlr-001.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vrl-001.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vrl-004.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-vlr-in-htb-001.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vrl-008.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-vlr-in-htb-008.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-prct-vrl-in-htb-002.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vrl-006.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-vrl-in-htb-004.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vlr-016.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-vrl-in-htb-020.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vlr-006.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vrl-013.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vlr-001.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vlr-008.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vlr-020.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-prct-vlr-in-htb-002.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-vrl-in-htb-001.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vrl-005.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-vrl-in-htb-008.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vlr-004.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-prct-vlr-in-htb-001.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-htb-in-vrl-016.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vlr-005.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-vlr-in-htb-004.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-prct-vrl-in-htb-001.xht [ Failure ] +crbug.com/626703 external/csswg-test/css-writing-modes-3/sizing-orthog-prct-htb-in-vlr-002.xht [ Failure ] crbug.com/626703 external/wpt/web-animations/animation-model/animation-types/spacing-keyframes-transform.html [ Failure ] crbug.com/626703 external/wpt/web-animations/animation-model/animation-types/interpolation-per-property.html [ Timeout ] crbug.com/626703 external/wpt/web-animations/interfaces/KeyframeEffectReadOnly/copy-contructor.html [ Failure ] @@ -1869,18 +1879,18 @@ crbug.com/626703 external/csswg-test/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/logical-physical-mapping-001.html [ Failure ] crbug.com/626703 external/wpt/html/semantics/grouping-content/the-li-element/grouping-li-reftest-list-owner-menu.html [ Failure ] crbug.com/626703 external/wpt/html/semantics/grouping-content/the-li-element/grouping-li-reftest-list-owner-skip-no-boxes.html [ Failure ] -crbug.com/626703 external/wpt/streams/count-queuing-strategy.https.html [ Pass Timeout ] -crbug.com/626703 external/wpt/streams/readable-streams/bad-strategies.https.html [ Pass Timeout ] -crbug.com/626703 external/wpt/streams/readable-streams/bad-underlying-sources.https.html [ Pass Timeout ] -crbug.com/626703 external/wpt/streams/readable-streams/brand-checks.https.html [ Pass Timeout ] -crbug.com/626703 external/wpt/streams/readable-streams/cancel.https.html [ Pass Timeout ] -crbug.com/626703 external/wpt/streams/readable-streams/count-queuing-strategy-integration.https.html [ Pass Timeout ] -crbug.com/626703 external/wpt/streams/readable-streams/garbage-collection.https.html [ Pass Timeout ] -crbug.com/626703 external/wpt/streams/readable-streams/general.https.html [ Timeout Failure ] -crbug.com/626703 external/wpt/streams/readable-streams/pipe-through.https.html [ Pass Timeout ] -crbug.com/626703 external/wpt/streams/readable-streams/readable-stream-reader.https.html [ Pass Timeout ] -crbug.com/626703 external/wpt/streams/readable-streams/tee.https.html [ Pass Timeout ] -crbug.com/626703 external/wpt/streams/readable-streams/templated.https.html [ Pass Timeout ] +crbug.com/626703 external/wpt/streams/count-queuing-strategy.html [ Failure Timeout ] +crbug.com/626703 external/wpt/streams/readable-streams/bad-strategies.html [ Failure Timeout ] +crbug.com/626703 external/wpt/streams/readable-streams/bad-underlying-sources.html [ Failure Timeout ] +crbug.com/626703 external/wpt/streams/readable-streams/brand-checks.html [ Failure Timeout ] +crbug.com/626703 external/wpt/streams/readable-streams/cancel.html [ Failure Timeout ] +crbug.com/626703 external/wpt/streams/readable-streams/count-queuing-strategy-integration.html [ Failure Timeout ] +crbug.com/626703 external/wpt/streams/readable-streams/garbage-collection.html [ Failure Timeout ] +crbug.com/626703 external/wpt/streams/readable-streams/general.html [ Failure Timeout ] +crbug.com/626703 external/wpt/streams/readable-streams/pipe-through.html [ Failure Timeout ] +crbug.com/626703 external/wpt/streams/readable-streams/readable-stream-reader.html [ Failure Timeout ] +crbug.com/626703 external/wpt/streams/readable-streams/tee.html [ Failure Timeout ] +crbug.com/626703 external/wpt/streams/readable-streams/templated.html [ Failure Timeout ] crbug.com/626703 external/wpt/html/webappapis/idle-callbacks/callback-timeout.html [ Timeout ] crbug.com/626703 external/wpt/html/webappapis/idle-callbacks/callback-multiple-calls.html [ Timeout ] crbug.com/626703 external/wpt/html/webappapis/idle-callbacks/callback-exception.html [ Timeout ] @@ -1907,6 +1917,8 @@ crbug.com/626703 external/wpt/workers/opaque-origin.html [ Failure Crash ] # Other untriaged test failures, timeouts and crashes from newly-imported WPT tests. +crbug.com/626703 external/wpt/html/syntax/parsing/template/creating-an-element-for-the-token/template-owner-document.html [ Pass Timeout ] +crbug.com/626703 external/wpt/selection/selectAllChildren.html [ Pass Timeout ] crbug.com/666703 external/wpt/html/browsers/sandboxing/sandbox-disallow-same-origin.html [ Timeout ] crbug.com/626703 external/wpt/fullscreen/api/element-request-fullscreen-two-iframes-manual.html [ Timeout ] crbug.com/626703 external/wpt/html/dom/documents/dom-tree-accessors/Document.currentScript.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations index 64b8391..eef9545 100644 --- a/third_party/WebKit/LayoutTests/W3CImportExpectations +++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -70,6 +70,7 @@ ## Owners: rego@igalia.com # external/csswg-test/css-ui-3 [ Pass ] external/csswg-test/css-values-3 [ Skip ] +external/csswg-test/css-values-4 [ Skip ] external/csswg-test/css-variables-1 [ Skip ] ## Owners: kojii@chromium.org # external/csswg-test/css-writing-modes-3 [ Pass ] @@ -476,6 +477,15 @@ external/wpt/svg/shapes/rect-03.svg [ Skip ] external/wpt/svg/shapes/rect-04.svg [ Skip ] +# The outputs of these tests contain random values generated by token() +# in common/utils.js. These could be imported if the results for +# testharness tests just had pass/fail but no console error messages. +crbug.com/679742 external/wpt/html/semantics/embedded-content/media-elements/track/track-element/cors [ Skip ] + +crbug.com/626703 external/csswg-test/css-values-4/ic-unit-004.html [ Failure ] +crbug.com/626703 external/csswg-test/css-values-4/ic-unit-001.html [ Failure ] +crbug.com/626703 external/csswg-test/css-values-4/ic-unit-003.html [ Failure ] + # https://github.com/w3c/web-platform-tests/issues/1861: A function can be # called before it's defined. # crbug.com/493465: Requires the pipe feature of wptserve
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-blocklisted.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-blocklisted.html new file mode 100644 index 0000000..f33cf80 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-blocklisted.html
@@ -0,0 +1,32 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then( + gattServer => + gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => characteristic.getDescriptor( + 'bad3ec61-3cc3-4954-9702-7977df514114')) + .then(descriptor => { + return assert_promise_rejects_with_message( + descriptor.readValue(), + new DOMException( + 'readValue() called on blocklisted object marked exclude-reads. ' + + 'https://goo.gl/4NeimX', + 'SecurityError')); + })}, + 'Attempt to call readValue on a blocked descriptor must generate a SecurityError'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html new file mode 100644 index 0000000..5fb1b5be --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html
@@ -0,0 +1,31 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + return setBluetoothFakeAdapter( + 'MissingDescriptorsDisconnectingHealthThermometerAdapter') + .then( + () => assert_promise_rejects_with_message( + descriptor.readValue(), + new DOMException( + 'GATT Descriptor no longer exists.', + 'InvalidStateError'), + 'Descriptor got removed.')); + }); +}, 'Descriptor gets removed. Reject with InvalidStateError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-device-goes-out-of-range.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-device-goes-out-of-range.html new file mode 100644 index 0000000..c9f76c2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-device-goes-out-of-range.html
@@ -0,0 +1,30 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + return setBluetoothFakeAdapter('EmptyAdapter') + .then( + () => assert_promise_rejects_with_message( + descriptor.readValue(), + new DOMException( + 'Bluetooth Device is no longer in range.', + 'NetworkError'), + 'Device went out of range.')); + }); +}, 'Device goes out of range. Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-before.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-before.html new file mode 100644 index 0000000..bbe10ea4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-before.html
@@ -0,0 +1,35 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['health_thermometer']}], + optionalServices: [request_disconnection_service_uuid] + })) + .then(device => device.gatt.connect()) + .then(gattServer => { + let measurement_interval; + return gattServer.getPrimaryService('health_thermometer') + .then(ht => ht.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(d => user_description = d) + .then(() => get_request_disconnection(gattServer)) + .then(requestDisconnection => requestDisconnection()) + .then( + () => assert_promise_rejects_with_message( + user_description.readValue(), + new DOMException( + 'GATT Server is disconnected. Cannot perform GATT operations.', + 'NetworkError'))); + }); +}, 'Device disconnects before readValue. Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-error.html new file mode 100644 index 0000000..92bf4cd4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-error.html
@@ -0,0 +1,39 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('FailingGATTOperationsAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: [errorUUID(0xA0)]}], + optionalServices: [request_disconnection_service_uuid] + })) + .then(device => device.gatt.connect()) + .then(gattServer => { + let error_characteristic; + return gattServer.getPrimaryService(errorUUID(0xA0)) + .then(es => es.getCharacteristic(errorUUID(0xA1))) + .then( + characteristic => characteristic.getDescriptor( + 'gatt.characteristic_user_description')) + .then(d => user_description = d) + .then(() => get_request_disconnection(gattServer)) + .then(requestDisconnection => { + requestDisconnection(); + return assert_promise_rejects_with_message( + user_description.readValue(), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + }); + }); + }, + 'Device disconnects during a readValue call that fails. ' + + 'Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-success.html new file mode 100644 index 0000000..8b37a66 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-success.html
@@ -0,0 +1,38 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['health_thermometer']}], + optionalServices: [request_disconnection_service_uuid] + })) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService('health_thermometer') + .then(ht => ht.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(d => user_description = d) + .then(() => get_request_disconnection(gattServer)) + .then(requestDisconnection => { + requestDisconnection(); + return assert_promise_rejects_with_message( + user_description.readValue(), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + }); + }); + }, + 'Device disconnects during a readValue call that succeeds. ' + + 'Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-error.html new file mode 100644 index 0000000..295f48d1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-error.html
@@ -0,0 +1,40 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter( + 'DisconnectingDuringFailureGATTOperationAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gatt => gatt.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let disconnected = eventPromise( + descriptor.characteristic.service.device, + 'gattserverdisconnected'); + let promise = assert_promise_rejects_with_message( + descriptor.readValue(), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + return disconnected + .then( + () => + descriptor.characteristic.service.device.gatt.connect()) + .then(() => promise); + }); + }, + 'Device reconnects during a readValue call that fails. Reject ' + + 'with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-success.html new file mode 100644 index 0000000..d0643a0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-success.html
@@ -0,0 +1,40 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter( + 'DisconnectingDuringSuccessGATTOperationAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gatt => gatt.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let disconnected = eventPromise( + descriptor.characteristic.service.device, + 'gattserverdisconnected'); + let promise = assert_promise_rejects_with_message( + descriptor.readValue(), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + return disconnected + .then( + () => + descriptor.characteristic.service.device.gatt.connect()) + .then(() => promise); + }); + }, + 'Device reconnects during a readValue call that succeeds. Reject ' + + 'with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-before.html new file mode 100644 index 0000000..8a1ca77f --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-before.html
@@ -0,0 +1,32 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService('health_thermometer') + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + gattServer.disconnect(); + return assert_promise_rejects_with_message( + descriptor.readValue(), + new DOMException( + 'GATT Server is disconnected. Cannot perform GATT operations.', + 'NetworkError')); + }); + }); +}, 'disconnect() called before readValue. Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-error.html new file mode 100644 index 0000000..6e6a9cf0d --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-error.html
@@ -0,0 +1,36 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('FailingGATTOperationsAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: [errorUUID(0xA0)]}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService(errorUUID(0xA0)) + .then(service => service.getCharacteristic(errorUUID(0xA1))) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let promise = assert_promise_rejects_with_message( + descriptor.readValue(), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + gattServer.disconnect(); + return promise; + }); + }); + }, + 'disconnect() called during a readValue call that fails. ' + + 'Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-success.html new file mode 100644 index 0000000..c8af17d7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-success.html
@@ -0,0 +1,38 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService('health_thermometer') + .then( + service => + service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let promise = assert_promise_rejects_with_message( + descriptor.readValue(), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + gattServer.disconnect(); + return promise; + }); + }); + }, + 'disconnect() called during a readValue call that succeeds. ' + + 'Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-fails.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-fails.html new file mode 100644 index 0000000..2b4aea8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-fails.html
@@ -0,0 +1,38 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + return setBluetoothFakeAdapter('FailingGATTOperationsAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: [errorUUID(0xA0)]}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService(errorUUID(0xA0))) + .then( + service => { + service.getCharacteristic(errorUUID(0xA1)) + .then(characteristic => { + let tests = Promise.resolve(); + gatt_errors_tests.forEach(testSpec => { + tests = + tests + .then( + () => characteristic.getDescriptor( + testSpec.uuid)) + .then( + descriptor => + assert_promise_rejects_with_message( + descriptor.readValue(), + testSpec.error, + testSpec.testName)); + }); + return tests; + })})}, + 'readValue fails. Should reject with appropriate error.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-error.html new file mode 100644 index 0000000..dee5638 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-error.html
@@ -0,0 +1,38 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + let promise; + return setBluetoothFakeAdapter('FailingGATTOperationsAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: [errorUUID(0xA0)]}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService(errorUUID(0xA0))) + .then(service => service.getCharacteristic(errorUUID(0xA1))) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(error_descriptor => { + promise = assert_promise_rejects_with_message( + error_descriptor.readValue(), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + // Disconnect called to clear attributeInstanceMap and allow the + // object to get garbage collected. + error_descriptor.characteristic.service.device.gatt.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); + }, + 'Garbage Collection ran during a readValue call that fails. ' + + 'Should not crash.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.html new file mode 100644 index 0000000..42dbf74 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.html
@@ -0,0 +1,38 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + let promise; + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then( + gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + promise = assert_promise_rejects_with_message( + descriptor.readValue(), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + // Disconnect called to clear attributeInstanceMap and allow the + // object to get garbage collected. + descriptor.characteristic.service.device.gatt.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); + }, + 'Garbage collection ran during a readValue call that succeeds. ' + + 'Should not crash.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.html new file mode 100644 index 0000000..5a1516f9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.html
@@ -0,0 +1,34 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +promise_test( + () => { + return setBluetoothFakeAdapter( + 'GATTOperationFailsAfterReconnectionAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gatt => gatt.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let promise = assert_promise_rejects_with_message( + descriptor.readValue(), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + let gatt = descriptor.characteristic.service.device.gatt; + gatt.disconnect(); + return gatt.connect().then(() => promise); + }); + }, + 'disconnect() and connect() called during a readValue call that ' + + 'fails. Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-success.html new file mode 100644 index 0000000..f7966e5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-success.html
@@ -0,0 +1,35 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter( + 'GATTOperationSucceedsAfterReconnectionAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gatt => gatt.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let promise = assert_promise_rejects_with_message( + descriptor.readValue(), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + let gatt = descriptor.characteristic.service.device.gatt; + gatt.disconnect(); + return gatt.connect().then(() => promise); + }); + }, + 'disconnect() and connect() called during a readValue call that ' + + 'succeeds. Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-service-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-service-is-removed.html new file mode 100644 index 0000000..2cd9e6d --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-service-is-removed.html
@@ -0,0 +1,30 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + return setBluetoothFakeAdapter('MissingServiceHeartRateAdapter') + .then( + () => assert_promise_rejects_with_message( + descriptor.readValue(), + new DOMException( + 'GATT Service no longer exists.', 'InvalidStateError'), + 'Service got removed.')); + }); +}, 'Service gets removed. Reject with InvalidStateError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/read-succeeds.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/read-succeeds.html new file mode 100644 index 0000000..f0ac2da --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/read-succeeds.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then(characteristic => characteristic.getDescriptor(user_description.name)) + .then(descriptor => descriptor.readValue()) + .then(value => { + let decoder = new TextDecoder('utf-8'); + let value_str = decoder.decode(value); + assert_equals(value_str, "gatt.characteristic_user_description"); + }); +}, 'A read request succeeds and returns the descriptor\'s value.'); +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/read-updates-value.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/read-updates-value.html new file mode 100644 index 0000000..811f074 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/read-updates-value.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then(characteristic => characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + assert_equals(descriptor.value, null); + return descriptor.readValue() + .then(() => { + let decoder = new TextDecoder('utf-8'); + let value_str = decoder.decode(descriptor.value); + assert_equals(value_str, user_description.name); + }); + }); +}, 'Succesful read should update descriptor\'s value.'); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-blocklisted.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-blocklisted.js new file mode 100644 index 0000000..7c93505 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-blocklisted.js
@@ -0,0 +1,24 @@ +'use strict'; +promise_test( + () => { + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then( + gattServer => + gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => characteristic.getDescriptor( + 'bad3ec61-3cc3-4954-9702-7977df514114')) + .then(descriptor => { + return assert_promise_rejects_with_message( + descriptor.CALLS([readValue()]), + new DOMException( + 'readValue() called on blocklisted object marked exclude-reads. ' + + 'https://goo.gl/4NeimX', + 'SecurityError')); + })}, + 'Attempt to call FUNCTION_NAME on a blocked descriptor must generate a SecurityError');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-removed.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-removed.js new file mode 100644 index 0000000..b9de7ed --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-removed.js
@@ -0,0 +1,23 @@ +'use strict'; +promise_test(() => { + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + return setBluetoothFakeAdapter( + 'MissingDescriptorsDisconnectingHealthThermometerAdapter') + .then( + () => assert_promise_rejects_with_message( + descriptor.CALLS([readValue()]), + new DOMException( + 'GATT Descriptor no longer exists.', + 'InvalidStateError'), + 'Descriptor got removed.')); + }); +}, 'Descriptor gets removed. Reject with InvalidStateError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/device-goes-out-of-range.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/device-goes-out-of-range.js new file mode 100644 index 0000000..ea193f02 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/device-goes-out-of-range.js
@@ -0,0 +1,22 @@ +'use strict'; +promise_test(() => { + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + return setBluetoothFakeAdapter('EmptyAdapter') + .then( + () => assert_promise_rejects_with_message( + descriptor.CALLS([readValue()]), + new DOMException( + 'Bluetooth Device is no longer in range.', + 'NetworkError'), + 'Device went out of range.')); + }); +}, 'Device goes out of range. Reject with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-before.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-before.js new file mode 100644 index 0000000..cc22a117 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-before.js
@@ -0,0 +1,27 @@ +'use strict'; +promise_test(() => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['health_thermometer']}], + optionalServices: [request_disconnection_service_uuid] + })) + .then(device => device.gatt.connect()) + .then(gattServer => { + let measurement_interval; + return gattServer.getPrimaryService('health_thermometer') + .then(ht => ht.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(d => user_description = d) + .then(() => get_request_disconnection(gattServer)) + .then(requestDisconnection => requestDisconnection()) + .then( + () => assert_promise_rejects_with_message( + user_description.CALLS([readValue()]), + new DOMException( + 'GATT Server is disconnected. Cannot perform GATT operations.', + 'NetworkError'))); + }); +}, 'Device disconnects before FUNCTION_NAME. Reject with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-error.js new file mode 100644 index 0000000..a34ac39d --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-error.js
@@ -0,0 +1,31 @@ +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('FailingGATTOperationsAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: [errorUUID(0xA0)]}], + optionalServices: [request_disconnection_service_uuid] + })) + .then(device => device.gatt.connect()) + .then(gattServer => { + let error_characteristic; + return gattServer.getPrimaryService(errorUUID(0xA0)) + .then(es => es.getCharacteristic(errorUUID(0xA1))) + .then( + characteristic => characteristic.getDescriptor( + 'gatt.characteristic_user_description')) + .then(d => user_description = d) + .then(() => get_request_disconnection(gattServer)) + .then(requestDisconnection => { + requestDisconnection(); + return assert_promise_rejects_with_message( + user_description.CALLS([readValue()]), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + }); + }); + }, + 'Device disconnects during a FUNCTION_NAME call that fails. ' + + 'Reject with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-success.js new file mode 100644 index 0000000..42ff8c7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-success.js
@@ -0,0 +1,30 @@ +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['health_thermometer']}], + optionalServices: [request_disconnection_service_uuid] + })) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService('health_thermometer') + .then(ht => ht.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(d => user_description = d) + .then(() => get_request_disconnection(gattServer)) + .then(requestDisconnection => { + requestDisconnection(); + return assert_promise_rejects_with_message( + user_description.CALLS([readValue()]), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + }); + }); + }, + 'Device disconnects during a FUNCTION_NAME call that succeeds. ' + + 'Reject with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-error.js new file mode 100644 index 0000000..721e2ce --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-error.js
@@ -0,0 +1,32 @@ +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter( + 'DisconnectingDuringFailureGATTOperationAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gatt => gatt.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let disconnected = eventPromise( + descriptor.characteristic.service.device, + 'gattserverdisconnected'); + let promise = assert_promise_rejects_with_message( + descriptor.CALLS([readValue()]), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + return disconnected + .then( + () => + descriptor.characteristic.service.device.gatt.connect()) + .then(() => promise); + }); + }, + 'Device reconnects during a FUNCTION_NAME call that fails. Reject ' + + 'with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-success.js new file mode 100644 index 0000000..425ec6f --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-success.js
@@ -0,0 +1,32 @@ +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter( + 'DisconnectingDuringSuccessGATTOperationAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gatt => gatt.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let disconnected = eventPromise( + descriptor.characteristic.service.device, + 'gattserverdisconnected'); + let promise = assert_promise_rejects_with_message( + descriptor.CALLS([readValue()]), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + return disconnected + .then( + () => + descriptor.characteristic.service.device.gatt.connect()) + .then(() => promise); + }); + }, + 'Device reconnects during a FUNCTION_NAME call that succeeds. Reject ' + + 'with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-before.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-before.js new file mode 100644 index 0000000..f2b7b9d --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-before.js
@@ -0,0 +1,24 @@ +'use strict'; +promise_test(() => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService('health_thermometer') + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + gattServer.disconnect(); + return assert_promise_rejects_with_message( + descriptor.CALLS([readValue()]), + new DOMException( + 'GATT Server is disconnected. Cannot perform GATT operations.', + 'NetworkError')); + }); + }); +}, 'disconnect() called before FUNCTION_NAME. Reject with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-error.js new file mode 100644 index 0000000..890a3da --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-error.js
@@ -0,0 +1,28 @@ +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('FailingGATTOperationsAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: [errorUUID(0xA0)]}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService(errorUUID(0xA0)) + .then(service => service.getCharacteristic(errorUUID(0xA1))) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let promise = assert_promise_rejects_with_message( + descriptor.CALLS([readValue()]), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + gattServer.disconnect(); + return promise; + }); + }); + }, + 'disconnect() called during a FUNCTION_NAME call that fails. ' + + 'Reject with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-success.js new file mode 100644 index 0000000..2f764f8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-success.js
@@ -0,0 +1,30 @@ +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService('health_thermometer') + .then( + service => + service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let promise = assert_promise_rejects_with_message( + descriptor.CALLS([readValue()]), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + gattServer.disconnect(); + return promise; + }); + }); + }, + 'disconnect() called during a FUNCTION_NAME call that succeeds. ' + + 'Reject with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-fails.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-fails.js new file mode 100644 index 0000000..741a419 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-fails.js
@@ -0,0 +1,30 @@ +'use strict'; +promise_test( + () => { + return setBluetoothFakeAdapter('FailingGATTOperationsAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: [errorUUID(0xA0)]}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService(errorUUID(0xA0))) + .then( + service => { + service.getCharacteristic(errorUUID(0xA1)) + .then(characteristic => { + let tests = Promise.resolve(); + gatt_errors_tests.forEach(testSpec => { + tests = + tests + .then( + () => characteristic.getDescriptor( + testSpec.uuid)) + .then( + descriptor => + assert_promise_rejects_with_message( + descriptor.CALLS([readValue()]), + testSpec.error, + testSpec.testName)); + }); + return tests; + })})}, + 'FUNCTION_NAME fails. Should reject with appropriate error.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-error.js new file mode 100644 index 0000000..1fdf14f --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-error.js
@@ -0,0 +1,30 @@ +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + let promise; + return setBluetoothFakeAdapter('FailingGATTOperationsAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: [errorUUID(0xA0)]}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService(errorUUID(0xA0))) + .then(service => service.getCharacteristic(errorUUID(0xA1))) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(error_descriptor => { + promise = assert_promise_rejects_with_message( + error_descriptor.CALLS([readValue()]), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + // Disconnect called to clear attributeInstanceMap and allow the + // object to get garbage collected. + error_descriptor.characteristic.service.device.gatt.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); + }, + 'Garbage Collection ran during a FUNCTION_NAME call that fails. ' + + 'Should not crash.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-success.js new file mode 100644 index 0000000..0d2ae3c --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-success.js
@@ -0,0 +1,30 @@ +'use strict'; +promise_test( + () => { + let promise; + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then( + gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + promise = assert_promise_rejects_with_message( + descriptor.CALLS([readValue()]), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + // Disconnect called to clear attributeInstanceMap and allow the + // object to get garbage collected. + descriptor.characteristic.service.device.gatt.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); + }, + 'Garbage collection ran during a FUNCTION_NAME call that succeeds. ' + + 'Should not crash.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-reconnect-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-reconnect-during-error.js new file mode 100644 index 0000000..e9a30a26 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-reconnect-during-error.js
@@ -0,0 +1,26 @@ +promise_test( + () => { + return setBluetoothFakeAdapter( + 'GATTOperationFailsAfterReconnectionAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gatt => gatt.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let promise = assert_promise_rejects_with_message( + descriptor.CALLS([readValue()]), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + let gatt = descriptor.characteristic.service.device.gatt; + gatt.disconnect(); + return gatt.connect().then(() => promise); + }); + }, + 'disconnect() and connect() called during a FUNCTION_NAME call that ' + + 'fails. Reject with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-reconnect-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-reconnect-during-success.js new file mode 100644 index 0000000..c82a267 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-reconnect-during-success.js
@@ -0,0 +1,27 @@ +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter( + 'GATTOperationSucceedsAfterReconnectionAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gatt => gatt.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let promise = assert_promise_rejects_with_message( + descriptor.CALLS([readValue()]), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + let gatt = descriptor.characteristic.service.device.gatt; + gatt.disconnect(); + return gatt.connect().then(() => promise); + }); + }, + 'disconnect() and connect() called during a FUNCTION_NAME call that ' + + 'succeeds. Reject with NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/service-is-removed.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/service-is-removed.js new file mode 100644 index 0000000..a6058a9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/service-is-removed.js
@@ -0,0 +1,22 @@ +'use strict'; +promise_test(() => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + return setBluetoothFakeAdapter('MissingServiceHeartRateAdapter') + .then( + () => assert_promise_rejects_with_message( + descriptor.CALLS([readValue()]), + new DOMException( + 'GATT Service no longer exists.', 'InvalidStateError'), + 'Service got removed.')); + }); +}, 'Service gets removed. Reject with InvalidStateError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-error-expected.txt b/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-error-expected.txt new file mode 100644 index 0000000..187bb4ec --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-error-expected.txt
@@ -0,0 +1,6 @@ +CONSOLE ERROR: Uncaught (in promise) NetworkError: Authentication canceled. +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Authentication canceled. +PASS Garbage collection ran during a connect call that fails. Should not crash. +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/css-display-3/display-flow-root-001-expected.html b/third_party/WebKit/LayoutTests/external/csswg-test/css-display-3/display-flow-root-001-expected.html new file mode 100644 index 0000000..fcb5ac27 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/csswg-test/css-display-3/display-flow-root-001-expected.html
@@ -0,0 +1,51 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>Reference: display:flow-root</title> + <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1322191"> + <style type="text/css"> +html,body { + color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0; +} + +.float { + float: left; + width: 20px; + height: 40px; + background: pink; +} + +.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden;} + + </style> +</head> +<body> + +<div style="border:1px solid"> + <div style="margin: 40px 0"> + <div>x</div> + </div> +</div> + +<div style="border:1px solid"> + <div class="float"></div> + <div class="clearfix"></div> +</div> + +<div style="border:1px solid"> + <div class="float"></div> + <div style="display:block; border:1px solid; margin-left:20px">x</div> +</div> + +<span> + <span style="display:block; background:grey; margin:20px 0 0 21px"><div style="padding:20px">x</div></span> +</span> + +<div style="border:3px solid; height:10px;"></div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/css-display-3/display-flow-root-001.html b/third_party/WebKit/LayoutTests/external/csswg-test/css-display-3/display-flow-root-001.html new file mode 100644 index 0000000..3d1dcb02 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/csswg-test/css-display-3/display-flow-root-001.html
@@ -0,0 +1,56 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>CSS Display Test: display:flow-root</title> + <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1322191"> + <link rel="help" href="https://drafts.csswg.org/css-display-3/#valdef-display-flow-root"> + <link rel="match" href="display-flow-root-001-ref.html"> + <style type="text/css"> +html,body { + color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0; +} + +.float { + float: left; + width: 20px; + height: 40px; + background: pink; +} + + </style> +</head> +<body> + +<div style="border:1px solid"> + <!-- this tests that the flow-root margins don't collapse with its children. --> + <span style="display:flow-root; margin: 20px 0"> + <div style="margin: 20px 0">x</div> + </span> +</div> + +<div style="border:1px solid"> + <!-- this tests that the flow-root grows to fit child floats --> + <span style="display:flow-root"><div class="float"></div></span> +</div> + +<div style="border:1px solid; margin-bottom:20px"> + <!-- this tests that a float does not intrude into flow-root box --> + <div class="float"></div> + <span style="display:flow-root; border:1px solid">x</span> +</div> + +<span> + <!-- this tests that a flow-root box is constructed also in the "ibsplit" case --> + <span style="display:flow-root; background:grey;"><div style="margin:20px">x</div></span> +</span> + +<span style="display:flow-root; border:3px solid; height:10px;"> + <!-- this tests that a flow-root fills the available width, and that 'height' applies --> +</span> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/css-flexbox-1/layout-algorithm_algo-cross-line-001-expected.html b/third_party/WebKit/LayoutTests/external/csswg-test/css-flexbox-1/layout-algorithm_algo-cross-line-001-expected.html new file mode 100644 index 0000000..5174bd1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/csswg-test/css-flexbox-1/layout-algorithm_algo-cross-line-001-expected.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html> + <head> + <title>CSS Flex-basis Test</title> + <link rel="author" title="Tomek Wytrebowicz" href="mailto:tomalecpub+github@gmail.com"> + <style type="text/css"> + .flex { + width: 200px; + height: 200px; + } + + .flex > * { + background: green; + height: 200px; + width: 100px; + overflow: scroll; + display: inline-block; + } + </style> + </head> + <body> + <p>Test passes if there is a filled green square with scrollbars and <strong>no red</strong>.</p> + + <div class="flex"> + <div></div><div></div> + </div> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/css-flexbox-1/layout-algorithm_algo-cross-line-001.html b/third_party/WebKit/LayoutTests/external/csswg-test/css-flexbox-1/layout-algorithm_algo-cross-line-001.html new file mode 100644 index 0000000..7fcc96f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/csswg-test/css-flexbox-1/layout-algorithm_algo-cross-line-001.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> + <head> + <title>CSS Grid Layout Test: cross size determination with overflow:scroll</title> + <link rel="author" title="Tomek Wytrebowicz" href="mailto:tomalecpub+github@gmail.com"> + <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#algo-cross-line" title="9.4. Cross Size Determination" /> + <link rel="match" href="reference/layout-algorithm_algo-cross-line-001-ref.html" /> + <meta name="assert" content="This test checks that correct height is applied if overflow: scroll is set" /> + <style type="text/css"> + .flex { + width: 200px; + display: flex; + background: red; + } + + .flex>* { + background: green; + height: 200px; + flex: 1; + overflow: scroll; + } + </style> + </head> + <body> + <p>Test passes if there is a filled green square with scrollbars and <strong>no red</strong>.</p> + + <div class="flex"> + <div></div> + <div></div> + </div> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/css-flexbox-1/layout-algorithm_algo-cross-line-002-expected.html b/third_party/WebKit/LayoutTests/external/csswg-test/css-flexbox-1/layout-algorithm_algo-cross-line-002-expected.html new file mode 100644 index 0000000..b3a1818 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/csswg-test/css-flexbox-1/layout-algorithm_algo-cross-line-002-expected.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html> + <head> + <title>CSS Flex-basis Test</title> + <link rel="author" title="Tomek Wytrebowicz" href="mailto:tomalecpub+github@gmail.com"> + <style type="text/css"> + .flex { + width: 200px; + height: 200px; + } + + .flex > * { + background: green; + height: 100px; + width: 200px; + overflow: scroll; + } + </style> + </head> + <body> + <p>Test passes if there is a filled green square with scrollbars and <strong>no red</strong>.</p> + + <div class="flex"> + <div></div><div></div> + </div> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/css-flexbox-1/layout-algorithm_algo-cross-line-002.html b/third_party/WebKit/LayoutTests/external/csswg-test/css-flexbox-1/layout-algorithm_algo-cross-line-002.html new file mode 100644 index 0000000..1d860b44 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/csswg-test/css-flexbox-1/layout-algorithm_algo-cross-line-002.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> + <head> + <title>CSS Grid Layout Test: cross size determination with overflow:scroll</title> + <link rel="author" title="Tomek Wytrebowicz" href="mailto:tomalecpub+github@gmail.com"> + <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#algo-cross-line" title="9.4. Cross Size Determination" /> + <link rel="match" href="reference/layout-algorithm_algo-cross-line-002-ref.html" /> + <meta name="assert" content="This test checks that correct width is applied if overflow: scroll is set" /> + <style type="text/css"> + .flex { + width: 200px; + height: 200px; + display: flex; + background: red; + flex-direction: column; + } + + .flex>* { + background: green; + width: 200px; + height: 100px; + overflow: scroll; + } + </style> + </head> + <body> + <p>Test passes if there is a filled green square with scrollbars and <strong>no red</strong>.</p> + + <div class="flex"> + <div></div><div></div> + </div> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/css-ui-3/support/cursors/woolly-64.svgz.headers b/third_party/WebKit/LayoutTests/external/csswg-test/css-ui-3/support/cursors/woolly-64.svgz.headers new file mode 100644 index 0000000..9e2c13e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/csswg-test/css-ui-3/support/cursors/woolly-64.svgz.headers
@@ -0,0 +1 @@ +Content-Encoding: gzip
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/css-ui-3/text-overflow-005-expected.html b/third_party/WebKit/LayoutTests/external/csswg-test/css-ui-3/text-overflow-005-expected.html new file mode 100644 index 0000000..c966cdb --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/csswg-test/css-ui-3/text-overflow-005-expected.html
@@ -0,0 +1,7 @@ +<!doctype html> +<meta charset="utf-8"> +<title>CSS-UI test reference</title> +<link rel="author" title="Michael Howell" href="mailto:michael@notriddle.com"> +<style>html{font-family:Ahem}</style> +<div style="width:20em"><p style="text-overflow:ellipsis;overflow:hidden">XXXXXXXXXX</p></div> +
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/css-ui-3/text-overflow-005.html b/third_party/WebKit/LayoutTests/external/csswg-test/css-ui-3/text-overflow-005.html new file mode 100644 index 0000000..e50a802 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/csswg-test/css-ui-3/text-overflow-005.html
@@ -0,0 +1,19 @@ +<!doctype html> +<html class="reftest-wait"> +<meta charset="utf-8"> +<title>CSS-UI test: text-overflow reflow</title> +<meta name="assert" content="Text overflow should disappear when the container becomes large enough. This test is targetted at bug #14952 in Servo's incremental reflow engine."> +<link rel="author" title="Michael Howell" href="mailto:michael@notriddle.com"> +<link rel="help" title="8.2. Overflow Ellipsis: the 'text-overflow' property" href="http://www.w3.org/TR/css3-ui/#text-overflow"> +<link rel="match" href="reference/text-overflow-005-ref.html"> +<meta name="flags" content="ahem"> +<style>html{font-family:Ahem}</style> +<div id=goat style="width:5em"><p style="text-overflow:ellipsis;overflow:hidden">XXXXXXXXXX</p></div> +<script> +var goat = document.getElementById("goat"); +requestAnimationFrame(function() { + goat.style.width = "20em"; + document.documentElement.className = ""; +}); +</script> +
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/lint b/third_party/WebKit/LayoutTests/external/csswg-test/lint index 4ac878dd..cd48ada 100755 --- a/third_party/WebKit/LayoutTests/external/csswg-test/lint +++ b/third_party/WebKit/LayoutTests/external/csswg-test/lint
@@ -8,4 +8,4 @@ '"git submodule update --init --recursive"?') sys.exit(2) -sys.exit(0 if lint.main() == 0 else 1) +sys.exit(0 if lint.main(force_css_mode=True) == 0 else 1)
diff --git a/third_party/WebKit/LayoutTests/external/csswg-test/lint.whitelist b/third_party/WebKit/LayoutTests/external/csswg-test/lint.whitelist index a3beb9f..621cfe4 100644 --- a/third_party/WebKit/LayoutTests/external/csswg-test/lint.whitelist +++ b/third_party/WebKit/LayoutTests/external/csswg-test/lint.whitelist
@@ -57,6 +57,11 @@ *: work-in-progress/* +## Test plans and implementation reports +*: */reports/* +*: */test-plan/* + + ## Things we don't have enabled yet OPEN-NO-MODE: * PARSE-FAILED: * @@ -66,6 +71,42 @@ CONTENT-MANUAL: * +## Support files not in /support/ or similar +SUPPORT-WRONG-DIR: */reftest.list +SUPPORT-WRONG-DIR: *.headers +SUPPORT-WRONG-DIR: */README +SUPPORT-WRONG-DIR: */README.md +SUPPORT-WRONG-DIR: *-README +SUPPORT-WRONG-DIR: */LICENSE +SUPPORT-WRONG-DIR: */LICENSE-* +SUPPORT-WRONG-DIR: */COPYING +SUPPORT-WRONG-DIR: */Makefile + +# The selectors-3 testsuite has a weird build system +SUPPORT-WRONG-DIR: selectors-3/* + +# Things we should fix +SUPPORT-WRONG-DIR: css-animations-1/animationevent-interface.js +SUPPORT-WRONG-DIR: css-backgrounds-3/justfortest.html +SUPPORT-WRONG-DIR: css-backgrounds-3/background-clip/list.txt +SUPPORT-WRONG-DIR: css-backgrounds-3/background-origin/list.txt +SUPPORT-WRONG-DIR: css-color-3/htaccess +SUPPORT-WRONG-DIR: css-fonts-3/font-variant-debug.html +SUPPORT-WRONG-DIR: css-masking-1/clip-path/svg-clipPath.svg +SUPPORT-WRONG-DIR: css21/section-index.xht +SUPPORT-WRONG-DIR: css21/other-formats/xml/background-18.css +SUPPORT-WRONG-DIR: css21/other-formats/xml/background-19-alt.xml +SUPPORT-WRONG-DIR: css21/other-formats/xml/background-19.css +SUPPORT-WRONG-DIR: filters-1/filter-external-002-filter.svg +SUPPORT-WRONG-DIR: vendor-imports/mozilla/mozilla-central-reftests/check-for-references.sh +SUPPORT-WRONG-DIR: vendor-imports/mozilla/mozilla-central-reftests/sync-tests-filter +SUPPORT-WRONG-DIR: vendor-imports/mozilla/mozilla-central-reftests/sync-tests.sh +SUPPORT-WRONG-DIR: vendor-imports/mozilla/mozilla-central-reftests/masking/blank.html +SUPPORT-WRONG-DIR: vendor-imports/mozilla/mozilla-central-reftests/transforms/green.html +SUPPORT-WRONG-DIR: WOFF2-UserAgent/manifest.txt +SUPPORT-WRONG-DIR: WOFF2-UserAgent/Tests/xhtml1/testcaseindex.xht + + ## Whitespace rules that we can't enforce yet INDENT TABS: .gitmodules INDENT TABS: compositing-1/*
diff --git a/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness-expected.txt index 05af2d4..74fd882 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness-expected.txt
@@ -1,4 +1,4 @@ -CONSOLE MESSAGE: line 236: callback not yet supported +CONSOLE MESSAGE: line 251: callback not yet supported This is a testharness.js-based test. PASS URL interface: operation createObjectURL(Blob) FAIL URL interface: operation createFor(Blob) assert_own_property: interface object missing static operation expected property "createFor" missing
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continuePrimaryKey.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continuePrimaryKey.htm deleted file mode 100644 index 773141c..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continuePrimaryKey.htm +++ /dev/null
@@ -1,134 +0,0 @@ -<!doctype html> -<meta charset="utf8"> -<title>IndexedDB: IDBCursor method continuePrimaryKey()</title> -<link rel="help" - href="http://w3c.github.io/IndexedDB/#dom-idbcursor-continueprimarykey"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="support.js"></script> - -<script> -'use strict'; - -indexeddb_test( - (t, db, txn) => { - const store = db.createObjectStore('store'); - const index = store.createIndex('index', 'indexKey', {multiEntry: true}); - - store.put({indexKey: ['a', 'b']}, 1); - store.put({indexKey: ['a', 'b']}, 2); - store.put({indexKey: ['a', 'b']}, 3); - store.put({indexKey: ['b']}, 4); - - const expectedIndexEntries = [ - {key: "a", primaryKey: 1}, - {key: "a", primaryKey: 2}, - {key: "a", primaryKey: 3}, - {key: "b", primaryKey: 1}, - {key: "b", primaryKey: 2}, - {key: "b", primaryKey: 3}, - {key: "b", primaryKey: 4}, - ]; - - const request = index.openCursor(); - request.onerror = t.unreached_func('IDBIndex.openCursor should not fail'); - request.onsuccess = t.step_func(() => { - const cursor = request.result; - const expectedEntry = expectedIndexEntries.shift(); - if (expectedEntry) { - assert_equals(cursor.key, expectedEntry.key, - 'The index entry keys should reflect the object store contents'); - assert_equals(cursor.primaryKey, expectedEntry.primaryKey, - 'The index entry primary keys should reflect the object store ' + - 'contents'); - cursor.continue(); - } else { - assert_equals(cursor, null, - 'The index should not have entries that do not reflect the ' + - 'object store contents'); - } - }); - }, - (t, db) => { - const testCases = [ - // Continuing index key - { call: cursor => { cursor.continue(); }, - result: { key: "a", primaryKey: 2 } }, - { call: cursor => { cursor.continue('a'); }, - exception: 'DataError' }, - { call: cursor => { cursor.continue('b'); }, - result: { key: "b", primaryKey: 1 } }, - { call: cursor => { cursor.continue('c'); }, result: null }, - - // Called w/ index key and primary key: - { call: cursor => { cursor.continuePrimaryKey('a', 3); }, - result: { key: 'a', primaryKey: 3 } }, - { call: cursor => { cursor.continuePrimaryKey('a', 4); }, - result: { key: 'b', primaryKey: 1 } }, - { call: cursor => { cursor.continuePrimaryKey('b', 1); }, - result: {key: 'b', primaryKey: 1} }, - { call: cursor => { cursor.continuePrimaryKey('b', 4); }, - result: {key: 'b', primaryKey: 4} }, - { call: cursor => { cursor.continuePrimaryKey('b', 5); }, - result: null }, - { call: cursor => { cursor.continuePrimaryKey('c', 1); }, - result: null }, - - // Called w/ primary key but w/o index key - { call: cursor => { cursor.continuePrimaryKey(null, 1); }, - exception: 'DataError' }, - { call: cursor => { cursor.continuePrimaryKey(null, 2); }, - exception: 'DataError' }, - { call: cursor => { cursor.continuePrimaryKey(null, 3); }, - exception: 'DataError' }, - { call: cursor => { cursor.continuePrimaryKey(null, 4); }, - exception: 'DataError' }, - { call: cursor => { cursor.continuePrimaryKey(null, 5); }, - exception: 'DataError' }, - - // Called w/ index key but w/o primary key - { call: cursor => { cursor.continuePrimaryKey('a', null); }, - exception: 'DataError' }, - ]; - - const verifyContinueCalls = () => { - if (!testCases.length) { - t.done(); - return; - } - - const testCase = testCases.shift(); - - const txn = db.transaction('store'); - txn.oncomplete = t.step_func(verifyContinueCalls); - - const request = txn.objectStore('store').index('index').openCursor(); - let calledContinue = false; - request.onerror = - t.unreached_func('IDBIndex.openCursor should not fail'); - request.onsuccess = t.step_func(() => { - const cursor = request.result; - if (calledContinue) { - if (testCase.result) { - assert_equals(cursor.key, testCase.result.key, - `${testCase.call.toString()} - result key`); - assert_equals(cursor.primaryKey, testCase.result.primaryKey, - `${testCase.call.toString()} - result primary key`); - } else { - assert_equals(cursor, null); - } - } else { - calledContinue = true; - if('exception' in testCase) { - assert_throws( - testCase.exception, () => { testCase.call(cursor); }, - testCase.call.toString()); - } else { - testCase.call(cursor); - } - } - }); - }; - verifyContinueCalls(); - }); -</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/MANIFEST.json b/third_party/WebKit/LayoutTests/external/wpt/MANIFEST.json index c01ee93..a43ba389 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/wpt/MANIFEST.json
@@ -4069,11 +4069,6 @@ {} ] ], - "common/vendor-prefix.js": [ - [ - {} - ] - ], "custom-elements/adopted-callback-expected.txt": [ [ {} @@ -4159,16 +4154,6 @@ {} ] ], - "dom/events/Event-cancelBubble-expected.txt": [ - [ - {} - ] - ], - "dom/events/Event-dispatch-bubble-canceled-expected.txt": [ - [ - {} - ] - ], "dom/events/Event-dispatch-bubbles-false-expected.txt": [ [ {} @@ -4179,7 +4164,7 @@ {} ] ], - "dom/events/Event-dispatch-multiple-cancelBubble-expected.txt": [ + "dom/events/Event-dispatch-click-expected.txt": [ [ {} ] @@ -4189,12 +4174,12 @@ {} ] ], - "dom/events/Event-propagation-expected.txt": [ + "dom/events/Event-subclasses-constructors-expected.txt": [ [ {} ] ], - "dom/events/Event-subclasses-constructors-expected.txt": [ + "dom/events/EventListener-incumbent-global-2.sub-expected.txt": [ [ {} ] @@ -4594,6 +4579,11 @@ {} ] ], + "dom/nodes/Element-matches-expected.txt": [ + [ + {} + ] + ], "dom/nodes/Element-matches.js": [ [ {} @@ -4874,6 +4864,11 @@ {} ] ], + "domparsing/innerhtml-05-expected.txt": [ + [ + {} + ] + ], "domparsing/insert_adjacent_html-expected.txt": [ [ {} @@ -6199,6 +6194,11 @@ {} ] ], + "html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub-expected.txt": [ + [ + {} + ] + ], "html/browsers/history/the-location-interface/assign_after_load-1.html": [ [ {} @@ -6239,6 +6239,16 @@ {} ] ], + "html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt": [ + [ + {} + ] + ], + "html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt": [ + [ + {} + ] + ], "html/browsers/history/the-location-interface/location-prototype-setting-expected.txt": [ [ {} @@ -6414,6 +6424,11 @@ {} ] ], + "html/browsers/origin/relaxing-the-same-origin-restriction/document_domain-expected.txt": [ + [ + {} + ] + ], "html/browsers/sandboxing/inner-iframe.html": [ [ {} @@ -11709,6 +11724,16 @@ {} ] ], + "html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub-expected.txt": [ + [ + {} + ] + ], + "html/infrastructure/urls/terminology-0/document-base-url-expected.txt": [ + [ + {} + ] + ], "html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/original-id.json": [ [ {} @@ -12234,11 +12259,21 @@ {} ] ], + "html/semantics/document-metadata/the-base-element/base_about_blank-expected.txt": [ + [ + {} + ] + ], "html/semantics/document-metadata/the-base-element/base_href_invalid-expected.txt": [ [ {} ] ], + "html/semantics/document-metadata/the-base-element/base_srcdoc-expected.txt": [ + [ + {} + ] + ], "html/semantics/document-metadata/the-base-element/example.html": [ [ {} @@ -12319,12 +12354,12 @@ {} ] ], - "html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/dynamic-append-expected.txt": [ + "html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1-expected.txt": [ [ {} ] ], - "html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/not-in-shadow-tree-expected.txt": [ + "html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/dynamic-append-expected.txt": [ [ {} ] @@ -12434,6 +12469,11 @@ {} ] ], + "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-networkState-expected.txt": [ + [ + {} + ] + ], "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-control-expected.txt": [ [ {} @@ -12814,6 +12854,11 @@ {} ] ], + "html/semantics/forms/form-submission-0/submit-entity-body-expected.txt": [ + [ + {} + ] + ], "html/semantics/forms/introduction-1/contains.json": [ [ {} @@ -12844,11 +12889,6 @@ {} ] ], - "html/semantics/forms/the-fieldset-element/disabled-001-expected.txt": [ - [ - {} - ] - ], "html/semantics/forms/the-form-element/form-autocomplete-expected.txt": [ [ {} @@ -12904,11 +12944,6 @@ {} ] ], - "html/semantics/forms/the-input-element/number-expected.txt": [ - [ - {} - ] - ], "html/semantics/forms/the-input-element/radio-expected.txt": [ [ {} @@ -12944,11 +12979,6 @@ {} ] ], - "html/semantics/forms/the-input-element/week-expected.txt": [ - [ - {} - ] - ], "html/semantics/forms/the-label-element/label-attributes-expected.txt": [ [ {} @@ -13224,6 +13254,16 @@ {} ] ], + "html/semantics/scripting-1/the-script-element/external-script-utf8.js": [ + [ + {} + ] + ], + "html/semantics/scripting-1/the-script-element/external-script-windows1250.js": [ + [ + {} + ] + ], "html/semantics/scripting-1/the-script-element/fetch-src/alpha/test.js": [ [ {} @@ -13259,6 +13299,21 @@ {} ] ], + "html/semantics/scripting-1/the-script-element/resources/cross-origin.py": [ + [ + {} + ] + ], + "html/semantics/scripting-1/the-script-element/script-charset-01-expected.txt": [ + [ + {} + ] + ], + "html/semantics/scripting-1/the-script-element/script-charset-02-expected.txt": [ + [ + {} + ] + ], "html/semantics/scripting-1/the-script-element/script-charset-03-expected.txt": [ [ {} @@ -13279,11 +13334,26 @@ {} ] ], + "html/semantics/scripting-1/the-script-element/script-not-found-not-executed-2.py": [ + [ + {} + ] + ], + "html/semantics/scripting-1/the-script-element/script-not-found-not-executed.py": [ + [ + {} + ] + ], "html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-2-expected.txt": [ [ {} ] ], + "html/semantics/scripting-1/the-script-element/serve-with-content-type.py": [ + [ + {} + ] + ], "html/semantics/scripting-1/the-script-element/support/script-onerror-insertion-point-1-helper.html": [ [ {} @@ -13894,6 +13964,21 @@ {} ] ], + "html/syntax/parsing/html5lib_innerHTML_adoption01-expected.txt": [ + [ + {} + ] + ], + "html/syntax/parsing/html5lib_innerHTML_foreign-fragment-expected.txt": [ + [ + {} + ] + ], + "html/syntax/parsing/html5lib_innerHTML_webkit02-expected.txt": [ + [ + {} + ] + ], "html/syntax/parsing/html5lib_isindex-expected.txt": [ [ {} @@ -13934,6 +14019,11 @@ {} ] ], + "html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset-expected.txt": [ + [ + {} + ] + ], "html/syntax/parsing/test.js": [ [ {} @@ -15899,12 +15989,7 @@ {} ] ], - "streams/piping/close-propagation-backward.dedicatedworker-expected.txt": [ - [ - {} - ] - ], - "streams/piping/close-propagation-backward.https-expected.txt": [ + "streams/piping/close-propagation-backward-expected.txt": [ [ {} ] @@ -15919,17 +16004,12 @@ {} ] ], - "streams/piping/close-propagation-backward.sharedworker-expected.txt": [ + "streams/piping/close-propagation-backward.serviceworker.https-expected.txt": [ [ {} ] ], - "streams/piping/close-propagation-forward.dedicatedworker-expected.txt": [ - [ - {} - ] - ], - "streams/piping/close-propagation-forward.https-expected.txt": [ + "streams/piping/close-propagation-forward-expected.txt": [ [ {} ] @@ -15944,17 +16024,12 @@ {} ] ], - "streams/piping/close-propagation-forward.sharedworker-expected.txt": [ + "streams/piping/close-propagation-forward.serviceworker.https-expected.txt": [ [ {} ] ], - "streams/piping/error-propagation-backward.dedicatedworker-expected.txt": [ - [ - {} - ] - ], - "streams/piping/error-propagation-backward.https-expected.txt": [ + "streams/piping/error-propagation-backward-expected.txt": [ [ {} ] @@ -15969,17 +16044,12 @@ {} ] ], - "streams/piping/error-propagation-backward.sharedworker-expected.txt": [ + "streams/piping/error-propagation-backward.serviceworker.https-expected.txt": [ [ {} ] ], - "streams/piping/error-propagation-forward.dedicatedworker-expected.txt": [ - [ - {} - ] - ], - "streams/piping/error-propagation-forward.https-expected.txt": [ + "streams/piping/error-propagation-forward-expected.txt": [ [ {} ] @@ -15994,17 +16064,12 @@ {} ] ], - "streams/piping/error-propagation-forward.sharedworker-expected.txt": [ + "streams/piping/error-propagation-forward.serviceworker.https-expected.txt": [ [ {} ] ], - "streams/piping/flow-control.dedicatedworker-expected.txt": [ - [ - {} - ] - ], - "streams/piping/flow-control.https-expected.txt": [ + "streams/piping/flow-control-expected.txt": [ [ {} ] @@ -16019,17 +16084,12 @@ {} ] ], - "streams/piping/flow-control.sharedworker-expected.txt": [ + "streams/piping/flow-control.serviceworker.https-expected.txt": [ [ {} ] ], - "streams/piping/general.dedicatedworker-expected.txt": [ - [ - {} - ] - ], - "streams/piping/general.https-expected.txt": [ + "streams/piping/general-expected.txt": [ [ {} ] @@ -16044,7 +16104,12 @@ {} ] ], - "streams/piping/general.sharedworker-expected.txt": [ + "streams/piping/general.serviceworker.https-expected.txt": [ + [ + {} + ] + ], + "streams/piping/multiple-propagation-expected.txt": [ [ {} ] @@ -16054,11 +16119,6 @@ {} ] ], - "streams/piping/multiple-propagation.https-expected.txt": [ - [ - {} - ] - ], "streams/piping/multiple-propagation.js": [ [ {} @@ -16069,17 +16129,17 @@ {} ] ], + "streams/piping/multiple-propagation.serviceworker.https-expected.txt": [ + [ + {} + ] + ], "streams/piping/multiple-propagation.sharedworker-expected.txt": [ [ {} ] ], - "streams/piping/pipe-through.dedicatedworker-expected.txt": [ - [ - {} - ] - ], - "streams/piping/pipe-through.https-expected.txt": [ + "streams/piping/pipe-through-expected.txt": [ [ {} ] @@ -16094,7 +16154,12 @@ {} ] ], - "streams/piping/pipe-through.sharedworker-expected.txt": [ + "streams/piping/pipe-through.serviceworker.https-expected.txt": [ + [ + {} + ] + ], + "streams/piping/transform-streams-expected.txt": [ [ {} ] @@ -16104,11 +16169,6 @@ {} ] ], - "streams/piping/transform-streams.https-expected.txt": [ - [ - {} - ] - ], "streams/piping/transform-streams.js": [ [ {} @@ -16119,17 +16179,22 @@ {} ] ], + "streams/piping/transform-streams.serviceworker.https-expected.txt": [ + [ + {} + ] + ], "streams/piping/transform-streams.sharedworker-expected.txt": [ [ {} ] ], - "streams/readable-byte-streams/general.dedicatedworker-expected.txt": [ + "streams/readable-byte-streams/general-expected.txt": [ [ {} ] ], - "streams/readable-byte-streams/general.https-expected.txt": [ + "streams/readable-byte-streams/general.dedicatedworker-expected.txt": [ [ {} ] @@ -16144,6 +16209,11 @@ {} ] ], + "streams/readable-byte-streams/general.serviceworker.https-expected.txt": [ + [ + {} + ] + ], "streams/readable-byte-streams/general.sharedworker-expected.txt": [ [ {} @@ -16224,12 +16294,12 @@ {} ] ], - "streams/readable-streams/general.sharedworker-expected.txt": [ + "streams/readable-streams/general.serviceworker.https-expected.txt": [ [ {} ] ], - "streams/readable-streams/pipe-through.dedicatedworker-expected.txt": [ + "streams/readable-streams/general.sharedworker-expected.txt": [ [ {} ] @@ -16244,7 +16314,7 @@ {} ] ], - "streams/readable-streams/pipe-through.sharedworker-expected.txt": [ + "streams/readable-streams/pipe-through.serviceworker.https-expected.txt": [ [ {} ] @@ -16269,11 +16339,6 @@ {} ] ], - "streams/readable-streams/templated.dedicatedworker-expected.txt": [ - [ - {} - ] - ], "streams/readable-streams/templated.js": [ [ {} @@ -16284,7 +16349,7 @@ {} ] ], - "streams/readable-streams/templated.sharedworker-expected.txt": [ + "streams/readable-streams/templated.serviceworker.https-expected.txt": [ [ {} ] @@ -17853,12 +17918,6 @@ {} ] ], - "IndexedDB/idbcursor-continuePrimaryKey.htm": [ - [ - "/IndexedDB/idbcursor-continuePrimaryKey.htm", - {} - ] - ], "IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm": [ [ "/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm", @@ -20087,6 +20146,18 @@ {} ] ], + "dom/events/EventListener-incumbent-global-1.sub.html": [ + [ + "/dom/events/EventListener-incumbent-global-1.sub.html", + {} + ] + ], + "dom/events/EventListener-incumbent-global-2.sub.html": [ + [ + "/dom/events/EventListener-incumbent-global-2.sub.html", + {} + ] + ], "dom/events/EventListenerOptions-capture.html": [ [ "/dom/events/EventListenerOptions-capture.html", @@ -20273,12 +20344,26 @@ {} ] ], + "dom/nodes/Document-URL.sub.html": [ + [ + "/dom/nodes/Document-URL.sub.html", + {} + ] + ], "dom/nodes/Document-adoptNode.html": [ [ "/dom/nodes/Document-adoptNode.html", {} ] ], + "dom/nodes/Document-characterSet-normalization.html": [ + [ + "/dom/nodes/Document-characterSet-normalization.html", + { + "timeout": "long" + } + ] + ], "dom/nodes/Document-constructor.html": [ [ "/dom/nodes/Document-constructor.html", @@ -20333,6 +20418,18 @@ {} ] ], + "dom/nodes/Document-contentType/contentType/contenttype_mimeheader_01.html": [ + [ + "/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_01.html", + {} + ] + ], + "dom/nodes/Document-contentType/contentType/contenttype_mimeheader_02.html": [ + [ + "/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_02.html", + {} + ] + ], "dom/nodes/Document-contentType/contentType/contenttype_png.html": [ [ "/dom/nodes/Document-contentType/contentType/contenttype_png.html", @@ -20345,6 +20442,12 @@ {} ] ], + "dom/nodes/Document-contentType/contentType/contenttype_xml.html": [ + [ + "/dom/nodes/Document-contentType/contentType/contenttype_xml.html", + {} + ] + ], "dom/nodes/Document-contentType/contentType/createDocument.html": [ [ "/dom/nodes/Document-contentType/contentType/createDocument.html", @@ -20357,6 +20460,12 @@ {} ] ], + "dom/nodes/Document-contentType/contentType/xhr_responseType_document.html": [ + [ + "/dom/nodes/Document-contentType/contentType/xhr_responseType_document.html", + {} + ] + ], "dom/nodes/Document-createAttribute.html": [ [ "/dom/nodes/Document-createAttribute.html", @@ -20639,6 +20748,12 @@ {} ] ], + "dom/nodes/Element-matches.html": [ + [ + "/dom/nodes/Element-matches.html", + {} + ] + ], "dom/nodes/Element-nextElementSibling-xhtml.xhtml": [ [ "/dom/nodes/Element-nextElementSibling-xhtml.xhtml", @@ -22561,6 +22676,28 @@ {} ] ], + "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html": [ + [ + "/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html", + { + "timeout": "long" + } + ] + ], + "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html": [ + [ + "/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html", + {} + ] + ], + "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html": [ + [ + "/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html", + { + "timeout": "long" + } + ] + ], "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc.html": [ [ "/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc.html", @@ -22735,6 +22872,12 @@ {} ] ], + "html/browsers/browsing-the-web/read-text/load-text-plain.html": [ + [ + "/html/browsers/browsing-the-web/read-text/load-text-plain.html", + {} + ] + ], "html/browsers/browsing-the-web/scroll-to-fragid/001.html": [ [ "/html/browsers/browsing-the-web/scroll-to-fragid/001.html", @@ -22957,6 +23100,12 @@ } ] ], + "html/browsers/history/the-history-interface/008.html": [ + [ + "/html/browsers/history/the-history-interface/008.html", + {} + ] + ], "html/browsers/history/the-history-interface/009.html": [ [ "/html/browsers/history/the-history-interface/009.html", @@ -23179,6 +23328,12 @@ {} ] ], + "html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub.html": [ + [ + "/html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub.html", + {} + ] + ], "html/browsers/history/the-location-interface/assign_after_load.html": [ [ "/html/browsers/history/the-location-interface/assign_after_load.html", @@ -23257,6 +23412,12 @@ {} ] ], + "html/browsers/history/the-location-interface/location_hostname.html": [ + [ + "/html/browsers/history/the-location-interface/location_hostname.html", + {} + ] + ], "html/browsers/history/the-location-interface/location_href.html": [ [ "/html/browsers/history/the-location-interface/location_href.html", @@ -23427,6 +23588,14 @@ } ] ], + "html/browsers/origin/cross-origin-objects/cross-origin-objects-on-new-window.html": [ + [ + "/html/browsers/origin/cross-origin-objects/cross-origin-objects-on-new-window.html", + { + "timeout": "long" + } + ] + ], "html/browsers/origin/cross-origin-objects/cross-origin-objects.html": [ [ "/html/browsers/origin/cross-origin-objects/cross-origin-objects.html", @@ -23441,6 +23610,12 @@ {} ] ], + "html/browsers/origin/relaxing-the-same-origin-restriction/document_domain.html": [ + [ + "/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain.html", + {} + ] + ], "html/browsers/sandboxing/sandbox-allow-same-origin.html": [ [ "/html/browsers/sandboxing/sandbox-allow-same-origin.html", @@ -23525,6 +23700,14 @@ {} ] ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html": [ + [ + "/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html", + { + "timeout": "long" + } + ] + ], "html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1.html": [ [ "/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1.html", @@ -23963,6 +24146,12 @@ {} ] ], + "html/dom/documents/resource-metadata-management/document-lastModified.html": [ + [ + "/html/dom/documents/resource-metadata-management/document-lastModified.html", + {} + ] + ], "html/dom/documents/resource-metadata-management/document-readyState.html": [ [ "/html/dom/documents/resource-metadata-management/document-readyState.html", @@ -24977,6 +25166,24 @@ {} ] ], + "html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml": [ + [ + "/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml", + {} + ] + ], + "html/infrastructure/urls/terminology-0/document-base-url.html": [ + [ + "/html/infrastructure/urls/terminology-0/document-base-url.html", + {} + ] + ], + "html/infrastructure/urls/terminology-0/multiple-base.sub.html": [ + [ + "/html/infrastructure/urls/terminology-0/multiple-base.sub.html", + {} + ] + ], "html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-all.html": [ [ "/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-all.html", @@ -25091,6 +25298,12 @@ {} ] ], + "html/semantics/document-metadata/the-base-element/base_about_blank.html": [ + [ + "/html/semantics/document-metadata/the-base-element/base_about_blank.html", + {} + ] + ], "html/semantics/document-metadata/the-base-element/base_href_empty.html": [ [ "/html/semantics/document-metadata/the-base-element/base_href_empty.html", @@ -25121,6 +25334,12 @@ {} ] ], + "html/semantics/document-metadata/the-base-element/base_srcdoc.html": [ + [ + "/html/semantics/document-metadata/the-base-element/base_srcdoc.html", + {} + ] + ], "html/semantics/document-metadata/the-link-element/document-without-browsing-context.html": [ [ "/html/semantics/document-metadata/the-link-element/document-without-browsing-context.html", @@ -25145,6 +25364,18 @@ {} ] ], + "html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1.html": [ + [ + "/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1.html", + {} + ] + ], + "html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-2.html": [ + [ + "/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-2.html", + {} + ] + ], "html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/dynamic-append.html": [ [ "/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/dynamic-append.html", @@ -25475,6 +25706,12 @@ {} ] ], + "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor-no-src.html": [ + [ + "/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor-no-src.html", + {} + ] + ], "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html": [ [ "/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html", @@ -25505,6 +25742,12 @@ {} ] ], + "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-namespace.html": [ + [ + "/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-namespace.html", + {} + ] + ], "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html": [ [ "/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html", @@ -25559,6 +25802,12 @@ {} ] ], + "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-not-in-document.html": [ + [ + "/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-not-in-document.html", + {} + ] + ], "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html": [ [ "/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html", @@ -25763,6 +26012,12 @@ {} ] ], + "html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html": [ + [ + "/html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html", + {} + ] + ], "html/semantics/embedded-content/the-iframe-element/historical.html": [ [ "/html/semantics/embedded-content/the-iframe-element/historical.html", @@ -26071,6 +26326,14 @@ {} ] ], + "html/semantics/forms/form-submission-0/submit-entity-body.html": [ + [ + "/html/semantics/forms/form-submission-0/submit-entity-body.html", + { + "timeout": "long" + } + ] + ], "html/semantics/forms/historical.html": [ [ "/html/semantics/forms/historical.html", @@ -26757,6 +27020,54 @@ {} ] ], + "html/semantics/scripting-1/the-script-element/async_003.htm": [ + [ + "/html/semantics/scripting-1/the-script-element/async_003.htm", + {} + ] + ], + "html/semantics/scripting-1/the-script-element/async_004.htm": [ + [ + "/html/semantics/scripting-1/the-script-element/async_004.htm", + {} + ] + ], + "html/semantics/scripting-1/the-script-element/async_005.htm": [ + [ + "/html/semantics/scripting-1/the-script-element/async_005.htm", + {} + ] + ], + "html/semantics/scripting-1/the-script-element/async_006.htm": [ + [ + "/html/semantics/scripting-1/the-script-element/async_006.htm", + {} + ] + ], + "html/semantics/scripting-1/the-script-element/async_007.htm": [ + [ + "/html/semantics/scripting-1/the-script-element/async_007.htm", + {} + ] + ], + "html/semantics/scripting-1/the-script-element/async_008.htm": [ + [ + "/html/semantics/scripting-1/the-script-element/async_008.htm", + {} + ] + ], + "html/semantics/scripting-1/the-script-element/async_009.htm": [ + [ + "/html/semantics/scripting-1/the-script-element/async_009.htm", + {} + ] + ], + "html/semantics/scripting-1/the-script-element/async_010.htm": [ + [ + "/html/semantics/scripting-1/the-script-element/async_010.htm", + {} + ] + ], "html/semantics/scripting-1/the-script-element/async_011.htm": [ [ "/html/semantics/scripting-1/the-script-element/async_011.htm", @@ -26805,12 +27116,30 @@ {} ] ], + "html/semantics/scripting-1/the-script-element/script-charset-01.html": [ + [ + "/html/semantics/scripting-1/the-script-element/script-charset-01.html", + {} + ] + ], + "html/semantics/scripting-1/the-script-element/script-charset-02.html": [ + [ + "/html/semantics/scripting-1/the-script-element/script-charset-02.html", + {} + ] + ], "html/semantics/scripting-1/the-script-element/script-charset-03.html": [ [ "/html/semantics/scripting-1/the-script-element/script-charset-03.html", {} ] ], + "html/semantics/scripting-1/the-script-element/script-crossorigin-network.html": [ + [ + "/html/semantics/scripting-1/the-script-element/script-crossorigin-network.html", + {} + ] + ], "html/semantics/scripting-1/the-script-element/script-crossorigin.html": [ [ "/html/semantics/scripting-1/the-script-element/script-crossorigin.html", @@ -26859,6 +27188,12 @@ {} ] ], + "html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html": [ + [ + "/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html", + {} + ] + ], "html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-1.html": [ [ "/html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-1.html", @@ -27291,6 +27626,66 @@ {} ] ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-001.html": [ + [ + "/html/syntax/parsing-html-fragments/the-input-byte-stream-001.html", + {} + ] + ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-007.html": [ + [ + "/html/syntax/parsing-html-fragments/the-input-byte-stream-007.html", + {} + ] + ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-009.html": [ + [ + "/html/syntax/parsing-html-fragments/the-input-byte-stream-009.html", + {} + ] + ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-015.html": [ + [ + "/html/syntax/parsing-html-fragments/the-input-byte-stream-015.html", + {} + ] + ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-016.html": [ + [ + "/html/syntax/parsing-html-fragments/the-input-byte-stream-016.html", + {} + ] + ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-018.html": [ + [ + "/html/syntax/parsing-html-fragments/the-input-byte-stream-018.html", + {} + ] + ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-030.html": [ + [ + "/html/syntax/parsing-html-fragments/the-input-byte-stream-030.html", + {} + ] + ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-034.html": [ + [ + "/html/syntax/parsing-html-fragments/the-input-byte-stream-034.html", + {} + ] + ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-037.html": [ + [ + "/html/syntax/parsing-html-fragments/the-input-byte-stream-037.html", + {} + ] + ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-038.html": [ + [ + "/html/syntax/parsing-html-fragments/the-input-byte-stream-038.html", + {} + ] + ], "html/syntax/parsing/DOMContentLoaded-defer.html": [ [ "/html/syntax/parsing/DOMContentLoaded-defer.html", @@ -28403,6 +28798,120 @@ {} ] ], + "html/syntax/parsing/template/additions-to-foster-parenting/template-is-a-foster-parent-element.html": [ + [ + "/html/syntax/parsing/template/additions-to-foster-parenting/template-is-a-foster-parent-element.html", + {} + ] + ], + "html/syntax/parsing/template/additions-to-foster-parenting/template-is-not-a-foster-parent-element.html": [ + [ + "/html/syntax/parsing/template/additions-to-foster-parenting/template-is-not-a-foster-parent-element.html", + {} + ] + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/generating-of-implied-end-tags.html": [ + [ + "/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/generating-of-implied-end-tags.html", + {} + ] + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-body-token.html": [ + [ + "/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-body-token.html", + {} + ] + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-frameset-token.html": [ + [ + "/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-frameset-token.html", + {} + ] + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-head-token.html": [ + [ + "/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-head-token.html", + {} + ] + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-html-token.html": [ + [ + "/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-html-token.html", + {} + ] + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-body.html": [ + [ + "/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-body.html", + {} + ] + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-html.html": [ + [ + "/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-html.html", + {} + ] + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/template-end-tag-without-start-one.html": [ + [ + "/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/template-end-tag-without-start-one.html", + {} + ] + ], + "html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset.html": [ + [ + "/html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset.html", + {} + ] + ], + "html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/generating-of-implied-end-tags.html": [ + [ + "/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/generating-of-implied-end-tags.html", + {} + ] + ], + "html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/template-end-tag-without-start-one.html": [ + [ + "/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/template-end-tag-without-start-one.html", + {} + ] + ], + "html/syntax/parsing/template/additions-to-the-in-table-insertion-mode/end-tag-table.html": [ + [ + "/html/syntax/parsing/template/additions-to-the-in-table-insertion-mode/end-tag-table.html", + {} + ] + ], + "html/syntax/parsing/template/appending-to-a-template/template-child-nodes.html": [ + [ + "/html/syntax/parsing/template/appending-to-a-template/template-child-nodes.html", + {} + ] + ], + "html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-body-context.html": [ + [ + "/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-body-context.html", + {} + ] + ], + "html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-context.html": [ + [ + "/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-context.html", + {} + ] + ], + "html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-row-context.html": [ + [ + "/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-row-context.html", + {} + ] + ], + "html/syntax/parsing/template/creating-an-element-for-the-token/template-owner-document.html": [ + [ + "/html/syntax/parsing/template/creating-an-element-for-the-token/template-owner-document.html", + {} + ] + ], "html/syntax/parsing/the-end.html": [ [ "/html/syntax/parsing/the-end.html", @@ -28841,6 +29350,12 @@ {} ] ], + "html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html": [ + [ + "/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html", + {} + ] + ], "html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.worker.js": [ [ "/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.worker.html", @@ -30827,15 +31342,15 @@ {} ] ], - "streams/byte-length-queuing-strategy.https.html": [ + "streams/byte-length-queuing-strategy.html": [ [ - "/streams/byte-length-queuing-strategy.https.html", + "/streams/byte-length-queuing-strategy.html", {} ] ], - "streams/byte-length-queuing-strategy.serviceworker.html": [ + "streams/byte-length-queuing-strategy.serviceworker.https.html": [ [ - "/streams/byte-length-queuing-strategy.serviceworker.html", + "/streams/byte-length-queuing-strategy.serviceworker.https.html", {} ] ], @@ -30851,15 +31366,15 @@ {} ] ], - "streams/count-queuing-strategy.https.html": [ + "streams/count-queuing-strategy.html": [ [ - "/streams/count-queuing-strategy.https.html", + "/streams/count-queuing-strategy.html", {} ] ], - "streams/count-queuing-strategy.serviceworker.html": [ + "streams/count-queuing-strategy.serviceworker.https.html": [ [ - "/streams/count-queuing-strategy.serviceworker.html", + "/streams/count-queuing-strategy.serviceworker.https.html", {} ] ], @@ -30875,15 +31390,15 @@ {} ] ], - "streams/piping/close-propagation-backward.https.html": [ + "streams/piping/close-propagation-backward.html": [ [ - "/streams/piping/close-propagation-backward.https.html", + "/streams/piping/close-propagation-backward.html", {} ] ], - "streams/piping/close-propagation-backward.serviceworker.html": [ + "streams/piping/close-propagation-backward.serviceworker.https.html": [ [ - "/streams/piping/close-propagation-backward.serviceworker.html", + "/streams/piping/close-propagation-backward.serviceworker.https.html", {} ] ], @@ -30899,15 +31414,15 @@ {} ] ], - "streams/piping/close-propagation-forward.https.html": [ + "streams/piping/close-propagation-forward.html": [ [ - "/streams/piping/close-propagation-forward.https.html", + "/streams/piping/close-propagation-forward.html", {} ] ], - "streams/piping/close-propagation-forward.serviceworker.html": [ + "streams/piping/close-propagation-forward.serviceworker.https.html": [ [ - "/streams/piping/close-propagation-forward.serviceworker.html", + "/streams/piping/close-propagation-forward.serviceworker.https.html", {} ] ], @@ -30923,15 +31438,15 @@ {} ] ], - "streams/piping/error-propagation-backward.https.html": [ + "streams/piping/error-propagation-backward.html": [ [ - "/streams/piping/error-propagation-backward.https.html", + "/streams/piping/error-propagation-backward.html", {} ] ], - "streams/piping/error-propagation-backward.serviceworker.html": [ + "streams/piping/error-propagation-backward.serviceworker.https.html": [ [ - "/streams/piping/error-propagation-backward.serviceworker.html", + "/streams/piping/error-propagation-backward.serviceworker.https.html", {} ] ], @@ -30947,15 +31462,15 @@ {} ] ], - "streams/piping/error-propagation-forward.https.html": [ + "streams/piping/error-propagation-forward.html": [ [ - "/streams/piping/error-propagation-forward.https.html", + "/streams/piping/error-propagation-forward.html", {} ] ], - "streams/piping/error-propagation-forward.serviceworker.html": [ + "streams/piping/error-propagation-forward.serviceworker.https.html": [ [ - "/streams/piping/error-propagation-forward.serviceworker.html", + "/streams/piping/error-propagation-forward.serviceworker.https.html", {} ] ], @@ -30971,15 +31486,15 @@ {} ] ], - "streams/piping/flow-control.https.html": [ + "streams/piping/flow-control.html": [ [ - "/streams/piping/flow-control.https.html", + "/streams/piping/flow-control.html", {} ] ], - "streams/piping/flow-control.serviceworker.html": [ + "streams/piping/flow-control.serviceworker.https.html": [ [ - "/streams/piping/flow-control.serviceworker.html", + "/streams/piping/flow-control.serviceworker.https.html", {} ] ], @@ -30995,15 +31510,15 @@ {} ] ], - "streams/piping/general.https.html": [ + "streams/piping/general.html": [ [ - "/streams/piping/general.https.html", + "/streams/piping/general.html", {} ] ], - "streams/piping/general.serviceworker.html": [ + "streams/piping/general.serviceworker.https.html": [ [ - "/streams/piping/general.serviceworker.html", + "/streams/piping/general.serviceworker.https.html", {} ] ], @@ -31019,15 +31534,15 @@ {} ] ], - "streams/piping/multiple-propagation.https.html": [ + "streams/piping/multiple-propagation.html": [ [ - "/streams/piping/multiple-propagation.https.html", + "/streams/piping/multiple-propagation.html", {} ] ], - "streams/piping/multiple-propagation.serviceworker.html": [ + "streams/piping/multiple-propagation.serviceworker.https.html": [ [ - "/streams/piping/multiple-propagation.serviceworker.html", + "/streams/piping/multiple-propagation.serviceworker.https.html", {} ] ], @@ -31043,15 +31558,15 @@ {} ] ], - "streams/piping/pipe-through.https.html": [ + "streams/piping/pipe-through.html": [ [ - "/streams/piping/pipe-through.https.html", + "/streams/piping/pipe-through.html", {} ] ], - "streams/piping/pipe-through.serviceworker.html": [ + "streams/piping/pipe-through.serviceworker.https.html": [ [ - "/streams/piping/pipe-through.serviceworker.html", + "/streams/piping/pipe-through.serviceworker.https.html", {} ] ], @@ -31067,15 +31582,15 @@ {} ] ], - "streams/piping/transform-streams.https.html": [ + "streams/piping/transform-streams.html": [ [ - "/streams/piping/transform-streams.https.html", + "/streams/piping/transform-streams.html", {} ] ], - "streams/piping/transform-streams.serviceworker.html": [ + "streams/piping/transform-streams.serviceworker.https.html": [ [ - "/streams/piping/transform-streams.serviceworker.html", + "/streams/piping/transform-streams.serviceworker.https.html", {} ] ], @@ -31091,15 +31606,15 @@ {} ] ], - "streams/readable-byte-streams/general.https.html": [ + "streams/readable-byte-streams/general.html": [ [ - "/streams/readable-byte-streams/general.https.html", + "/streams/readable-byte-streams/general.html", {} ] ], - "streams/readable-byte-streams/general.serviceworker.html": [ + "streams/readable-byte-streams/general.serviceworker.https.html": [ [ - "/streams/readable-byte-streams/general.serviceworker.html", + "/streams/readable-byte-streams/general.serviceworker.https.html", {} ] ], @@ -31115,15 +31630,15 @@ {} ] ], - "streams/readable-streams/bad-strategies.https.html": [ + "streams/readable-streams/bad-strategies.html": [ [ - "/streams/readable-streams/bad-strategies.https.html", + "/streams/readable-streams/bad-strategies.html", {} ] ], - "streams/readable-streams/bad-strategies.serviceworker.html": [ + "streams/readable-streams/bad-strategies.serviceworker.https.html": [ [ - "/streams/readable-streams/bad-strategies.serviceworker.html", + "/streams/readable-streams/bad-strategies.serviceworker.https.html", {} ] ], @@ -31139,15 +31654,15 @@ {} ] ], - "streams/readable-streams/bad-underlying-sources.https.html": [ + "streams/readable-streams/bad-underlying-sources.html": [ [ - "/streams/readable-streams/bad-underlying-sources.https.html", + "/streams/readable-streams/bad-underlying-sources.html", {} ] ], - "streams/readable-streams/bad-underlying-sources.serviceworker.html": [ + "streams/readable-streams/bad-underlying-sources.serviceworker.https.html": [ [ - "/streams/readable-streams/bad-underlying-sources.serviceworker.html", + "/streams/readable-streams/bad-underlying-sources.serviceworker.https.html", {} ] ], @@ -31163,15 +31678,15 @@ {} ] ], - "streams/readable-streams/brand-checks.https.html": [ + "streams/readable-streams/brand-checks.html": [ [ - "/streams/readable-streams/brand-checks.https.html", + "/streams/readable-streams/brand-checks.html", {} ] ], - "streams/readable-streams/brand-checks.serviceworker.html": [ + "streams/readable-streams/brand-checks.serviceworker.https.html": [ [ - "/streams/readable-streams/brand-checks.serviceworker.html", + "/streams/readable-streams/brand-checks.serviceworker.https.html", {} ] ], @@ -31187,15 +31702,15 @@ {} ] ], - "streams/readable-streams/cancel.https.html": [ + "streams/readable-streams/cancel.html": [ [ - "/streams/readable-streams/cancel.https.html", + "/streams/readable-streams/cancel.html", {} ] ], - "streams/readable-streams/cancel.serviceworker.html": [ + "streams/readable-streams/cancel.serviceworker.https.html": [ [ - "/streams/readable-streams/cancel.serviceworker.html", + "/streams/readable-streams/cancel.serviceworker.https.html", {} ] ], @@ -31211,15 +31726,15 @@ {} ] ], - "streams/readable-streams/count-queuing-strategy-integration.https.html": [ + "streams/readable-streams/count-queuing-strategy-integration.html": [ [ - "/streams/readable-streams/count-queuing-strategy-integration.https.html", + "/streams/readable-streams/count-queuing-strategy-integration.html", {} ] ], - "streams/readable-streams/count-queuing-strategy-integration.serviceworker.html": [ + "streams/readable-streams/count-queuing-strategy-integration.serviceworker.https.html": [ [ - "/streams/readable-streams/count-queuing-strategy-integration.serviceworker.html", + "/streams/readable-streams/count-queuing-strategy-integration.serviceworker.https.html", {} ] ], @@ -31235,15 +31750,15 @@ {} ] ], - "streams/readable-streams/garbage-collection.https.html": [ + "streams/readable-streams/garbage-collection.html": [ [ - "/streams/readable-streams/garbage-collection.https.html", + "/streams/readable-streams/garbage-collection.html", {} ] ], - "streams/readable-streams/garbage-collection.serviceworker.html": [ + "streams/readable-streams/garbage-collection.serviceworker.https.html": [ [ - "/streams/readable-streams/garbage-collection.serviceworker.html", + "/streams/readable-streams/garbage-collection.serviceworker.https.html", {} ] ], @@ -31259,15 +31774,15 @@ {} ] ], - "streams/readable-streams/general.https.html": [ + "streams/readable-streams/general.html": [ [ - "/streams/readable-streams/general.https.html", + "/streams/readable-streams/general.html", {} ] ], - "streams/readable-streams/general.serviceworker.html": [ + "streams/readable-streams/general.serviceworker.https.html": [ [ - "/streams/readable-streams/general.serviceworker.html", + "/streams/readable-streams/general.serviceworker.https.html", {} ] ], @@ -31283,15 +31798,15 @@ {} ] ], - "streams/readable-streams/pipe-through.https.html": [ + "streams/readable-streams/pipe-through.html": [ [ - "/streams/readable-streams/pipe-through.https.html", + "/streams/readable-streams/pipe-through.html", {} ] ], - "streams/readable-streams/pipe-through.serviceworker.html": [ + "streams/readable-streams/pipe-through.serviceworker.https.html": [ [ - "/streams/readable-streams/pipe-through.serviceworker.html", + "/streams/readable-streams/pipe-through.serviceworker.https.html", {} ] ], @@ -31307,15 +31822,15 @@ {} ] ], - "streams/readable-streams/readable-stream-reader.https.html": [ + "streams/readable-streams/readable-stream-reader.html": [ [ - "/streams/readable-streams/readable-stream-reader.https.html", + "/streams/readable-streams/readable-stream-reader.html", {} ] ], - "streams/readable-streams/readable-stream-reader.serviceworker.html": [ + "streams/readable-streams/readable-stream-reader.serviceworker.https.html": [ [ - "/streams/readable-streams/readable-stream-reader.serviceworker.html", + "/streams/readable-streams/readable-stream-reader.serviceworker.https.html", {} ] ], @@ -31331,15 +31846,15 @@ {} ] ], - "streams/readable-streams/tee.https.html": [ + "streams/readable-streams/tee.html": [ [ - "/streams/readable-streams/tee.https.html", + "/streams/readable-streams/tee.html", {} ] ], - "streams/readable-streams/tee.serviceworker.html": [ + "streams/readable-streams/tee.serviceworker.https.html": [ [ - "/streams/readable-streams/tee.serviceworker.html", + "/streams/readable-streams/tee.serviceworker.https.html", {} ] ], @@ -31355,15 +31870,15 @@ {} ] ], - "streams/readable-streams/templated.https.html": [ + "streams/readable-streams/templated.html": [ [ - "/streams/readable-streams/templated.https.html", + "/streams/readable-streams/templated.html", {} ] ], - "streams/readable-streams/templated.serviceworker.html": [ + "streams/readable-streams/templated.serviceworker.https.html": [ [ - "/streams/readable-streams/templated.serviceworker.html", + "/streams/readable-streams/templated.serviceworker.https.html", {} ] ], @@ -31379,15 +31894,15 @@ {} ] ], - "streams/writable-streams/aborting.https.html": [ + "streams/writable-streams/aborting.html": [ [ - "/streams/writable-streams/aborting.https.html", + "/streams/writable-streams/aborting.html", {} ] ], - "streams/writable-streams/aborting.serviceworker.html": [ + "streams/writable-streams/aborting.serviceworker.https.html": [ [ - "/streams/writable-streams/aborting.serviceworker.html", + "/streams/writable-streams/aborting.serviceworker.https.html", {} ] ], @@ -31403,15 +31918,15 @@ {} ] ], - "streams/writable-streams/bad-strategies.https.html": [ + "streams/writable-streams/bad-strategies.html": [ [ - "/streams/writable-streams/bad-strategies.https.html", + "/streams/writable-streams/bad-strategies.html", {} ] ], - "streams/writable-streams/bad-strategies.serviceworker.html": [ + "streams/writable-streams/bad-strategies.serviceworker.https.html": [ [ - "/streams/writable-streams/bad-strategies.serviceworker.html", + "/streams/writable-streams/bad-strategies.serviceworker.https.html", {} ] ], @@ -31427,15 +31942,15 @@ {} ] ], - "streams/writable-streams/bad-underlying-sinks.https.html": [ + "streams/writable-streams/bad-underlying-sinks.html": [ [ - "/streams/writable-streams/bad-underlying-sinks.https.html", + "/streams/writable-streams/bad-underlying-sinks.html", {} ] ], - "streams/writable-streams/bad-underlying-sinks.serviceworker.html": [ + "streams/writable-streams/bad-underlying-sinks.serviceworker.https.html": [ [ - "/streams/writable-streams/bad-underlying-sinks.serviceworker.html", + "/streams/writable-streams/bad-underlying-sinks.serviceworker.https.html", {} ] ], @@ -31451,15 +31966,15 @@ {} ] ], - "streams/writable-streams/brand-checks.https.html": [ + "streams/writable-streams/brand-checks.html": [ [ - "/streams/writable-streams/brand-checks.https.html", + "/streams/writable-streams/brand-checks.html", {} ] ], - "streams/writable-streams/brand-checks.serviceworker.html": [ + "streams/writable-streams/brand-checks.serviceworker.https.html": [ [ - "/streams/writable-streams/brand-checks.serviceworker.html", + "/streams/writable-streams/brand-checks.serviceworker.https.html", {} ] ], @@ -31475,15 +31990,15 @@ {} ] ], - "streams/writable-streams/byte-length-queuing-strategy.https.html": [ + "streams/writable-streams/byte-length-queuing-strategy.html": [ [ - "/streams/writable-streams/byte-length-queuing-strategy.https.html", + "/streams/writable-streams/byte-length-queuing-strategy.html", {} ] ], - "streams/writable-streams/byte-length-queuing-strategy.serviceworker.html": [ + "streams/writable-streams/byte-length-queuing-strategy.serviceworker.https.html": [ [ - "/streams/writable-streams/byte-length-queuing-strategy.serviceworker.html", + "/streams/writable-streams/byte-length-queuing-strategy.serviceworker.https.html", {} ] ], @@ -31499,15 +32014,15 @@ {} ] ], - "streams/writable-streams/close.https.html": [ + "streams/writable-streams/close.html": [ [ - "/streams/writable-streams/close.https.html", + "/streams/writable-streams/close.html", {} ] ], - "streams/writable-streams/close.serviceworker.html": [ + "streams/writable-streams/close.serviceworker.https.html": [ [ - "/streams/writable-streams/close.serviceworker.html", + "/streams/writable-streams/close.serviceworker.https.html", {} ] ], @@ -31523,15 +32038,15 @@ {} ] ], - "streams/writable-streams/constructor.https.html": [ + "streams/writable-streams/constructor.html": [ [ - "/streams/writable-streams/constructor.https.html", + "/streams/writable-streams/constructor.html", {} ] ], - "streams/writable-streams/constructor.serviceworker.html": [ + "streams/writable-streams/constructor.serviceworker.https.html": [ [ - "/streams/writable-streams/constructor.serviceworker.html", + "/streams/writable-streams/constructor.serviceworker.https.html", {} ] ], @@ -31547,15 +32062,15 @@ {} ] ], - "streams/writable-streams/count-queuing-strategy.https.html": [ + "streams/writable-streams/count-queuing-strategy.html": [ [ - "/streams/writable-streams/count-queuing-strategy.https.html", + "/streams/writable-streams/count-queuing-strategy.html", {} ] ], - "streams/writable-streams/count-queuing-strategy.serviceworker.html": [ + "streams/writable-streams/count-queuing-strategy.serviceworker.https.html": [ [ - "/streams/writable-streams/count-queuing-strategy.serviceworker.html", + "/streams/writable-streams/count-queuing-strategy.serviceworker.https.html", {} ] ], @@ -31571,15 +32086,15 @@ {} ] ], - "streams/writable-streams/general.https.html": [ + "streams/writable-streams/general.html": [ [ - "/streams/writable-streams/general.https.html", + "/streams/writable-streams/general.html", {} ] ], - "streams/writable-streams/general.serviceworker.html": [ + "streams/writable-streams/general.serviceworker.https.html": [ [ - "/streams/writable-streams/general.serviceworker.html", + "/streams/writable-streams/general.serviceworker.https.html", {} ] ], @@ -31595,15 +32110,15 @@ {} ] ], - "streams/writable-streams/start.https.html": [ + "streams/writable-streams/start.html": [ [ - "/streams/writable-streams/start.https.html", + "/streams/writable-streams/start.html", {} ] ], - "streams/writable-streams/start.serviceworker.html": [ + "streams/writable-streams/start.serviceworker.https.html": [ [ - "/streams/writable-streams/start.serviceworker.html", + "/streams/writable-streams/start.serviceworker.https.html", {} ] ], @@ -31619,15 +32134,15 @@ {} ] ], - "streams/writable-streams/write.https.html": [ + "streams/writable-streams/write.html": [ [ - "/streams/writable-streams/write.https.html", + "/streams/writable-streams/write.html", {} ] ], - "streams/writable-streams/write.serviceworker.html": [ + "streams/writable-streams/write.serviceworker.https.html": [ [ - "/streams/writable-streams/write.serviceworker.html", + "/streams/writable-streams/write.serviceworker.https.html", {} ] ], @@ -34517,7 +35032,7 @@ "support" ], "./check_stability.py": [ - "502bff24c8b9d4562ac1d07466c2a031a83276fb", + "9396b01f28c0e6a19a68f515eb19b4f340c0e98f", "support" ], "./ci_built_diff.sh": [ @@ -34641,7 +35156,7 @@ "testharness" ], "FileAPI/idlharness-expected.txt": [ - "9e6dd3881ce2d3d1813e52dc1011554efdcf6512", + "e57737f937070ac349c5a4d9932c487e62018def", "support" ], "FileAPI/idlharness.html": [ @@ -36036,10 +36551,6 @@ "1d8598ff2c801c54c0f9be1c688b753bb6291c94", "support" ], - "common/vendor-prefix.js": [ - "2807645fda3cb1decbb944627b038fc87ef019a0", - "support" - ], "css-values/unset-value-storage.html": [ "d2e5101f623e29cc993fe2460f6c85f6ec31b471", "testharness" @@ -36332,10 +36843,6 @@ "ffd8a316822ad17adeefc1bd0da4b3a429b458b7", "testharness" ], - "dom/events/Event-cancelBubble-expected.txt": [ - "c3d9e7a5535a9eed9c4627a680644d5470d2ca30", - "support" - ], "dom/events/Event-cancelBubble.html": [ "8fea6ad0d9c8128b124c5becca41bb913c5f6ca1", "testharness" @@ -36356,10 +36863,6 @@ "47a15a9120d9612d522641f723cffb31aa0a8b58", "testharness" ], - "dom/events/Event-dispatch-bubble-canceled-expected.txt": [ - "7a91e950c8e3520079e3b63119eac788b19232b4", - "support" - ], "dom/events/Event-dispatch-bubble-canceled.html": [ "be0c3aaa90cde5bb0954147b13795da1e898d186", "testharness" @@ -36380,6 +36883,10 @@ "5c57fd9a2cf06ca774163354ae37c2af215ba3fd", "testharness" ], + "dom/events/Event-dispatch-click-expected.txt": [ + "49dc0bdb9a15de4279c2020266b23d4a68a062be", + "support" + ], "dom/events/Event-dispatch-click.html": [ "9d1941dd42c70c1551b680f1a8fb06f68f0cb7a5", "testharness" @@ -36392,10 +36899,6 @@ "d709a217f9dccd39653a9b6f585a7b8ecd551f1b", "testharness" ], - "dom/events/Event-dispatch-multiple-cancelBubble-expected.txt": [ - "a583a800ae4c9128a6381c365309e77506f41f11", - "support" - ], "dom/events/Event-dispatch-multiple-cancelBubble.html": [ "eb36d3be528dbe0984e349ba655263681f4b170d", "testharness" @@ -36452,10 +36955,6 @@ "b15976446b454c1554360c2cc39e2ae52e10e825", "testharness" ], - "dom/events/Event-propagation-expected.txt": [ - "b6d12bfe9456240bfa74876e908d49f75a62fa88", - "support" - ], "dom/events/Event-propagation.html": [ "43ec5c9e681c20864a932635889e05969fd7b8f1", "testharness" @@ -36480,6 +36979,18 @@ "ab486987bcf7b723ff5abddcf972251413bbb1ac", "testharness" ], + "dom/events/EventListener-incumbent-global-1.sub.html": [ + "ae87021507925f1f027cb4cb2cb9112a07f9c63a", + "testharness" + ], + "dom/events/EventListener-incumbent-global-2.sub-expected.txt": [ + "f6ecdf668b8447f01466cdac4d588df41bbc39b9", + "support" + ], + "dom/events/EventListener-incumbent-global-2.sub.html": [ + "55c2db9f9e4a752198a5e52aac088c1736f15a8a", + "testharness" + ], "dom/events/EventListener-incumbent-global-subframe-1.sub.html": [ "aafbe98b7950479da0aaf91c6a66d20c575af057", "support" @@ -36533,7 +37044,7 @@ "testharness" ], "dom/interfaces-expected.txt": [ - "add948a4e312b6151a67f20047e6c1371ea95c28", + "736c279a0fd985f14413551d6ce01f5393416265", "support" ], "dom/interfaces.html": [ @@ -36672,10 +37183,18 @@ "e34e5db66000a8aa51caa26b0725bd171ee4ceb5", "support" ], + "dom/nodes/Document-URL.sub.html": [ + "1b04398f6f5657ca4ed97d41de565fe52e1853e2", + "testharness" + ], "dom/nodes/Document-adoptNode.html": [ "30b4aa92d7d7811f4c6b71cc543cd09ecb3a19f1", "testharness" ], + "dom/nodes/Document-characterSet-normalization.html": [ + "fee8777427d2db47164e793ce5b00e5645ac6080", + "testharness" + ], "dom/nodes/Document-constructor-expected.txt": [ "e0997a83feef4328ec555e587c114f16ee7aeafb", "support" @@ -36720,6 +37239,14 @@ "0b0694aebaf5006fbcbedfb4a0350733265b6761", "testharness" ], + "dom/nodes/Document-contentType/contentType/contenttype_mimeheader_01.html": [ + "cc55c015eccf1e82aac5a73b3313819ebd947867", + "testharness" + ], + "dom/nodes/Document-contentType/contentType/contenttype_mimeheader_02.html": [ + "adbfab0791c0c02974f3561ad335d6f949462289", + "testharness" + ], "dom/nodes/Document-contentType/contentType/contenttype_png.html": [ "508d9203a77ad7cf355df2a18dc15c47d6616a9e", "testharness" @@ -36728,6 +37255,10 @@ "498a6622be5b4b562fea917c6484891c2a3573a4", "testharness" ], + "dom/nodes/Document-contentType/contentType/contenttype_xml.html": [ + "25bcf3dd7b7e2d0b18e525c2b17807c8e3809ba8", + "testharness" + ], "dom/nodes/Document-contentType/contentType/createDocument.html": [ "f93ae2cc88a85dec74085d4cdb1f6770b46f7746", "testharness" @@ -36736,6 +37267,10 @@ "9b59f5b10d20aad34b16a2fa009c520c617fd4f7", "testharness" ], + "dom/nodes/Document-contentType/contentType/xhr_responseType_document.html": [ + "fa1c8338a9effac407e9523b1d697f382d937c35", + "testharness" + ], "dom/nodes/Document-contentType/resources/blob.htm": [ "8c51fb6a0b587ec95ca74acfa43df7539b486297", "support" @@ -37164,6 +37699,14 @@ "252ff76fd5ebecbe451151fa7b7b6acef44f1a45", "testharness" ], + "dom/nodes/Element-matches-expected.txt": [ + "c217ff1479fa2b8f7dc81907fb71b83a23d85684", + "support" + ], + "dom/nodes/Element-matches.html": [ + "cd92efe8ce474ce030e3e9ad5997c5ee247e481a", + "testharness" + ], "dom/nodes/Element-matches.js": [ "f3923e42c55eac3f4dc9d2f8fb128e4e9b1b3afb", "support" @@ -37952,6 +38495,10 @@ "c543183d2f6b636a1e64a593f00599046a6aa632", "testharness" ], + "domparsing/innerhtml-05-expected.txt": [ + "11b3f513b7cc424896e5854ccfd6950d7da6940f", + "support" + ], "domparsing/innerhtml-05.xhtml": [ "3b31aaee88263c1458f5472adc52ab47a5a9ec29", "testharness" @@ -38077,7 +38624,7 @@ "testharness" ], "encoding/textdecoder-labels.html": [ - "c2b81d49c84e519b2c0b58dd42f405ef9f084693", + "9b1dd122e3f42ad192bed72be377a278cc487830", "testharness" ], "encoding/textdecoder-streaming.html": [ @@ -39168,6 +39715,18 @@ "07869d8baa29c9e0baf7e987f8e40f4f3c7df2e7", "testharness" ], + "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html": [ + "18bd98353460da1c9d376e9453d9a96b7c273291", + "testharness" + ], + "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html": [ + "58663b2992725c767aaabaf685f49db895e798b6", + "testharness" + ], + "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html": [ + "9a2631564f17e1e156fc6fd4fff0a595e490ba07", + "testharness" + ], "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc.html": [ "8f266717a7be3336b00b8bcef70e003bbb2c2e9d", "testharness" @@ -39436,6 +39995,10 @@ "c3d7d9a9c75a0174a179b65c46a207910835387c", "testharness" ], + "html/browsers/browsing-the-web/read-text/load-text-plain.html": [ + "c271fb10d4d7ce4c72399e4bc06fb8d311b6ffe7", + "testharness" + ], "html/browsers/browsing-the-web/scroll-to-fragid/001.html": [ "e5b02d601942664d5c30460ad1984d7721b44258", "testharness" @@ -39836,6 +40399,10 @@ "e20860d928e7b504b6322c3367c0637091d98760", "testharness" ], + "html/browsers/history/the-history-interface/008.html": [ + "714880d41e15849bdeb2ca41bfaaa0237a975923", + "testharness" + ], "html/browsers/history/the-history-interface/008.js": [ "b3b2292a1225847efdca7daf1d3055f4c8468c8f", "support" @@ -40172,6 +40739,14 @@ "2690350e1c90a432a5b48118074c6c747508acce", "testharness" ], + "html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub-expected.txt": [ + "e616fac38d90ab248493ba719c5f545c9fae04c9", + "support" + ], + "html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub.html": [ + "06f1491747305f05c0e25027ac3efddc2c719bfc", + "testharness" + ], "html/browsers/history/the-location-interface/assign_after_load-1.html": [ "0d62a80c91e3d6191dff8ed1aaf03d8955a2d544", "support" @@ -40220,6 +40795,14 @@ "011522f6b56184f49dd6555b507d6d895b53f11e", "testharness" ], + "html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt": [ + "dba0da022025260daffcf99f99ee4d65bfaa6dfe", + "support" + ], + "html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt": [ + "60f2755719f6074c3f6e67e4fe140358acf6093c", + "support" + ], "html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird.html": [ "13a360b3010a85c1661d9357355894453137c9df", "testharness" @@ -40264,6 +40847,10 @@ "8a476ad13abe5a0bde6dfad4db840563bb502a89", "testharness" ], + "html/browsers/history/the-location-interface/location_hostname.html": [ + "46ee84a0b03fb55e18044ba7acaba2e57ab2ea82", + "testharness" + ], "html/browsers/history/the-location-interface/location_href.html": [ "ba4014b9c60c9ef1c477d37ad939c7203d7709b9", "testharness" @@ -40489,7 +41076,7 @@ "support" ], "html/browsers/origin/cross-origin-objects/cross-origin-objects-exceptions-expected.txt": [ - "56bb3aabf5fe7ba9d38e088224ad3b7ee60d8c3a", + "5074e545dc1000b55718c5c6bd9de0a7b6832a9c", "support" ], "html/browsers/origin/cross-origin-objects/cross-origin-objects-exceptions.html": [ @@ -40500,6 +41087,10 @@ "94b45bfb4fbf4ebd1b3c126df025440d176209ac", "support" ], + "html/browsers/origin/cross-origin-objects/cross-origin-objects-on-new-window.html": [ + "604c6ee2bd78187a600dd28e03b60caf89580cfe", + "testharness" + ], "html/browsers/origin/cross-origin-objects/cross-origin-objects.html": [ "4397388c56189b03b7cf2fb195449fff6c895c81", "testharness" @@ -40516,6 +41107,14 @@ "360415417ed0dadfaf947954fbd0cf801dbd5bdc", "testharness" ], + "html/browsers/origin/relaxing-the-same-origin-restriction/document_domain-expected.txt": [ + "35f3ae9d7539026756a6e2a8a4b17a7c1bbe7bdb", + "support" + ], + "html/browsers/origin/relaxing-the-same-origin-restriction/document_domain.html": [ + "9839a9c24ce78ec42da8a60d2175df06e19983c1", + "testharness" + ], "html/browsers/sandboxing/inner-iframe.html": [ "ba143e41121916fba5522d5e1dca29d04ab5f4ce", "support" @@ -40620,6 +41219,10 @@ "0774f038a82d1ebc612e7c0c711954eb9e00c70c", "testharness" ], + "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html": [ + "bfe0358e85d6b436e6e30cdc77c6b0e0bd33163d", + "testharness" + ], "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/non_automated/001-1.html": [ "66b9ad9bc1a36be79f76fcff27133ea8eb9e23fb", "support" @@ -40785,7 +41388,7 @@ "testharness" ], "html/browsers/the-window-object/window-named-properties-expected.txt": [ - "69d7277e89d99a74a6ed29c627733280c1470185", + "c3ddb934740e5b85737f08b2320003491d12a276", "support" ], "html/browsers/the-window-object/window-named-properties.html": [ @@ -41164,6 +41767,10 @@ "43ca280deb707482f4fa7a327e00a5a24cedc848", "testharness" ], + "html/dom/documents/resource-metadata-management/document-lastModified.html": [ + "9e3b552d47b7ae89c17a9341a9224afbd6dc3102", + "testharness" + ], "html/dom/documents/resource-metadata-management/document-lastModified.html.headers": [ "53d13d660a3eecc04265e1ae6bba8d4c09fd7b94", "support" @@ -46328,6 +46935,26 @@ "d5b9668048b1c4f3599ff4ac4476e9587cefc352", "testharness" ], + "html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub-expected.txt": [ + "8862b9460b11b6afbd81d9382ff79375d4f69f70", + "support" + ], + "html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml": [ + "ed3aa629bb438b285cc30761f526e76bad8c01b8", + "testharness" + ], + "html/infrastructure/urls/terminology-0/document-base-url-expected.txt": [ + "f6c6e95beebcbe393896d1b31941141e7c45b97e", + "support" + ], + "html/infrastructure/urls/terminology-0/document-base-url.html": [ + "eef89bcfc8df29b79707b9fa5ea63707a839281e", + "testharness" + ], + "html/infrastructure/urls/terminology-0/multiple-base.sub.html": [ + "399834df0104e545523749fb6758f586765251c5", + "testharness" + ], "html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-all.html": [ "c585848ac662bdb43dbfcb96c1e65284f9aef73c", "testharness" @@ -47060,6 +47687,14 @@ "adf136354fb5d5e70f2fa016712eff8995fa4710", "support" ], + "html/semantics/document-metadata/the-base-element/base_about_blank-expected.txt": [ + "767a96a1017a2a3578c72bd873d0b75313adba03", + "support" + ], + "html/semantics/document-metadata/the-base-element/base_about_blank.html": [ + "6867a4d38382a9c981832c93712aa0484bf161f3", + "testharness" + ], "html/semantics/document-metadata/the-base-element/base_href_empty.html": [ "737d8340ecefb177759786e52084d681620d2e13", "testharness" @@ -47084,6 +47719,14 @@ "4d7278090c1feb19e7de60ca9ab55810d949a86d", "testharness" ], + "html/semantics/document-metadata/the-base-element/base_srcdoc-expected.txt": [ + "27ef651daa93b6d8fb783302a9383ebdd5985c51", + "support" + ], + "html/semantics/document-metadata/the-base-element/base_srcdoc.html": [ + "7c607f8f41d2d8f4b395a081812d6eb3d36e4495", + "testharness" + ], "html/semantics/document-metadata/the-base-element/example.html": [ "f566fd16393069f65492097e084eba1408e124b3", "support" @@ -47176,6 +47819,18 @@ "a87934d6ec713c3349a9e0e643e2f7362fe090f7", "support" ], + "html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1-expected.txt": [ + "5871308257bb66f08724986967040012edc1f5d5", + "support" + ], + "html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1.html": [ + "26f5160ab02a74fd5148018893932bbc8cb01198", + "testharness" + ], + "html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-2.html": [ + "212740e5977533ccd69e370d109438bdf4c2a5d2", + "testharness" + ], "html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/dynamic-append-expected.txt": [ "dbf17ca8e33bca9bc2c67390a704c824cd4ff04a", "support" @@ -47188,10 +47843,6 @@ "050190b2706ff41b0a5844ca159990908d57177c", "testharness" ], - "html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/not-in-shadow-tree-expected.txt": [ - "fd72553cfc141995ec78c5f566976d8dc32da5fa", - "support" - ], "html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/not-in-shadow-tree.html": [ "0d5f568af3b295b36e390156caf5ce523fd83d93", "testharness" @@ -47257,7 +47908,7 @@ "support" ], "html/semantics/embedded-content/image-maps/image-map-processing-model/hash-name-reference-expected.txt": [ - "ea9c8663f79e6019fcd291be5e66ed6b25dd64ec", + "eec10c1f9afcedeaf7a89648d073fc0bb9795560", "support" ], "html/semantics/embedded-content/image-maps/image-map-processing-model/hash-name-reference-test-data.html": [ @@ -47468,6 +48119,10 @@ "85074dd09d194ded62141e0e724a444f6e5f1c5c", "testharness" ], + "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor-no-src.html": [ + "bb04c2e07224b24cdb1a64c171cd76bd97383995", + "testharness" + ], "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html": [ "dd952004c3449ed543b4b0f9b53d9f03f407a7f3", "testharness" @@ -47496,6 +48151,10 @@ "9c34d3e7eaf90aaa6b4084eb580bc45866b5e226", "testharness" ], + "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-namespace.html": [ + "f3bbb0f87c26f01b76c6e032891bbbc45b964f77", + "testharness" + ], "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html": [ "a8a3ebdf73b02bb2fc14f3f1fe09e85a091af1d1", "testharness" @@ -47544,10 +48203,18 @@ "db82f82f73fe633307e94df5582ef83448698c83", "testharness" ], + "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-networkState-expected.txt": [ + "989cb63b58d092d0d1ce1bd25073dec3ef153abc", + "support" + ], "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-networkState.html": [ "f45e4ebd634489d9187259ae64bad04d33d5e6a2", "testharness" ], + "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-not-in-document.html": [ + "ce8e1baa91c253ad2e365bb6e1380b783eeab2fa", + "testharness" + ], "html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html": [ "faab19884033e0ab5189483dca6eaf5b4d7afba0", "testharness" @@ -47820,6 +48487,10 @@ "5654d0f8b2a68e96f4d13d480f768f8fadea39e2", "support" ], + "html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html": [ + "30f590a975529a8975bea659be46192c755f2bac", + "testharness" + ], "html/semantics/embedded-content/the-iframe-element/historical.html": [ "cf6e961b764d5c6e7e1289f3db988fe94efaf030", "testharness" @@ -48029,7 +48700,7 @@ "testharness" ], "html/semantics/embedded-content/the-img-element/usemap-casing-expected.txt": [ - "cefce32704068e2e9a744727cea15d777276df73", + "ea5151cf6e1d2ca4d704afd73e3060a8d1875b84", "support" ], "html/semantics/embedded-content/the-img-element/usemap-casing.html": [ @@ -48256,6 +48927,14 @@ "92c8c30e186f0a94a962bb5c4be7acf0860b943e", "testharness" ], + "html/semantics/forms/form-submission-0/submit-entity-body-expected.txt": [ + "40598e87f886906294a176573b4c22ea35cf574e", + "support" + ], + "html/semantics/forms/form-submission-0/submit-entity-body.html": [ + "f73376af978f2fb89dcbd6e9092f113d90c7a3d6", + "testharness" + ], "html/semantics/forms/historical.html": [ "96c0951e2b6d718c1b044f71911508cc673e37de", "testharness" @@ -48340,10 +49019,6 @@ "7d6b7eb6d9daa95a09469181e8c62c8174be5d52", "testharness" ], - "html/semantics/forms/the-fieldset-element/disabled-001-expected.txt": [ - "c9ee727c5101c14d586d41e8c61da9f2a2aaa8e1", - "support" - ], "html/semantics/forms/the-fieldset-element/disabled-001.html": [ "f8c2eeac272c802f70ee5e520eab3212c016604f", "testharness" @@ -48441,11 +49116,11 @@ "support" ], "html/semantics/forms/the-input-element/date-expected.txt": [ - "ae1c5529fc065ba5ddf18e5e25640f63374391c4", + "d867bda4f83fe88ccc672ebb053bf8b7a96bad28", "support" ], "html/semantics/forms/the-input-element/date.html": [ - "e8ea33c1a5d1b009d2a0639ed37760801f1f57d6", + "6f60577eb930ff28d0da0874bfc97bc0f40cf2e7", "testharness" ], "html/semantics/forms/the-input-element/datetime-local-expected.txt": [ @@ -48504,12 +49179,8 @@ "1d833657f1db1e58fcc12a01af2ba06a665344aa", "testharness" ], - "html/semantics/forms/the-input-element/number-expected.txt": [ - "63cf413de3b09c8c06d7fca9096e2cccee301219", - "support" - ], "html/semantics/forms/the-input-element/number.html": [ - "0bbea7d06019aee83c867000ddf731d67441f5f6", + "dd4d991e33a2657a858657c455fdb5c75b02453d", "testharness" ], "html/semantics/forms/the-input-element/password.html": [ @@ -48537,11 +49208,11 @@ "testharness" ], "html/semantics/forms/the-input-element/range-expected.txt": [ - "8438e9bcb766666546e80d68c6ce3c9fd94edf09", + "41087e2783650709041989a1c283bf4a17591bbd", "support" ], "html/semantics/forms/the-input-element/range.html": [ - "ea08abb623b159195601145e58c138352f6cf331", + "dd51c517a149c51e939a30dcad5e93f196e35cff", "testharness" ], "html/semantics/forms/the-input-element/required_attribute.html": [ @@ -48581,11 +49252,11 @@ "testharness" ], "html/semantics/forms/the-input-element/time-expected.txt": [ - "0ffa59f153e1aac3f7dcfab21df9584b2a361826", + "cb71268f9bb4870786ece914dbfc3a31e89f02fc", "support" ], "html/semantics/forms/the-input-element/time.html": [ - "481e1565792abc2f8a4e5e6e423e524da10f90b1", + "71ec9a48d420683524432c5fb1086b67cd858d9a", "testharness" ], "html/semantics/forms/the-input-element/type-change-state-expected.txt": [ @@ -48608,12 +49279,8 @@ "ee58fbca9963dee22a2572eecf8fa9b047e7a837", "testharness" ], - "html/semantics/forms/the-input-element/week-expected.txt": [ - "e4596fb2f6f05b2c2d90c9c5f059a4ea5af4476b", - "support" - ], "html/semantics/forms/the-input-element/week.html": [ - "2ead9548ce288a2a10249476dec87986046fce81", + "851b1b794f820b1fb9b7ee57fe39f8f2977b7fe6", "testharness" ], "html/semantics/forms/the-label-element/label-attributes-expected.txt": [ @@ -49173,7 +49840,7 @@ "testharness" ], "html/semantics/interfaces-expected.txt": [ - "c07c7a890f8d7ba9a626d7b63de29ac11691b79f", + "0370383eb0419d761e112e984ba8e7246ea82902", "support" ], "html/semantics/interfaces.html": [ @@ -49252,6 +49919,38 @@ "8908535f03ac4eb049a41f10325ce92d537c8a70", "testharness" ], + "html/semantics/scripting-1/the-script-element/async_003.htm": [ + "45e8191d3a478622bd66ceaf4a502571b6cd7e0c", + "testharness" + ], + "html/semantics/scripting-1/the-script-element/async_004.htm": [ + "1290ac30a783a6ab0ea769e14b1cba41fb8fe936", + "testharness" + ], + "html/semantics/scripting-1/the-script-element/async_005.htm": [ + "a8887e05818c697f01656ca9d5e4ef741e7f8cc3", + "testharness" + ], + "html/semantics/scripting-1/the-script-element/async_006.htm": [ + "2672763da93ef5b99483c1112a09d3ff10297b01", + "testharness" + ], + "html/semantics/scripting-1/the-script-element/async_007.htm": [ + "08dd1b73a114bf0717b855e7c16430ab1b9b43c6", + "testharness" + ], + "html/semantics/scripting-1/the-script-element/async_008.htm": [ + "2e989abad4570d32e890aafe31f01b188c9c02e0", + "testharness" + ], + "html/semantics/scripting-1/the-script-element/async_009.htm": [ + "4a1ffef24c90abffe9f12bd36912e211da630c4e", + "testharness" + ], + "html/semantics/scripting-1/the-script-element/async_010.htm": [ + "febc63e0b0676fccebc45cfe5acfde2e4c704326", + "testharness" + ], "html/semantics/scripting-1/the-script-element/async_011.htm": [ "c5147ae243c2a2855397c94f23c73c0bf8a729ce", "testharness" @@ -49264,6 +49963,14 @@ "77882c90bfdaffd912fda1eeb1d274136c4d93bd", "testharness" ], + "html/semantics/scripting-1/the-script-element/external-script-utf8.js": [ + "2d1c2cf696010feb64b17f00a072f3bbe6b1d713", + "support" + ], + "html/semantics/scripting-1/the-script-element/external-script-windows1250.js": [ + "43e3b65a18328fa95ba89cb4f075d1ab422580fa", + "support" + ], "html/semantics/scripting-1/the-script-element/fetch-src/alpha/base.html": [ "13d313f817d5597dd0cecbc23f0162f95f9634cc", "testharness" @@ -49316,14 +50023,38 @@ "12842b6e600ac2fc737718d8a9ba3385ed8b678b", "support" ], + "html/semantics/scripting-1/the-script-element/resources/cross-origin.py": [ + "33c88a19aa061be518067c54019190ec979d4c82", + "support" + ], + "html/semantics/scripting-1/the-script-element/script-charset-01-expected.txt": [ + "a8ae591ec0e456203b9f7dda9edce12b44c038b5", + "support" + ], + "html/semantics/scripting-1/the-script-element/script-charset-01.html": [ + "4d8f27447b5c76174a2e353f160066fbe156a005", + "testharness" + ], + "html/semantics/scripting-1/the-script-element/script-charset-02-expected.txt": [ + "4a85d08d344151889a33fea7bc6a170f244db03d", + "support" + ], + "html/semantics/scripting-1/the-script-element/script-charset-02.html": [ + "fd855537451d81818fda97de8a6eff2f8ebd7a5e", + "testharness" + ], "html/semantics/scripting-1/the-script-element/script-charset-03-expected.txt": [ - "d29941bf3196e1aa0ad3c03d8dd705e464671a05", + "a77ed7620d50ecf98ba93f936ceb320717715347", "support" ], "html/semantics/scripting-1/the-script-element/script-charset-03.html": [ "c1daf890ff2c71f63d1c668de9002d493dbcb417", "testharness" ], + "html/semantics/scripting-1/the-script-element/script-crossorigin-network.html": [ + "ca03ec45f3b8d117d0488b67f082868bac847af6", + "testharness" + ], "html/semantics/scripting-1/the-script-element/script-crossorigin.html": [ "e3209904d340a7f9803af6828cd830f2bd26cbc5", "testharness" @@ -49368,6 +50099,18 @@ "3aac1b140c0958949c3073385c917118f1c160da", "support" ], + "html/semantics/scripting-1/the-script-element/script-not-found-not-executed-2.py": [ + "08750e5a3d154f9bdc3fbc484d722ee0a5ed994a", + "support" + ], + "html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html": [ + "30ef220fcc52cb3a73b39c643b0b38026ff2233b", + "testharness" + ], + "html/semantics/scripting-1/the-script-element/script-not-found-not-executed.py": [ + "f6a4ba53dc3e9f3d419314beec881f653fc4c6a5", + "support" + ], "html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-1.html": [ "2e04cf7c26b8c870a7b9002743a914645f7914fe", "testharness" @@ -49400,6 +50143,10 @@ "4a1324770dec284d6a8432a1ae94ff27f4fe5322", "testharness" ], + "html/semantics/scripting-1/the-script-element/serve-with-content-type.py": [ + "808137b7dc8db35d1c1778ef7a61efd626f05f3b", + "support" + ], "html/semantics/scripting-1/the-script-element/support/script-onerror-insertion-point-1-helper.html": [ "328f38410a6bbf83bc9b12bc961b606e9730f75e", "support" @@ -50140,42 +50887,82 @@ "31f340b75a7e142237eab798ca81454eaee67488", "support" ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-001.html": [ + "b8685f4ad7e9e58f6ae3fbb77adee07217ea5108", + "testharness" + ], "html/syntax/parsing-html-fragments/the-input-byte-stream-001.html.headers": [ "95824c1ab5c56d44ed673647c0aa35fa4cf9164b", "support" ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-007.html": [ + "b5a2f102bb1cf2afca78718a128dc205e7ead3c0", + "testharness" + ], "html/syntax/parsing-html-fragments/the-input-byte-stream-007.html.headers": [ "41e260e7df49e0e4ddb1fc5df11913dbda15edd7", "support" ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-009.html": [ + "f1543f505f496c38058dbd39e6642c4f2adc280b", + "testharness" + ], "html/syntax/parsing-html-fragments/the-input-byte-stream-009.html.headers": [ "41e260e7df49e0e4ddb1fc5df11913dbda15edd7", "support" ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-015.html": [ + "6564a6f963fdccf6156287f0acd6c20eaacbd48a", + "testharness" + ], "html/syntax/parsing-html-fragments/the-input-byte-stream-015.html.headers": [ "41e260e7df49e0e4ddb1fc5df11913dbda15edd7", "support" ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-016.html": [ + "60de0ad291a918bacc47556736867f671bdd1bb8", + "testharness" + ], "html/syntax/parsing-html-fragments/the-input-byte-stream-016.html.headers": [ "95824c1ab5c56d44ed673647c0aa35fa4cf9164b", "support" ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-018.html": [ + "2dbc07dd921a70dac3d9dbdd78546a5edb5e3195", + "testharness" + ], "html/syntax/parsing-html-fragments/the-input-byte-stream-018.html.headers": [ "95824c1ab5c56d44ed673647c0aa35fa4cf9164b", "support" ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-030.html": [ + "60b79d110131ac100879b4279b2954ab50c4c3cc", + "testharness" + ], "html/syntax/parsing-html-fragments/the-input-byte-stream-030.html.headers": [ "41e260e7df49e0e4ddb1fc5df11913dbda15edd7", "support" ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-034.html": [ + "95f2cf4b3f6a0ae661a8d7d7a88bc067d24dd7fc", + "testharness" + ], "html/syntax/parsing-html-fragments/the-input-byte-stream-034.html.headers": [ "95824c1ab5c56d44ed673647c0aa35fa4cf9164b", "support" ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-037.html": [ + "915d9ea57a0db0f9c943083868abd7421cad5947", + "testharness" + ], "html/syntax/parsing-html-fragments/the-input-byte-stream-037.html.headers": [ "41e260e7df49e0e4ddb1fc5df11913dbda15edd7", "support" ], + "html/syntax/parsing-html-fragments/the-input-byte-stream-038.html": [ + "6b8b90d1fc8ec549aaa557d1d146e4f240083308", + "testharness" + ], "html/syntax/parsing-html-fragments/the-input-byte-stream-038.html.headers": [ "41e260e7df49e0e4ddb1fc5df11913dbda15edd7", "support" @@ -50300,10 +51087,18 @@ "1e8001486b51c6c37c6d9ae5ccb2540f8ff7676f", "testharness" ], + "html/syntax/parsing/html5lib_innerHTML_adoption01-expected.txt": [ + "e20b5700663042e08dda128f81b1153af0313219", + "support" + ], "html/syntax/parsing/html5lib_innerHTML_adoption01.html": [ "988287d4d91febf0cfd26ef6d924b7897ee4b466", "testharness" ], + "html/syntax/parsing/html5lib_innerHTML_foreign-fragment-expected.txt": [ + "b8d888f99891d285605d6742af902c8ef2c55f1c", + "support" + ], "html/syntax/parsing/html5lib_innerHTML_foreign-fragment.html": [ "56a56f17ebaf055fe4bc4406cbffe93752788f5a", "testharness" @@ -50328,6 +51123,10 @@ "8d3285ea7c424a5d566fbcd91c778ee819f0298d", "testharness" ], + "html/syntax/parsing/html5lib_innerHTML_webkit02-expected.txt": [ + "2edd0f778f3b61b1337eabd80e4906a5840078f6", + "support" + ], "html/syntax/parsing/html5lib_innerHTML_webkit02.html": [ "b40d5aae2dbb2b14a3bb5a2a2a59d8c85ad1757b", "testharness" @@ -50540,6 +51339,86 @@ "02c52b20e3a36e821cf44ad1e35a5b0ee852d8fc", "support" ], + "html/syntax/parsing/template/additions-to-foster-parenting/template-is-a-foster-parent-element.html": [ + "8bfafadc326ae0d84ed12b1c6e766863963fac1a", + "testharness" + ], + "html/syntax/parsing/template/additions-to-foster-parenting/template-is-not-a-foster-parent-element.html": [ + "4ca027894dd1aa9734a4ff34ba8651417e673f5d", + "testharness" + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/generating-of-implied-end-tags.html": [ + "631a7f400581baa27d1d7670215baad1ee96ec8d", + "testharness" + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-body-token.html": [ + "0cc3a2bab129d9262ff0a169b5b9d79135a4e0e4", + "testharness" + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-frameset-token.html": [ + "ba3a4e20e1889228f2cfb8eb3f20df2dfd2ca50d", + "testharness" + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-head-token.html": [ + "f964a85aecb619ba3700028d44d60c39c09e1d95", + "testharness" + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-html-token.html": [ + "c8ad8b09e89901e8d09311366f4dea3cf086d3c9", + "testharness" + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-body.html": [ + "3d088b6892644e2603e489cb627f395451faa41e", + "testharness" + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-html.html": [ + "716c7088477c5f327b2f01d00c0a7a5937ef028d", + "testharness" + ], + "html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/template-end-tag-without-start-one.html": [ + "767b31417493fc2b45498677830ea04a7a22cf61", + "testharness" + ], + "html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset-expected.txt": [ + "149750460e75ef8ad8b84e3a8c1ac4a35ea36860", + "support" + ], + "html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset.html": [ + "9295e29e9e1ea13de8a25dd34637fa016b45d437", + "testharness" + ], + "html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/generating-of-implied-end-tags.html": [ + "643a0fad71edcb0dba6363c5fc5b26e5bdcc5886", + "testharness" + ], + "html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/template-end-tag-without-start-one.html": [ + "7df497d30a239ed45440c5eafc2bddc49bb402b1", + "testharness" + ], + "html/syntax/parsing/template/additions-to-the-in-table-insertion-mode/end-tag-table.html": [ + "23d35745c08bb11558a8133422caca9e5fa7e49f", + "testharness" + ], + "html/syntax/parsing/template/appending-to-a-template/template-child-nodes.html": [ + "8610c1b75e3e2fce015636cdafe3628335571254", + "testharness" + ], + "html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-body-context.html": [ + "1dfa36bf50caf606e1a198f31b2cf42845ccd101", + "testharness" + ], + "html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-context.html": [ + "fbc4ffcded6f1641e72508587518b30867d25125", + "testharness" + ], + "html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-row-context.html": [ + "a8dcf6da9595981b320a9597815b884cf031f70d", + "testharness" + ], + "html/syntax/parsing/template/creating-an-element-for-the-token/template-owner-document.html": [ + "baf663a8a4d99d6f1cc9fb489065654b170e4e4c", + "testharness" + ], "html/syntax/parsing/test.js": [ "601fc3cf58080c100c5f0a16f097d5d518d91efe", "support" @@ -51000,6 +51879,10 @@ "ab8348537b946dcb70e91187e4cf7a260c6b92ed", "testharness" ], + "html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html": [ + "61f05d56702a02acf80809605c46a31033192df9", + "testharness" + ], "html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.js": [ "37f13d24527fcdb5ded608b2ce58e1b51343cf96", "support" @@ -51489,7 +52372,7 @@ "manual" ], "pointerevents/idlharness-expected.txt": [ - "2b5467e712996f729ec3db46dba07831ab79fadd", + "58a39c41b4659be21d863eebf232058d58565ee1", "support" ], "pointerevents/idlharness.html": [ @@ -51525,7 +52408,7 @@ "manual" ], "pointerevents/pointerevent_constructor.html": [ - "b039bf32c411312990f846e01f3dc08283656619", + "0b247d3b7dfd047c217a78c59652a3c32df0fcfa", "testharness" ], "pointerevents/pointerevent_element_haspointercapture-manual.html": [ @@ -52261,7 +53144,7 @@ "support" ], "service-workers/cache-storage/serviceworker/cache-add.https-expected.txt": [ - "9ab6547c22563e9cc30f98bc01a7978a9af150f5", + "29b6b9d6234097f6e28efb9abb06920fb9fa7d87", "support" ], "service-workers/cache-storage/serviceworker/cache-add.https.html": [ @@ -52317,7 +53200,7 @@ "testharness" ], "service-workers/cache-storage/window/cache-add.https-expected.txt": [ - "13f759ed04030f399e2dea17500b673779bb80b3", + "315e6cde8490f8821de90e690553912765865a20", "support" ], "service-workers/cache-storage/window/cache-add.https.html": [ @@ -52373,7 +53256,7 @@ "testharness" ], "service-workers/cache-storage/worker/cache-add.https-expected.txt": [ - "13f759ed04030f399e2dea17500b673779bb80b3", + "315e6cde8490f8821de90e690553912765865a20", "support" ], "service-workers/cache-storage/worker/cache-add.https.html": [ @@ -54104,7 +54987,7 @@ "bdbd5627125bd25f84f0431b1bc752ceeb5015ba", "testharness" ], - "streams/byte-length-queuing-strategy.https.html": [ + "streams/byte-length-queuing-strategy.html": [ "61532943318bcf1a978018ba04579dffb0f7290b", "testharness" ], @@ -54116,7 +54999,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/byte-length-queuing-strategy.serviceworker.html": [ + "streams/byte-length-queuing-strategy.serviceworker.https.html": [ "83c7631272f9c04011e179a1d5f2c6744ab09e2d", "testharness" ], @@ -54128,7 +55011,7 @@ "8406ee4393da4130128cd402824d344716119460", "testharness" ], - "streams/count-queuing-strategy.https.html": [ + "streams/count-queuing-strategy.html": [ "660a512e4227f96651216629f32faf1139a31187", "testharness" ], @@ -54140,7 +55023,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/count-queuing-strategy.serviceworker.html": [ + "streams/count-queuing-strategy.serviceworker.https.html": [ "7f59d0e37562a6adfb2972b61928375047266ac7", "testharness" ], @@ -54149,10 +55032,10 @@ "testharness" ], "streams/generate-test-wrappers.js": [ - "5d7ad85aacba724570c88d7f0d31bb347e07451e", + "729d86f589af914bf59f046f40e3d98b5f37efc7", "support" ], - "streams/piping/close-propagation-backward.dedicatedworker-expected.txt": [ + "streams/piping/close-propagation-backward-expected.txt": [ "2c78c276cdbf8f7b60303f7cae9323203f08336a", "support" ], @@ -54160,11 +55043,7 @@ "17e143af0bd875f6097c2314ea9861e4b19ff91a", "testharness" ], - "streams/piping/close-propagation-backward.https-expected.txt": [ - "2c78c276cdbf8f7b60303f7cae9323203f08336a", - "support" - ], - "streams/piping/close-propagation-backward.https.html": [ + "streams/piping/close-propagation-backward.html": [ "12e087aed62dfde8130ad241c261e6863147e3d1", "testharness" ], @@ -54176,19 +55055,19 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/piping/close-propagation-backward.serviceworker.html": [ + "streams/piping/close-propagation-backward.serviceworker.https-expected.txt": [ + "ba6e2b8a2a88f9178fa6e1c1dcffcebc54803040", + "support" + ], + "streams/piping/close-propagation-backward.serviceworker.https.html": [ "29ce859faa5a374d86c4f10e2c638061ce378a01", "testharness" ], - "streams/piping/close-propagation-backward.sharedworker-expected.txt": [ - "2c78c276cdbf8f7b60303f7cae9323203f08336a", - "support" - ], "streams/piping/close-propagation-backward.sharedworker.html": [ "7ef2ba0b429b2032e099f62cf2bc17d606ad1c64", "testharness" ], - "streams/piping/close-propagation-forward.dedicatedworker-expected.txt": [ + "streams/piping/close-propagation-forward-expected.txt": [ "4ab6fa412936f3290fec500ed4766d2331e86150", "support" ], @@ -54196,11 +55075,7 @@ "d227631adae0611f7920d33343d148f19c13f833", "testharness" ], - "streams/piping/close-propagation-forward.https-expected.txt": [ - "4ab6fa412936f3290fec500ed4766d2331e86150", - "support" - ], - "streams/piping/close-propagation-forward.https.html": [ + "streams/piping/close-propagation-forward.html": [ "705a73f3cb1cf7334456070a00b7525defb26840", "testharness" ], @@ -54212,19 +55087,19 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/piping/close-propagation-forward.serviceworker.html": [ + "streams/piping/close-propagation-forward.serviceworker.https-expected.txt": [ + "e19b7cadf3133b589aea0f812c8a1b9f239fdcd3", + "support" + ], + "streams/piping/close-propagation-forward.serviceworker.https.html": [ "759ca4e212311a001d0abae2b2f21d1dca42736b", "testharness" ], - "streams/piping/close-propagation-forward.sharedworker-expected.txt": [ - "4ab6fa412936f3290fec500ed4766d2331e86150", - "support" - ], "streams/piping/close-propagation-forward.sharedworker.html": [ "277a94372fc8359b631b46ea79778ce2ec0e928c", "testharness" ], - "streams/piping/error-propagation-backward.dedicatedworker-expected.txt": [ + "streams/piping/error-propagation-backward-expected.txt": [ "bbe079c575b2d825134e679e61566da325745fee", "support" ], @@ -54232,11 +55107,7 @@ "2f7ad2bf616e612f8cae9c61264d1ea012be2561", "testharness" ], - "streams/piping/error-propagation-backward.https-expected.txt": [ - "bbe079c575b2d825134e679e61566da325745fee", - "support" - ], - "streams/piping/error-propagation-backward.https.html": [ + "streams/piping/error-propagation-backward.html": [ "3fa70d5f0b864846b699ffd94b10a19a331fa65c", "testharness" ], @@ -54248,19 +55119,19 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/piping/error-propagation-backward.serviceworker.html": [ + "streams/piping/error-propagation-backward.serviceworker.https-expected.txt": [ + "945748a9d526697937ab913a7c9b612449aa9604", + "support" + ], + "streams/piping/error-propagation-backward.serviceworker.https.html": [ "3502f6514992dab5662a5088c518d3a775863770", "testharness" ], - "streams/piping/error-propagation-backward.sharedworker-expected.txt": [ - "bbe079c575b2d825134e679e61566da325745fee", - "support" - ], "streams/piping/error-propagation-backward.sharedworker.html": [ "464dbfc87804e207057de70b2dcbb0aacf03b92e", "testharness" ], - "streams/piping/error-propagation-forward.dedicatedworker-expected.txt": [ + "streams/piping/error-propagation-forward-expected.txt": [ "5244bd0323cc4426671f43de90f3f4e8ca0cf0db", "support" ], @@ -54268,11 +55139,7 @@ "a2520ea68491b9e0987a63c9d5653a19ffff440d", "testharness" ], - "streams/piping/error-propagation-forward.https-expected.txt": [ - "5244bd0323cc4426671f43de90f3f4e8ca0cf0db", - "support" - ], - "streams/piping/error-propagation-forward.https.html": [ + "streams/piping/error-propagation-forward.html": [ "ed2d748eaec992b2c930a923d3288883e8d3e9dc", "testharness" ], @@ -54284,19 +55151,19 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/piping/error-propagation-forward.serviceworker.html": [ + "streams/piping/error-propagation-forward.serviceworker.https-expected.txt": [ + "14492b1c0b191299083792c701971693f981e0a5", + "support" + ], + "streams/piping/error-propagation-forward.serviceworker.https.html": [ "44db4461afd113439e349a05a08410ff58655850", "testharness" ], - "streams/piping/error-propagation-forward.sharedworker-expected.txt": [ - "5244bd0323cc4426671f43de90f3f4e8ca0cf0db", - "support" - ], "streams/piping/error-propagation-forward.sharedworker.html": [ "c19cba806d0c806452464b7ede268458c65556a9", "testharness" ], - "streams/piping/flow-control.dedicatedworker-expected.txt": [ + "streams/piping/flow-control-expected.txt": [ "f87be7d24d09906c86bc5e7ae4847b5b8fc8122c", "support" ], @@ -54304,11 +55171,7 @@ "3936fceee569de910a7e3e4d5e3af9e7c4d1e942", "testharness" ], - "streams/piping/flow-control.https-expected.txt": [ - "f87be7d24d09906c86bc5e7ae4847b5b8fc8122c", - "support" - ], - "streams/piping/flow-control.https.html": [ + "streams/piping/flow-control.html": [ "0b60c58f59b5a58f366bb29e05e0a36fc3ab2da7", "testharness" ], @@ -54320,31 +55183,27 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/piping/flow-control.serviceworker.html": [ + "streams/piping/flow-control.serviceworker.https-expected.txt": [ + "5aabb47c1d495403fa0bac70b75ee617ba8b3214", + "support" + ], + "streams/piping/flow-control.serviceworker.https.html": [ "c6962c1f0358867289e1e9b36dac492059f4f9fe", "testharness" ], - "streams/piping/flow-control.sharedworker-expected.txt": [ - "f87be7d24d09906c86bc5e7ae4847b5b8fc8122c", - "support" - ], "streams/piping/flow-control.sharedworker.html": [ "74e67f2ad62720eb3314a1cdec5b4c28ca3ea5f6", "testharness" ], - "streams/piping/general.dedicatedworker-expected.txt": [ - "c2e502278e3c290e0f4fed85c4ee7e21a741e13e", + "streams/piping/general-expected.txt": [ + "9b373b5ed079db8c554da1df08fe91dbdb9e6a4d", "support" ], "streams/piping/general.dedicatedworker.html": [ "8583d80450b090c16ed0795170340d040449bbc1", "testharness" ], - "streams/piping/general.https-expected.txt": [ - "c2e502278e3c290e0f4fed85c4ee7e21a741e13e", - "support" - ], - "streams/piping/general.https.html": [ + "streams/piping/general.html": [ "d7f2a0e97922ba446f7c3cfd245706dc5a6beb65", "testharness" ], @@ -54356,31 +55215,31 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/piping/general.serviceworker.html": [ + "streams/piping/general.serviceworker.https-expected.txt": [ + "97eafbd7ab102636b641e34862c62d587a221ea4", + "support" + ], + "streams/piping/general.serviceworker.https.html": [ "1792d6c45a5687777291a4dab031a954aa053752", "testharness" ], - "streams/piping/general.sharedworker-expected.txt": [ - "c2e502278e3c290e0f4fed85c4ee7e21a741e13e", - "support" - ], "streams/piping/general.sharedworker.html": [ "44f9ceaa3bfc9d8b92885997d322486bd0f237a6", "testharness" ], + "streams/piping/multiple-propagation-expected.txt": [ + "ce9eac70da5aff617fcba34317a9357332ed5aa2", + "support" + ], "streams/piping/multiple-propagation.dedicatedworker-expected.txt": [ - "350ef7e6627b4cbf1558f31304d834becc3161ce", + "ce9eac70da5aff617fcba34317a9357332ed5aa2", "support" ], "streams/piping/multiple-propagation.dedicatedworker.html": [ "ef3d8a0ab031c3e25c6fcd083e7361a449ed671d", "testharness" ], - "streams/piping/multiple-propagation.https-expected.txt": [ - "350ef7e6627b4cbf1558f31304d834becc3161ce", - "support" - ], - "streams/piping/multiple-propagation.https.html": [ + "streams/piping/multiple-propagation.html": [ "a0c329fc93126deca9a1fa354ae536fdbe20d5a7", "testharness" ], @@ -54392,31 +55251,31 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/piping/multiple-propagation.serviceworker.html": [ + "streams/piping/multiple-propagation.serviceworker.https-expected.txt": [ + "46ba0a5a3b8864c2be80fe138bfeda70bc60d726", + "support" + ], + "streams/piping/multiple-propagation.serviceworker.https.html": [ "b1ec8a36de6b683fcfc9b3af35f7544d4806bdb6", "testharness" ], "streams/piping/multiple-propagation.sharedworker-expected.txt": [ - "350ef7e6627b4cbf1558f31304d834becc3161ce", + "e1c701155da2752a69ab048a1d2b0d02ee9c23b0", "support" ], "streams/piping/multiple-propagation.sharedworker.html": [ "a2aaf43f0d2eb831bd9f8e379fbf0076eee76633", "testharness" ], - "streams/piping/pipe-through.dedicatedworker-expected.txt": [ - "b1e36e9438f5afd1093f58ef115d9f497811e45e", + "streams/piping/pipe-through-expected.txt": [ + "7a6f52b7ff44ea026c05f844f0c737e7f91704b0", "support" ], "streams/piping/pipe-through.dedicatedworker.html": [ "ed05dd7416cc07e178e481375c2372ce1094905e", "testharness" ], - "streams/piping/pipe-through.https-expected.txt": [ - "b1e36e9438f5afd1093f58ef115d9f497811e45e", - "support" - ], - "streams/piping/pipe-through.https.html": [ + "streams/piping/pipe-through.html": [ "ef036e94d09d47d1dc160a38ee6be2499431bf5f", "testharness" ], @@ -54428,18 +55287,22 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/piping/pipe-through.serviceworker.html": [ + "streams/piping/pipe-through.serviceworker.https-expected.txt": [ + "cff39f6bf90e28753dd1cfa283918f87550450db", + "support" + ], + "streams/piping/pipe-through.serviceworker.https.html": [ "e6604dc4e7f4404ee9dea5ab237fb4636bf9e85a", "testharness" ], - "streams/piping/pipe-through.sharedworker-expected.txt": [ - "b1e36e9438f5afd1093f58ef115d9f497811e45e", - "support" - ], "streams/piping/pipe-through.sharedworker.html": [ "8ecb019e754fd4239cb35c27787897efc2dacccb", "testharness" ], + "streams/piping/transform-streams-expected.txt": [ + "bf4796f48fee73c9f766ab40e9c498db7d8a8af2", + "support" + ], "streams/piping/transform-streams.dedicatedworker-expected.txt": [ "bf4796f48fee73c9f766ab40e9c498db7d8a8af2", "support" @@ -54448,11 +55311,7 @@ "bd73374617b11acfcaecbf478ad050ab8621754a", "testharness" ], - "streams/piping/transform-streams.https-expected.txt": [ - "bf4796f48fee73c9f766ab40e9c498db7d8a8af2", - "support" - ], - "streams/piping/transform-streams.https.html": [ + "streams/piping/transform-streams.html": [ "b440ca628c12437ab81141960a0ce45c348d4a54", "testharness" ], @@ -54464,7 +55323,11 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/piping/transform-streams.serviceworker.html": [ + "streams/piping/transform-streams.serviceworker.https-expected.txt": [ + "20a2b0f7db575a01a6695b64878eb1b65d5bde94", + "support" + ], + "streams/piping/transform-streams.serviceworker.https.html": [ "2aa56e69ebdceb784921a6486bffce43e43a99a9", "testharness" ], @@ -54476,6 +55339,10 @@ "005490d4fc62797e432b03c33c349d9136815625", "testharness" ], + "streams/readable-byte-streams/general-expected.txt": [ + "2733ed7714db628e3d92947717d41e2f50f7aabd", + "support" + ], "streams/readable-byte-streams/general.dedicatedworker-expected.txt": [ "2733ed7714db628e3d92947717d41e2f50f7aabd", "support" @@ -54484,11 +55351,7 @@ "8583d80450b090c16ed0795170340d040449bbc1", "testharness" ], - "streams/readable-byte-streams/general.https-expected.txt": [ - "2733ed7714db628e3d92947717d41e2f50f7aabd", - "support" - ], - "streams/readable-byte-streams/general.https.html": [ + "streams/readable-byte-streams/general.html": [ "9e349695974543b322e5c1447352e0ab4dc490e6", "testharness" ], @@ -54500,7 +55363,11 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/readable-byte-streams/general.serviceworker.html": [ + "streams/readable-byte-streams/general.serviceworker.https-expected.txt": [ + "6f3121158edcbd2e3ed62a83fdfc1c35518f6a2c", + "support" + ], + "streams/readable-byte-streams/general.serviceworker.https.html": [ "1792d6c45a5687777291a4dab031a954aa053752", "testharness" ], @@ -54516,7 +55383,7 @@ "269e32606201603b326048f42573c8535c060a18", "testharness" ], - "streams/readable-streams/bad-strategies.https.html": [ + "streams/readable-streams/bad-strategies.html": [ "ce222675f5d45cf56f3f283cfab416472cb770b9", "testharness" ], @@ -54528,7 +55395,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/readable-streams/bad-strategies.serviceworker.html": [ + "streams/readable-streams/bad-strategies.serviceworker.https.html": [ "1cc76d2d9135082afcaba8e45de4a4cbdf0c35e0", "testharness" ], @@ -54540,7 +55407,7 @@ "4f1aac6cadab470ec4474741712bdd65d2670918", "testharness" ], - "streams/readable-streams/bad-underlying-sources.https.html": [ + "streams/readable-streams/bad-underlying-sources.html": [ "620b444181a2d25199445b94faa4560829a4a713", "testharness" ], @@ -54552,7 +55419,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/readable-streams/bad-underlying-sources.serviceworker.html": [ + "streams/readable-streams/bad-underlying-sources.serviceworker.https.html": [ "2e8501ec4c83340149486ea1f19d35a3c90d85e9", "testharness" ], @@ -54564,7 +55431,7 @@ "b0f32b03a352ef7ac1940eda90414a5f65980194", "testharness" ], - "streams/readable-streams/brand-checks.https.html": [ + "streams/readable-streams/brand-checks.html": [ "317e5c5cc2eedcc6902e8cc44567ea59e7f173ac", "testharness" ], @@ -54576,7 +55443,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/readable-streams/brand-checks.serviceworker.html": [ + "streams/readable-streams/brand-checks.serviceworker.https.html": [ "c8279e28f5cd80d454d884154ae883a8c965705f", "testharness" ], @@ -54588,7 +55455,7 @@ "6116c2563dd3d642a91eb7996cf60babe1796976", "testharness" ], - "streams/readable-streams/cancel.https.html": [ + "streams/readable-streams/cancel.html": [ "7132ea4a7785ec4b0caed2cfe860c99852c391a2", "testharness" ], @@ -54600,7 +55467,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/readable-streams/cancel.serviceworker.html": [ + "streams/readable-streams/cancel.serviceworker.https.html": [ "815c9b14a88bb84526e3ea0b93ba8d74bb57838a", "testharness" ], @@ -54612,7 +55479,7 @@ "8e023ec682231d47d43549e26636758652c8f702", "testharness" ], - "streams/readable-streams/count-queuing-strategy-integration.https.html": [ + "streams/readable-streams/count-queuing-strategy-integration.html": [ "be512c75571757d8d64d110d1028abd20ce1a9ae", "testharness" ], @@ -54624,7 +55491,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/readable-streams/count-queuing-strategy-integration.serviceworker.html": [ + "streams/readable-streams/count-queuing-strategy-integration.serviceworker.https.html": [ "846fb89188f3df93de85bdbb6c5b39fddd82ed9c", "testharness" ], @@ -54636,7 +55503,7 @@ "0c774ff797fda7a5b5a828a4600a39dae72cac0c", "testharness" ], - "streams/readable-streams/garbage-collection.https.html": [ + "streams/readable-streams/garbage-collection.html": [ "b338e65673939e598b0f8e5a28591bfb040755fb", "testharness" ], @@ -54648,7 +55515,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/readable-streams/garbage-collection.serviceworker.html": [ + "streams/readable-streams/garbage-collection.serviceworker.https.html": [ "c35eb996cbf796eadbb52f4a3288c8452765b952", "testharness" ], @@ -54657,14 +55524,14 @@ "testharness" ], "streams/readable-streams/general.dedicatedworker-expected.txt": [ - "9cf94a3ca917ad6cf576f91fb73965fabd7ad83e", + "230256a7de8610f843228e826d4f3b0049204c64", "support" ], "streams/readable-streams/general.dedicatedworker.html": [ "8583d80450b090c16ed0795170340d040449bbc1", "testharness" ], - "streams/readable-streams/general.https.html": [ + "streams/readable-streams/general.html": [ "adc5be693f0e3218419c447767678c4a3274767a", "testharness" ], @@ -54676,27 +55543,27 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/readable-streams/general.serviceworker.html": [ + "streams/readable-streams/general.serviceworker.https-expected.txt": [ + "5bf1010b9d29e4ccbe6183ac88f3fa3ab57ad908", + "support" + ], + "streams/readable-streams/general.serviceworker.https.html": [ "1792d6c45a5687777291a4dab031a954aa053752", "testharness" ], "streams/readable-streams/general.sharedworker-expected.txt": [ - "9cf94a3ca917ad6cf576f91fb73965fabd7ad83e", + "230256a7de8610f843228e826d4f3b0049204c64", "support" ], "streams/readable-streams/general.sharedworker.html": [ "44f9ceaa3bfc9d8b92885997d322486bd0f237a6", "testharness" ], - "streams/readable-streams/pipe-through.dedicatedworker-expected.txt": [ - "c16e012b228fa7423e443954c95c36a33a5adfaf", - "support" - ], "streams/readable-streams/pipe-through.dedicatedworker.html": [ "ed05dd7416cc07e178e481375c2372ce1094905e", "testharness" ], - "streams/readable-streams/pipe-through.https.html": [ + "streams/readable-streams/pipe-through.html": [ "fddee6be61036c7fcd88a2e4661fbf5b5f796a18", "testharness" ], @@ -54708,14 +55575,14 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/readable-streams/pipe-through.serviceworker.html": [ + "streams/readable-streams/pipe-through.serviceworker.https-expected.txt": [ + "3d8cf26fa4dc94303e587c86459b1f9942aa4dfb", + "support" + ], + "streams/readable-streams/pipe-through.serviceworker.https.html": [ "e6604dc4e7f4404ee9dea5ab237fb4636bf9e85a", "testharness" ], - "streams/readable-streams/pipe-through.sharedworker-expected.txt": [ - "c16e012b228fa7423e443954c95c36a33a5adfaf", - "support" - ], "streams/readable-streams/pipe-through.sharedworker.html": [ "8ecb019e754fd4239cb35c27787897efc2dacccb", "testharness" @@ -54724,7 +55591,7 @@ "1e6d8e7a09378353b62385ca3bb88961ac4b329c", "testharness" ], - "streams/readable-streams/readable-stream-reader.https.html": [ + "streams/readable-streams/readable-stream-reader.html": [ "952983c614a48e3e3cb80e9c498a1dbff4b666ad", "testharness" ], @@ -54736,7 +55603,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/readable-streams/readable-stream-reader.serviceworker.html": [ + "streams/readable-streams/readable-stream-reader.serviceworker.https.html": [ "e320ca7c96cfd77589d783f4e6a088935b277b82", "testharness" ], @@ -54748,7 +55615,7 @@ "028f2d402a74140b40a9a3eace6aad1cc862bb64", "testharness" ], - "streams/readable-streams/tee.https.html": [ + "streams/readable-streams/tee.html": [ "2cebca15a9977e98c8f2f85648d6a72b5341464e", "testharness" ], @@ -54760,7 +55627,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/readable-streams/tee.serviceworker.html": [ + "streams/readable-streams/tee.serviceworker.https.html": [ "d99b0e2bf22cbf2ed0ba27f51e3d944c34ca6ae5", "testharness" ], @@ -54768,15 +55635,11 @@ "d766db1743ba40112c561f69072c096036c34179", "testharness" ], - "streams/readable-streams/templated.dedicatedworker-expected.txt": [ - "b92097406b4a55566ceff5caddf981f244fc3fe1", - "support" - ], "streams/readable-streams/templated.dedicatedworker.html": [ "261d2d62a136be25be0c60c85ac301f2ec0c910e", "testharness" ], - "streams/readable-streams/templated.https.html": [ + "streams/readable-streams/templated.html": [ "7af7ba9e9cb785cb068742e2a14e7868bc70610e", "testharness" ], @@ -54788,14 +55651,14 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/readable-streams/templated.serviceworker.html": [ + "streams/readable-streams/templated.serviceworker.https-expected.txt": [ + "22c4a140e5f962f55d8d78441ed3157df488e008", + "support" + ], + "streams/readable-streams/templated.serviceworker.https.html": [ "82dcb18ef90fb8a957cd2a991cafc598e918e35b", "testharness" ], - "streams/readable-streams/templated.sharedworker-expected.txt": [ - "b92097406b4a55566ceff5caddf981f244fc3fe1", - "support" - ], "streams/readable-streams/templated.sharedworker.html": [ "e21d57a0dd02a13b9b93ace6ab2f292f29bd4f93", "testharness" @@ -54820,7 +55683,7 @@ "89cfc3ba5cfbb426b6ac60c32aa5cfe9dd0ad8b4", "testharness" ], - "streams/writable-streams/aborting.https.html": [ + "streams/writable-streams/aborting.html": [ "9cacb1967fee9eab8619b949101e28ffde922ed9", "testharness" ], @@ -54832,7 +55695,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/writable-streams/aborting.serviceworker.html": [ + "streams/writable-streams/aborting.serviceworker.https.html": [ "b69530ebf51ccaf781ff78172be2f4607ee22c86", "testharness" ], @@ -54844,7 +55707,7 @@ "269e32606201603b326048f42573c8535c060a18", "testharness" ], - "streams/writable-streams/bad-strategies.https.html": [ + "streams/writable-streams/bad-strategies.html": [ "ce222675f5d45cf56f3f283cfab416472cb770b9", "testharness" ], @@ -54856,7 +55719,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/writable-streams/bad-strategies.serviceworker.html": [ + "streams/writable-streams/bad-strategies.serviceworker.https.html": [ "1cc76d2d9135082afcaba8e45de4a4cbdf0c35e0", "testharness" ], @@ -54868,7 +55731,7 @@ "1b17838179df4a18b4a2d06a1d977cbb26d3b4b9", "testharness" ], - "streams/writable-streams/bad-underlying-sinks.https.html": [ + "streams/writable-streams/bad-underlying-sinks.html": [ "416a7768757c202cae70acf4ac22073f9d066336", "testharness" ], @@ -54880,7 +55743,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/writable-streams/bad-underlying-sinks.serviceworker.html": [ + "streams/writable-streams/bad-underlying-sinks.serviceworker.https.html": [ "fbddba953d4b50ed43b1e03cab6eb8931db71ffe", "testharness" ], @@ -54892,7 +55755,7 @@ "b0f32b03a352ef7ac1940eda90414a5f65980194", "testharness" ], - "streams/writable-streams/brand-checks.https.html": [ + "streams/writable-streams/brand-checks.html": [ "884307be73730033fe07625cdecd6487468c4f96", "testharness" ], @@ -54904,7 +55767,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/writable-streams/brand-checks.serviceworker.html": [ + "streams/writable-streams/brand-checks.serviceworker.https.html": [ "c8279e28f5cd80d454d884154ae883a8c965705f", "testharness" ], @@ -54916,7 +55779,7 @@ "bdbd5627125bd25f84f0431b1bc752ceeb5015ba", "testharness" ], - "streams/writable-streams/byte-length-queuing-strategy.https.html": [ + "streams/writable-streams/byte-length-queuing-strategy.html": [ "61532943318bcf1a978018ba04579dffb0f7290b", "testharness" ], @@ -54928,7 +55791,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/writable-streams/byte-length-queuing-strategy.serviceworker.html": [ + "streams/writable-streams/byte-length-queuing-strategy.serviceworker.https.html": [ "83c7631272f9c04011e179a1d5f2c6744ab09e2d", "testharness" ], @@ -54940,7 +55803,7 @@ "cccf37e3bcc4be858fb41be465c38e7785db4508", "testharness" ], - "streams/writable-streams/close.https.html": [ + "streams/writable-streams/close.html": [ "70e009ba3ef83ab35b0f64ded234ecbe0409a1fe", "testharness" ], @@ -54952,7 +55815,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/writable-streams/close.serviceworker.html": [ + "streams/writable-streams/close.serviceworker.https.html": [ "5461a766e8047c6d50b7943d99f8ebb4c140a547", "testharness" ], @@ -54964,7 +55827,7 @@ "6c954f0d265d21fe1dae9d85afbcc79e8d875797", "testharness" ], - "streams/writable-streams/constructor.https.html": [ + "streams/writable-streams/constructor.html": [ "cedc1d744e01b63e27503f59791cd45834db039e", "testharness" ], @@ -54976,7 +55839,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/writable-streams/constructor.serviceworker.html": [ + "streams/writable-streams/constructor.serviceworker.https.html": [ "025f934a714ce8c52df953ba570a527cbcb88399", "testharness" ], @@ -54988,7 +55851,7 @@ "8406ee4393da4130128cd402824d344716119460", "testharness" ], - "streams/writable-streams/count-queuing-strategy.https.html": [ + "streams/writable-streams/count-queuing-strategy.html": [ "660a512e4227f96651216629f32faf1139a31187", "testharness" ], @@ -55000,7 +55863,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/writable-streams/count-queuing-strategy.serviceworker.html": [ + "streams/writable-streams/count-queuing-strategy.serviceworker.https.html": [ "7f59d0e37562a6adfb2972b61928375047266ac7", "testharness" ], @@ -55012,7 +55875,7 @@ "8583d80450b090c16ed0795170340d040449bbc1", "testharness" ], - "streams/writable-streams/general.https.html": [ + "streams/writable-streams/general.html": [ "e48bbd4dc77262037901c0f0da486ca53a84c939", "testharness" ], @@ -55024,7 +55887,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/writable-streams/general.serviceworker.html": [ + "streams/writable-streams/general.serviceworker.https.html": [ "1792d6c45a5687777291a4dab031a954aa053752", "testharness" ], @@ -55036,7 +55899,7 @@ "cef789c53d44cdb3e20a1187c90aae8c5d25d488", "testharness" ], - "streams/writable-streams/start.https.html": [ + "streams/writable-streams/start.html": [ "fd89e0ef48512dc37a612722ee3d5c54dd661e7e", "testharness" ], @@ -55048,7 +55911,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/writable-streams/start.serviceworker.html": [ + "streams/writable-streams/start.serviceworker.https.html": [ "3d8b4b8eb8e1b7dcc6629e82fc0c5eb5e3be8633", "testharness" ], @@ -55060,7 +55923,7 @@ "acf001a2d0b9803a5269ca637f135ff175c7488a", "testharness" ], - "streams/writable-streams/write.https.html": [ + "streams/writable-streams/write.html": [ "ce79444590f85c4606825f08f469219d9ab60c48", "testharness" ], @@ -55072,7 +55935,7 @@ "04408971a1d82a7d3c990774456381313f1584bb", "support" ], - "streams/writable-streams/write.serviceworker.html": [ + "streams/writable-streams/write.serviceworker.https.html": [ "e9714118595843498ed1a54228dc7006fffbc793", "testharness" ], @@ -55093,7 +55956,7 @@ "testharness" ], "svg/interfaces-expected.txt": [ - "f07dc4ac9925d5f1439129e0d7c4e857394bf6d2", + "175c415b82d99e95cbf026ecd52a493f6808d71f", "support" ], "svg/interfaces.html": [ @@ -56493,7 +57356,7 @@ "testharness" ], "webrtc/rtcpeerconnection/rtcpeerconnection-idl-expected.txt": [ - "c4f8983576ea6fbb22e8282ac76a0b07236f906c", + "c43f434595ce174a5e0eb86c638ed64e508ff874", "support" ], "webrtc/rtcpeerconnection/rtcpeerconnection-idl.html": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/check_stability.py b/third_party/WebKit/LayoutTests/external/wpt/check_stability.py index 611be00..248c447f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/check_stability.py +++ b/third_party/WebKit/LayoutTests/external/wpt/check_stability.py
@@ -404,52 +404,62 @@ if not files: return [] assert files[-1] == "\0" - return ["%s/%s" % (wpt_root, item) + return [os.path.join(wpt_root, item) for item in files[:-1].split("\0")] def get_affected_testfiles(files_changed): - affected_testfiles = [] - all_tests = set() + affected_testfiles = set() nontests_changed = set(files_changed) manifest_file = os.path.join(wpt_root, "MANIFEST.json") - for _, test, _ in manifest.load(wpt_root, manifest_file): - test_full_path = os.path.join(wpt_root, test) - all_tests.add(test_full_path) - if test_full_path in nontests_changed: - # Reduce the set of changed files to only non-tests. - nontests_changed.remove(test_full_path) - for changedfile_pathname in nontests_changed: - changed_file_repo_path = os.path.join(os.path.sep, os.path.relpath(changedfile_pathname, wpt_root)) - os.path.normpath(changed_file_repo_path) - path_components = changed_file_repo_path.split(os.sep)[1:] + skip_dirs = ["conformance-checkers", "docs", "tools"] + test_types = ["testharness", "reftest", "wdspec"] + + wpt_manifest = manifest.load(wpt_root, manifest_file) + + support_files = {os.path.join(wpt_root, path) + for _, path, _ in wpt_manifest.itertypes("support")} + test_files = {os.path.join(wpt_root, path) + for _, path, _ in wpt_manifest.itertypes(*test_types)} + + nontests_changed = nontests_changed.intersection(support_files) + + nontest_changed_paths = set() + for full_path in nontests_changed: + rel_path = os.path.relpath(full_path, wpt_root) + path_components = rel_path.split(os.sep) if len(path_components) < 2: # This changed file is in the repo root, so skip it # (because it's not part of any test). continue top_level_subdir = path_components[0] - if top_level_subdir in ["conformance-checkers", "docs"]: + if top_level_subdir in skip_dirs: continue - # OK, this changed file is the kind we care about: It's something - # other than a test (e.g., it's a .js or .json file), and it's - # somewhere down beneath one of the top-level "spec" directories. - # So now we try to find any tests that reference it. - for root, dirs, fnames in os.walk(os.path.join(wpt_root, top_level_subdir)): - # Walk top_level_subdir looking for test files containing either the - # relative filepath or absolute filepatch to the changed file. - for fname in fnames: - testfile_full_path = os.path.join(root, fname) - # Skip any test file that's already in files_changed. - if testfile_full_path in files_changed: - continue - # Skip any file that's not a test file. - if testfile_full_path not in all_tests: - continue - with open(testfile_full_path, "r") as fh: - file_contents = fh.read() - changed_file_relpath = os.path.relpath(changedfile_pathname, root).replace(os.path.sep, "/") - if changed_file_relpath in file_contents or changed_file_repo_path.replace(os.path.sep, "/") in file_contents: - affected_testfiles.append(testfile_full_path) + repo_path = "/" + os.path.relpath(full_path, wpt_root).replace(os.path.sep, "/") + nontest_changed_paths.add((full_path, repo_path)) + + for root, dirs, fnames in os.walk(wpt_root): + # Walk top_level_subdir looking for test files containing either the + # relative filepath or absolute filepatch to the changed files. + if root == wpt_root: + for dir_name in skip_dirs: + dirs.remove(dir_name) + for fname in fnames: + test_full_path = os.path.join(root, fname) + # Skip any file that's not a test file. + if test_full_path not in test_files: + continue + with open(test_full_path, "rb") as fh: + file_contents = fh.read() + if file_contents.startswith("\xfe\xff"): + file_contents = file_contents.decode("utf-16be") + elif file_contents.startswith("\xff\xfe"): + file_contents = file_contents.decode("utf-16le") + for full_path, repo_path in nontest_changed_paths: + rel_path = os.path.relpath(full_path, root).replace(os.path.sep, "/") + if rel_path in file_contents or repo_path in file_contents: + affected_testfiles.add(test_full_path) + continue return affected_testfiles
diff --git a/third_party/WebKit/LayoutTests/external/wpt/common/vendor-prefix.js b/third_party/WebKit/LayoutTests/external/wpt/common/vendor-prefix.js deleted file mode 100644 index 1a91632..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/common/vendor-prefix.js +++ /dev/null
@@ -1,115 +0,0 @@ -/* Use this script when you want to test APIs that use vendor prefixes - and define which objects need to be checked for prefixed versions, à la - <script src="vendor-prefix.js" - data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]' - data-prefixed-prototypes='[{"ancestors":["HTMLMediaElement"],"name":"srcObject"}]'></script> - data-prefixed-objects lets prefix objects in the global space - data-prefixed-prototypes adds prefixes to interfaces, for objects that - get created during the tests - - NB: vendor prefixes are expected to go away in favor of putting - new features behind flag, so hopefully there will be only limited - need to use this -*/ - -(function () { - var aliases = {}; - var documentingPrefixUsage = document.createElement('div'); - var vendorPrefixes = ["moz", "ms", "o", "webkit", "Moz", "MS", "O", "WebKit", "op"]; - - function getParentObject(ancestors) { - var parent = window; - var currentName = ""; - ancestors.forEach(function (p) { - currentName = currentName ? currentName + "." + p : p; - if (parent[p] === undefined) { - throw currentName + " is undefined, cannot set prefix alias on child object"; - } - parent = parent[p]; - }); - return parent; - } - - function prependPrefix(prefix, name) { - var newName = name[0].toUpperCase() + name.substr(1, name.length); - return prefix + newName; - } - - function setPrototypeAlias(obj) { - var parent = getParentObject(obj.ancestors); - if (!parent.prototype.hasOwnProperty(obj.name)) { - vendorPrefixes.forEach(function (prefix) { - if (parent.prototype.hasOwnProperty(prependPrefix(prefix, obj.name))) { - Object.defineProperty(parent.prototype, obj.name, - {get: function() {return this[prependPrefix(prefix, obj.name)];}, - set: function(v) {this[prependPrefix(prefix, obj.name)] = v;} - }); - aliases[obj.ancestors.join(".") + ".prototype." + obj.name] = obj.ancestors.join(".") + ".prototype." + prependPrefix(prefix, obj.name); - return; - } - }); - } - } - - function setAlias(obj) { - var parent = getParentObject(obj.ancestors); - if (parent[obj.name] === undefined) { - vendorPrefixes.forEach(function (prefix) { - if (parent[prependPrefix(prefix, obj.name)] !== undefined) { - parent[obj.name] = parent[prependPrefix(prefix, obj.name)]; - aliases[obj.ancestors.join(".") + "." + obj.name] = obj.ancestors.join(".") + "." + prependPrefix(prefix, obj.name); - return; - } - }); - } - } - - if (location.search.indexOf('usePrefixes=1') !== -1) { - if (document.querySelector("script[data-prefixed-objects]")) { - var prefixObjectsData = document.querySelector("script[data-prefixed-objects]").dataset["prefixedObjects"]; - try { - var prefixedObjects = JSON.parse(prefixObjectsData); - } catch (e) { - throw "couldn't parse data-prefixed-objects as JSON:" + e; - } - prefixedObjects.forEach(setAlias); - } - if (document.querySelector("script[data-prefixed-prototypes]")) { - var prefixProtoData = document.querySelector("script[data-prefixed-prototypes]").dataset["prefixedPrototypes"]; - try { - var prefixedPrototypes = JSON.parse(prefixProtoData); - } catch (e) { - throw "couldn't parse data-prefixed-prototypes as JSON:" + e; - } - prefixedPrototypes.forEach(setPrototypeAlias); - } - var ul = document.createElement("ul"); - Object.keys(aliases).forEach(function (alias) { - var li = document.createElement("li"); - li.appendChild(document.createTextNode(alias + " has been set to be an alias of vendor-prefixed " + aliases[alias])); - ul.appendChild(li); - }); - documentingPrefixUsage.appendChild(ul); - } else { - // Document that the test can be run with prefixes enabled - - var a = document.createElement('a'); - var link = ""; - if (location.search) { - link = location.search + "&usePrefixes=1"; - } else { - link = "?usePrefixes=1"; - } - a.setAttribute("href", link); - a.appendChild(document.createTextNode("with vendor prefixes enabled")); - documentingPrefixUsage.appendChild(document.createTextNode("The feature(s) tested here are known to have been made available via vendor prefixes; you can run this test ")); - documentingPrefixUsage.appendChild(a); - documentingPrefixUsage.appendChild(document.createTextNode(".")); - } - var log = document.getElementById('log'); - if (log) { - log.parentNode.insertBefore(documentingPrefixUsage, log); - } else { - document.body.appendChild(documentingPrefixUsage); - } -})();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventListener-incumbent-global-1.sub.html b/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventListener-incumbent-global-1.sub.html new file mode 100644 index 0000000..9d941385 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventListener-incumbent-global-1.sub.html
@@ -0,0 +1,20 @@ +<!doctype html> +<meta charset=utf-8> +<title></title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<iframe src="{{location[scheme]}}://{{domains[www1]}}:{{ports[http][0]}}{{location[path]}}/../EventListener-incumbent-global-subframe-1.sub.html"></iframe> +<script> + +var t = async_test("Check the incumbent global EventListeners are called with"); + +onload = t.step_func(function() { + onmessage = t.step_func_done(function(e) { + var d = e.data; + assert_equals(d.actual, d.expected, d.reason); + }); + + frames[0].postMessage("start", "*"); +}); + +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventListener-incumbent-global-2.sub-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventListener-incumbent-global-2.sub-expected.txt new file mode 100644 index 0000000..ebe0bd5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventListener-incumbent-global-2.sub-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Check the incumbent global EventListeners are called with assert_equals: Incumbent should have been the caller of addEventListener() expected "http://www1.web-platform.test:8001" but got "http://www2.web-platform.test:8001" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventListener-incumbent-global-2.sub.html b/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventListener-incumbent-global-2.sub.html new file mode 100644 index 0000000..4433c09 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventListener-incumbent-global-2.sub.html
@@ -0,0 +1,20 @@ +<!doctype html> +<meta charset=utf-8> +<title></title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<iframe src="{{location[scheme]}}://{{domains[www1]}}:{{ports[http][0]}}{{location[path]}}/../EventListener-incumbent-global-subframe-2.sub.html"></iframe> +<script> + +var t = async_test("Check the incumbent global EventListeners are called with"); + +onload = t.step_func(function() { + onmessage = t.step_func_done(function(e) { + var d = e.data; + assert_equals(d.actual, d.expected, d.reason); + }); + + frames[0].postMessage("start", "*"); +}); + +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt index f35909b..a9e23107 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt
@@ -1,4 +1,4 @@ -CONSOLE MESSAGE: line 236: callback not yet supported +CONSOLE MESSAGE: line 251: callback not yet supported This is a testharness.js-based test. PASS Event interface: existence and properties of interface object PASS Event interface object length @@ -1545,7 +1545,7 @@ PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "nextSibling" with the proper type (8) PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "previousNode" with the proper type (9) PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "nextNode" with the proper type (10) -FAIL NodeFilter interface: existence and properties of interface object assert_equals: prototype of self's property "NodeFilter" is not Object.prototype expected (object) object "[object Object]" but got (function) function "function () { [native code] }" +PASS NodeFilter interface: existence and properties of interface object PASS NodeFilter interface object name FAIL NodeFilter interface: existence and properties of interface prototype object assert_false: NodeFilter should not have a "prototype" property expected false got true FAIL NodeFilter interface: existence and properties of interface prototype object's "constructor" property assert_false: NodeFilter should not have a "prototype" property expected false got true
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-URL.sub.html b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-URL.sub.html new file mode 100644 index 0000000..8e960110 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-URL.sub.html
@@ -0,0 +1,18 @@ +<!doctype html> +<meta charset=utf-8> +<title>Document.URL with redirect</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement("iframe"); + iframe.src = "/common/redirect.py?location=/common/blank.html"; + document.body.appendChild(iframe); + this.add_cleanup(function() { document.body.removeChild(iframe); }); + iframe.onload = this.step_func_done(function() { + assert_equals(iframe.contentDocument.URL, + "http://{{host}}:{{ports[http][0]}}/common/blank.html"); + }); +}) +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-characterSet-normalization.html b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-characterSet-normalization.html new file mode 100644 index 0000000..746792f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-characterSet-normalization.html
@@ -0,0 +1,373 @@ +<!doctype html> +<title>document.characterSet (inputEncoding and charset as aliases) normalization tests</title> +<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name> +<meta name=timeout content=long> +<div id=log></div> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<style>iframe { display: none }</style> +<script> +"use strict"; + +// Taken straight from https://encoding.spec.whatwg.org/ +var encodingMap = { + "UTF-8": [ + "unicode-1-1-utf-8", + "utf-8", + "utf8", + // As we use <meta>, utf-16 will map to utf-8 per + // https://html.spec.whatwg.org/multipage/#documentEncoding + "utf-16", + "utf-16le", + "utf-16be", + ], + "IBM866": [ + "866", + "cp866", + "csibm866", + "ibm866", + ], + "ISO-8859-2": [ + "csisolatin2", + "iso-8859-2", + "iso-ir-101", + "iso8859-2", + "iso88592", + "iso_8859-2", + "iso_8859-2:1987", + "l2", + "latin2", + ], + "ISO-8859-3": [ + "csisolatin3", + "iso-8859-3", + "iso-ir-109", + "iso8859-3", + "iso88593", + "iso_8859-3", + "iso_8859-3:1988", + "l3", + "latin3", + ], + "ISO-8859-4": [ + "csisolatin4", + "iso-8859-4", + "iso-ir-110", + "iso8859-4", + "iso88594", + "iso_8859-4", + "iso_8859-4:1988", + "l4", + "latin4", + ], + "ISO-8859-5": [ + "csisolatincyrillic", + "cyrillic", + "iso-8859-5", + "iso-ir-144", + "iso8859-5", + "iso88595", + "iso_8859-5", + "iso_8859-5:1988", + ], + "ISO-8859-6": [ + "arabic", + "asmo-708", + "csiso88596e", + "csiso88596i", + "csisolatinarabic", + "ecma-114", + "iso-8859-6", + "iso-8859-6-e", + "iso-8859-6-i", + "iso-ir-127", + "iso8859-6", + "iso88596", + "iso_8859-6", + "iso_8859-6:1987", + ], + "ISO-8859-7": [ + "csisolatingreek", + "ecma-118", + "elot_928", + "greek", + "greek8", + "iso-8859-7", + "iso-ir-126", + "iso8859-7", + "iso88597", + "iso_8859-7", + "iso_8859-7:1987", + "sun_eu_greek", + ], + "ISO-8859-8": [ + "csiso88598e", + "csisolatinhebrew", + "hebrew", + "iso-8859-8", + "iso-8859-8-e", + "iso-ir-138", + "iso8859-8", + "iso88598", + "iso_8859-8", + "iso_8859-8:1988", + "visual", + ], + "ISO-8859-8-I": [ + "csiso88598i", + "iso-8859-8-i", + "logical", + ], + "ISO-8859-10": [ + "csisolatin6", + "iso-8859-10", + "iso-ir-157", + "iso8859-10", + "iso885910", + "l6", + "latin6", + ], + "ISO-8859-13": [ + "iso-8859-13", + "iso8859-13", + "iso885913", + ], + "ISO-8859-14": [ + "iso-8859-14", + "iso8859-14", + "iso885914", + ], + "ISO-8859-15": [ + "csisolatin9", + "iso-8859-15", + "iso8859-15", + "iso885915", + "iso_8859-15", + "l9", + ], + "ISO-8859-16": [ + "iso-8859-16", + ], + "KOI8-R": [ + "cskoi8r", + "koi", + "koi8", + "koi8-r", + "koi8_r", + ], + "KOI8-U": [ + "koi8-ru", + "koi8-u", + ], + "macintosh": [ + "csmacintosh", + "mac", + "macintosh", + "x-mac-roman", + ], + "windows-874": [ + "dos-874", + "iso-8859-11", + "iso8859-11", + "iso885911", + "tis-620", + "windows-874", + ], + "windows-1250": [ + "cp1250", + "windows-1250", + "x-cp1250", + ], + "windows-1251": [ + "cp1251", + "windows-1251", + "x-cp1251", + ], + "windows-1252": [ + "ansi_x3.4-1968", + "ascii", + "cp1252", + "cp819", + "csisolatin1", + "ibm819", + "iso-8859-1", + "iso-ir-100", + "iso8859-1", + "iso88591", + "iso_8859-1", + "iso_8859-1:1987", + "l1", + "latin1", + "us-ascii", + "windows-1252", + "x-cp1252", + // As we use <meta>, x-user-defined will map to windows-1252 per + // https://html.spec.whatwg.org/multipage/#documentEncoding + "x-user-defined" + ], + "windows-1253": [ + "cp1253", + "windows-1253", + "x-cp1253", + ], + "windows-1254": [ + "cp1254", + "csisolatin5", + "iso-8859-9", + "iso-ir-148", + "iso8859-9", + "iso88599", + "iso_8859-9", + "iso_8859-9:1989", + "l5", + "latin5", + "windows-1254", + "x-cp1254", + ], + "windows-1255": [ + "cp1255", + "windows-1255", + "x-cp1255", + ], + "windows-1256": [ + "cp1256", + "windows-1256", + "x-cp1256", + ], + "windows-1257": [ + "cp1257", + "windows-1257", + "x-cp1257", + ], + "windows-1258": [ + "cp1258", + "windows-1258", + "x-cp1258", + ], + "x-mac-cyrillic": [ + "x-mac-cyrillic", + "x-mac-ukrainian", + ], + "GBK": [ + "chinese", + "csgb2312", + "csiso58gb231280", + "gb2312", + "gb_2312", + "gb_2312-80", + "gbk", + "iso-ir-58", + "x-gbk", + ], + "gb18030": [ + "gb18030", + ], + "Big5": [ + "big5", + "big5-hkscs", + "cn-big5", + "csbig5", + "x-x-big5", + ], + "EUC-JP": [ + "cseucpkdfmtjapanese", + "euc-jp", + "x-euc-jp", + ], + "ISO-2022-JP": [ + "csiso2022jp", + "iso-2022-jp", + ], + "Shift_JIS": [ + "csshiftjis", + "ms932", + "ms_kanji", + "shift-jis", + "shift_jis", + "sjis", + "windows-31j", + "x-sjis", + ], + "EUC-KR": [ + "cseuckr", + "csksc56011987", + "euc-kr", + "iso-ir-149", + "korean", + "ks_c_5601-1987", + "ks_c_5601-1989", + "ksc5601", + "ksc_5601", + "windows-949", + ], + "replacement": [ + "csiso2022kr", + "hz-gb-2312", + "iso-2022-cn", + "iso-2022-cn-ext", + "iso-2022-kr", + ], +}; + +// Add spaces and mix up case +Object.keys(encodingMap).forEach(function(name) { + var lower = encodingMap[name]; + var upper = encodingMap[name].map(function(s) { return s.toUpperCase() }); + var mixed = encodingMap[name].map(function(s) { + var ret = ""; + for (var i = 0; i < s.length; i += 2) { + ret += s[i].toUpperCase(); + if (i + 1 < s.length) { + ret += s[i + 1]; + } + } + return ret; + }); + var spacey = encodingMap[name].map(function(s) { + return " \t\n\f\r" + s + " \t\n\f\r"; + }); + encodingMap[name] = []; + for (var i = 0; i < lower.length; i++) { + encodingMap[name].push(lower[i]); + /* + if (lower[i] != upper[i]) { + encodingMap[name].push(upper[i]); + } + if (lower[i] != mixed[i] && upper[i] != mixed[i]) { + encodingMap[name].push(mixed[i]); + } + encodingMap[name].push(spacey[i]); + */ + } +}); + +Object.keys(encodingMap).forEach(function(name) { + encodingMap[name].forEach(function(label) { + var iframe = document.createElement("iframe"); + var t = async_test("Name " + format_value(name) + + " has label " + format_value(label) + " (characterSet)"); + var t2 = async_test("Name " + format_value(name) + + " has label " + format_value(label) + " (inputEncoding)"); + var t3 = async_test("Name " + format_value(name) + + " has label " + format_value(label) + " (charset)"); + iframe.src = "encoding.py?label=" + label; + iframe.onload = function() { + t.step(function() { + assert_equals(iframe.contentDocument.characterSet, name); + }); + t2.step(function() { + assert_equals(iframe.contentDocument.inputEncoding, name); + }); + t3.step(function() { + assert_equals(iframe.contentDocument.charset, name); + }); + document.body.removeChild(iframe); + t.done(); + t2.done(); + t3.done(); + }; + document.body.appendChild(iframe); + }); +}); +</script> +<!-- vim: set expandtab tabstop=2 shiftwidth=2: -->
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_01.html b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_01.html new file mode 100644 index 0000000..87885ef --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_01.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>Custom document.contentType === 'text/xml' when explicitly set to this value</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "text/xml"); + }), false); + iframe.src = "../support/contenttype_setter.py?type=text&subtype=xml"; + document.body.appendChild(iframe); +}); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_02.html b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_02.html new file mode 100644 index 0000000..3387014 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_02.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>Custom document.contentType === 'text/html' when explicitly set to this value and an attempt is made to override this value in an HTML meta header</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "text/html"); + }), false); + iframe.src = "../support/contenttype_setter.py?type=text&subtype=html&mimeHead=text%2Fxml"; + document.body.appendChild(iframe); +}); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-contentType/contentType/contenttype_xml.html b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-contentType/contentType/contenttype_xml.html new file mode 100644 index 0000000..c382de8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-contentType/contentType/contenttype_xml.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>XML document.contentType === 'application/xml'</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "application/xml"); + }), false); + iframe.src = "../resources/blob.xml"; + document.body.appendChild(iframe); +}); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-contentType/contentType/xhr_responseType_document.html b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-contentType/contentType/xhr_responseType_document.html new file mode 100644 index 0000000..c2fb6c1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-contentType/contentType/xhr_responseType_document.html
@@ -0,0 +1,18 @@ +<!DOCTYPE html> +<title>XHR - retrieve HTML document: document.contentType === 'application/xml'</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var xhr = new XMLHttpRequest(); + xhr.open("GET", "../resources/blob.xml"); + xhr.responseType = "document"; + xhr.onload = this.step_func_done(function(response) { + assert_equals(xhr.readyState, 4); + assert_equals(xhr.status, 200); + assert_equals(xhr.responseXML.contentType, "application/xml"); + }); + xhr.send(null); +}); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Element-matches-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Element-matches-expected.txt new file mode 100644 index 0000000..7be8ef93 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Element-matches-expected.txt
@@ -0,0 +1,737 @@ +This is a testharness.js-based test. +PASS Selectors-API Level 2 Test Suite: HTML with Selectors Level 3 +PASS Detached Element supports matches +PASS In-document Element supports matches +PASS DIV Element.matches(null) +PASS DIV Element.matches(undefined) +PASS DIV Element.matches no parameter +PASS NULL Element.matches(null) +PASS NULL Element.matches(undefined) +PASS NULL Element.matches no parameter +PASS UNDEFINED Element.matches(null) +PASS UNDEFINED Element.matches(undefined) +PASS UNDEFINED Element.matches no parameter +PASS Detached Element.matches: Empty String: +PASS Detached Element.matches: Invalid character: [ +PASS Detached Element.matches: Invalid character: ] +PASS Detached Element.matches: Invalid character: ( +PASS Detached Element.matches: Invalid character: ) +PASS Detached Element.matches: Invalid character: { +PASS Detached Element.matches: Invalid character: } +PASS Detached Element.matches: Invalid character: < +PASS Detached Element.matches: Invalid character: > +PASS Detached Element.matches: Invalid ID: # +PASS Detached Element.matches: Invalid group of selectors: div, +PASS Detached Element.matches: Invalid class: . +PASS Detached Element.matches: Invalid class: .5cm +PASS Detached Element.matches: Invalid class: ..test +PASS Detached Element.matches: Invalid class: .foo..quux +PASS Detached Element.matches: Invalid class: .bar. +PASS Detached Element.matches: Invalid combinator: div & address, p +PASS Detached Element.matches: Invalid combinator: div ++ address, p +PASS Detached Element.matches: Invalid combinator: div ~~ address, p +PASS Detached Element.matches: Invalid [att=value] selector: [*=test] +PASS Detached Element.matches: Invalid [att=value] selector: [*|*=test] +PASS Detached Element.matches: Invalid [att=value] selector: [class= space unquoted ] +PASS Detached Element.matches: Unknown pseudo-class: div:example +PASS Detached Element.matches: Unknown pseudo-class: :example +PASS Detached Element.matches: Unknown pseudo-element: div::example +PASS Detached Element.matches: Unknown pseudo-element: ::example +PASS Detached Element.matches: Invalid pseudo-element: :::before +PASS Detached Element.matches: Undeclared namespace: ns|div +PASS Detached Element.matches: Undeclared namespace: :not(ns|div) +PASS Detached Element.matches: Invalid namespace: ^|div +PASS Detached Element.matches: Invalid namespace: $|div +PASS In-document Element.matches: Empty String: +PASS In-document Element.matches: Invalid character: [ +PASS In-document Element.matches: Invalid character: ] +PASS In-document Element.matches: Invalid character: ( +PASS In-document Element.matches: Invalid character: ) +PASS In-document Element.matches: Invalid character: { +PASS In-document Element.matches: Invalid character: } +PASS In-document Element.matches: Invalid character: < +PASS In-document Element.matches: Invalid character: > +PASS In-document Element.matches: Invalid ID: # +PASS In-document Element.matches: Invalid group of selectors: div, +PASS In-document Element.matches: Invalid class: . +PASS In-document Element.matches: Invalid class: .5cm +PASS In-document Element.matches: Invalid class: ..test +PASS In-document Element.matches: Invalid class: .foo..quux +PASS In-document Element.matches: Invalid class: .bar. +PASS In-document Element.matches: Invalid combinator: div & address, p +PASS In-document Element.matches: Invalid combinator: div ++ address, p +PASS In-document Element.matches: Invalid combinator: div ~~ address, p +PASS In-document Element.matches: Invalid [att=value] selector: [*=test] +PASS In-document Element.matches: Invalid [att=value] selector: [*|*=test] +PASS In-document Element.matches: Invalid [att=value] selector: [class= space unquoted ] +PASS In-document Element.matches: Unknown pseudo-class: div:example +PASS In-document Element.matches: Unknown pseudo-class: :example +PASS In-document Element.matches: Unknown pseudo-element: div::example +PASS In-document Element.matches: Unknown pseudo-element: ::example +PASS In-document Element.matches: Invalid pseudo-element: :::before +PASS In-document Element.matches: Undeclared namespace: ns|div +PASS In-document Element.matches: Undeclared namespace: :not(ns|div) +PASS In-document Element.matches: Invalid namespace: ^|div +PASS In-document Element.matches: Invalid namespace: $|div +PASS In-document Element.matches: Type selector, matching html element (with no refNodes): html +PASS In-document Element.matches: Type selector, matching body element (with no refNodes): body +PASS In-document Element.matches: Universal selector, matching all children of element with specified ID (with no refNodes): #universal>* +PASS In-document Element.matches: Universal selector, matching all grandchildren of element with specified ID (with no refNodes): #universal>*>* +PASS In-document Element.matches: Universal selector, matching all descendants of element with specified ID (with no refNodes): #universal * +PASS In-document Element.matches: Attribute presence selector, matching align attribute with value (with no refNodes): .attr-presence-div1[align] +PASS In-document Element.matches: Attribute presence selector, matching align attribute with empty value (with no refNodes): .attr-presence-div2[align] +PASS In-document Element.matches: Attribute presence selector, matching title attribute, case insensitivity (with no refNodes): #attr-presence [TiTlE] +PASS In-document Element.matches: Attribute presence selector, matching custom data-* attribute (with no refNodes): [data-attr-presence] +PASS In-document Element.matches: Attribute presence selector, matching attribute with non-ASCII characters (with no refNodes): ul[data-中文] +PASS In-document Element.matches: Attribute presence selector, matching option with selected attribute (with no refNodes): #attr-presence-select2 option[selected] +PASS In-document Element.matches: Attribute presence selector, matching multiple options with selected attributes (with no refNodes): #attr-presence-select3 option[selected] +PASS In-document Element.matches: Attribute value selector, matching align attribute with value (with no refNodes): #attr-value [align="center"] +PASS In-document Element.matches: Attribute value selector, matching align attribute with empty value (with no refNodes): #attr-value [align=""] +PASS In-document Element.matches: Attribute value selector, matching custom data-* attribute with unicode escaped value (with no refNodes): [data-attr-value="\e9"] +PASS In-document Element.matches: Attribute value selector, matching custom data-* attribute with escaped character (with no refNodes): [data-attr-value_foo="\e9"] +PASS In-document Element.matches: Attribute value selector with single-quoted value, matching multiple inputs with type attributes (with no refNodes): #attr-value input[type='hidden'],#attr-value input[type='radio'] +PASS In-document Element.matches: Attribute value selector with double-quoted value, matching multiple inputs with type attributes (with no refNodes): #attr-value input[type="hidden"],#attr-value input[type='radio'] +PASS In-document Element.matches: Attribute value selector with unquoted value, matching multiple inputs with type attributes (with no refNodes): #attr-value input[type=hidden],#attr-value input[type=radio] +PASS In-document Element.matches: Attribute value selector, matching attribute with value using non-ASCII characters (with no refNodes): [data-attr-value=中文] +PASS In-document Element.matches: Attribute whitespace-separated list selector, matching class attribute with value (with no refNodes): #attr-whitespace [class~="div1"] +PASS In-document Element.matches: Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value (with no refNodes): [data-attr-whitespace~="\0000e9"] +PASS In-document Element.matches: Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character (with no refNodes): [data-attr-whitespace_foo~="\e9"] +PASS In-document Element.matches: Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes (with no refNodes): #attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow'] +PASS In-document Element.matches: Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes (with no refNodes): #attr-whitespace a[rel~="bookmark"],#attr-whitespace a[rel~='nofollow'] +PASS In-document Element.matches: Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes (with no refNodes): #attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow] +PASS In-document Element.matches: Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters (with no refNodes): #attr-whitespace [title~=中文] +PASS In-document Element.matches: Attribute hyphen-separated list selector, matching lang attribute with exact value (with no refNodes): #attr-hyphen-div2[lang|="fr"] +PASS In-document Element.matches: Attribute hyphen-separated list selector, matching lang attribute with partial value (with no refNodes): #attr-hyphen-div3[lang|="en"] +PASS In-document Element.matches: Attribute begins with selector, matching href attributes beginning with specified substring (with no refNodes): #attr-begins a[href^="http://www"] +PASS In-document Element.matches: Attribute begins with selector, matching lang attributes beginning with specified substring, (with no refNodes): #attr-begins [lang^="en-"] +PASS In-document Element.matches: Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-begins [class^=' apple'] +PASS In-document Element.matches: Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-begins [class^=" apple"] +PASS In-document Element.matches: Attribute ends with selector, matching href attributes ending with specified substring (with no refNodes): #attr-ends a[href$=".org"] +PASS In-document Element.matches: Attribute ends with selector, matching lang attributes ending with specified substring, (with no refNodes): #attr-ends [lang$="-CH"] +PASS In-document Element.matches: Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring (with no refNodes): #attr-ends [class$='apple '] +PASS In-document Element.matches: Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring (with no refNodes): #attr-ends [class$="apple "] +PASS In-document Element.matches: Attribute contains selector, matching href attributes beginning with specified substring (with no refNodes): #attr-contains a[href*="http://www"] +PASS In-document Element.matches: Attribute contains selector, matching href attributes ending with specified substring (with no refNodes): #attr-contains a[href*=".org"] +PASS In-document Element.matches: Attribute contains selector, matching href attributes containing specified substring (with no refNodes): #attr-contains a[href*=".example."] +PASS In-document Element.matches: Attribute contains selector, matching lang attributes beginning with specified substring, (with no refNodes): #attr-contains [lang*="en-"] +PASS In-document Element.matches: Attribute contains selector, matching lang attributes ending with specified substring, (with no refNodes): #attr-contains [lang*="-CH"] +PASS In-document Element.matches: Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-contains [class*=' apple'] +PASS In-document Element.matches: Attribute contains selector with single-quoted value, matching class attribute ending with specified substring (with no refNodes): #attr-contains [class*='orange '] +PASS In-document Element.matches: Attribute contains selector with single-quoted value, matching class attribute containing specified substring (with no refNodes): #attr-contains [class*='ple banana ora'] +PASS In-document Element.matches: Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-contains [class*=" apple"] +PASS In-document Element.matches: Attribute contains selector with double-quoted value, matching class attribute ending with specified substring (with no refNodes): #attr-contains [class*="orange "] +PASS In-document Element.matches: Attribute contains selector with double-quoted value, matching class attribute containing specified substring (with no refNodes): #attr-contains [class*="ple banana ora"] +PASS In-document Element.matches: Attribute contains selector with unquoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-contains [class*= apple] +PASS In-document Element.matches: Attribute contains selector with unquoted value, matching class attribute ending with specified substring (with no refNodes): #attr-contains [class*=orange ] +PASS In-document Element.matches: Attribute contains selector with unquoted value, matching class attribute containing specified substring (with no refNodes): #attr-contains [class*= banana ] +PASS In-document Element.matches: :root pseudo-class selector, matching document root element (with no refNodes): :root +PASS In-document Element.matches: :nth-child selector, matching the third child element (with no refNodes): #pseudo-nth-table1 :nth-child(3) +PASS In-document Element.matches: :nth-child selector, matching every third child element (with no refNodes): #pseudo-nth li:nth-child(3n) +PASS In-document Element.matches: :nth-child selector, matching every second child element, starting from the fourth (with no refNodes): #pseudo-nth li:nth-child(2n+4) +PASS In-document Element.matches: :nth-child selector, matching every fourth child element, starting from the third (with no refNodes): #pseudo-nth-p1 :nth-child(4n-1) +PASS In-document Element.matches: :nth-last-child selector, matching the third last child element (with no refNodes): #pseudo-nth-table1 :nth-last-child(3) +PASS In-document Element.matches: :nth-last-child selector, matching every third child element from the end (with no refNodes): #pseudo-nth li:nth-last-child(3n) +PASS In-document Element.matches: :nth-last-child selector, matching every second child element from the end, starting from the fourth last (with no refNodes): #pseudo-nth li:nth-last-child(2n+4) +PASS In-document Element.matches: :nth-last-child selector, matching every fourth element from the end, starting from the third last (with no refNodes): #pseudo-nth-p1 :nth-last-child(4n-1) +PASS In-document Element.matches: :nth-of-type selector, matching the third em element (with no refNodes): #pseudo-nth-p1 em:nth-of-type(3) +PASS In-document Element.matches: :nth-of-type selector, matching every second element of their type (with no refNodes): #pseudo-nth-p1 :nth-of-type(2n) +PASS In-document Element.matches: :nth-of-type selector, matching every second elemetn of their type, starting from the first (with no refNodes): #pseudo-nth-p1 span:nth-of-type(2n-1) +PASS In-document Element.matches: :nth-last-of-type selector, matching the thrid last em element (with no refNodes): #pseudo-nth-p1 em:nth-last-of-type(3) +PASS In-document Element.matches: :nth-last-of-type selector, matching every second last element of their type (with no refNodes): #pseudo-nth-p1 :nth-last-of-type(2n) +PASS In-document Element.matches: :nth-last-of-type selector, matching every second last element of their type, starting from the last (with no refNodes): #pseudo-nth-p1 span:nth-last-of-type(2n-1) +PASS In-document Element.matches: :first-of-type selector, matching the first em element (with no refNodes): #pseudo-nth-p1 em:first-of-type +PASS In-document Element.matches: :first-of-type selector, matching the first of every type of element (with no refNodes): #pseudo-nth-p1 :first-of-type +PASS In-document Element.matches: :first-of-type selector, matching the first td element in each table row (with no refNodes): #pseudo-nth-table1 tr :first-of-type +PASS In-document Element.matches: :last-of-type selector, matching the last em elemnet (with no refNodes): #pseudo-nth-p1 em:last-of-type +PASS In-document Element.matches: :last-of-type selector, matching the last of every type of element (with no refNodes): #pseudo-nth-p1 :last-of-type +PASS In-document Element.matches: :last-of-type selector, matching the last td element in each table row (with no refNodes): #pseudo-nth-table1 tr :last-of-type +PASS In-document Element.matches: :first-child pseudo-class selector, matching first child div element (with no refNodes): #pseudo-first-child div:first-child +PASS In-document Element.matches: :first-child pseudo-class selector, matching first-child of multiple elements (with no refNodes): #pseudo-first-child span:first-child +PASS In-document Element.matches: :last-child pseudo-class selector, matching last child div element (with no refNodes): #pseudo-last-child div:last-child +PASS In-document Element.matches: :last-child pseudo-class selector, matching first-child of multiple elements (with no refNodes): #pseudo-last-child span:last-child +PASS In-document Element.matches: :pseudo-only-child pseudo-class selector, matching all only-child elements (with no refNodes): #pseudo-only :only-child +PASS In-document Element.matches: :pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type (with no refNodes): #pseudo-only :only-of-type +PASS In-document Element.matches: :pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type (with no refNodes): #pseudo-only em:only-of-type +PASS In-document Element.matches: :empty pseudo-class selector, matching empty p elements (with no refNodes): #pseudo-empty p:empty +PASS In-document Element.matches: :empty pseudo-class selector, matching all empty elements (with no refNodes): #pseudo-empty :empty +PASS In-document Element.matches: :link and :visited pseudo-class selectors, matching a and area elements with href attributes (with no refNodes): #pseudo-link :link, #pseudo-link :visited +FAIL In-document Element.matches: :link and :visited pseudo-class selectors, matching link elements with href attributes (with no refNodes): #head :link, #head :visited assert_true: The element #pseudo-link-link1 should match the selector. expected true got false +PASS In-document Element.matches: :target pseudo-class selector, matching the element referenced by the URL fragment identifier (with no refNodes): :target +PASS In-document Element.matches: :lang pseudo-class selector, matching inherited language (with no refNodes): #pseudo-lang-div1:lang(en) +PASS In-document Element.matches: :lang pseudo-class selector, matching specified language with exact value (with no refNodes): #pseudo-lang-div2:lang(fr) +PASS In-document Element.matches: :lang pseudo-class selector, matching specified language with partial value (with no refNodes): #pseudo-lang-div3:lang(en) +PASS In-document Element.matches: :enabled pseudo-class selector, matching all enabled form controls (with no refNodes): #pseudo-ui :enabled +PASS In-document Element.matches: :enabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS In-document Element.matches: :checked pseudo-class selector, matching checked radio buttons and checkboxes (with no refNodes): #pseudo-ui :checked +PASS In-document Element.matches: :not pseudo-class selector, matching (with no refNodes): #not>:not(div) +PASS In-document Element.matches: :not pseudo-class selector, matching (with no refNodes): #not * :not(:first-child) +PASS In-document Element.matches: Class selector, matching element with specified class (with no refNodes): .class-p +PASS In-document Element.matches: Class selector, chained, matching only elements with all specified classes (with no refNodes): #class .apple.orange.banana +PASS In-document Element.matches: Class Selector, chained, with type selector (with no refNodes): div.apple.banana.orange +PASS In-document Element.matches: Class selector, matching element with class value using non-ASCII characters (1) (with no refNodes): .台北Táiběi +PASS In-document Element.matches: Class selector, matching multiple elements with class value using non-ASCII characters (with no refNodes): .台北 +PASS In-document Element.matches: Class selector, chained, matching element with multiple class values using non-ASCII characters (1) (with no refNodes): .台北Táiběi.台北 +PASS In-document Element.matches: Class selector, matching element with class with escaped character (with no refNodes): .foo\:bar +PASS In-document Element.matches: Class selector, matching element with class with escaped character (with no refNodes): .test\.foo\[5\]bar +PASS In-document Element.matches: ID selector, matching element with specified id (with no refNodes): #id #id-div1 +PASS In-document Element.matches: ID selector, chained, matching element with specified id (with no refNodes): #id-div1, #id-div1 +PASS In-document Element.matches: ID selector, chained, matching element with specified id (with no refNodes): #id-div1, #id-div2 +PASS In-document Element.matches: ID Selector, chained, with type selector (with no refNodes): div#id-div1, div#id-div2 +PASS In-document Element.matches: ID selector, matching multiple elements with duplicate id (with no refNodes): #id-li-duplicate +PASS In-document Element.matches: ID selector, matching id value using non-ASCII characters (1) (with no refNodes): #台北Táiběi +PASS In-document Element.matches: ID selector, matching id value using non-ASCII characters (2) (with no refNodes): #台北 +PASS In-document Element.matches: ID selector, matching id values using non-ASCII characters (1) (with no refNodes): #台北Táiběi, #台北 +PASS In-document Element.matches: Descendant combinator, matching element that is a descendant of an element with id (with no refNodes): #descendant div +PASS In-document Element.matches: Descendant combinator, matching element with id that is a descendant of an element (with no refNodes): body #descendant-div1 +PASS In-document Element.matches: Descendant combinator, matching element with id that is a descendant of an element (with no refNodes): div #descendant-div1 +PASS In-document Element.matches: Descendant combinator, matching element with id that is a descendant of an element with id (with no refNodes): #descendant #descendant-div2 +PASS In-document Element.matches: Descendant combinator, matching element with class that is a descendant of an element with id (with no refNodes): #descendant .descendant-div2 +PASS In-document Element.matches: Descendant combinator, matching element with class that is a descendant of an element with class (with no refNodes): .descendant-div1 .descendant-div3 +PASS In-document Element.matches: Descendant combinator, whitespace characters (with no refNodes): #descendant \r +#descendant-div2 +FAIL In-document Element.matches: Descendant combinator '>>', matching element that is a descendant of an element with id (with no refNodes): #descendant>>div Failed to execute 'matches' on 'Element': '#descendant>>div' is not a valid selector. +FAIL In-document Element.matches: Descendant combinator '>>', matching element with id that is a descendant of an element (with no refNodes): body>>#descendant-div1 Failed to execute 'matches' on 'Element': 'body>>#descendant-div1' is not a valid selector. +FAIL In-document Element.matches: Descendant combinator '>>', matching element with id that is a descendant of an element (with no refNodes): div>>#descendant-div1 Failed to execute 'matches' on 'Element': 'div>>#descendant-div1' is not a valid selector. +FAIL In-document Element.matches: Descendant combinator '>>', matching element with id that is a descendant of an element with id (with no refNodes): #descendant>>#descendant-div2 Failed to execute 'matches' on 'Element': '#descendant>>#descendant-div2' is not a valid selector. +FAIL In-document Element.matches: Descendant combinator '>>', matching element with class that is a descendant of an element with id (with no refNodes): #descendant>>.descendant-div2 Failed to execute 'matches' on 'Element': '#descendant>>.descendant-div2' is not a valid selector. +FAIL In-document Element.matches: Descendant combinator '>>', matching element with class that is a descendant of an element with class (with no refNodes): .descendant-div1>>.descendant-div3 Failed to execute 'matches' on 'Element': '.descendant-div1>>.descendant-div3' is not a valid selector. +PASS In-document Element.matches: Child combinator, matching element that is a child of an element with id (with no refNodes): #child>div +PASS In-document Element.matches: Child combinator, matching element with id that is a child of an element (with no refNodes): div>#child-div1 +PASS In-document Element.matches: Child combinator, matching element with id that is a child of an element with id (with no refNodes): #child>#child-div1 +PASS In-document Element.matches: Child combinator, matching element with id that is a child of an element with class (with no refNodes): #child-div1>.child-div2 +PASS In-document Element.matches: Child combinator, matching element with class that is a child of an element with class (with no refNodes): .child-div1>.child-div2 +PASS In-document Element.matches: Child combinator, surrounded by whitespace (with no refNodes): #child-div1 \r +> \r +#child-div2 +PASS In-document Element.matches: Child combinator, whitespace after (with no refNodes): #child-div1> \r +#child-div2 +PASS In-document Element.matches: Child combinator, whitespace before (with no refNodes): #child-div1 \r +>#child-div2 +PASS In-document Element.matches: Child combinator, no whitespace (with no refNodes): #child-div1>#child-div2 +PASS In-document Element.matches: Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id (with no refNodes): #adjacent-div2+div +PASS In-document Element.matches: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element (with no refNodes): div+#adjacent-div4 +PASS In-document Element.matches: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id (with no refNodes): #adjacent-div2+#adjacent-div4 +PASS In-document Element.matches: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id (with no refNodes): #adjacent-div2+.adjacent-div4 +PASS In-document Element.matches: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class (with no refNodes): .adjacent-div2+.adjacent-div4 +PASS In-document Element.matches: Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element (with no refNodes): #adjacent div+p +PASS In-document Element.matches: Adjacent sibling combinator, surrounded by whitespace (with no refNodes): #adjacent-p2 \r ++ \r +#adjacent-p3 +PASS In-document Element.matches: Adjacent sibling combinator, whitespace after (with no refNodes): #adjacent-p2+ \r +#adjacent-p3 +PASS In-document Element.matches: Adjacent sibling combinator, whitespace before (with no refNodes): #adjacent-p2 \r ++#adjacent-p3 +PASS In-document Element.matches: Adjacent sibling combinator, no whitespace (with no refNodes): #adjacent-p2+#adjacent-p3 +PASS In-document Element.matches: General sibling combinator, matching element that is a sibling of an element with id (with no refNodes): #sibling-div2~div +PASS In-document Element.matches: General sibling combinator, matching element with id that is a sibling of an element (with no refNodes): div~#sibling-div4 +PASS In-document Element.matches: General sibling combinator, matching element with id that is a sibling of an element with id (with no refNodes): #sibling-div2~#sibling-div4 +PASS In-document Element.matches: General sibling combinator, matching element with class that is a sibling of an element with id (with no refNodes): #sibling-div2~.sibling-div +PASS In-document Element.matches: General sibling combinator, matching p element that is a sibling of a div element (with no refNodes): #sibling div~p +PASS In-document Element.matches: General sibling combinator, surrounded by whitespace (with no refNodes): #sibling-p2 \r +~ \r +#sibling-p3 +PASS In-document Element.matches: General sibling combinator, whitespace after (with no refNodes): #sibling-p2~ \r +#sibling-p3 +PASS In-document Element.matches: General sibling combinator, whitespace before (with no refNodes): #sibling-p2 \r +~#sibling-p3 +PASS In-document Element.matches: General sibling combinator, no whitespace (with no refNodes): #sibling-p2~#sibling-p3 +PASS In-document Element.matches: Syntax, group of selectors separator, surrounded by whitespace (with no refNodes): #group em \r +, \r +#group strong +PASS In-document Element.matches: Syntax, group of selectors separator, whitespace after (with no refNodes): #group em, \r +#group strong +PASS In-document Element.matches: Syntax, group of selectors separator, whitespace before (with no refNodes): #group em \r +,#group strong +PASS In-document Element.matches: Syntax, group of selectors separator, no whitespace (with no refNodes): #group em,#group strong +PASS Detached Element.matches: Universal selector, matching all children of element with specified ID (with no refNodes): #universal>* +PASS Detached Element.matches: Universal selector, matching all grandchildren of element with specified ID (with no refNodes): #universal>*>* +PASS Detached Element.matches: Universal selector, matching all descendants of element with specified ID (with no refNodes): #universal * +PASS Detached Element.matches: Attribute presence selector, matching align attribute with value (with no refNodes): .attr-presence-div1[align] +PASS Detached Element.matches: Attribute presence selector, matching align attribute with empty value (with no refNodes): .attr-presence-div2[align] +PASS Detached Element.matches: Attribute presence selector, matching title attribute, case insensitivity (with no refNodes): #attr-presence [TiTlE] +PASS Detached Element.matches: Attribute presence selector, matching custom data-* attribute (with no refNodes): [data-attr-presence] +PASS Detached Element.matches: Attribute presence selector, matching attribute with non-ASCII characters (with no refNodes): ul[data-中文] +PASS Detached Element.matches: Attribute presence selector, matching option with selected attribute (with no refNodes): #attr-presence-select2 option[selected] +PASS Detached Element.matches: Attribute presence selector, matching multiple options with selected attributes (with no refNodes): #attr-presence-select3 option[selected] +PASS Detached Element.matches: Attribute value selector, matching align attribute with value (with no refNodes): #attr-value [align="center"] +PASS Detached Element.matches: Attribute value selector, matching align attribute with empty value (with no refNodes): #attr-value [align=""] +PASS Detached Element.matches: Attribute value selector, matching custom data-* attribute with unicode escaped value (with no refNodes): [data-attr-value="\e9"] +PASS Detached Element.matches: Attribute value selector, matching custom data-* attribute with escaped character (with no refNodes): [data-attr-value_foo="\e9"] +PASS Detached Element.matches: Attribute value selector with single-quoted value, matching multiple inputs with type attributes (with no refNodes): #attr-value input[type='hidden'],#attr-value input[type='radio'] +PASS Detached Element.matches: Attribute value selector with double-quoted value, matching multiple inputs with type attributes (with no refNodes): #attr-value input[type="hidden"],#attr-value input[type='radio'] +PASS Detached Element.matches: Attribute value selector with unquoted value, matching multiple inputs with type attributes (with no refNodes): #attr-value input[type=hidden],#attr-value input[type=radio] +PASS Detached Element.matches: Attribute value selector, matching attribute with value using non-ASCII characters (with no refNodes): [data-attr-value=中文] +PASS Detached Element.matches: Attribute whitespace-separated list selector, matching class attribute with value (with no refNodes): #attr-whitespace [class~="div1"] +PASS Detached Element.matches: Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value (with no refNodes): [data-attr-whitespace~="\0000e9"] +PASS Detached Element.matches: Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character (with no refNodes): [data-attr-whitespace_foo~="\e9"] +PASS Detached Element.matches: Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes (with no refNodes): #attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow'] +PASS Detached Element.matches: Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes (with no refNodes): #attr-whitespace a[rel~="bookmark"],#attr-whitespace a[rel~='nofollow'] +PASS Detached Element.matches: Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes (with no refNodes): #attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow] +PASS Detached Element.matches: Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters (with no refNodes): #attr-whitespace [title~=中文] +PASS Detached Element.matches: Attribute hyphen-separated list selector, matching lang attribute with exact value (with no refNodes): #attr-hyphen-div2[lang|="fr"] +PASS Detached Element.matches: Attribute hyphen-separated list selector, matching lang attribute with partial value (with no refNodes): #attr-hyphen-div3[lang|="en"] +PASS Detached Element.matches: Attribute begins with selector, matching href attributes beginning with specified substring (with no refNodes): #attr-begins a[href^="http://www"] +PASS Detached Element.matches: Attribute begins with selector, matching lang attributes beginning with specified substring, (with no refNodes): #attr-begins [lang^="en-"] +PASS Detached Element.matches: Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-begins [class^=' apple'] +PASS Detached Element.matches: Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-begins [class^=" apple"] +PASS Detached Element.matches: Attribute ends with selector, matching href attributes ending with specified substring (with no refNodes): #attr-ends a[href$=".org"] +PASS Detached Element.matches: Attribute ends with selector, matching lang attributes ending with specified substring, (with no refNodes): #attr-ends [lang$="-CH"] +PASS Detached Element.matches: Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring (with no refNodes): #attr-ends [class$='apple '] +PASS Detached Element.matches: Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring (with no refNodes): #attr-ends [class$="apple "] +PASS Detached Element.matches: Attribute contains selector, matching href attributes beginning with specified substring (with no refNodes): #attr-contains a[href*="http://www"] +PASS Detached Element.matches: Attribute contains selector, matching href attributes ending with specified substring (with no refNodes): #attr-contains a[href*=".org"] +PASS Detached Element.matches: Attribute contains selector, matching href attributes containing specified substring (with no refNodes): #attr-contains a[href*=".example."] +PASS Detached Element.matches: Attribute contains selector, matching lang attributes beginning with specified substring, (with no refNodes): #attr-contains [lang*="en-"] +PASS Detached Element.matches: Attribute contains selector, matching lang attributes ending with specified substring, (with no refNodes): #attr-contains [lang*="-CH"] +PASS Detached Element.matches: Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-contains [class*=' apple'] +PASS Detached Element.matches: Attribute contains selector with single-quoted value, matching class attribute ending with specified substring (with no refNodes): #attr-contains [class*='orange '] +PASS Detached Element.matches: Attribute contains selector with single-quoted value, matching class attribute containing specified substring (with no refNodes): #attr-contains [class*='ple banana ora'] +PASS Detached Element.matches: Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-contains [class*=" apple"] +PASS Detached Element.matches: Attribute contains selector with double-quoted value, matching class attribute ending with specified substring (with no refNodes): #attr-contains [class*="orange "] +PASS Detached Element.matches: Attribute contains selector with double-quoted value, matching class attribute containing specified substring (with no refNodes): #attr-contains [class*="ple banana ora"] +PASS Detached Element.matches: Attribute contains selector with unquoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-contains [class*= apple] +PASS Detached Element.matches: Attribute contains selector with unquoted value, matching class attribute ending with specified substring (with no refNodes): #attr-contains [class*=orange ] +PASS Detached Element.matches: Attribute contains selector with unquoted value, matching class attribute containing specified substring (with no refNodes): #attr-contains [class*= banana ] +PASS Detached Element.matches: :nth-child selector, matching the third child element (with no refNodes): #pseudo-nth-table1 :nth-child(3) +PASS Detached Element.matches: :nth-child selector, matching every third child element (with no refNodes): #pseudo-nth li:nth-child(3n) +PASS Detached Element.matches: :nth-child selector, matching every second child element, starting from the fourth (with no refNodes): #pseudo-nth li:nth-child(2n+4) +PASS Detached Element.matches: :nth-child selector, matching every fourth child element, starting from the third (with no refNodes): #pseudo-nth-p1 :nth-child(4n-1) +PASS Detached Element.matches: :nth-last-child selector, matching the third last child element (with no refNodes): #pseudo-nth-table1 :nth-last-child(3) +PASS Detached Element.matches: :nth-last-child selector, matching every third child element from the end (with no refNodes): #pseudo-nth li:nth-last-child(3n) +PASS Detached Element.matches: :nth-last-child selector, matching every second child element from the end, starting from the fourth last (with no refNodes): #pseudo-nth li:nth-last-child(2n+4) +PASS Detached Element.matches: :nth-last-child selector, matching every fourth element from the end, starting from the third last (with no refNodes): #pseudo-nth-p1 :nth-last-child(4n-1) +PASS Detached Element.matches: :nth-of-type selector, matching the third em element (with no refNodes): #pseudo-nth-p1 em:nth-of-type(3) +PASS Detached Element.matches: :nth-of-type selector, matching every second element of their type (with no refNodes): #pseudo-nth-p1 :nth-of-type(2n) +PASS Detached Element.matches: :nth-of-type selector, matching every second elemetn of their type, starting from the first (with no refNodes): #pseudo-nth-p1 span:nth-of-type(2n-1) +PASS Detached Element.matches: :nth-last-of-type selector, matching the thrid last em element (with no refNodes): #pseudo-nth-p1 em:nth-last-of-type(3) +PASS Detached Element.matches: :nth-last-of-type selector, matching every second last element of their type (with no refNodes): #pseudo-nth-p1 :nth-last-of-type(2n) +PASS Detached Element.matches: :nth-last-of-type selector, matching every second last element of their type, starting from the last (with no refNodes): #pseudo-nth-p1 span:nth-last-of-type(2n-1) +PASS Detached Element.matches: :first-of-type selector, matching the first em element (with no refNodes): #pseudo-nth-p1 em:first-of-type +PASS Detached Element.matches: :first-of-type selector, matching the first of every type of element (with no refNodes): #pseudo-nth-p1 :first-of-type +PASS Detached Element.matches: :first-of-type selector, matching the first td element in each table row (with no refNodes): #pseudo-nth-table1 tr :first-of-type +PASS Detached Element.matches: :last-of-type selector, matching the last em elemnet (with no refNodes): #pseudo-nth-p1 em:last-of-type +PASS Detached Element.matches: :last-of-type selector, matching the last of every type of element (with no refNodes): #pseudo-nth-p1 :last-of-type +PASS Detached Element.matches: :last-of-type selector, matching the last td element in each table row (with no refNodes): #pseudo-nth-table1 tr :last-of-type +PASS Detached Element.matches: :first-child pseudo-class selector, matching first child div element (with no refNodes): #pseudo-first-child div:first-child +PASS Detached Element.matches: :first-child pseudo-class selector, matching first-child of multiple elements (with no refNodes): #pseudo-first-child span:first-child +PASS Detached Element.matches: :last-child pseudo-class selector, matching last child div element (with no refNodes): #pseudo-last-child div:last-child +PASS Detached Element.matches: :last-child pseudo-class selector, matching first-child of multiple elements (with no refNodes): #pseudo-last-child span:last-child +PASS Detached Element.matches: :pseudo-only-child pseudo-class selector, matching all only-child elements (with no refNodes): #pseudo-only :only-child +PASS Detached Element.matches: :pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type (with no refNodes): #pseudo-only :only-of-type +PASS Detached Element.matches: :pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type (with no refNodes): #pseudo-only em:only-of-type +PASS Detached Element.matches: :empty pseudo-class selector, matching empty p elements (with no refNodes): #pseudo-empty p:empty +PASS Detached Element.matches: :empty pseudo-class selector, matching all empty elements (with no refNodes): #pseudo-empty :empty +PASS Detached Element.matches: :link and :visited pseudo-class selectors, matching a and area elements with href attributes (with no refNodes): #pseudo-link :link, #pseudo-link :visited +PASS Detached Element.matches: :lang pseudo-class selector, matching specified language with exact value (with no refNodes): #pseudo-lang-div2:lang(fr) +PASS Detached Element.matches: :lang pseudo-class selector, matching specified language with partial value (with no refNodes): #pseudo-lang-div3:lang(en) +PASS Detached Element.matches: :enabled pseudo-class selector, matching all enabled form controls (with no refNodes): #pseudo-ui :enabled +PASS Detached Element.matches: :enabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS Detached Element.matches: :checked pseudo-class selector, matching checked radio buttons and checkboxes (with no refNodes): #pseudo-ui :checked +PASS Detached Element.matches: :not pseudo-class selector, matching (with no refNodes): #not>:not(div) +PASS Detached Element.matches: :not pseudo-class selector, matching (with no refNodes): #not * :not(:first-child) +PASS Detached Element.matches: Class selector, matching element with specified class (with no refNodes): .class-p +PASS Detached Element.matches: Class selector, chained, matching only elements with all specified classes (with no refNodes): #class .apple.orange.banana +PASS Detached Element.matches: Class Selector, chained, with type selector (with no refNodes): div.apple.banana.orange +PASS Detached Element.matches: Class selector, matching element with class value using non-ASCII characters (1) (with no refNodes): .台北Táiběi +PASS Detached Element.matches: Class selector, matching multiple elements with class value using non-ASCII characters (with no refNodes): .台北 +PASS Detached Element.matches: Class selector, chained, matching element with multiple class values using non-ASCII characters (1) (with no refNodes): .台北Táiběi.台北 +PASS Detached Element.matches: Class selector, matching element with class with escaped character (with no refNodes): .foo\:bar +PASS Detached Element.matches: Class selector, matching element with class with escaped character (with no refNodes): .test\.foo\[5\]bar +PASS Detached Element.matches: ID selector, matching element with specified id (with no refNodes): #id #id-div1 +PASS Detached Element.matches: ID selector, chained, matching element with specified id (with no refNodes): #id-div1, #id-div1 +PASS Detached Element.matches: ID selector, chained, matching element with specified id (with no refNodes): #id-div1, #id-div2 +PASS Detached Element.matches: ID Selector, chained, with type selector (with no refNodes): div#id-div1, div#id-div2 +PASS Detached Element.matches: ID selector, matching multiple elements with duplicate id (with no refNodes): #id-li-duplicate +PASS Detached Element.matches: ID selector, matching id value using non-ASCII characters (1) (with no refNodes): #台北Táiběi +PASS Detached Element.matches: ID selector, matching id value using non-ASCII characters (2) (with no refNodes): #台北 +PASS Detached Element.matches: ID selector, matching id values using non-ASCII characters (1) (with no refNodes): #台北Táiběi, #台北 +PASS Detached Element.matches: Descendant combinator, matching element that is a descendant of an element with id (with no refNodes): #descendant div +PASS Detached Element.matches: Descendant combinator, matching element with id that is a descendant of an element (with no refNodes): div #descendant-div1 +PASS Detached Element.matches: Descendant combinator, matching element with id that is a descendant of an element with id (with no refNodes): #descendant #descendant-div2 +PASS Detached Element.matches: Descendant combinator, matching element with class that is a descendant of an element with id (with no refNodes): #descendant .descendant-div2 +PASS Detached Element.matches: Descendant combinator, matching element with class that is a descendant of an element with class (with no refNodes): .descendant-div1 .descendant-div3 +PASS Detached Element.matches: Descendant combinator, whitespace characters (with no refNodes): #descendant \r +#descendant-div2 +FAIL Detached Element.matches: Descendant combinator '>>', matching element that is a descendant of an element with id (with no refNodes): #descendant>>div Failed to execute 'matches' on 'Element': '#descendant>>div' is not a valid selector. +FAIL Detached Element.matches: Descendant combinator '>>', matching element with id that is a descendant of an element (with no refNodes): div>>#descendant-div1 Failed to execute 'matches' on 'Element': 'div>>#descendant-div1' is not a valid selector. +FAIL Detached Element.matches: Descendant combinator '>>', matching element with id that is a descendant of an element with id (with no refNodes): #descendant>>#descendant-div2 Failed to execute 'matches' on 'Element': '#descendant>>#descendant-div2' is not a valid selector. +FAIL Detached Element.matches: Descendant combinator '>>', matching element with class that is a descendant of an element with id (with no refNodes): #descendant>>.descendant-div2 Failed to execute 'matches' on 'Element': '#descendant>>.descendant-div2' is not a valid selector. +FAIL Detached Element.matches: Descendant combinator '>>', matching element with class that is a descendant of an element with class (with no refNodes): .descendant-div1>>.descendant-div3 Failed to execute 'matches' on 'Element': '.descendant-div1>>.descendant-div3' is not a valid selector. +PASS Detached Element.matches: Child combinator, matching element that is a child of an element with id (with no refNodes): #child>div +PASS Detached Element.matches: Child combinator, matching element with id that is a child of an element (with no refNodes): div>#child-div1 +PASS Detached Element.matches: Child combinator, matching element with id that is a child of an element with id (with no refNodes): #child>#child-div1 +PASS Detached Element.matches: Child combinator, matching element with id that is a child of an element with class (with no refNodes): #child-div1>.child-div2 +PASS Detached Element.matches: Child combinator, matching element with class that is a child of an element with class (with no refNodes): .child-div1>.child-div2 +PASS Detached Element.matches: Child combinator, surrounded by whitespace (with no refNodes): #child-div1 \r +> \r +#child-div2 +PASS Detached Element.matches: Child combinator, whitespace after (with no refNodes): #child-div1> \r +#child-div2 +PASS Detached Element.matches: Child combinator, whitespace before (with no refNodes): #child-div1 \r +>#child-div2 +PASS Detached Element.matches: Child combinator, no whitespace (with no refNodes): #child-div1>#child-div2 +PASS Detached Element.matches: Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id (with no refNodes): #adjacent-div2+div +PASS Detached Element.matches: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element (with no refNodes): div+#adjacent-div4 +PASS Detached Element.matches: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id (with no refNodes): #adjacent-div2+#adjacent-div4 +PASS Detached Element.matches: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id (with no refNodes): #adjacent-div2+.adjacent-div4 +PASS Detached Element.matches: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class (with no refNodes): .adjacent-div2+.adjacent-div4 +PASS Detached Element.matches: Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element (with no refNodes): #adjacent div+p +PASS Detached Element.matches: Adjacent sibling combinator, surrounded by whitespace (with no refNodes): #adjacent-p2 \r ++ \r +#adjacent-p3 +PASS Detached Element.matches: Adjacent sibling combinator, whitespace after (with no refNodes): #adjacent-p2+ \r +#adjacent-p3 +PASS Detached Element.matches: Adjacent sibling combinator, whitespace before (with no refNodes): #adjacent-p2 \r ++#adjacent-p3 +PASS Detached Element.matches: Adjacent sibling combinator, no whitespace (with no refNodes): #adjacent-p2+#adjacent-p3 +PASS Detached Element.matches: General sibling combinator, matching element that is a sibling of an element with id (with no refNodes): #sibling-div2~div +PASS Detached Element.matches: General sibling combinator, matching element with id that is a sibling of an element (with no refNodes): div~#sibling-div4 +PASS Detached Element.matches: General sibling combinator, matching element with id that is a sibling of an element with id (with no refNodes): #sibling-div2~#sibling-div4 +PASS Detached Element.matches: General sibling combinator, matching element with class that is a sibling of an element with id (with no refNodes): #sibling-div2~.sibling-div +PASS Detached Element.matches: General sibling combinator, matching p element that is a sibling of a div element (with no refNodes): #sibling div~p +PASS Detached Element.matches: General sibling combinator, surrounded by whitespace (with no refNodes): #sibling-p2 \r +~ \r +#sibling-p3 +PASS Detached Element.matches: General sibling combinator, whitespace after (with no refNodes): #sibling-p2~ \r +#sibling-p3 +PASS Detached Element.matches: General sibling combinator, whitespace before (with no refNodes): #sibling-p2 \r +~#sibling-p3 +PASS Detached Element.matches: General sibling combinator, no whitespace (with no refNodes): #sibling-p2~#sibling-p3 +PASS Detached Element.matches: Syntax, group of selectors separator, surrounded by whitespace (with no refNodes): #group em \r +, \r +#group strong +PASS Detached Element.matches: Syntax, group of selectors separator, whitespace after (with no refNodes): #group em, \r +#group strong +PASS Detached Element.matches: Syntax, group of selectors separator, whitespace before (with no refNodes): #group em \r +,#group strong +PASS Detached Element.matches: Syntax, group of selectors separator, no whitespace (with no refNodes): #group em,#group strong +PASS Fragment Element.matches: Universal selector, matching all children of element with specified ID (with no refNodes): #universal>* +PASS Fragment Element.matches: Universal selector, matching all grandchildren of element with specified ID (with no refNodes): #universal>*>* +PASS Fragment Element.matches: Universal selector, matching all descendants of element with specified ID (with no refNodes): #universal * +PASS Fragment Element.matches: Attribute presence selector, matching align attribute with value (with no refNodes): .attr-presence-div1[align] +PASS Fragment Element.matches: Attribute presence selector, matching align attribute with empty value (with no refNodes): .attr-presence-div2[align] +PASS Fragment Element.matches: Attribute presence selector, matching title attribute, case insensitivity (with no refNodes): #attr-presence [TiTlE] +PASS Fragment Element.matches: Attribute presence selector, matching custom data-* attribute (with no refNodes): [data-attr-presence] +PASS Fragment Element.matches: Attribute presence selector, matching attribute with non-ASCII characters (with no refNodes): ul[data-中文] +PASS Fragment Element.matches: Attribute presence selector, matching option with selected attribute (with no refNodes): #attr-presence-select2 option[selected] +PASS Fragment Element.matches: Attribute presence selector, matching multiple options with selected attributes (with no refNodes): #attr-presence-select3 option[selected] +PASS Fragment Element.matches: Attribute value selector, matching align attribute with value (with no refNodes): #attr-value [align="center"] +PASS Fragment Element.matches: Attribute value selector, matching align attribute with empty value (with no refNodes): #attr-value [align=""] +PASS Fragment Element.matches: Attribute value selector, matching custom data-* attribute with unicode escaped value (with no refNodes): [data-attr-value="\e9"] +PASS Fragment Element.matches: Attribute value selector, matching custom data-* attribute with escaped character (with no refNodes): [data-attr-value_foo="\e9"] +PASS Fragment Element.matches: Attribute value selector with single-quoted value, matching multiple inputs with type attributes (with no refNodes): #attr-value input[type='hidden'],#attr-value input[type='radio'] +PASS Fragment Element.matches: Attribute value selector with double-quoted value, matching multiple inputs with type attributes (with no refNodes): #attr-value input[type="hidden"],#attr-value input[type='radio'] +PASS Fragment Element.matches: Attribute value selector with unquoted value, matching multiple inputs with type attributes (with no refNodes): #attr-value input[type=hidden],#attr-value input[type=radio] +PASS Fragment Element.matches: Attribute value selector, matching attribute with value using non-ASCII characters (with no refNodes): [data-attr-value=中文] +PASS Fragment Element.matches: Attribute whitespace-separated list selector, matching class attribute with value (with no refNodes): #attr-whitespace [class~="div1"] +PASS Fragment Element.matches: Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value (with no refNodes): [data-attr-whitespace~="\0000e9"] +PASS Fragment Element.matches: Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character (with no refNodes): [data-attr-whitespace_foo~="\e9"] +PASS Fragment Element.matches: Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes (with no refNodes): #attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow'] +PASS Fragment Element.matches: Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes (with no refNodes): #attr-whitespace a[rel~="bookmark"],#attr-whitespace a[rel~='nofollow'] +PASS Fragment Element.matches: Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes (with no refNodes): #attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow] +PASS Fragment Element.matches: Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters (with no refNodes): #attr-whitespace [title~=中文] +PASS Fragment Element.matches: Attribute hyphen-separated list selector, matching lang attribute with exact value (with no refNodes): #attr-hyphen-div2[lang|="fr"] +PASS Fragment Element.matches: Attribute hyphen-separated list selector, matching lang attribute with partial value (with no refNodes): #attr-hyphen-div3[lang|="en"] +PASS Fragment Element.matches: Attribute begins with selector, matching href attributes beginning with specified substring (with no refNodes): #attr-begins a[href^="http://www"] +PASS Fragment Element.matches: Attribute begins with selector, matching lang attributes beginning with specified substring, (with no refNodes): #attr-begins [lang^="en-"] +PASS Fragment Element.matches: Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-begins [class^=' apple'] +PASS Fragment Element.matches: Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-begins [class^=" apple"] +PASS Fragment Element.matches: Attribute ends with selector, matching href attributes ending with specified substring (with no refNodes): #attr-ends a[href$=".org"] +PASS Fragment Element.matches: Attribute ends with selector, matching lang attributes ending with specified substring, (with no refNodes): #attr-ends [lang$="-CH"] +PASS Fragment Element.matches: Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring (with no refNodes): #attr-ends [class$='apple '] +PASS Fragment Element.matches: Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring (with no refNodes): #attr-ends [class$="apple "] +PASS Fragment Element.matches: Attribute contains selector, matching href attributes beginning with specified substring (with no refNodes): #attr-contains a[href*="http://www"] +PASS Fragment Element.matches: Attribute contains selector, matching href attributes ending with specified substring (with no refNodes): #attr-contains a[href*=".org"] +PASS Fragment Element.matches: Attribute contains selector, matching href attributes containing specified substring (with no refNodes): #attr-contains a[href*=".example."] +PASS Fragment Element.matches: Attribute contains selector, matching lang attributes beginning with specified substring, (with no refNodes): #attr-contains [lang*="en-"] +PASS Fragment Element.matches: Attribute contains selector, matching lang attributes ending with specified substring, (with no refNodes): #attr-contains [lang*="-CH"] +PASS Fragment Element.matches: Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-contains [class*=' apple'] +PASS Fragment Element.matches: Attribute contains selector with single-quoted value, matching class attribute ending with specified substring (with no refNodes): #attr-contains [class*='orange '] +PASS Fragment Element.matches: Attribute contains selector with single-quoted value, matching class attribute containing specified substring (with no refNodes): #attr-contains [class*='ple banana ora'] +PASS Fragment Element.matches: Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-contains [class*=" apple"] +PASS Fragment Element.matches: Attribute contains selector with double-quoted value, matching class attribute ending with specified substring (with no refNodes): #attr-contains [class*="orange "] +PASS Fragment Element.matches: Attribute contains selector with double-quoted value, matching class attribute containing specified substring (with no refNodes): #attr-contains [class*="ple banana ora"] +PASS Fragment Element.matches: Attribute contains selector with unquoted value, matching class attribute beginning with specified substring (with no refNodes): #attr-contains [class*= apple] +PASS Fragment Element.matches: Attribute contains selector with unquoted value, matching class attribute ending with specified substring (with no refNodes): #attr-contains [class*=orange ] +PASS Fragment Element.matches: Attribute contains selector with unquoted value, matching class attribute containing specified substring (with no refNodes): #attr-contains [class*= banana ] +PASS Fragment Element.matches: :nth-child selector, matching the third child element (with no refNodes): #pseudo-nth-table1 :nth-child(3) +PASS Fragment Element.matches: :nth-child selector, matching every third child element (with no refNodes): #pseudo-nth li:nth-child(3n) +PASS Fragment Element.matches: :nth-child selector, matching every second child element, starting from the fourth (with no refNodes): #pseudo-nth li:nth-child(2n+4) +PASS Fragment Element.matches: :nth-child selector, matching every fourth child element, starting from the third (with no refNodes): #pseudo-nth-p1 :nth-child(4n-1) +PASS Fragment Element.matches: :nth-last-child selector, matching the third last child element (with no refNodes): #pseudo-nth-table1 :nth-last-child(3) +PASS Fragment Element.matches: :nth-last-child selector, matching every third child element from the end (with no refNodes): #pseudo-nth li:nth-last-child(3n) +PASS Fragment Element.matches: :nth-last-child selector, matching every second child element from the end, starting from the fourth last (with no refNodes): #pseudo-nth li:nth-last-child(2n+4) +PASS Fragment Element.matches: :nth-last-child selector, matching every fourth element from the end, starting from the third last (with no refNodes): #pseudo-nth-p1 :nth-last-child(4n-1) +PASS Fragment Element.matches: :nth-of-type selector, matching the third em element (with no refNodes): #pseudo-nth-p1 em:nth-of-type(3) +PASS Fragment Element.matches: :nth-of-type selector, matching every second element of their type (with no refNodes): #pseudo-nth-p1 :nth-of-type(2n) +PASS Fragment Element.matches: :nth-of-type selector, matching every second elemetn of their type, starting from the first (with no refNodes): #pseudo-nth-p1 span:nth-of-type(2n-1) +PASS Fragment Element.matches: :nth-last-of-type selector, matching the thrid last em element (with no refNodes): #pseudo-nth-p1 em:nth-last-of-type(3) +PASS Fragment Element.matches: :nth-last-of-type selector, matching every second last element of their type (with no refNodes): #pseudo-nth-p1 :nth-last-of-type(2n) +PASS Fragment Element.matches: :nth-last-of-type selector, matching every second last element of their type, starting from the last (with no refNodes): #pseudo-nth-p1 span:nth-last-of-type(2n-1) +PASS Fragment Element.matches: :first-of-type selector, matching the first em element (with no refNodes): #pseudo-nth-p1 em:first-of-type +PASS Fragment Element.matches: :first-of-type selector, matching the first of every type of element (with no refNodes): #pseudo-nth-p1 :first-of-type +PASS Fragment Element.matches: :first-of-type selector, matching the first td element in each table row (with no refNodes): #pseudo-nth-table1 tr :first-of-type +PASS Fragment Element.matches: :last-of-type selector, matching the last em elemnet (with no refNodes): #pseudo-nth-p1 em:last-of-type +PASS Fragment Element.matches: :last-of-type selector, matching the last of every type of element (with no refNodes): #pseudo-nth-p1 :last-of-type +PASS Fragment Element.matches: :last-of-type selector, matching the last td element in each table row (with no refNodes): #pseudo-nth-table1 tr :last-of-type +PASS Fragment Element.matches: :first-child pseudo-class selector, matching first child div element (with no refNodes): #pseudo-first-child div:first-child +PASS Fragment Element.matches: :first-child pseudo-class selector, matching first-child of multiple elements (with no refNodes): #pseudo-first-child span:first-child +PASS Fragment Element.matches: :last-child pseudo-class selector, matching last child div element (with no refNodes): #pseudo-last-child div:last-child +PASS Fragment Element.matches: :last-child pseudo-class selector, matching first-child of multiple elements (with no refNodes): #pseudo-last-child span:last-child +PASS Fragment Element.matches: :pseudo-only-child pseudo-class selector, matching all only-child elements (with no refNodes): #pseudo-only :only-child +PASS Fragment Element.matches: :pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type (with no refNodes): #pseudo-only :only-of-type +PASS Fragment Element.matches: :pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type (with no refNodes): #pseudo-only em:only-of-type +PASS Fragment Element.matches: :empty pseudo-class selector, matching empty p elements (with no refNodes): #pseudo-empty p:empty +PASS Fragment Element.matches: :empty pseudo-class selector, matching all empty elements (with no refNodes): #pseudo-empty :empty +PASS Fragment Element.matches: :link and :visited pseudo-class selectors, matching a and area elements with href attributes (with no refNodes): #pseudo-link :link, #pseudo-link :visited +PASS Fragment Element.matches: :lang pseudo-class selector, matching specified language with exact value (with no refNodes): #pseudo-lang-div2:lang(fr) +PASS Fragment Element.matches: :lang pseudo-class selector, matching specified language with partial value (with no refNodes): #pseudo-lang-div3:lang(en) +PASS Fragment Element.matches: :enabled pseudo-class selector, matching all enabled form controls (with no refNodes): #pseudo-ui :enabled +PASS Fragment Element.matches: :enabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS Fragment Element.matches: :checked pseudo-class selector, matching checked radio buttons and checkboxes (with no refNodes): #pseudo-ui :checked +PASS Fragment Element.matches: :not pseudo-class selector, matching (with no refNodes): #not>:not(div) +PASS Fragment Element.matches: :not pseudo-class selector, matching (with no refNodes): #not * :not(:first-child) +PASS Fragment Element.matches: Class selector, matching element with specified class (with no refNodes): .class-p +PASS Fragment Element.matches: Class selector, chained, matching only elements with all specified classes (with no refNodes): #class .apple.orange.banana +PASS Fragment Element.matches: Class Selector, chained, with type selector (with no refNodes): div.apple.banana.orange +PASS Fragment Element.matches: Class selector, matching element with class value using non-ASCII characters (1) (with no refNodes): .台北Táiběi +PASS Fragment Element.matches: Class selector, matching multiple elements with class value using non-ASCII characters (with no refNodes): .台北 +PASS Fragment Element.matches: Class selector, chained, matching element with multiple class values using non-ASCII characters (1) (with no refNodes): .台北Táiběi.台北 +PASS Fragment Element.matches: Class selector, matching element with class with escaped character (with no refNodes): .foo\:bar +PASS Fragment Element.matches: Class selector, matching element with class with escaped character (with no refNodes): .test\.foo\[5\]bar +PASS Fragment Element.matches: ID selector, matching element with specified id (with no refNodes): #id #id-div1 +PASS Fragment Element.matches: ID selector, chained, matching element with specified id (with no refNodes): #id-div1, #id-div1 +PASS Fragment Element.matches: ID selector, chained, matching element with specified id (with no refNodes): #id-div1, #id-div2 +PASS Fragment Element.matches: ID Selector, chained, with type selector (with no refNodes): div#id-div1, div#id-div2 +PASS Fragment Element.matches: ID selector, matching multiple elements with duplicate id (with no refNodes): #id-li-duplicate +PASS Fragment Element.matches: ID selector, matching id value using non-ASCII characters (1) (with no refNodes): #台北Táiběi +PASS Fragment Element.matches: ID selector, matching id value using non-ASCII characters (2) (with no refNodes): #台北 +PASS Fragment Element.matches: ID selector, matching id values using non-ASCII characters (1) (with no refNodes): #台北Táiběi, #台北 +PASS Fragment Element.matches: Descendant combinator, matching element that is a descendant of an element with id (with no refNodes): #descendant div +PASS Fragment Element.matches: Descendant combinator, matching element with id that is a descendant of an element (with no refNodes): div #descendant-div1 +PASS Fragment Element.matches: Descendant combinator, matching element with id that is a descendant of an element with id (with no refNodes): #descendant #descendant-div2 +PASS Fragment Element.matches: Descendant combinator, matching element with class that is a descendant of an element with id (with no refNodes): #descendant .descendant-div2 +PASS Fragment Element.matches: Descendant combinator, matching element with class that is a descendant of an element with class (with no refNodes): .descendant-div1 .descendant-div3 +PASS Fragment Element.matches: Descendant combinator, whitespace characters (with no refNodes): #descendant \r +#descendant-div2 +FAIL Fragment Element.matches: Descendant combinator '>>', matching element that is a descendant of an element with id (with no refNodes): #descendant>>div Failed to execute 'matches' on 'Element': '#descendant>>div' is not a valid selector. +FAIL Fragment Element.matches: Descendant combinator '>>', matching element with id that is a descendant of an element (with no refNodes): div>>#descendant-div1 Failed to execute 'matches' on 'Element': 'div>>#descendant-div1' is not a valid selector. +FAIL Fragment Element.matches: Descendant combinator '>>', matching element with id that is a descendant of an element with id (with no refNodes): #descendant>>#descendant-div2 Failed to execute 'matches' on 'Element': '#descendant>>#descendant-div2' is not a valid selector. +FAIL Fragment Element.matches: Descendant combinator '>>', matching element with class that is a descendant of an element with id (with no refNodes): #descendant>>.descendant-div2 Failed to execute 'matches' on 'Element': '#descendant>>.descendant-div2' is not a valid selector. +FAIL Fragment Element.matches: Descendant combinator '>>', matching element with class that is a descendant of an element with class (with no refNodes): .descendant-div1>>.descendant-div3 Failed to execute 'matches' on 'Element': '.descendant-div1>>.descendant-div3' is not a valid selector. +PASS Fragment Element.matches: Child combinator, matching element that is a child of an element with id (with no refNodes): #child>div +PASS Fragment Element.matches: Child combinator, matching element with id that is a child of an element (with no refNodes): div>#child-div1 +PASS Fragment Element.matches: Child combinator, matching element with id that is a child of an element with id (with no refNodes): #child>#child-div1 +PASS Fragment Element.matches: Child combinator, matching element with id that is a child of an element with class (with no refNodes): #child-div1>.child-div2 +PASS Fragment Element.matches: Child combinator, matching element with class that is a child of an element with class (with no refNodes): .child-div1>.child-div2 +PASS Fragment Element.matches: Child combinator, surrounded by whitespace (with no refNodes): #child-div1 \r +> \r +#child-div2 +PASS Fragment Element.matches: Child combinator, whitespace after (with no refNodes): #child-div1> \r +#child-div2 +PASS Fragment Element.matches: Child combinator, whitespace before (with no refNodes): #child-div1 \r +>#child-div2 +PASS Fragment Element.matches: Child combinator, no whitespace (with no refNodes): #child-div1>#child-div2 +PASS Fragment Element.matches: Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id (with no refNodes): #adjacent-div2+div +PASS Fragment Element.matches: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element (with no refNodes): div+#adjacent-div4 +PASS Fragment Element.matches: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id (with no refNodes): #adjacent-div2+#adjacent-div4 +PASS Fragment Element.matches: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id (with no refNodes): #adjacent-div2+.adjacent-div4 +PASS Fragment Element.matches: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class (with no refNodes): .adjacent-div2+.adjacent-div4 +PASS Fragment Element.matches: Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element (with no refNodes): #adjacent div+p +PASS Fragment Element.matches: Adjacent sibling combinator, surrounded by whitespace (with no refNodes): #adjacent-p2 \r ++ \r +#adjacent-p3 +PASS Fragment Element.matches: Adjacent sibling combinator, whitespace after (with no refNodes): #adjacent-p2+ \r +#adjacent-p3 +PASS Fragment Element.matches: Adjacent sibling combinator, whitespace before (with no refNodes): #adjacent-p2 \r ++#adjacent-p3 +PASS Fragment Element.matches: Adjacent sibling combinator, no whitespace (with no refNodes): #adjacent-p2+#adjacent-p3 +PASS Fragment Element.matches: General sibling combinator, matching element that is a sibling of an element with id (with no refNodes): #sibling-div2~div +PASS Fragment Element.matches: General sibling combinator, matching element with id that is a sibling of an element (with no refNodes): div~#sibling-div4 +PASS Fragment Element.matches: General sibling combinator, matching element with id that is a sibling of an element with id (with no refNodes): #sibling-div2~#sibling-div4 +PASS Fragment Element.matches: General sibling combinator, matching element with class that is a sibling of an element with id (with no refNodes): #sibling-div2~.sibling-div +PASS Fragment Element.matches: General sibling combinator, matching p element that is a sibling of a div element (with no refNodes): #sibling div~p +PASS Fragment Element.matches: General sibling combinator, surrounded by whitespace (with no refNodes): #sibling-p2 \r +~ \r +#sibling-p3 +PASS Fragment Element.matches: General sibling combinator, whitespace after (with no refNodes): #sibling-p2~ \r +#sibling-p3 +PASS Fragment Element.matches: General sibling combinator, whitespace before (with no refNodes): #sibling-p2 \r +~#sibling-p3 +PASS Fragment Element.matches: General sibling combinator, no whitespace (with no refNodes): #sibling-p2~#sibling-p3 +PASS Fragment Element.matches: Syntax, group of selectors separator, surrounded by whitespace (with no refNodes): #group em \r +, \r +#group strong +PASS Fragment Element.matches: Syntax, group of selectors separator, whitespace after (with no refNodes): #group em, \r +#group strong +PASS Fragment Element.matches: Syntax, group of selectors separator, whitespace before (with no refNodes): #group em \r +,#group strong +PASS Fragment Element.matches: Syntax, group of selectors separator, no whitespace (with no refNodes): #group em,#group strong +FAIL In-document Element.matches: Universal selector, matching all children of the specified reference element (with refNode Element): >* Failed to execute 'matches' on 'Element': '>*' is not a valid selector. +FAIL In-document Element.matches: Universal selector, matching all grandchildren of the specified reference element (with refNode Element): >*>* Failed to execute 'matches' on 'Element': '>*>*' is not a valid selector. +FAIL In-document Element.matches: Universal selector, matching all descendants of the specified reference element (with refNode Element): * assert_false: The element #universal should not match the selector. expected false got true +PASS In-document Element.matches: Attribute presence selector, matching align attribute with value (with refNode Element): .attr-presence-div1[align] +PASS In-document Element.matches: Attribute presence selector, matching align attribute with empty value (with refNode Element): .attr-presence-div2[align] +PASS In-document Element.matches: Attribute presence selector, matching title attribute, case insensitivity (with refNode Element): [TiTlE] +PASS In-document Element.matches: Attribute presence selector, matching custom data-* attribute (with refNode Element): [data-attr-presence] +PASS In-document Element.matches: Attribute presence selector, matching attribute with non-ASCII characters (with refNode Element): ul[data-中文] +PASS In-document Element.matches: Attribute presence selector, matching option with selected attribute (with refNode Element): #attr-presence-select2 option[selected] +PASS In-document Element.matches: Attribute presence selector, matching multiple options with selected attributes (with refNode Element): #attr-presence-select3 option[selected] +PASS In-document Element.matches: Attribute value selector, matching align attribute with value (with refNode Element): [align="center"] +PASS In-document Element.matches: Attribute value selector, matching align attribute with empty value (with refNode Element): [align=""] +PASS In-document Element.matches: Attribute value selector, matching custom data-* attribute with unicode escaped value (with refNode Element): [data-attr-value="\e9"] +PASS In-document Element.matches: Attribute value selector, matching custom data-* attribute with escaped character (with refNode Element): [data-attr-value_foo="\e9"] +PASS In-document Element.matches: Attribute value selector with single-quoted value, matching multiple inputs with type attributes (with refNode Element): input[type='hidden'],#attr-value input[type='radio'] +PASS In-document Element.matches: Attribute value selector with double-quoted value, matching multiple inputs with type attributes (with refNode Element): input[type="hidden"],#attr-value input[type='radio'] +PASS In-document Element.matches: Attribute value selector with unquoted value, matching multiple inputs with type attributes (with refNode Element): input[type=hidden],#attr-value input[type=radio] +PASS In-document Element.matches: Attribute value selector, matching attribute with value using non-ASCII characters (with refNode Element): [data-attr-value=中文] +PASS In-document Element.matches: Attribute whitespace-separated list selector, matching class attribute with value (with refNode Element): [class~="div1"] +PASS In-document Element.matches: Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value (with refNode Element): [data-attr-whitespace~="\0000e9"] +PASS In-document Element.matches: Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character (with refNode Element): [data-attr-whitespace_foo~="\e9"] +PASS In-document Element.matches: Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes (with refNode Element): a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow'] +PASS In-document Element.matches: Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes (with refNode Element): a[rel~="bookmark"],#attr-whitespace a[rel~='nofollow'] +PASS In-document Element.matches: Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes (with refNode Element): a[rel~=bookmark], #attr-whitespace a[rel~=nofollow] +PASS In-document Element.matches: Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters (with refNode Element): [title~=中文] +PASS In-document Element.matches: Attribute hyphen-separated list selector, matching lang attribute with exact value (with refNode Element): #attr-hyphen-div2[lang|="fr"] +PASS In-document Element.matches: Attribute hyphen-separated list selector, matching lang attribute with partial value (with refNode Element): #attr-hyphen-div3[lang|="en"] +PASS In-document Element.matches: Attribute begins with selector, matching href attributes beginning with specified substring (with refNode Element): a[href^="http://www"] +PASS In-document Element.matches: Attribute begins with selector, matching lang attributes beginning with specified substring, (with refNode Element): [lang^="en-"] +PASS In-document Element.matches: Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring (with refNode Element): [class^=' apple'] +PASS In-document Element.matches: Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring (with refNode Element): [class^=" apple"] +PASS In-document Element.matches: Attribute ends with selector, matching href attributes ending with specified substring (with refNode Element): a[href$=".org"] +PASS In-document Element.matches: Attribute ends with selector, matching lang attributes ending with specified substring, (with refNode Element): [lang$="-CH"] +PASS In-document Element.matches: Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring (with refNode Element): [class$='apple '] +PASS In-document Element.matches: Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring (with refNode Element): [class$="apple "] +PASS In-document Element.matches: Attribute contains selector, matching href attributes beginning with specified substring (with refNode Element): a[href*="http://www"] +PASS In-document Element.matches: Attribute contains selector, matching href attributes ending with specified substring (with refNode Element): a[href*=".org"] +PASS In-document Element.matches: Attribute contains selector, matching href attributes containing specified substring (with refNode Element): a[href*=".example."] +PASS In-document Element.matches: Attribute contains selector, matching lang attributes beginning with specified substring, (with refNode Element): [lang*="en-"] +PASS In-document Element.matches: Attribute contains selector, matching lang attributes ending with specified substring, (with refNode Element): [lang*="-CH"] +PASS In-document Element.matches: Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring (with refNode Element): [class*=' apple'] +PASS In-document Element.matches: Attribute contains selector with single-quoted value, matching class attribute ending with specified substring (with refNode Element): [class*='orange '] +PASS In-document Element.matches: Attribute contains selector with single-quoted value, matching class attribute containing specified substring (with refNode Element): [class*='ple banana ora'] +PASS In-document Element.matches: Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring (with refNode Element): [class*=" apple"] +PASS In-document Element.matches: Attribute contains selector with double-quoted value, matching class attribute ending with specified substring (with refNode Element): [class*="orange "] +PASS In-document Element.matches: Attribute contains selector with double-quoted value, matching class attribute containing specified substring (with refNode Element): [class*="ple banana ora"] +PASS In-document Element.matches: Attribute contains selector with unquoted value, matching class attribute beginning with specified substring (with refNode Element): [class*= apple] +PASS In-document Element.matches: Attribute contains selector with unquoted value, matching class attribute ending with specified substring (with refNode Element): [class*=orange ] +PASS In-document Element.matches: Attribute contains selector with unquoted value, matching class attribute containing specified substring (with refNode Element): [class*= banana ] +PASS In-document Element.matches: :nth-child selector, matching the third child element (with refNode Element): :nth-child(3) +PASS In-document Element.matches: :nth-child selector, matching every third child element (with refNode Element): li:nth-child(3n) +PASS In-document Element.matches: :nth-child selector, matching every second child element, starting from the fourth (with refNode Element): li:nth-child(2n+4) +PASS In-document Element.matches: :nth-child selector, matching every fourth child element, starting from the third (with refNode Element): :nth-child(4n-1) +PASS In-document Element.matches: :nth-last-child selector, matching the third last child element (with refNode Element): :nth-last-child(3) +PASS In-document Element.matches: :nth-last-child selector, matching every third child element from the end (with refNode Element): li:nth-last-child(3n) +PASS In-document Element.matches: :nth-last-child selector, matching every second child element from the end, starting from the fourth last (with refNode Element): li:nth-last-child(2n+4) +PASS In-document Element.matches: :nth-last-child selector, matching every fourth element from the end, starting from the third last (with refNode Element): :nth-last-child(4n-1) +PASS In-document Element.matches: :nth-of-type selector, matching the third em element (with refNode Element): em:nth-of-type(3) +PASS In-document Element.matches: :nth-of-type selector, matching every second element of their type (with refNode Element): :nth-of-type(2n) +PASS In-document Element.matches: :nth-of-type selector, matching every second elemetn of their type, starting from the first (with refNode Element): span:nth-of-type(2n-1) +PASS In-document Element.matches: :nth-last-of-type selector, matching the thrid last em element (with refNode Element): em:nth-last-of-type(3) +PASS In-document Element.matches: :nth-last-of-type selector, matching every second last element of their type (with refNode Element): :nth-last-of-type(2n) +PASS In-document Element.matches: :nth-last-of-type selector, matching every second last element of their type, starting from the last (with refNode Element): span:nth-last-of-type(2n-1) +PASS In-document Element.matches: :first-of-type selector, matching the first em element (with refNode Element): em:first-of-type +PASS In-document Element.matches: :first-of-type selector, matching the first of every type of element (with refNode Element): :first-of-type +PASS In-document Element.matches: :first-of-type selector, matching the first td element in each table row (with refNode Element): tr :first-of-type +PASS In-document Element.matches: :last-of-type selector, matching the last em elemnet (with refNode Element): em:last-of-type +PASS In-document Element.matches: :last-of-type selector, matching the last of every type of element (with refNode Element): :last-of-type +PASS In-document Element.matches: :last-of-type selector, matching the last td element in each table row (with refNode Element): tr :last-of-type +PASS In-document Element.matches: :first-child pseudo-class selector, matching first child div element (with refNode Element): div:first-child +PASS In-document Element.matches: :first-child pseudo-class selector, matching first-child of multiple elements (with refNode Element): span:first-child +PASS In-document Element.matches: :last-child pseudo-class selector, matching last child div element (with refNode Element): div:last-child +PASS In-document Element.matches: :last-child pseudo-class selector, matching first-child of multiple elements (with refNode Element): span:last-child +PASS In-document Element.matches: :pseudo-only-child pseudo-class selector, matching all only-child elements (with refNode Element): :only-child +PASS In-document Element.matches: :pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type (with refNode Element): :only-of-type +PASS In-document Element.matches: :pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type (with refNode Element): em:only-of-type +PASS In-document Element.matches: :empty pseudo-class selector, matching empty p elements (with refNode Element): p:empty +PASS In-document Element.matches: :empty pseudo-class selector, matching all empty elements (with refNode Element): :empty +PASS In-document Element.matches: :link and :visited pseudo-class selectors, matching a and area elements with href attributes (with refNode Element): :link, #pseudo-link :visited +FAIL In-document Element.matches: :link and :visited pseudo-class selectors, matching link elements with href attributes (with refNode Element): :link, #head :visited assert_true: The element #pseudo-link-link1 should match the selector. expected true got false +PASS In-document Element.matches: :lang pseudo-class selector, matching inherited language (1) (with no refNodes): #pseudo-lang-div1:lang(en) +PASS In-document Element.matches: :lang pseudo-class selector, matching specified language with exact value (1) (with no refNodes): #pseudo-lang-div2:lang(fr) +PASS In-document Element.matches: :lang pseudo-class selector, matching specified language with partial value (1) (with no refNodes): #pseudo-lang-div3:lang(en) +PASS In-document Element.matches: :enabled pseudo-class selector, matching all enabled form controls (1) (with no refNodes): #pseudo-ui :enabled +PASS In-document Element.matches: :enabled pseudo-class selector, matching all disabled form controls (1) (with no refNodes): #pseudo-ui :disabled +PASS In-document Element.matches: :checked pseudo-class selector, matching checked radio buttons and checkboxes (1) (with no refNodes): #pseudo-ui :checked +PASS In-document Element.matches: :not pseudo-class selector, matching (1) (with no refNodes): #not>:not(div) +PASS In-document Element.matches: :not pseudo-class selector, matching (1) (with no refNodes): #not * :not(:first-child) +PASS In-document Element.matches: Class selector, matching element with specified class (1) (with no refNodes): .class-p +PASS In-document Element.matches: Class selector, chained, matching only elements with all specified classes (1) (with no refNodes): #class .apple.orange.banana +PASS In-document Element.matches: Class Selector, chained, with type selector (1) (with no refNodes): div.apple.banana.orange +PASS In-document Element.matches: Class selector, matching element with class value using non-ASCII characters (2) (with no refNodes): .台北Táiběi +PASS In-document Element.matches: Class selector, matching multiple elements with class value using non-ASCII characters (1) (with no refNodes): .台北 +PASS In-document Element.matches: Class selector, chained, matching element with multiple class values using non-ASCII characters (2) (with no refNodes): .台北Táiběi.台北 +PASS In-document Element.matches: Class selector, matching element with class with escaped character (1) (with no refNodes): .foo\:bar +PASS In-document Element.matches: Class selector, matching element with class with escaped character (1) (with no refNodes): .test\.foo\[5\]bar +PASS In-document Element.matches: ID selector, matching element with specified id (1) (with no refNodes): #id #id-div1 +PASS In-document Element.matches: ID selector, chained, matching element with specified id (1) (with no refNodes): #id-div1, #id-div1 +PASS In-document Element.matches: ID selector, chained, matching element with specified id (1) (with no refNodes): #id-div1, #id-div2 +PASS In-document Element.matches: ID Selector, chained, with type selector (1) (with no refNodes): div#id-div1, div#id-div2 +PASS In-document Element.matches: ID selector, matching multiple elements with duplicate id (1) (with no refNodes): #id-li-duplicate +PASS In-document Element.matches: ID selector, matching id value using non-ASCII characters (3) (with no refNodes): #台北Táiběi +PASS In-document Element.matches: ID selector, matching id value using non-ASCII characters (4) (with no refNodes): #台北 +PASS In-document Element.matches: ID selector, matching id values using non-ASCII characters (2) (with no refNodes): #台北Táiběi, #台北 +PASS In-document Element.matches: Descendant combinator, matching element that is a descendant of an element with id (1) (with no refNodes): #descendant div +PASS In-document Element.matches: Descendant combinator, matching element with id that is a descendant of an element (1) (with no refNodes): body #descendant-div1 +PASS In-document Element.matches: Descendant combinator, matching element with id that is a descendant of an element (1) (with no refNodes): div #descendant-div1 +PASS In-document Element.matches: Descendant combinator, matching element with id that is a descendant of an element with id (1) (with no refNodes): #descendant #descendant-div2 +PASS In-document Element.matches: Descendant combinator, matching element with class that is a descendant of an element with id (1) (with no refNodes): #descendant .descendant-div2 +PASS In-document Element.matches: Descendant combinator, matching element with class that is a descendant of an element with class (1) (with no refNodes): .descendant-div1 .descendant-div3 +PASS In-document Element.matches: Descendant combinator, whitespace characters (1) (with no refNodes): #descendant \r +#descendant-div2 +FAIL In-document Element.matches: Descendant combinator '>>', matching element that is a descendant of an element with id (1) (with no refNodes): #descendant>>div Failed to execute 'matches' on 'Element': '#descendant>>div' is not a valid selector. +FAIL In-document Element.matches: Descendant combinator '>>', matching element with id that is a descendant of an element (1) (with no refNodes): body>>#descendant-div1 Failed to execute 'matches' on 'Element': 'body>>#descendant-div1' is not a valid selector. +FAIL In-document Element.matches: Descendant combinator '>>', matching element with id that is a descendant of an element (1) (with no refNodes): div>>#descendant-div1 Failed to execute 'matches' on 'Element': 'div>>#descendant-div1' is not a valid selector. +FAIL In-document Element.matches: Descendant combinator '>>', matching element with id that is a descendant of an element with id (1) (with no refNodes): #descendant>>#descendant-div2 Failed to execute 'matches' on 'Element': '#descendant>>#descendant-div2' is not a valid selector. +FAIL In-document Element.matches: Descendant combinator '>>', matching element with class that is a descendant of an element with id (1) (with no refNodes): #descendant>>.descendant-div2 Failed to execute 'matches' on 'Element': '#descendant>>.descendant-div2' is not a valid selector. +FAIL In-document Element.matches: Descendant combinator, '>>', matching element with class that is a descendant of an element with class (1) (with no refNodes): .descendant-div1>>.descendant-div3 Failed to execute 'matches' on 'Element': '.descendant-div1>>.descendant-div3' is not a valid selector. +PASS In-document Element.matches: Child combinator, matching element that is a child of an element with id (1) (with no refNodes): #child>div +PASS In-document Element.matches: Child combinator, matching element with id that is a child of an element (1) (with no refNodes): div>#child-div1 +PASS In-document Element.matches: Child combinator, matching element with id that is a child of an element with id (1) (with no refNodes): #child>#child-div1 +PASS In-document Element.matches: Child combinator, matching element with id that is a child of an element with class (1) (with no refNodes): #child-div1>.child-div2 +PASS In-document Element.matches: Child combinator, matching element with class that is a child of an element with class (1) (with no refNodes): .child-div1>.child-div2 +PASS In-document Element.matches: Child combinator, surrounded by whitespace (1) (with no refNodes): #child-div1 \r +> \r +#child-div2 +PASS In-document Element.matches: Child combinator, whitespace after (1) (with no refNodes): #child-div1> \r +#child-div2 +PASS In-document Element.matches: Child combinator, whitespace before (1) (with no refNodes): #child-div1 \r +>#child-div2 +PASS In-document Element.matches: Child combinator, no whitespace (1) (with no refNodes): #child-div1>#child-div2 +PASS In-document Element.matches: Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id (1) (with no refNodes): #adjacent-div2+div +PASS In-document Element.matches: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element (1) (with no refNodes): div+#adjacent-div4 +PASS In-document Element.matches: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id (1) (with no refNodes): #adjacent-div2+#adjacent-div4 +PASS In-document Element.matches: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id (1) (with no refNodes): #adjacent-div2+.adjacent-div4 +PASS In-document Element.matches: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class (1) (with no refNodes): .adjacent-div2+.adjacent-div4 +PASS In-document Element.matches: Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element (1) (with no refNodes): #adjacent div+p +PASS In-document Element.matches: Adjacent sibling combinator, surrounded by whitespace (1) (with no refNodes): #adjacent-p2 \r ++ \r +#adjacent-p3 +PASS In-document Element.matches: Adjacent sibling combinator, whitespace after (1) (with no refNodes): #adjacent-p2+ \r +#adjacent-p3 +PASS In-document Element.matches: Adjacent sibling combinator, whitespace before (1) (with no refNodes): #adjacent-p2 \r ++#adjacent-p3 +PASS In-document Element.matches: Adjacent sibling combinator, no whitespace (1) (with no refNodes): #adjacent-p2+#adjacent-p3 +PASS In-document Element.matches: General sibling combinator, matching element that is a sibling of an element with id (1) (with no refNodes): #sibling-div2~div +PASS In-document Element.matches: General sibling combinator, matching element with id that is a sibling of an element (1) (with no refNodes): div~#sibling-div4 +PASS In-document Element.matches: General sibling combinator, matching element with id that is a sibling of an element with id (1) (with no refNodes): #sibling-div2~#sibling-div4 +PASS In-document Element.matches: General sibling combinator, matching element with class that is a sibling of an element with id (1) (with no refNodes): #sibling-div2~.sibling-div +PASS In-document Element.matches: General sibling combinator, matching p element that is a sibling of a div element (1) (with no refNodes): #sibling div~p +PASS In-document Element.matches: General sibling combinator, surrounded by whitespace (1) (with no refNodes): #sibling-p2 \r +~ \r +#sibling-p3 +PASS In-document Element.matches: General sibling combinator, whitespace after (1) (with no refNodes): #sibling-p2~ \r +#sibling-p3 +PASS In-document Element.matches: General sibling combinator, whitespace before (1) (with no refNodes): #sibling-p2 \r +~#sibling-p3 +PASS In-document Element.matches: General sibling combinator, no whitespace (1) (with no refNodes): #sibling-p2~#sibling-p3 +PASS In-document Element.matches: Syntax, group of selectors separator, surrounded by whitespace (1) (with no refNodes): #group em \r +, \r +#group strong +PASS In-document Element.matches: Syntax, group of selectors separator, whitespace after (1) (with no refNodes): #group em, \r +#group strong +PASS In-document Element.matches: Syntax, group of selectors separator, whitespace before (1) (with no refNodes): #group em \r +,#group strong +PASS In-document Element.matches: Syntax, group of selectors separator, no whitespace (1) (with no refNodes): #group em,#group strong +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Element-matches.html b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Element-matches.html new file mode 100644 index 0000000..e04c0f9d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Element-matches.html
@@ -0,0 +1,87 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>Selectors-API Level 2 Test Suite: HTML with Selectors Level 3</title> +<!-- Selectors API Test Suite Version 3 --> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/dom/nodes/selectors.js"></script> +<script src="/dom/nodes/ParentNode-querySelector-All.js"></script> +<script src="Element-matches.js"></script> +<style>iframe { visibility: hidden; position: absolute; }</style> + +<div id="log">This test requires JavaScript.</div> + +<script> +async_test(function() { + var frame = document.createElement("iframe"); + frame.onload = this.step_func_done(init); + frame.src = "/dom/nodes/ParentNode-querySelector-All-content.html#target"; + document.body.appendChild(frame); +}); + +function init(e) { + /* + * This test suite tests Selectors API methods in 4 different contexts: + * 1. Document node + * 2. In-document Element node + * 3. Detached Element node (an element with no parent, not in the document) + * 4. Document Fragment node + * + * For each context, the following tests are run: + * + * The interface check tests ensure that each type of node exposes the Selectors API methods. + * + * The matches() tests are run + * All the selectors tested for both the valid and invalid selector tests are found in selectors.js. + * See comments in that file for documentation of the format used. + * + * The level2-lib.js file contains all the common test functions for running each of the aforementioned tests + */ + + var docType = "html"; // Only run tests suitable for HTML + + // Prepare the nodes for testing + var doc = e.target.contentDocument; // Document Node tests + + var element = doc.getElementById("root"); // In-document Element Node tests + + //Setup the namespace tests + setupSpecialElements(doc, element); + + var outOfScope = element.cloneNode(true); // Append this to the body before running the in-document + // Element tests, but after running the Document tests. This + // tests that no elements that are not descendants of element + // are selected. + + traverse(outOfScope, function(elem) { // Annotate each element as being a clone; used for verifying + elem.setAttribute("data-clone", ""); // that none of these elements ever match. + }); + + + var detached = element.cloneNode(true); // Detached Element Node tests + + var fragment = doc.createDocumentFragment(); // Fragment Node tests + fragment.appendChild(element.cloneNode(true)); + + // Setup Tests + interfaceCheckMatches("Document", doc); + interfaceCheckMatches("Detached Element", detached); + interfaceCheckMatches("Fragment", fragment); + interfaceCheckMatches("In-document Element", element); + + runSpecialMatchesTests("DIV Element", element); + runSpecialMatchesTests("NULL Element", document.createElement("null")); + runSpecialMatchesTests("UNDEFINED Element", document.createElement("undefined")); + + runInvalidSelectorTestMatches("Document", doc, invalidSelectors); + runInvalidSelectorTestMatches("Detached Element", detached, invalidSelectors); + runInvalidSelectorTestMatches("Fragment", fragment, invalidSelectors); + runInvalidSelectorTestMatches("In-document Element", element, invalidSelectors); + + runMatchesTest("In-document", doc, validSelectors, "html"); + runMatchesTest("Detached", detached, validSelectors, "html"); + runMatchesTest("Fragment", fragment, validSelectors, "html"); + + runMatchesTest("In-document", doc, scopedSelectors, "html"); +} +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-labels.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-labels.html index 1f3202c9..04ae026 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-labels.html +++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-labels.html
@@ -4,33 +4,32 @@ <script src="/resources/testharnessreport.js"></script> <script src="resources/encodings.js"></script> <script> -var tests = []; -setup(function() { - var whitespace = [' ', '\t', '\n', '\f', '\r']; - encodings_table.forEach(function(section) { - section.encodings.filter(function(encoding) { - return encoding.name !== 'replacement'; - }).forEach(function(encoding) { - var name = encoding.name; - encoding.labels.forEach(function(label) { - tests.push([label, encoding.name]); +var whitespace = [' ', '\t', '\n', '\f', '\r']; +encodings_table.forEach(function(section) { + section.encodings.filter(function(encoding) { + return encoding.name !== 'replacement'; + }).forEach(function(encoding) { + encoding.labels.forEach(function(label) { + test(function(t) { + assert_equals( + new TextDecoder(label).encoding, encoding.name, + 'label for encoding should match'); + assert_equals( + new TextDecoder(label.toUpperCase()).encoding, encoding.name, + 'label matching should be case-insensitive'); whitespace.forEach(function(ws) { - tests.push([ws + label, encoding.name]); - tests.push([label + ws, encoding.name]); - tests.push([ws + label + ws, encoding.name]); + assert_equals( + new TextDecoder(ws + label).encoding, encoding.name, + 'label for encoding with leading whitespace should match'); + assert_equals( + new TextDecoder(label + ws).encoding, encoding.name, + 'label for encoding with trailing whitespace should match'); + assert_equals( + new TextDecoder(ws + label + ws).encoding, encoding.name, + 'label for encoding with surrounding whitespace should match'); }); - }); + }, label + ' => ' + encoding.name); }); }); }); - -tests.forEach(function(t) { - var input = t[0], output = t[1]; - test(function() { - assert_equals(new TextDecoder(input).encoding, output, - 'label for encoding should match'); - assert_equals(new TextDecoder(input.toUpperCase()).encoding, output, - 'label matching should be case-insensitive'); - }, format_value(input) + " => " + format_value(output)); -}); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html new file mode 100644 index 0000000..e3da59e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html
@@ -0,0 +1,67 @@ +<!DOCTYPE html> +<meta name=timeout content=long> +<title>Precedence of scroll restoration mode over fragment scrolling in cross-origin history traversal</title> +<style> + iframe { + height: 300px; + width: 300px; + } +</style> + +<body> + <iframe></iframe> +</body> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="text/javascript"> + 'use strict'; + + // The test does the following navigation steps for iframe + // 1. load page-with-fragment.html#fragment + // 2. load blank1 + // 3. go back to page-with-fragment.html + async_test(function(t) { + var iframe = document.querySelector('iframe'); + var baseURL = location.href.substring(0, location.href.lastIndexOf('/')); + + var steps = [ + function() { + iframe.src = 'resources/page-with-fragment.html#fragment'; + }, function() { + assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/page-with-fragment.html#fragment', 'should be on page-with-fragment page'); + // wait one animation frame to ensure layout is run and fragment scrolling is complete + iframe.contentWindow.requestAnimationFrame(function() { + assert_equals(iframe.contentWindow.scrollY, 800, 'should scroll to fragment'); + + iframe.contentWindow.history.scrollRestoration = 'manual'; + assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual'); + setTimeout(next, 0); + }); + }, function() { + // navigate to a new page from a different origin + iframe.src = iframe.src.replace("http://", "http://www.").replace("page-with-fragment.html#fragment", "blank1.html"); + }, function() { + // going back causes the iframe to traverse back + history.back(); + }, function() { + // coming back from history, scrollRestoration should be set to manual and respected + assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/page-with-fragment.html#fragment', 'should be back on page-with-fragment page'); + iframe.contentWindow.requestAnimationFrame(function() { + assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual', 'navigating back should retain scrollRestoration value'); + assert_equals(iframe.contentWindow.scrollX, 0, 'should not scroll to fragment'); + assert_equals(iframe.contentWindow.scrollY, 0, 'should not scroll to fragment'); + t.done(); + }); + } + ]; + + var stepCount = 0; + var next = t.step_func(function() { + steps[stepCount++](); + }); + + iframe.onload = next; + next(); + }, 'Manual scroll restoration should take precedent over scrolling to fragment in cross origin navigation'); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html new file mode 100644 index 0000000..d837b8f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html
@@ -0,0 +1,54 @@ +<!DOCTYPE html> +<style> + body { + height: 2000px; + width: 2000px; + } + + #fragment { + position: absolute; + top: 800px; + background-color: #faa; + display: block; + height: 100px; + width: 100px; + } +</style> + +<body> + <a id="fragment" name="fragment" class='box'></a> +</body> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="text/javascript"> + 'use strict'; + + async_test(function(t) { + history.scrollRestoration = 'manual'; + assert_equals(history.scrollRestoration, 'manual'); + + location.hash = '#fragment'; + assert_equals(window.scrollY, 800, 'new navigations should scroll to fragment'); + + // create a new entry and reset the scroll before verification + history.pushState(null, null, '#done'); + window.scrollTo(0, 0); + assert_equals(window.scrollY, 0, 'should reset scroll before verification'); + + setTimeout(function() { + // setup verification + window.addEventListener('hashchange', t.step_func(function() { + assert_equals(location.hash, '#fragment'); + assert_equals(history.scrollRestoration, 'manual'); + // navigating back should give precedent to history restoration which is 'manual' + assert_equals(window.scrollX, 0, 'should not scroll to fragment'); + assert_equals(window.scrollY, 0, 'should not scroll to fragment'); + t.done(); + })); + // kick off verification + window.history.back(); + }, 0); + + }, 'Manual scroll restoration should take precedent over scrolling to fragment in cross doc navigation'); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html new file mode 100644 index 0000000..87a337b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html
@@ -0,0 +1,71 @@ +<!DOCTYPE html> +<meta name=timeout content=long> +<title>Correct behaviour of scroll restoration mode is cross origin history traversal</title> + +<style> + iframe { + height: 300px; + width: 300px; + } +</style> + +<body> + <iframe></iframe> +</body> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="text/javascript"> + 'use strict'; + + // The test does the following navigation steps for iframe + // 1. load blank1 + // 2. load blank2 + // 3. go back to blank1 + async_test(function(t) { + var iframe = document.querySelector('iframe'); + var baseURL = location.href.substring(0, location.href.lastIndexOf('/')); + + var steps = [ + function() { + iframe.src = 'resources/blank1.html'; + }, + function() { + assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/blank1.html', 'should be on first blank page'); + iframe.contentWindow.history.scrollRestoration = 'manual'; + assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual'); + iframe.contentWindow.scrollTo(500, 500); + assert_equals(iframe.contentWindow.scrollX, 500, 'scripted scrolling should take effect'); + assert_equals(iframe.contentWindow.scrollY, 500, 'scripted scrolling should take effect'); + setTimeout(next, 0); + }, + function() { + // navigate to new page + iframe.src = 'resources/blank2.html'; + }, + function() { + assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/blank2.html', 'should be on second blank page'); + assert_equals(iframe.contentWindow.history.scrollRestoration, 'auto', 'new page loads should set scrollRestoration to "auto"'); + setTimeout(next, 0); + }, function() { + iframe.contentWindow.history.back(); + }, function() { + // coming back scrollRestoration should be restored to 'manual' and respected + assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/blank1.html', 'should be back on first blank page'); + assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual', 'navigating back should retain scrollRestoration value'); + assert_equals(iframe.contentWindow.scrollX, 0, 'horizontal scroll offset should not be restored'); + assert_equals(iframe.contentWindow.scrollY, 0, 'vertical scroll offset should not be restored'); + t.done(); + } + ]; + + var stepCount = 0; + var next = t.step_func(function() { + steps[stepCount++](); + }); + + iframe.onload = next; + next(); + }, 'Navigating to new page should reset to "auto" and navigating back should restore and respect scroll restoration mode'); + +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/read-text/load-text-plain.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/read-text/load-text-plain.html new file mode 100644 index 0000000..bd4fd78 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/read-text/load-text-plain.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<title>Page load processing model for text files</title> +<link rel="author" title="Ms2ger" href="ms2ger@gmail.com"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#read-text"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +var t = async_test("Checking document metadata for text file"); +var tD = async_test("Checking DOM for text file"); +var tC = async_test("Checking contents for text file"); +var iframe = document.body.appendChild(document.createElement("iframe")); +iframe.onload = function(e) { + var doc = iframe.contentDocument; + t.step(function() { + assert_equals(doc.compatMode, "BackCompat"); + assert_equals(doc.contentType, "text/plain"); + assert_equals(doc.doctype, null); + t.done(); + }) + tD.step(function() { + assert_equals(doc.childNodes.length, 1, "Document should have 1 child") + assert_equals(doc.documentElement.tagName, "HTML"); + assert_equals(doc.documentElement.childNodes.length, 2, + "Root element should have 2 children") + assert_equals(doc.documentElement.firstChild.tagName, "HEAD"); + assert_equals(doc.documentElement.lastChild.tagName, "BODY"); + assert_equals(doc.documentElement.lastChild.childNodes.length, 1, + "Body element should have 1 child") + assert_equals(doc.documentElement.lastChild.firstChild.tagName, "PRE"); + tD.done(); + }) + tC.step(function() { + assert_equals(doc.documentElement.lastChild.firstChild.firstChild.data, + "This is a sample text/plain document.\n\nThis is not an HTML document.\n\n"); + tC.done(); + }) +}; +iframe.src = "../../../../common/text-plain.txt"; +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-history-interface/008.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-history-interface/008.html new file mode 100644 index 0000000..c8071e31 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-history-interface/008.html
@@ -0,0 +1,40 @@ +<!doctype html> +<html> + +<!-- configure this test below to point to the script --> + + <head> + <title>history.pushState/replaceState resolving</title> + <script type="text/javascript" src="/resources/testharness.js"></script> + <script type="text/javascript" src="/resources/testharnessreport.js"></script> + </head> + <body> + + <p></p> + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + <script type="text/javascript"> + +/* +Location of the script (which must be hosted on a separate domain from this test) containing the test code: +var beforehref = location.href; +test(function () { + history.pushState('','','/testing_ignore_me_404'); + assert_equals(location.href,beforehref.replace(/^(\w*:\/\/[^\/]*\/)[\w\W]*$/,'$1testing_ignore_me_404')); +}, 'history.pushState URL resolving should be done relative to the document, not the script'); +test(function () { + history.replaceState('','','/testing_ignore_me_404_2'); + assert_equals(location.href,beforehref.replace(/^(\w*:\/\/[^\/]*\/)[\w\W]*$/,'$1testing_ignore_me_404_2')); +}, 'history.replaceState URL resolving should be done relative to the document, not the script'); +*/ +var scriptlocation = 'http://www.' + location.host + location.pathname.split("/").slice(0,-1).join("/") + "/008.js"; + +if( location.protocol == 'file:' ) { + document.getElementsByTagName('p')[0].innerHTML = 'ERROR: This test cannot be run from file: (URL resolving will not work). It must be loaded over HTTP.'; +} else { + document.write('<script type="text\/javascript" src="'+scriptlocation+'"><\/script>'); +} + </script> + + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub-expected.txt new file mode 100644 index 0000000..881c688 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub-expected.txt
@@ -0,0 +1,7 @@ +This is a testharness.js-based test. +FAIL same-origin, same-window location cycle Cyclic __proto__ value +PASS cross-origin location has null prototype +FAIL same-origin, different-window location cycle Cyclic __proto__ value +FAIL cross-origin, but joined via document.domain, location cycle Cyclic __proto__ value +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub.html new file mode 100644 index 0000000..f72ed1e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub.html
@@ -0,0 +1,197 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="UTF-8"> + + <title>Location objects' custom [[GetPrototypeOf]] trap permit [[Prototype]] chain cycles to be created through them</title> + + <link rel="author" title="Jeff Walden" href="http://whereswalden.com/" /> + <link rel="help" href="https://tc39.github.io/ecma262/#sec-ordinarysetprototypeof" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/browsers.html#location-getprototypeof" /> + + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"></div> + +<hr /> + +<iframe id="same-origin-different-window"></iframe> +<iframe id="cross-origin-joined-via-document-domain"></iframe> + +<script> +"use strict"; + +// Handle same-origin, same-window testing first, before any async-requiring +// testing. +test(function() { + var LocationPrototype = Location.prototype; + var ObjectPrototype = Object.prototype; + + var loc = window.location; + + var locProto = Object.getPrototypeOf(loc); + assert_equals(locProto, LocationPrototype, + "loc's initial [[Prototype]]"); + + var originalLocProtoProto = Object.getPrototypeOf(locProto); + assert_equals(originalLocProtoProto, ObjectPrototype, + "Location.prototype's initial [[Prototype]]"); + + Object.setPrototypeOf(locProto, loc); + + assert_equals(Object.getPrototypeOf(locProto), loc, + "LocationPrototype's new [[Prototype]]"); + assert_equals(Object.getPrototypeOf(loc), locProto, + "loc's new [[Prototype]]"); + + // Reset so as not to muck with testharness.js expectations. + Object.setPrototypeOf(locProto, originalLocProtoProto); +}, "same-origin, same-window location cycle"); + +var pathdir = + location.pathname.substring(0, location.pathname.lastIndexOf('/') + 1); + +var triggerCrossOriginTest = (function() { + var crossOrigin = + document.getElementById("cross-origin-joined-via-document-domain"); + + var t = async_test("cross-origin location has null prototype"); + + return new Promise(function(resolve, reject) { + crossOrigin.onload = t.step_func_done(function(e) { + try { + var win = crossOrigin.contentWindow; + + var loc = win.location; + + // Between un-opted-in windows, location objects appear to have null + // [[Prototype]]. + assert_equals(Object.getPrototypeOf(loc), null, + "cross-origin unjoined location's [[Prototype]"); + + resolve(); + } catch (e) { + reject(e); + throw e; + } + }); + + crossOrigin.src = + "//{{domains[www]}}:" + location.port + pathdir + "cross_origin_joined_frame.sub.html"; + }) + .catch(t.unreached_func("crossOrigin onload/src setting")); +})(); + +var triggerSameOriginTest = (function() { + var sameOriginDifferentWindow = + document.getElementById("same-origin-different-window"); + + var t = async_test("same-origin, different-window location cycle"); + + return new Promise(function(resolve, reject) { + sameOriginDifferentWindow.onload = t.step_func_done(function() { + try { + var win = sameOriginDifferentWindow.contentWindow; + + var loc = win.location; + var LocationPrototype = win.Location.prototype; + var ObjectPrototype = win.Object.prototype; + + var locProto = Object.getPrototypeOf(loc); + assert_equals(locProto, LocationPrototype, + "loc's initial [[Prototype]]"); + + var originalLocProtoProto = Object.getPrototypeOf(locProto); + assert_equals(originalLocProtoProto, ObjectPrototype, + "Location.prototype's initial [[Prototype]]"); + + Object.setPrototypeOf(locProto, loc); + + assert_equals(Object.getPrototypeOf(locProto), loc, + "LocationPrototype's new [[Prototype]]"); + assert_equals(Object.getPrototypeOf(loc), locProto, + "loc's new [[Prototype]]"); + + // Reset so as not to muck with testharness.js expectations. + Object.setPrototypeOf(locProto, originalLocProtoProto); + + resolve(); + } catch (e) { + reject(e); + throw e; + } + }); + + sameOriginDifferentWindow.src = "same_origin_frame.html"; + }) + .catch(t.unreached_func("sameOriginDifferentWindow onload/src setting")); +})(); + +function crossOriginJoinTest() { + var win = + document.getElementById("cross-origin-joined-via-document-domain") + .contentWindow; + + assert_equals(document.domain, "{{host}}"); + + var loc = win.location; + + var threw = false; + try { + // Still cross-origin until the document.domain set below. + win.Location; + } catch (e) { + threw = true; + } + + assert_equals(threw, true, + "accessing win.Location before joining win's origin"); + + // Join with other frames that have set |document.domain| to this same + // value -- namely, this cross-origin frame. Now access between the two + // windows should be permitted. + assert_equals(document.domain, "{{host}}", + "initial document.domain sanity check"); + document.domain = "{{host}}"; + + var LocationPrototype = win.Location.prototype; + var ObjectPrototype = win.Object.prototype; + + var locProto = Object.getPrototypeOf(loc); + assert_equals(locProto, LocationPrototype, + "loc's initial [[Prototype]]"); + + var originalLocProtoProto = Object.getPrototypeOf(locProto); + assert_equals(originalLocProtoProto, ObjectPrototype, + "Location.prototype's initial [[Prototype]]"); + + Object.setPrototypeOf(locProto, loc); + + assert_equals(Object.getPrototypeOf(locProto), loc, + "LocationPrototype's new [[Prototype]]"); + assert_equals(Object.getPrototypeOf(loc), locProto, + "loc's new [[Prototype]]"); + + // Reset so as not to muck with testharness.js expectations. + Object.setPrototypeOf(locProto, originalLocProtoProto); +} + +function run() { + var t = + async_test("cross-origin, but joined via document.domain, location cycle"); + + // The cross-origin/joined case must be tested after both unjoined same-origin + // and unjoined cross-origin tests: by mucking with document.domain, the + // cross-origin/joined case makes it impossible to perform those tests. + t.step(function() { + Promise.all([triggerCrossOriginTest, triggerSameOriginTest]) + .then(t.step_func_done(crossOriginJoinTest), + t.unreached_func("cross-origin joined error case")); + }); +} +run(); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location_hostname.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location_hostname.html new file mode 100644 index 0000000..2ffa0e5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location_hostname.html
@@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>location_hostname</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + var hostname = location.hostname; + var url = location.href; + + var pos = url.indexOf("//"); + if (pos != -1) { + url = url.substr(pos+2, url.length-pos-2); + pos = url.indexOf(":"); + if (pos != -1) { + url = url.substr(0, pos); + } else { + pos = url.indexOf("/"); + if (pos != -1) + url = url.substr(0, pos); + } + } + + assert_equals(hostname, url, "hostname"); + + }, "location hostname"); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-on-new-window.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-on-new-window.html new file mode 100644 index 0000000..3ad0de6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-on-new-window.html
@@ -0,0 +1,25 @@ +<!doctype html> +<meta charset=utf-8> +<meta name="timeout" content="long"> +<title>Cross-origin behavior of Window and Location on new Window</title> +<link rel="author" title="Bobby Holley (:bholley)" href="bobbyholley@gmail.com"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#security-window"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#security-location"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +setup({explicit_done: true}); + +window.addEventListener('message', function onmessage(evt) { + window.removeEventListener('message', onmessage); + test(function() { + var results = evt.data; + assert_true(results.length > 0, 'Need results'); + results.forEach(function(r) { assert_true(r.pass, r.message); }); + }, "Cross-origin object identity preserved across document.domain"); + win.close(); + done(); +}); +var win = window.open('win-documentdomain.sub.html'); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain-expected.txt new file mode 100644 index 0000000..6282ea6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +PASS sanity checks +PASS current document +FAIL new document Illegal constructor +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain.html new file mode 100644 index 0000000..af93321 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain.html
@@ -0,0 +1,25 @@ +<!doctype html> +<html> + <head> + <title></title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + assert_equals(typeof document.domain, "string", "document.domain is a string"); + assert_not_equals(document.domain, "", "document.domain is not empty"); + }, "sanity checks"); + + test(function() { + assert_equals(document.domain, window.location.hostname, "equals location.hostname"); + }, "current document"); + + test(function() { + var doc = new Document(); + assert_equals(doc.domain, "", "new document has empty domain"); + }, "new document"); + </script> + </head> + <body> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html new file mode 100644 index 0000000..75c8729c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>[Browsing Context] : [APIs for creating browsing_contexts by name]</title> +<link rel="author" title="Duhyeong Kim" href="mailto:dduskim@gmail.com"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name"> +<meta name=timeout content=long> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +async_test(function() { + var currentUrl = 'http://' + window.location.host + '/common/blank.html'; + var win = window.open(currentUrl, '', 'height=1,width=1'); + this.add_cleanup(function() { win.close(); }); + win.onload = this.step_func_done(function () { + assert_equals(win.location.href, currentUrl, 'should be equal to result url'); + }); +}, 'first argument: absolute url'); + +test(function() { + var win = window.open('', '', 'height=1,width=1'); + this.add_cleanup(function() { win.close(); }); + assert_equals(win.location.href, 'about:blank', 'win.location.href'); +}, 'first argument: empty url'); + +test(function () { + var win = window.open('', 'testWindow', 'height=1,width=1'); + win.close(); + assert_equals(win.name, 'testWindow', 'should have a browsing context name'); +}, 'second argument: passing a non-empty name'); + +test(function () { + var win = window.open('', '', 'height=1,width=1'); + this.add_cleanup(function() { win.close(); }); + assert_equals(win.name, '', 'window should not have a name'); + win.name = 'testWindow'; + assert_equals(win.name, 'testWindow', 'window should have a name'); +}, 'second argument: setting name after opening'); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/documents/resource-metadata-management/document-lastModified.html b/third_party/WebKit/LayoutTests/external/wpt/html/dom/documents/resource-metadata-management/document-lastModified.html new file mode 100644 index 0000000..9e0a07d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/documents/resource-metadata-management/document-lastModified.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>document.lastModified</title> +<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org"> +<link rel=help href="https://html.spec.whatwg.org/multipage/#resource-metadata-management"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + test(function(){ + var date = new Date("Thu, 01 Jan 1970 01:23:45 GMT"); + var result = ('0' + (date.getMonth()+1)).slice(-2) + '/' + ('0' + date.getDate()).slice(-2) + '/' + date.getFullYear() + " " + [date.getHours(),date.getMinutes(),date.getSeconds()].map(function(n){return ("0" + n).slice(-2);}).join(":"); + assert_equals(document.lastModified, result); + }, "lastModified should return the last modified date and time"); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub-expected.txt new file mode 100644 index 0000000..755a2ea7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub-expected.txt
@@ -0,0 +1,21 @@ +This is a testharness.js-based test. +FAIL The 'href' attribute of the 'a' element assert_equals: The 'href' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'href' attribute of the 'link' element assert_equals: The 'href' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'href' attribute of the 'area' element assert_equals: The 'href' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'cite' attribute of the 'q' element assert_equals: The 'cite' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'cite' attribute of the 'blockquote' element assert_equals: The 'cite' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'cite' attribute of the 'ins' element assert_equals: The 'cite' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'cite' attribute of the 'del' element assert_equals: The 'cite' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'src' attribute of the 'img' element assert_equals: The 'src' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'src' attribute of the 'embed' element assert_equals: The 'src' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'src' attribute of the 'video' element assert_equals: The 'src' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'src' attribute of the 'iframe' element assert_equals: The 'src' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'src' attribute of the 'script' element assert_equals: The 'src' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'src' attribute of the 'source' element assert_equals: The 'src' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'src' attribute of the 'track' element assert_equals: The 'src' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'action' attribute of the 'form' element assert_equals: The 'action' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'data' attribute of the 'object' element assert_equals: The 'data' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL The 'formaction' attribute of the 'button' element assert_equals: The 'formAction' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +FAIL Change the base URL must effect the descendant elements only assert_not_equals: The inner element must be effected. got disallowed value "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml new file mode 100644 index 0000000..7302ed6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml
@@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html> +<html id="h" xmlns="http://www.w3.org/1999/xhtml" xml:base=""> + <head> + <title>HTML Test: Dynamic changes to base URLs</title> + <link rel="author" title="Intel" href="http://www.intel.com/"/> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#dynamic-changes-to-base-urls" /> + <script src="/resources/testharness.js" id="s1"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <div id="div" style="display:none" xml:base=""></div> + <script> + <![CDATA[ + var div = document.getElementById("div"), + html = document.getElementById("h"), + url = document.location.href; + + var testData = [ + {elements: ["a", "link", "area"], set: "href", get: "href"}, + {elements: ["q", "blockquote", "ins", "del"], set: "cite", get: "cite"}, + {elements: ["img", "embed", "video", "iframe", "script", "source", "track"], set: "src", get: "src"}, + {elements: ["form"], set: "action", get: "action"}, + {elements: ["object"], set: "data", get: "data"}, + {elements: ["button"], set: "formaction", get: "formAction"} + ]; + + for (var i in testData) { + var item = testData[i]; + for (var j in item.elements) { + test(function () { + var ele = document.createElement(item.elements[j]); + + ele.setAttribute(item.set, "test.txt"); + div.appendChild(ele); + + html.setAttribute("xml:base", ""); + assert_equals(ele[item.get], url.substr(0, url.lastIndexOf("/")) +"/test.txt", "The '" + item.get + "' attribute is incorrect."); + html.setAttribute("xml:base", "http://{{domains[www]}}:{{ports[http][0]}}"); + assert_equals(ele[item.get], "http://{{domains[www]}}:{{ports[http][0]}}/test.txt", "The '" + item.get + "' attribute is incorrect."); + }, "The '" + item.set + "' attribute of the '" + item.elements[j] + "' element"); + } + } + + test(function () { + var s1 = document.getElementById("s1"); + var val1 = s1.src; + var val2 = div.firstChild.href; + + div.setAttribute("xml:base", "http://{{domains[www2]}}:{{ports[http][0]}}"); + assert_equals(s1.src, val1, "The outer element must not be effected."); + assert_not_equals(div.firstChild.href, val2, "The inner element must be effected."); + assert_equals(div.firstChild.href, "http://{{domains[www2]}}:{{ports[http][0]}}/test.txt"); + }, "Change the base URL must effect the descendant elements only"); + ]]> + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/terminology-0/document-base-url-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/terminology-0/document-base-url-expected.txt new file mode 100644 index 0000000..56dd69d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/terminology-0/document-base-url-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +PASS The document base URL of a document containing one or more base elements with href attributes is the frozen base URL of the first base element in the document that has an href attribute, in tree order. +PASS The fallback base URL of a document containing no base element is the document's address. +FAIL The fallback base URL of a document whose address is about:blank is the document base URL of the creator document. assert_equals: The document base URL should be the creator document's base URL. expected "http://web-platform.test:8001/html/infrastructure/urls/terminology-0/document-base-url.html" but got "about:blank" +FAIL about:blank with a base element. assert_equals: img src should resolve correctly expected "http://web-platform.test:8001/html/infrastructure/urls/terminology-0/sub/foo" but got "http://web-platform.test:8001/html/infrastructure/urls/terminology-0/foo" +PASS The fallback base URL of an iframe srcdoc document is the document base URL of the document's browsing context's browsing context container's document. +FAIL The base URL of an iframe srcdoc document with a <base> tag should be set by that tag. assert_equals: img src should resolve correctly expected "http://web-platform.test:8001/html/infrastructure/urls/terminology-0/sub/foo" but got "http://web-platform.test:8001/html/infrastructure/urls/terminology-0/foo" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/terminology-0/document-base-url.html b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/terminology-0/document-base-url.html new file mode 100644 index 0000000..ee9d7264 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/terminology-0/document-base-url.html
@@ -0,0 +1,93 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>HTML Test: document base URL</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + iframe { display: none } +</style> +<body onload="on_load()"> + <div id="log"></div> + <script> + function assert_resolve_url(doc, base) { + var img = doc.createElement("img"); + img.src = "foo"; + var actual = img.src; + var expected = base + "/foo"; + assert_equals(actual, expected, "img src should resolve correctly"); + } + + var t1 = async_test("The document base URL of a document containing one or more base elements with href attributes is the frozen base URL of the first base element in the document that has an href attribute, in tree order."); + + function on_load() { + t1.step(function () { + var base = document.createElement("base"); + base.setAttribute("href", "/foo/bar"); + document.head.appendChild(base); + t1.add_cleanup(function () { + document.head.removeChild(base); + }); + + assert_resolve_url(document, location.href.replace(location.pathname, "/foo")); + assert_equals(document.baseURI, base.href, "The document base URL should be URL of the first base element that has an href attribute."); + }); + t1.done(); + } + + async_test(function() { + var iframe = document.createElement("iframe"); + iframe.onload = this.step_func_done(function () { + assert_resolve_url(iframe.contentDocument, location.href.replace(location.pathname, "/common")); + assert_equals(iframe.contentDocument.baseURI, iframe.contentDocument.location.href, "The document base URL should be the document's address."); + }); + iframe.setAttribute("src", "/common/blank.html"); + document.body.appendChild(iframe); + }, "The fallback base URL of a document containing no base element is the document's address."); + + async_test(function () { + var iframe = document.createElement("iframe"); + iframe.onload = this.step_func_done(function () { + assert_resolve_url(iframe.contentDocument, location.href.replace("/document-base-url.html", "")); + assert_equals(iframe.contentDocument.baseURI, document.baseURI, "The document base URL should be the creator document's base URL."); + }); + iframe.setAttribute("src", "about:blank"); + document.body.appendChild(iframe); + }, "The fallback base URL of a document whose address is about:blank is the document base URL of the creator document."); + + async_test(function () { + var iframe = document.createElement("iframe"); + iframe.onload = this.step_func_done(function () { + var doc = iframe.contentDocument; + var base = doc.body.appendChild(doc.createElement("base")); + base.href = "sub/"; + assert_resolve_url(doc, location.href.replace("/document-base-url.html", "/sub")); + assert_equals(doc.baseURI, document.baseURI.replace("/document-base-url.html", "/sub/")); + }); + iframe.setAttribute("src", "about:blank"); + document.body.appendChild(iframe); + }, "about:blank with a base element."); + + async_test(function () { + var iframe = document.createElement("iframe"); + iframe.onload = this.step_func_done(function () { + assert_resolve_url(iframe.contentDocument, location.href.replace("/document-base-url.html", "")); + assert_equals(iframe.contentDocument.baseURI, document.baseURI, "The document base URL should be the containing document's base URL."); + }); + iframe.setAttribute("srcdoc", "<p>foobar</p>"); + document.body.appendChild(iframe); + }, "The fallback base URL of an iframe srcdoc document is the document base URL of the document's browsing context's browsing context container's document."); + + async_test(function () { + var iframe = document.createElement("iframe"); + iframe.onload = this.step_func_done(function () { + var doc = iframe.contentDocument; + assert_resolve_url(doc, location.href.replace("/document-base-url.html", "/sub")); + assert_equals(doc.baseURI, document.baseURI.replace("/document-base-url.html", "/sub/"), + "The srcdoc document's base URL should be set by the <base> tag."); + }); + iframe.setAttribute("srcdoc", "<base href='sub/'><p>foobar</p>"); + document.body.appendChild(iframe); + }, "The base URL of an iframe srcdoc document with a <base> tag should be set by that tag."); + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/terminology-0/multiple-base.sub.html b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/terminology-0/multiple-base.sub.html new file mode 100644 index 0000000..49c428c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/terminology-0/multiple-base.sub.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>document base URL: multiple base elements</title> +<base target="_blank" > +<base href="http://{{domains[www]}}:{{ports[http][0]}}/"> +<base href="http://{{domains[www1]}}:{{ports[http][0]}}/"> +<base href="http://{{domains[www2]}}:{{ports[http][0]}}/"> +<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + test(function(){ + var base = document.querySelectorAll("base"); + assert_equals(document.baseURI, document.querySelectorAll("base[href]")[0].href); + }, "If there are multiple <base> elements, the document base URL is the frozen base URL of the first one that has an href attribute"); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-base-element/base_about_blank-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-base-element/base_about_blank-expected.txt new file mode 100644 index 0000000..b7c96f7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-base-element/base_about_blank-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL base element in about:blank document should resolve against its fallback base URI assert_equals: expected "http://web-platform.test:8001/html/semantics/document-metadata/the-base-element/test" but got "" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-base-element/base_about_blank.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-base-element/base_about_blank.html new file mode 100644 index 0000000..54c4794 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-base-element/base_about_blank.html
@@ -0,0 +1,19 @@ +<!doctype html> +<meta charset=utf-8> +<title>base element in about:blank document should resolve against its fallback base URI</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<iframe></iframe> +<script> +var t = async_test(); +addEventListener("load", t.step_func_done(function() { + var doc = frames[0].document; + var b = doc.createElement("base"); + b.setAttribute("href", "test"); + var newBaseValue = location.href.replace(/\/[^/]*$/, "/") + "test"; + assert_equals(b.href, newBaseValue); + assert_equals(doc.baseURI, location.href); + doc.head.appendChild(b); + assert_equals(doc.baseURI, newBaseValue); +})); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-base-element/base_srcdoc-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-base-element/base_srcdoc-expected.txt new file mode 100644 index 0000000..15b63e0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-base-element/base_srcdoc-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL base element in srcdoc document should resolve against its fallback base URI assert_equals: expected "http://web-platform.test:8001/html/semantics/document-metadata/the-base-element/test" but got "" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-base-element/base_srcdoc.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-base-element/base_srcdoc.html new file mode 100644 index 0000000..eea1efe --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-base-element/base_srcdoc.html
@@ -0,0 +1,19 @@ +<!doctype html> +<meta charset=utf-8> +<title>base element in srcdoc document should resolve against its fallback base URI</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<iframe srcdoc=""></iframe> +<script> +var t = async_test(); +addEventListener("load", t.step_func_done(function() { + var doc = frames[0].document; + var b = doc.createElement("base"); + b.setAttribute("href", "test"); + var newBaseValue = location.href.replace(/\/[^/]*$/, "/") + "test"; + assert_equals(b.href, newBaseValue); + assert_equals(doc.baseURI, location.href); + doc.head.appendChild(b); + assert_equals(doc.baseURI, newBaseValue); +})); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1-expected.txt new file mode 100644 index 0000000..458abdc --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1-expected.txt
@@ -0,0 +1,6 @@ +CONSOLE ERROR: line 47: Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'. +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'. +PASS Meta refresh is blocked by the allow-scripts sandbox flag at its creation time, not when refresh comes due +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1.html new file mode 100644 index 0000000..09454a1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1.html
@@ -0,0 +1,56 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Meta refresh is blocked by the allow-scripts sandbox flag at its creation time, not when refresh comes due</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-refresh"> + +<div id="log"></div> + +<script> +"use strict"; + +const sourceIFrame = document.createElement("iframe"); +sourceIFrame.setAttribute("sandbox", "allow-same-origin"); + +const destIFrame = document.createElement("iframe"); + +let sourceLoadCount = 0; +let destLoadCount = 0; + +sourceIFrame.onload = () => { + ++sourceLoadCount; + + if (sourceLoadCount === 2) { + assert_unreached("The iframe from which the meta came from must not refresh"); + } + + maybeStartTest(); +}; + +destIFrame.onload = () => { + ++destLoadCount; + + if (destLoadCount === 2) { + assert_unreached("The iframe into which the meta was moved must not refresh"); + } + + maybeStartTest(); +}; + +function maybeStartTest() { + if (sourceLoadCount === 1 && destLoadCount === 1) { + // Test that no refreshes occur within 3 seconds + step_timeout(done, 3000); + + const meta = sourceIFrame.contentDocument.querySelector("meta"); + destIFrame.contentDocument.body.appendChild(meta); + } +} + +sourceIFrame.src = "support/refresh.sub.html?input=" + encodeURIComponent("1; url=foo"); +destIFrame.src = "support/ufoo"; + +document.body.appendChild(sourceIFrame); +document.body.appendChild(destIFrame); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-2.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-2.html new file mode 100644 index 0000000..f5c4e99 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-2.html
@@ -0,0 +1,54 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Meta refresh of the original iframe is not blocked if moved into a sandboxed iframe</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-refresh"> + +<div id="log"></div> + +<script> +"use strict"; + +const sourceIFrame = document.createElement("iframe"); + +const destIFrame = document.createElement("iframe"); +destIFrame.setAttribute("sandbox", "allow-same-origin"); + +let sourceLoadCount = 0; +let destLoadCount = 0; + +sourceIFrame.onload = () => { + ++sourceLoadCount; + + if (sourceLoadCount === 2) { + assert_equals(sourceIFrame.contentDocument.body.textContent.trim(), "foo"); + done(); + } + + maybeStartTest(); +}; + +destIFrame.onload = () => { + ++destLoadCount; + + if (destLoadCount === 2) { + assert_unreached("The iframe into which the meta was moved must not refresh"); + } + + maybeStartTest(); +}; + +function maybeStartTest() { + if (sourceLoadCount === 1 && destLoadCount === 1) { + const meta = sourceIFrame.contentDocument.querySelector("meta"); + destIFrame.contentDocument.body.appendChild(meta); + } +} + +sourceIFrame.src = "support/refresh.sub.html?input=" + encodeURIComponent("1; url=foo"); +destIFrame.src = "support/ufoo"; + +document.body.appendChild(sourceIFrame); +document.body.appendChild(destIFrame); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor-no-src.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor-no-src.html new file mode 100644 index 0000000..cb2a5795 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor-no-src.html
@@ -0,0 +1,13 @@ +<!doctype html> +<title>NOT invoking resource selection with new Audio() sans src</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function(t) { + var a = new Audio(); + assert_equals(a.networkState, a.NETWORK_EMPTY); + a.onloadstart = t.step_func(function() { assert_unreached(); }); + window.onload = t.step_func(function() { t.done(); }); +}); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-namespace.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-namespace.html new file mode 100644 index 0000000..b73f229 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-namespace.html
@@ -0,0 +1,14 @@ +<!doctype html> +<title>NOT invoking resource selection by inserting <source> in the wrong namespace</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<video></video> +<script> +async_test(function(t) { + var v = document.querySelector('video'); + v.onloadstart = t.step_func(function() { assert_unreached(); }); + v.appendChild(document.createElementNS('bogus','source')); + window.onload = t.step_func(function() { t.done(); }); +}); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-networkState-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-networkState-expected.txt new file mode 100644 index 0000000..c289c6a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-networkState-expected.txt
@@ -0,0 +1,6 @@ +CONSOLE ERROR: line 12: Uncaught (in promise) AbortError: The play() request was interrupted by a new load request. +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = The play() request was interrupted by a new load request. +PASS invoking load by setting src when networkState is not NETWORK_EMPTY +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-not-in-document.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-not-in-document.html new file mode 100644 index 0000000..f6c4f24 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-not-in-document.html
@@ -0,0 +1,13 @@ +<!doctype html> +<title>invoking load by setting src on video not in a document</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function(t) { + var v = document.createElement('video'); + v.onloadstart = t.step_func(function() { t.done(); }); + v.setAttribute('src',''); + window.onload = t.step_func(function() { assert_unreached(); }); +}); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html new file mode 100644 index 0000000..cd27b8e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html
@@ -0,0 +1,19 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Check the frame heriarchy</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="iframe_harness.js"></script> +<body> + <iframe src="http://www1.web-platform.test:8000/html/semantics/embedded-content/the-iframe-element/cross_origin_child.html"></iframe> +</body> +<script> + get_test_results('bffa23ee-b45a-4e9a-9405-87ab437d5cfa'); + get_test_results('79a52de8-4222-427e-92db-caec28e75f8e'); + get_test_results('6c8da65d-2c5e-44ef-bb0b-b8b9849aab19'); + send_test_results({ + "id": 'bffa23ee-b45a-4e9a-9405-87ab437d5cfa', + "parent": window.parent === window, + "top": window.top === window, + }); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/form-submission-0/submit-entity-body-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/form-submission-0/submit-entity-body-expected.txt new file mode 100644 index 0000000..efe7db8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/form-submission-0/submit-entity-body-expected.txt
@@ -0,0 +1,14 @@ +This is a testharness.js-based test. +PASS form submission from form should navigate to url with x-www-form-urlencoded +PASS form submission from form should navigate to url with multipart/form-data +FAIL form submission from form should navigate to url with text/plain assert_equals: expected "OK" but got "FAIL" +PASS form submission from button should navigate to url with x-www-form-urlencoded +PASS form submission from button should navigate to url with multipart/form-data +FAIL form submission from button should navigate to url with text/plain assert_equals: expected "OK" but got "FAIL" +PASS form submission from input should navigate to url with x-www-form-urlencoded +PASS form submission from input should navigate to url with multipart/form-data +FAIL form submission from input should navigate to url with text/plain assert_equals: expected "OK" but got "FAIL" +PASS form submission from submit input should contain submit button value +PASS form submission from submit button should contain submit button value +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/form-submission-0/submit-entity-body.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/form-submission-0/submit-entity-body.html new file mode 100644 index 0000000..8363f39 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/form-submission-0/submit-entity-body.html
@@ -0,0 +1,114 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +var simple_tests = [ + { + name: "form submission from form should navigate to url with x-www-form-urlencoded", + input: "<input name=foo value=bara>", + enctype: "application/x-www-form-urlencoded", + submitelement: "", + submitaction: function(doc) { doc.getElementById("testform").submit(); } + }, + { + name: "form submission from form should navigate to url with multipart/form-data", + input: "<textarea name=foo>bar</textarea>", + enctype: "multipart/form-data", + submitelement: "", + submitaction: function(doc) { doc.getElementById("testform").submit(); } + }, + { + name: "form submission from form should navigate to url with text/plain", + input: "<textarea name=qux>baz</textarea>", + enctype: "text/plain", + submitelement: "", + submitaction: function(doc) { doc.getElementById("testform").submit(); } + }, + { + name: "form submission from button should navigate to url with x-www-form-urlencoded", + input: "<input name=foo value=bara>", + enctype: "application/x-www-form-urlencoded", + submitelement: "<button id=buttonsubmit type=\"submit\">Submit</button>", + submitaction: function(doc) { doc.getElementById("buttonsubmit").click(); } + }, + { + name: "form submission from button should navigate to url with multipart/form-data", + input: "<textarea name=foo>bar</textarea>", + enctype: "multipart/form-data", + submitelement: "<button id=buttonsubmit type=\"submit\">Submit</button>", + submitaction: function(doc) { doc.getElementById("buttonsubmit").click(); } + }, + { + name: "form submission from button should navigate to url with text/plain", + input: "<textarea name=qux>baz</textarea>", + enctype: "text/plain", + submitelement: "<button id=buttonsubmit type=\"submit\">Submit</button>", + submitaction: function(doc) { doc.getElementById("buttonsubmit").click(); } + }, + { + name: "form submission from input should navigate to url with x-www-form-urlencoded", + input: "<input name=foo value=bara>", + enctype: "application/x-www-form-urlencoded", + submitelement: "<input id=inputsubmit type=\"submit\">Submit</input>", + submitaction: function(doc) { doc.getElementById("inputsubmit").click(); } + }, + { + name: "form submission from input should navigate to url with multipart/form-data", + input: "<textarea name=foo>bar</textarea>", + enctype: "multipart/form-data", + submitelement: "<input id=inputsubmit type=\"submit\">Submit</input>", + submitaction: function(doc) { doc.getElementById("inputsubmit").click(); } + }, + { + name: "form submission from input should navigate to url with text/plain", + input: "<input name=qux value=baz>", + enctype: "text/plain", + submitelement: "<input id=inputsubmit type=\"submit\">Submit</input>", + submitaction: function(doc) { doc.getElementById("inputsubmit").click(); } + }, + { + name: "form submission from submit input should contain submit button value", + input: "<button type=submit name=notclicked value=nope>not clicked</button>", + enctype: "application/x-www-form-urlencoded", + submitelement: "<button id=inputsubmit type=\"submit\" name=foo value=bara>Submit</button>", + submitaction: function(doc) { doc.getElementById("inputsubmit").click(); } + } +, + { + name: "form submission from submit button should contain submit button value", + input: "<input type=submit name=notclicked value=nope/>", + enctype: "application/x-www-form-urlencoded", + submitelement: "<input id=inputsubmit type=\"submit\" name=foo value=bara >", + submitaction: function(doc) { doc.getElementById("inputsubmit").click(); } + } +]; +simple_tests.forEach(function(test_obj) { + test_obj.test = async_test(test_obj.name); +}); +function run_simple_test() { + if (simple_tests.length == 0) { + return; + } + var test_obj = simple_tests.pop(); + var t = test_obj.test; + var testframe = document.getElementById("testframe"); + var testdocument = testframe.contentWindow.document; + testdocument.body.innerHTML = + "<form id=testform method=post action=\"form-submission.py\" enctype=\"" + test_obj.enctype + "\">" + + test_obj.input + + test_obj.submitelement + + "</form>"; + testframe.onload = function() { + t.step(function (){ + var response = testframe.contentDocument.documentElement.textContent; + assert_equals(response, "OK"); + }); + t.done(); + run_simple_test(); + }; + test_obj.submitaction(testdocument); +} +</script> +<iframe id=testframe src="/common/blank.html" onload="run_simple_test();"></iframe>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/date-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/date-expected.txt index efff42f5..64de5bb 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/date-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/date-expected.txt
@@ -1,9 +1,9 @@ CONSOLE WARNING: line 20: The specified value "invalid-date" does not conform to the required format, "yyyy-MM-dd". This is a testharness.js-based test. PASS date type support on input element -FAIL The value attribute, if specified and not empty, must have a value that is a valid date string. assert_equals: expected "2011-01-01" but got "1999-01-31" -FAIL The min attribute, if specified, must have a value that is a valid date string. assert_equals: expected "" but got "1999-1" -FAIL The max attribute, if specified, must have a value that is a valid date string. assert_equals: expected "2099-01" but got "2011-12-31" +PASS The value attribute, if specified and not empty, must have a value that is a valid date string. +PASS The min attribute must be reflected verbatim by the min property. +PASS The max attribute must be reflected verbatim by the max property. PASS User agents must not allow the user to set the value to a non-empty string that is not a valid date string. PASS Number of days Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/date.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/date.html index 70885ed0..9b95b86 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/date.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/date.html
@@ -16,7 +16,7 @@ <input id="too_large_value" type="date" value="2099-01-31" min="2011-01-01" max="2011-12-31"/> <input id="invalid_min" type="date" value="2011-01-01" min="1999-1" max="2011-12-31"/> <input id="invalid_max" type="date" value="2011-01-01" min="2011-01-01" max="2011-13-162-777"/> - <input id="min_larger_than_max" type="date" value="2011-01-01" min="2099-01" max="2011-12-31"/> + <input id="min_larger_than_max" type="date" value="2011-01-01" min="2099-01-01" max="2011-12-31"/> <input id="invalid_value" type="date" value="invalid-date" min="2011-01-01" max="2011-12-31"/> </div> @@ -29,20 +29,20 @@ test(function() { assert_equals(document.getElementById("valid").value, "2011-11-01"); - assert_equals(document.getElementById("too_small_value").value, "2011-01-01"); - assert_equals(document.getElementById("too_large_value").value, "2011-12-31"); + assert_equals(document.getElementById("too_small_value").value, "1999-01-31"); + assert_equals(document.getElementById("too_large_value").value, "2099-01-31"); }, "The value attribute, if specified and not empty, must have a value that is a valid date string."); test(function() { - assert_equals(document.getElementById("valid").min, "2011-01-01"), - assert_equals(document.getElementById("invalid_min").min, "") - }, "The min attribute, if specified, must have a value that is a valid date string."); + assert_equals(document.getElementById("valid").min, "2011-01-01"); + assert_equals(document.getElementById("invalid_min").min, "1999-1"); + }, "The min attribute must be reflected verbatim by the min property."); test(function() { - assert_equals(document.getElementById("valid").max, "2011-12-31"), - assert_equals(document.getElementById("min_larger_than_max").max, "2099-01"), - assert_equals(document.getElementById("invalid_max").max, "") - },"The max attribute, if specified, must have a value that is a valid date string."); + assert_equals(document.getElementById("valid").max, "2011-12-31"); + assert_equals(document.getElementById("min_larger_than_max").max, "2011-12-31"); + assert_equals(document.getElementById("invalid_max").max, "2011-13-162-777"); + }, "The max attribute must be reflected verbatim by the max property."); test(function() { assert_equals(document.getElementById("invalid_value").value, "");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/number-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/number-expected.txt deleted file mode 100644 index ab7b71b6..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/number-expected.txt +++ /dev/null
@@ -1,32 +0,0 @@ -This is a testharness.js-based test. -PASS empty value -PASS value = 11 -PASS value = 11.12 -PASS value = -11111 -PASS value = -11111.123 -PASS value = 1e2 -PASS value = 1E2 -PASS value = 1e+2 -PASS value = 1e-2 -PASS value is not a valid floating-point number: 1d+2 -PASS value not a valid floating-point number: random string -PASS Value >= min attribute -PASS Value < min attribute -PASS Value <= max attribute -PASS Value > max attribute -PASS value with a leading '.' -PASS value ending with '.' -PASS value = -0 -PASS value = Infinity -PASS value = -Infinity -PASS value = NaN -FAIL value = 2^53+1 assert_equals: expected "9007199254740992" but got "9007199254740993" -PASS value >= Number.MAX_VALUE -PASS value = 1e -FAIL value = +1 assert_equals: expected "1" but got "" -PASS value = '+' -PASS value = '-' -FAIL value with a leading whitespace assert_equals: expected "1" but got "" -FAIL value = 1trailing junk assert_equals: expected "1" but got "" -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/number.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/number.html index 5067d0e..64868f02 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/number.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/number.html
@@ -2,7 +2,7 @@ <meta charset=utf-8> <title>Form input type=number</title> <link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org"> -<link rel=help href="https://html.spec.whatwg.org/multipage/#password-state-(type=number)"> +<link rel=help href="https://html.spec.whatwg.org/multipage/#number-state-(type=number)"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <div id="log"></div> @@ -29,14 +29,14 @@ {value: "Infinity", expected: "", testname: " value = Infinity"}, {value: "-Infinity", expected: "", testname: "value = -Infinity"}, {value: "NaN", expected: "", testname: "value = NaN"}, - {value: "9007199254740993", expected: "9007199254740992", testname: "value = 2^53+1"}, + {value: "9007199254740993", expected: "9007199254740993", testname: "value = 2^53+1"}, {value: "2e308", expected: "", testname: "value >= Number.MAX_VALUE"}, {value: "1e", expected: "", testname: "value = 1e"}, - {value: "+1", expected: "1", testname: "value = +1"}, + {value: "+1", expected: "", testname: "value = +1"}, {value: "+", expected: "", testname: "value = '+'"}, {value: "-", expected: "", testname: "value = '-'"}, - {value: " 1", expected: "1", testname: "value with a leading whitespace"}, - {value: "1trailing junk", expected: "1", testname: "value = 1trailing junk"} + {value: " 1", expected: "", testname: "value with a leading whitespace"}, + {value: "1trailing junk", expected: "", testname: "value = 1trailing junk"} ]; for (var i = 0; i < numbers.length; i++) { var w = numbers[i];
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/range-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/range-expected.txt index 23d87f0..24ab49f6 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/range-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/range-expected.txt
@@ -2,14 +2,14 @@ PASS range type support on input element PASS min attribute support on input element PASS max attribute support on input element -FAIL Illegal value of min attribute assert_equals: expected "0" but got "ab" -FAIL Illegal value of max attribute assert_equals: expected "100" but got "f" +PASS Illegal value of min attribute +PASS Illegal value of max attribute PASS Converting an illegal string to the default value -FAIL Converting an illegal string to the default step assert_equals: expected "1" but got "xyz" +PASS Illegal value of step attribute PASS the value is set to min when a smaller value than min attribute is given PASS the value is set to max when a larger value than max attribute is given -FAIL default value of min attribute in input type=range assert_equals: expected "0" but got "" -FAIL default value of max attribute in input type=range assert_equals: expected "100" but got "" +PASS default value of min attribute in input type=range +PASS default value of max attribute in input type=range PASS default value when min and max attributes are given (= min plus half the difference between min and max) PASS default value with step control when both min and max attributes are given FAIL default value when both min and max attributes are given, while min > max assert_equals: expected "2" but got "51"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/range.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/range.html index 2e7a85ea..6ae5b8aeb 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/range.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/range.html
@@ -71,24 +71,30 @@ } ); - // HTML5 spec says the default vaules of min and max attributes are 0 and 100 respectively, - // however, Chrome, Opera and Firefox would not give any default value at all... test( function() { - assert_equals(document.getElementById('illegal_min_and_max').min, "0") + assert_equals(document.getElementById('illegal_min_and_max').min, "ab") }, "Illegal value of min attribute", { - "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)" + "help" : [ + "https://html.spec.whatwg.org/multipage/#dom-input-min", + "https://html.spec.whatwg.org/multipage/#range-state-(type=range)" + ] } ); test( function() { - assert_equals(document.getElementById('illegal_min_and_max').max, "100") + assert_equals(document.getElementById('illegal_min_and_max').max, "f") }, "Illegal value of max attribute", - { "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)" } + { + "help" : [ + "https://html.spec.whatwg.org/multipage/#dom-input-max", + "https://html.spec.whatwg.org/multipage/#range-state-(type=range)" + ] + } ); test( @@ -103,10 +109,15 @@ test( function() { - assert_equals(document.getElementById('illegal_value_and_step').step, "1") + assert_equals(document.getElementById('illegal_value_and_step').step, "xyz") }, - "Converting an illegal string to the default step", - { "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)" } + "Illegal value of step attribute", + { + "help" : [ + "https://html.spec.whatwg.org/multipage/#dom-input-step", + "https://html.spec.whatwg.org/multipage/#range-state-(type=range)" + ] + } ); test( @@ -131,7 +142,7 @@ test( function() { - assert_equals(document.getElementById('empty_attributes').min, "0") + assert_equals(document.getElementById('empty_attributes').min, "") }, "default value of min attribute in input type=range", { "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min" } @@ -139,7 +150,7 @@ test( function() { - assert_equals(document.getElementById('empty_attributes').max, "100") + assert_equals(document.getElementById('empty_attributes').max, "") }, "default value of max attribute in input type=range", {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/time-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/time-expected.txt index 101266d3..edd9253 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/time-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/time-expected.txt
@@ -21,13 +21,13 @@ PASS stepDown on step value hour PASS stepUp on step value second PASS stepDown on step value second -PASS stepUp on step value miri second -PASS stepDown on step value miri second -PASS stepUp argment 2 times -PASS stepDown argment 2 times -FAIL stepUp stop because it exceeds the maximum value assert_equals: expected "15:00" but got "15:00:00" -FAIL stepDown Stop so lower than the minimum value assert_equals: expected "13:00" but got "13:00:00" -FAIL stop at border on stepUp assert_equals: expected "15:01" but got "15:00" +PASS stepUp on step value with fractional seconds +PASS stepDown on step value with fractional seconds +PASS stepUp argument 2 times +PASS stepDown argument 2 times +PASS stepUp stop because it exceeds the maximum value +PASS stepDown stop so lower than the minimum value +FAIL stop at border on stepUp assert_in_array: a valid time string representing 1 minute after 3pm value "15:00" not in array ["15:01", "15:01:00", "15:01:00.0", "15:01:00.00", "15:01:00.000"] PASS stop at border on stepDown PASS empty value of stepUp PASS set value on not time format value
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/time.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/time.html index 5178d91d..eabb6cbd 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/time.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/time.html
@@ -104,26 +104,56 @@ _StepTest.value = "12:00"; _StepTest.step = "3600"; _StepTest.stepUp(); - assert_equals(_StepTest.value, "13:00"); + assert_in_array( + _StepTest.value, + [ + "13:00", + "13:00:00", + "13:00:00.0", + "13:00:00.00", + "13:00:00.000"], + "a valid time string representing 1pm"); } , "stepUp on step value hour "); test(function(){ _StepTest.value = "12:00"; _StepTest.step = "3600"; _StepTest.stepDown(); - assert_equals(_StepTest.value, "11:00"); + assert_in_array( + _StepTest.value, + [ + "11:00", + "11:00:00", + "11:00:00.0", + "11:00:00.00", + "11:00:00.000"], + "a valid time string representing 11am"); } , "stepDown on step value hour "); test(function(){ _StepTest.value = "12:00"; _StepTest.step = "1"; _StepTest.stepUp(); - assert_equals(_StepTest.value, "12:00:01"); + assert_in_array( + _StepTest.value, + [ + "12:00:01", + "12:00:01.0", + "12:00:01.00", + "12:00:01.000"], + "a valid time string representing 1 second after noon"); } , "stepUp on step value second "); test(function(){ _StepTest.value = "12:00"; _StepTest.step = "1"; _StepTest.stepDown(); - assert_equals(_StepTest.value, "11:59:59"); + assert_in_array( + _StepTest.value, + [ + "11:59:59", + "11:59:59.0", + "11:59:59.00", + "11:59:59.000"], + "a valid time string representing 1 second before noon"); } , "stepDown on step value second "); test(function(){ @@ -131,64 +161,118 @@ _StepTest.step = "0.001"; _StepTest.stepUp(); assert_equals(_StepTest.value, "12:00:00.001"); -} , "stepUp on step value miri second "); +} , "stepUp on step value with fractional seconds"); test(function(){ _StepTest.value = "12:00"; _StepTest.step = "0.001"; _StepTest.stepDown(); assert_equals(_StepTest.value, "11:59:59.999"); -} , "stepDown on step value miri second "); +} , "stepDown on step value with fractional seconds"); test(function(){ _StepTest.value = "13:00:00"; _StepTest.step = "1"; _StepTest.stepUp(2); - assert_equals(_StepTest.value, "13:00:02"); -}, "stepUp argment 2 times"); + assert_in_array( + _StepTest.value, + [ + "13:00:02", + "13:00:02.0", + "13:00:02.00", + "13:00:02.000"], + "a valid time string representing 2 seconds after 1pm"); +}, "stepUp argument 2 times"); test(function(){ _StepTest.value = "13:00:00"; _StepTest.step = "1"; _StepTest.stepDown(2); - assert_equals(_StepTest.value, "12:59:58"); -}, "stepDown argment 2 times"); + assert_in_array( + _StepTest.value, + [ + "12:59:58", + "12:59:58.0", + "12:59:58.00", + "12:59:58.000"], + "a valid time string representing 2 seconds before 1pm"); +}, "stepDown argument 2 times"); test(function(){ _StepTest.max = "15:00"; + this.add_cleanup(function() { _StepTest.max = ""; }); _StepTest.value = "15:00"; _StepTest.stepUp(); - assert_equals(_StepTest.value, "15:00"); - _StepTest.max = ""; + assert_in_array( + _StepTest.value, + [ + "15:00", + "15:00:00", + "15:00:00.0", + "15:00:00.00", + "15:00:00.000"], + "a valid time string representing 3pm"); } , "stepUp stop because it exceeds the maximum value"); test(function(){ _StepTest.min = "13:00"; + this.add_cleanup(function() { _StepTest.min = ""; }); _StepTest.value = "13:00"; _StepTest.stepDown(); - assert_equals(_StepTest.value, "13:00"); - _StepTest.min=""; -} , "stepDown Stop so lower than the minimum value"); + assert_in_array( + _StepTest.value, + [ + "13:00", + "13:00:00", + "13:00:00.0", + "13:00:00.00", + "13:00:00.000"], + "a valid time string representing 1pm"); +} , "stepDown stop so lower than the minimum value"); test(function(){ _StepTest.max = "15:01"; + this.add_cleanup(function() { _StepTest.max = ""; }); _StepTest.value = "15:00"; _StepTest.step = "120"; _StepTest.stepUp(); - assert_equals(_StepTest.value, "15:01"); - _StepTest.max = ""; + assert_in_array( + _StepTest.value, + [ + "15:01", + "15:01:00", + "15:01:00.0", + "15:01:00.00", + "15:01:00.000"], + "a valid time string representing 1 minute after 3pm"); } , "stop at border on stepUp"); test(function(){ _StepTest.min = "12:59"; + this.add_cleanup(function() { _StepTest.min = ""; }); _StepTest.value = "13:00"; _StepTest.step = "120"; _StepTest.stepDown(); - assert_equals(_StepTest.value, "12:59"); - _StepTest.min=""; + assert_in_array( + _StepTest.value, + [ + "12:59", + "12:59:00", + "12:59:00.0", + "12:59:00.00", + "12:59:00.000"], + "a valid time string representing 1 minute before 2pm"); } , "stop at border on stepDown"); test(function(){ _StepTest.value = ""; _StepTest.step = "60"; _StepTest.stepUp(); - assert_equals(_StepTest.value, "00:01"); + assert_in_array( + _StepTest.value, + [ + "00:01", + "00:01:00", + "00:01:00.0", + "00:01:00.00", + "00:01:00.000"], + "a valid time string representing 1 minute after midnight"); } , " empty value of stepUp");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/week-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/week-expected.txt deleted file mode 100644 index 88b09ae..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/week-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -This is a testharness.js-based test. -PASS empty value -PASS Valid value: Value should be 2014-W52 -PASS 2014 has 52 weeks: Value should be empty -PASS 2015 has 53 weeks: Value should be 2015-W53 -PASS Invalid value: year only -PASS Invalid value: no week number -PASS Invalid value: no '-' (U+002D) -PASS Invalid value: yearless week -PASS Invalid value: yearless week and no '-' (U+002D) -PASS Value >= min attribute -FAIL Value < min attribute assert_equals: expected "2014-W02" but got "2014-W01" -PASS Value <= max attribute -FAIL Value > max attribute assert_equals: expected "2014-W11" but got "2014-W12" -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/week.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/week.html index e06b678..77978a2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/week.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/week.html
@@ -19,9 +19,9 @@ {value: "-W52", expected: "", testname: "Invalid value: yearless week"}, {value: "W52", expected: "", testname: "Invalid value: yearless week and no '-' (U+002D)"}, {value: "2014-W03", attributes: { min: "2014-W02" }, expected: "2014-W03", testname: "Value >= min attribute"}, - {value: "2014-W01", attributes: { min: "2014-W02" }, expected: "2014-W02", testname: "Value < min attribute"}, + {value: "2014-W01", attributes: { min: "2014-W02" }, expected: "2014-W01", testname: "Value < min attribute"}, {value: "2014-W10", attributes: { max: "2014-W11" }, expected: "2014-W10", testname: "Value <= max attribute"}, - {value: "2014-W12", attributes: { max: "2014-W11" }, expected: "2014-W11", testname: "Value > max attribute"} + {value: "2014-W12", attributes: { max: "2014-W11" }, expected: "2014-W12", testname: "Value > max attribute"} ]; for (var i = 0; i < weeks.length; i++) { var w = weeks[i];
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_003.htm b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_003.htm new file mode 100644 index 0000000..b9a854c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_003.htm
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> + <head> + <title>An async script does not block the parser while downloading</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures an async script does not block the parser while downloading." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-script-async"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script type="text/javascript"> + var t = async_test("An async script does not block the parser while downloading"); + + function timeout() + { + t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "21")}); + t.done(); + } + + var timer = setTimeout(timeout, 4000); + + function log(text) + { + var textNode = document.createTextNode(text); + document.getElementById("testresult").appendChild(textNode); + } + </script> + + <span id="testresult"></span> + + <script src="log.py?sec=3&id=1" async></script> + <script> + log('2'); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_004.htm b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_004.htm new file mode 100644 index 0000000..7908b75 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_004.htm
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html> + <head> + <title>An async script executes as soon as possible after a download is complete</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures an async script executes as soon as possible after a download is complete." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-script-async"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script type="text/javascript"> + var t = async_test("async script executes as soon as possible after a download is complete"); + + function timeout() + { + t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "21")}); + t.done(); + } + + var timer = setTimeout(timeout, 4000); + + function log(text) + { + var textNode = document.createTextNode(text); + document.getElementById("testresult").appendChild(textNode); + } + </script> + + <span id="testresult"></span> + + <script src="log.py?sec=3&id=1" async></script> + <script src="log.py?sec=1&id=2" async></script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_005.htm b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_005.htm new file mode 100644 index 0000000..4519d72 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_005.htm
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> + <head> + <title>A script element with both async and defer set should execute asynchronously</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures a script element with both async and defer set should execute asynchronously." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-script-async"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script type="text/javascript"> + var t = async_test("A script element with both async and defer set should execute asynchronously"); + + function timeout() + { + t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "2134")}); + t.done(); + } + + var timer = setTimeout(timeout, 5000); + + function log(text) + { + var textNode = document.createTextNode(text); + document.getElementById("testresult").appendChild(textNode); + } + </script> + + <span id="testresult"></span> + + <script type="text/javascript" src="log.py?sec=1&id=1" defer async></script> + <script type="text/javascript">log('2');</script> + <script type="text/javascript" src="log.py?sec=3&id=3"></script> + <script type="text/javascript">log('4');</script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_006.htm b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_006.htm new file mode 100644 index 0000000..86eb9989 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_006.htm
@@ -0,0 +1,45 @@ +<!DOCTYPE html> +<html> + <head> + <title>A dynamically created external script executes asynchronously</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures a dynamically created external script executes asynchronously." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#force-async"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script type="text/javascript"> + var t = async_test("dynamically created external script executes asynchronously"); + + function timeout() + { + t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "321")}); + t.done(); + } + + var timer = setTimeout(timeout, 4000); + + function log(text) + { + var textNode = document.createTextNode(text); + document.getElementById("testresult").appendChild(textNode); + } + </script> + + <span id="testresult"></span> + <script type="text/javascript"> + var one = document.createElement("script"); + one.src="log.py?sec=3&id=1"; + document.head.appendChild(one); + + var two = document.createElement("script"); + two.src="log.py?sec=1&id=2"; + document.head.appendChild(two); + + log('3'); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_007.htm b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_007.htm new file mode 100644 index 0000000..8df0fba3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_007.htm
@@ -0,0 +1,48 @@ +<!DOCTYPE html> +<html> + <head> + <title>Ordered async script execution when script.async == false</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures Ordered async script execution when script.async == false" /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#script-processing-src-sync"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script type="text/javascript"> + var t = async_test("Ordered async script execution when script.async == false"); + + function timeout() + { + t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "312")}); + t.done(); + } + + var timer = setTimeout(timeout, 8000); + + function log(text) + { + var textNode = document.createTextNode(text); + document.getElementById("testresult").appendChild(textNode); + } + </script> + + <span id="testresult"></span> + <script type="text/javascript"> + var one = document.createElement("script"); + one.src="log.py?sec=3&id=1"; + one.async = false; + document.head.appendChild(one); + + var two = document.createElement("script"); + two.src="log.py?sec=1&id=2"; + two.async = false; + document.head.appendChild(two); + </script> + <script type="text/javascript"> + log('3'); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_008.htm b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_008.htm new file mode 100644 index 0000000..73529cc3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_008.htm
@@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html> + <head> + <title>Async script element execution delays the window's load event</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures an async script element's execution delays the window's load event." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#delay-the-load-event"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script type="text/javascript"> + var t = async_test("Async script element execution delays the window's load event"); + + function timeout() + { + t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "213")}); + t.done(); + } + + var timer = setTimeout(timeout, 8000); + + function log(text) + { + var textNode = document.createTextNode(text); + document.getElementById("testresult").appendChild(textNode); + } + </script> + + <span id="testresult"></span> + <script type="text/javascript"> + window.addEventListener("load", function() { + log("3"); + timeout(); + }, false); + + var s1 = document.createElement("script"); + s1.src = "log.py?sec=2&id=1"; + document.head.appendChild(s1); + </script> + <script type="text/javascript"> + log('2'); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_009.htm b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_009.htm new file mode 100644 index 0000000..501edda0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_009.htm
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html> + <head> + <title>Document.write() silently fails from an Async script</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures Document.write() silently fails from an Async script." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script type="text/javascript"> + var t = async_test("Document.write() silently fails from an Async script"); + + var log = t.step_func(function() { + document.write("<span id='writtenText'/>"); + assert_equals(null, document.getElementById('writtenText')); + t.done(); + }); + </script> + </head> + <body> + <div id=log></div> + <script type="text/javascript" src="log.py?sec=1&id=1" async></script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_010.htm b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_010.htm new file mode 100644 index 0000000..959a8aa --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/async_010.htm
@@ -0,0 +1,54 @@ +<!DOCTYPE html> +<html> + <head> + <title>Removing an async script before execution</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures that an async script still executes if it is removed from a markup before the download is complete. The other two scripts that come after it in insertion order should execute as well." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script type="text/javascript"> + var t = async_test("Removing an async script before execution"); + + function timeout() + { + t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "4123")}); + t.done(); + } + + var timer = setTimeout(timeout, 8000); + + function log(text) + { + var textNode = document.createTextNode(text); + document.getElementById("testresult").appendChild(textNode); + } + </script> + </head> + <body> + <div id=log></div> + <span id="testresult"></span> + <script type="text/javascript"> + var s1 = document.createElement("script"); + s1.src="log.py?sec=2&id=1"; + s1.async = false; + document.body.appendChild(s1); + + var s2 = document.createElement("script"); + s2.src="log.py?sec=1&id=2"; + s2.async = false; + document.body.appendChild(s2); + + var s3 = document.createElement("script"); + s3.id = "s3"; + s3.src="log.py?sec=0&id=3"; + s3.async = false; + document.body.appendChild(s3); + + //Remove s1 (Should still execute) + document.body.removeChild(s1); + </script> + <script type="text/javascript">log('4');</script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/external-script-utf8.js b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/external-script-utf8.js new file mode 100644 index 0000000..eb442c9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/external-script-utf8.js
@@ -0,0 +1,5 @@ +(function() { + window.getSomeString = function() { + return "śćążź"; //<- these are five Polish letters, similar to scazz. It can be read correctly only with windows 1250 encoding. + }; +})();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/external-script-windows1250.js b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/external-script-windows1250.js new file mode 100644 index 0000000..4ac83bf --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/external-script-windows1250.js
@@ -0,0 +1,5 @@ +(function() { + window.getSomeString = function() { + return "湿"; //<- these are five Polish letters, similar to scazz. It can be read correctly only with windows 1250 encoding. + }; +})();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/resources/cross-origin.py b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/resources/cross-origin.py new file mode 100644 index 0000000..f8e05d96 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/resources/cross-origin.py
@@ -0,0 +1,10 @@ +def main(request, response): + headers = [("Content-Type", "text/javascript")] + milk = request.cookies.first("milk", None) + + if milk is None: + return headers, "var included = false;" + elif milk.value == "yes": + return headers, "var included = true;" + + return headers, "var included = false;"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-01-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-01-expected.txt new file mode 100644 index 0000000..1a29dad --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-01-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +PASS Script @type: unknown parameters +FAIL Script @type: unknown parameters 1 assert_equals: expected "śćążź" but got "œæ¹¿Ÿ" +PASS Script @type: unknown parameters 2 +FAIL Script @type: unknown parameters 3 assert_equals: expected "śćążź" but got "湿" +PASS Script @type: unknown parameters 4 +PASS Script @type: unknown parameters 5 +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-01.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-01.html new file mode 100644 index 0000000..c5ac0d0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-01.html
@@ -0,0 +1,89 @@ +<!DOCTYPE html> +<head> + <meta charset="utf-8"> + <title>Script @type: unknown parameters</title> + <link rel="author" title="askalski" href="github.com/askalski"> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#scriptingLanguages"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <div id="log"></div> + + <!-- "Step1" tests --> + <!-- charset is set incorrectly via Content Type "text/javascript;charset=utf-8" in response + which has priority before a correct setting in "charset" attribute of script tag. + --> + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript%3Bcharset=utf-8" charset="windows-1250"> + </script> + <script> + test(function() { + //these strings should not match, since the file charset is set incorrectly + assert_not_equals(window.getSomeString(), "śćążź"); + }); + </script> + <!-- charset is set correctly via Content Type "text/javascript;charset=utf-8" in response + which has priority before a incorrect setting in "charset" attribute of script tag. + --> + + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript%3Bcharset=windows-1250" charset="utf-8"> + </script> + <script> + //the charset is set correctly via Content Type "text/javascript;charset=windows-1250" in respones + test(function() { + assert_equals(window.getSomeString(), "śćążź"); + }); + </script> + + <!-- end of step1 tests, now step2 tests --> + <!-- in this case, the response's Content Type does not bring charset information. + Second step takes block character encoding if available.--> + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript" charset="utf-8"> + </script> + <script> + test(function() { + //these strings should not match, since the file charset is set incorrectly in "charset" tag of <script> above + assert_not_equals(window.getSomeString(), "śćążź"); + }); + </script> + <!-- charset is set correctly via Content Type "text/javascript;charset=utf-8" in response + which has priority before a incorrect setting in "charset" attribute of script tag. + --> + + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript" charset="windows-1250"> + </script> + <script> + //the charset is set correctly via content attribute in <script> above + test(function() { + assert_equals(window.getSomeString(), "śćążź"); + }); + </script> + + <!-- end of step2 tests, now step3 tests --> + <!-- in this case, neither response's Content Type nor charset attribute bring correct charset information. + Third step takes this document's character encoding (declared correctly as UTF-8).--> + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript"> + </script> + <script> + test(function() { + //these strings should not match, since the tested file is in windows-1250, and document is utf-8 + assert_not_equals(window.getSomeString(), "śćążź"); + }); + </script> + + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-utf8.js&ct=text/javascript"> + </script> + <script> + //these strings should match, both document and tested file are utf-8 + test(function() { + assert_equals(window.getSomeString(), "śćążź"); + }); + </script> + + <!-- the last portion of tests (step4) are in file script-charset-02.html + +</head>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-02-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-02-expected.txt new file mode 100644 index 0000000..409c18225 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-02-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +PASS Script @type: unknown parameters +FAIL Script @type: unknown parameters 1 assert_equals: expected 5 but got 10 +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-02.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-02.html new file mode 100644 index 0000000..77a015b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-02.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<head> + <!-- TODO: + askalski: while this test pass, it does not test anything now. + It should test, whether with no document.charset set in any way, the + external scripts will get decoded using utf-8 as fallback character encoding. + It seems like utf-8 is also a fallback encoding to html (my guess), so + the part of the code I was attempting to test is never reached. + --> + <title>Script @type: unknown parameters</title> + <link rel="author" title="askalski" href="github.com/askalski"> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#scriptingLanguages"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <div id="log"></div> + + <!-- test of step4, which is taking utf-8 as fallback --> + <!-- in this case, neither response's Content Type nor charset attribute bring correct charset information. + Furthermore, document's encoding is not set.--> + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript"> + </script> + <script> + test(function() { + //these strings should not match, since the tested file is in windows-1250, and fallback is defined as utf-8 + assert_not_equals(window.getSomeString().length, 5); + }); + </script> + + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-utf8.js&ct=text/javascript"> + </script> + <script> + //these strings should match, since fallback utf-8 is the correct setting. + test(function() { + assert_equals(window.getSomeString().length, 5); + }); + </script> + +</head>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-03-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-03-expected.txt index 62615fe..db53b8b4 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-03-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-charset-03-expected.txt
@@ -1,4 +1,4 @@ This is a testharness.js-based test. -FAIL Script changing @charset window.getSomeString is not a function +FAIL Script changing @charset assert_equals: expected "śćążź" but got "œæ¹¿Ÿ" Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-crossorigin-network.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-crossorigin-network.html new file mode 100644 index 0000000..488dd448 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-crossorigin-network.html
@@ -0,0 +1,49 @@ +<!doctype html> +<meta charset="utf-8"> +<title>HTMLScriptElement: crossorigin attribute network test</title> +<link rel="author" title="KiChjang" href="mailto:kungfukeith11@gmail.com"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#cors-settings-attribute"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> + <script type="text/javascript"> + var test1 = async_test(document.title + "1"); + var test2 = async_test(document.title + "2"); + var test3 = async_test(document.title + "3"); + + var script1 = document.createElement("script"); + script1.src = "resources/cross-origin.py"; + script1.crossOrigin = "use-credentials"; + var script2 = document.createElement("script"); + script2.src = "resources/cross-origin.py"; + script2.crossOrigin = "gibberish"; + var script3 = document.createElement("script"); + script3.src = "resources/cross-origin.py"; + + document.cookie = "milk=yes"; + document.body.appendChild(script1); + script1.onload = function() { + test1.step(function() { + assert_true(included, "credentials should be included in script request"); + test1.done(); + }); + }; + + document.body.appendChild(script2); + script2.onload = function() { + test2.step(function() { + assert_true(included, "invalid values should default to include credentials due to response tainting"); + test2.done(); + }); + }; + + document.body.appendChild(script3); + script3.onload = function() { + test3.step(function() { + assert_true(included, "missing value should default to include credentials"); + test3.done(); + }); + }; + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-not-found-not-executed-2.py b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-not-found-not-executed-2.py new file mode 100644 index 0000000..53caed7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-not-found-not-executed-2.py
@@ -0,0 +1,4 @@ +def main(request, response): + headers = [("Content-Type", "text/javascript")] + body = "test2_token = \"script executed\";" + return 200, headers, body
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html new file mode 100644 index 0000000..44ad30b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html
@@ -0,0 +1,19 @@ +<!doctype html> +<meta charset="utf-8"> +<title></title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script>var test1_token = "script not executed";</script> +<script src="script-not-found-not-executed.py"></script> +<script> +test(function(){ + assert_equals(test1_token, "script not executed"); +}, "Script that 404"); +</script> +<script>var test2_token = "script not executed";</script> +<script src="script-not-found-not-executed-2.py"></script> +<script> +test(function(){ + assert_equals(test2_token, "script executed"); +}, "Script that does not 404"); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.py b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.py new file mode 100644 index 0000000..7722bd3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.py
@@ -0,0 +1,4 @@ +def main(request, response): + headers = [("Content-Type", "text/javascript")] + body = "test1_token = \"script executed\";" + return 404, headers, body
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/serve-with-content-type.py b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/serve-with-content-type.py new file mode 100644 index 0000000..7cfe6f4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/serve-with-content-type.py
@@ -0,0 +1,15 @@ +import os + +def main(request, response): + directory = os.path.dirname(__file__) + + try: + file_name = request.GET.first("fn") + content_type = request.GET.first("ct") + with open(os.path.join(directory, file_name), "rb") as fh: + content = fh.read() + + response.headers.set("Content-Type", content_type) + response.content = content + except: + response.set_error(400, "Not enough parameters or file not found")
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-001.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-001.html new file mode 100644 index 0000000..a85682ad --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-001.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html lang="en" > +<head> + <title>HTTP charset</title> +<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta name='flags' content='http'> +<style type='text/css'> +.test div { width: 50px; }</style> +<link rel="stylesheet" type="text/css" href="support/encodingtests-15.css"> +</head> +<body> + + + +<div class='test'><div id='box' class='ýäè'> </div></div> + + +<!--Notes: + +The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ÜÀÚ</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass. + +The only character encoding declaration for this HTML file is in the HTTP header, which sets the encoding to ISO 8859-15. + +--> +<script> +test(function() { +assert_equals(document.getElementById('box').offsetWidth, 100); +}, "The character encoding of a page can be set using the HTTP header charset declaration."); +</script> + +<div id='log'></div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-007.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-007.html new file mode 100644 index 0000000..03dd532b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-007.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html lang="en" > +<head> + <meta http-equiv="content-type" content="text/html; charset=iso-8859-15"> <title>meta content attribute</title> +<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta name='flags' content='http'> +<style type='text/css'> +.test div { width: 50px; }</style> +<link rel="stylesheet" type="text/css" href="support/encodingtests-15.css"> +</head> +<body> + + + +<div class='test'><div id='box' class='ýäè'> </div></div> + + +<!--Notes: + +The only character encoding declaration for this HTML file is in the content attribute of the meta element, which declares the encoding to be ISO 8859-15. + +The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ÜÀÚ</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass. + +--> +<script> +test(function() { +assert_equals(document.getElementById('box').offsetWidth, 100); +}, "The character encoding of the page can be set by a meta element with http-equiv and content attributes."); +</script> + +<div id='log'></div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-009.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-009.html new file mode 100644 index 0000000..1383292 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-009.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html lang="en" > +<head> + <meta charset="iso-8859-15"> <title>meta charset attribute</title> +<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta name='flags' content='http'> +<style type='text/css'> +.test div { width: 50px; }</style> +<link rel="stylesheet" type="text/css" href="support/encodingtests-15.css"> +</head> +<body> + + + +<div class='test'><div id='box' class='ýäè'> </div></div> + + +<!--Notes: + +The only character encoding declaration for this HTML file is in the charset attribute of the meta element, which declares the encoding to be ISO 8859-15. + +The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ÜÀÚ</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass. + +--> +<script> +test(function() { +assert_equals(document.getElementById('box').offsetWidth, 100); +}, "The character encoding of the page can be set by a meta element with charset attribute."); +</script> + +<div id='log'></div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-015.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-015.html new file mode 100644 index 0000000..383c93b5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-015.html
@@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html lang="en" > +<head> + <title>No encoding declaration</title> +<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta name='flags' content='http'> +<style type='text/css'> +.test div { width: 50px; }</style> +<link rel="stylesheet" type="text/css" href="support/encodingtests-utf8.css"> +</head> +<body> + + + +<div class='test'><div id='box' class='ýäè'> </div></div> + + +<!--Notes: + +The test on this page contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ýäè</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass. + +--> +<script> +test(function() { +assert_equals(document.getElementById('box').offsetWidth, 100); +}, "A page with no encoding information in HTTP, BOM, XML declaration or meta element will be treated as UTF-8."); +</script> + +<div id='log'></div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-016.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-016.html new file mode 100644 index 0000000..141ca3e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-016.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html lang="en" > +<head> + <meta http-equiv="content-type" content="text/html;charset=iso-8859-1" > <title>HTTP vs meta content</title> +<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta name='flags' content='http'> +<style type='text/css'> +.test div { width: 50px; }.test div { width: 90px; } +</style> +<link rel="stylesheet" type="text/css" href="support/encodingtests-15.css"> +</head> +<body> + + + +<div class='test'><div id='box' class='ýäè'> </div></div> + + +<!--Notes: + +The HTTP header attempts to set the character encoding to ISO 8859-15. The page contains an encoding declaration in a meta content attribute that attempts to set the character encoding to ISO 8859-1. + +The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ÜÀÚ</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass. + +--> +<script> +test(function() { +assert_equals(document.getElementById('box').offsetWidth, 100); +}, "The HTTP header has a higher precedence than an encoding declaration in a meta content attribute."); +</script> + +<div id='log'></div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-018.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-018.html new file mode 100644 index 0000000..9ee7510e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-018.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html lang="en" > +<head> + <meta charset="iso-8859-1" > <title>HTTP vs meta charset</title> +<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta name='flags' content='http'> +<style type='text/css'> +.test div { width: 50px; }.test div { width: 90px; } +</style> +<link rel="stylesheet" type="text/css" href="support/encodingtests-15.css"> +</head> +<body> + + + +<div class='test'><div id='box' class='ýäè'> </div></div> + + +<!--Notes: + +The HTTP header attempts to set the character encoding to ISO 8859-15. The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-1. + +The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ÜÀÚ</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass. + +--> +<script> +test(function() { +assert_equals(document.getElementById('box').offsetWidth, 100); +}, "The HTTP header has a higher precedence than an encoding declaration in a meta charset attribute."); +</script> + +<div id='log'></div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-030.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-030.html new file mode 100644 index 0000000..5f851999 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-030.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html lang="en" > +<head> + <meta charset="iso-8859-15" ><meta http-equiv="content-type" content="text/html;charset=iso-8859-1" > <title>meta charset, then meta content</title> +<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta name='flags' content='http'> +<style type='text/css'> +.test div { width: 50px; }.test div { width: 90px; } +</style> +<link rel="stylesheet" type="text/css" href="support/encodingtests-15.css"> +</head> +<body> + + + +<div class='test'><div id='box' class='ýäè'> </div></div> + + +<!--Notes: + +The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-15, followed by a meta content attribute that tries to set the encoding to ISO 8859-1. + +The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ÜÀÚ</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass. + +--> +<script> +test(function() { +assert_equals(document.getElementById('box').offsetWidth, 100); +}, "An encoding declaration in a meta charset attribute has a higher precedence than a following encoding declaration in a meta charset attribute."); +</script> + +<div id='log'></div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-034.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-034.html new file mode 100644 index 0000000..f0b6997 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-034.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html lang="en" > +<head> + <title>HTTP vs UTF-8 BOM</title> +<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta name='flags' content='http'> +<style type='text/css'> +.test div { width: 50px; }</style> +<link rel="stylesheet" type="text/css" href="support/encodingtests-utf8.css"> +</head> +<body> + + + +<div class='test'><div id='box' class='ýäè'> </div></div> + + +<!--Notes: + +The HTTP header attempts to set the character encoding to ISO 8859-15. The page starts with a UTF-8 signature. + +The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ýäè</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass. + +If the test is unsuccessful, the characters  should appear at the top of the page. These represent the bytes that make up the UTF-8 signature when encountered in the ISO 8859-15 encoding. + +--> +<script> +test(function() { +assert_equals(document.getElementById('box').offsetWidth, 100); +}, "A character encoding set in the HTTP header has lower precedence than the UTF-8 signature."); +</script> + +<div id='log'></div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-037.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-037.html new file mode 100644 index 0000000..1fcf157 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-037.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html lang="en" > +<head> + <meta http-equiv="content-type" content="text/html; charset=iso-8859-15"> <title>UTF-8 BOM vs meta content</title> +<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta name='flags' content='http'> +<style type='text/css'> +.test div { width: 50px; }</style> +<link rel="stylesheet" type="text/css" href="support/encodingtests-utf8.css"> +</head> +<body> + + + +<div class='test'><div id='box' class='ýäè'> </div></div> + + +<!--Notes: + +The page contains an encoding declaration in a meta content attribute that attempts to set the character encoding to ISO 8859-15, but the file starts with a UTF-8 signature. + +The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ýäè</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass. + +--> +<script> +test(function() { +assert_equals(document.getElementById('box').offsetWidth, 100); +}, "A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta content attribute declares a different encoding."); +</script> + +<div id='log'></div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-038.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-038.html new file mode 100644 index 0000000..9432113a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing-html-fragments/the-input-byte-stream-038.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html lang="en" > +<head> + <meta charset="iso-8859-15"> <title>UTF-8 BOM vs meta charset</title> +<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta name='flags' content='http'> +<style type='text/css'> +.test div { width: 50px; }.test div { width: 90px; } +</style> +<link rel="stylesheet" type="text/css" href="support/encodingtests-utf8.css"> +</head> +<body> + + + +<div class='test'><div id='box' class='ýäè'> </div></div> + + +<!--Notes: + +The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-15, but the file starts with a UTF-8 signature. + +The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ýäè</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass. + +--> +<script> +test(function() { +assert_equals(document.getElementById('box').offsetWidth, 100); +}, "A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta charset attribute declares a different encoding."); +</script> + +<div id='log'></div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-foster-parenting/template-is-a-foster-parent-element.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-foster-parenting/template-is-a-foster-parent-element.html new file mode 100644 index 0000000..6f6e7a72 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-foster-parenting/template-is-a-foster-parent-element.html
@@ -0,0 +1,63 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Template is a foster parent element</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="assert" content="The last template element with either no table element is below it, or a table element immediately below it, in the stack of open elements is the foster parent element (NOT the template's parent!)"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#foster-parent-addition"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + +test(function () { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '' + + '<div id="tmplParent">' + + '<template id="tmpl1">' + + '<table id="tbl">' + + '<tr><td>Cell 1</td></tr>' + + // Misplaced <div>. It should be foster parented + '<div id="orphanDiv">Orphan div content</div>' + + '<tr><td>Cell 2</td></tr>' + + '</table>' + + '</template>' + + '</div>'; + + var template = doc.querySelector('#tmpl1'); + var div = template.content.querySelector('#orphanDiv'); + + assert_equals(div.parentNode, template.content, 'Wrong foster parent element'); + +}, 'Template is a foster parent element. Test <table> immediately below <template>'); + + + +test(function () { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '' + + '<div id="tmplParent">' + + '<template id="tmpl1">' + + '<tr><td>Cell 1</td></tr>' + + // Misplaced <div>. It should be foster parented + '<div id="orphanDiv">Orphan div content</div>' + + '<tr><td>Cell 2</td></tr>' + + '</template>' + + '</div>'; + + var template = doc.querySelector('#tmpl1'); + var div = template.content.querySelector('#orphanDiv'); + + assert_equals(div.parentNode, template.content, 'Wrong foster parent element'); + +}, 'Template is a foster parent element. Test <template> element without <table>'); + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-foster-parenting/template-is-not-a-foster-parent-element.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-foster-parenting/template-is-not-a-foster-parent-element.html new file mode 100644 index 0000000..677dfaf --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-foster-parenting/template-is-not-a-foster-parent-element.html
@@ -0,0 +1,70 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Template is not a foster parent element</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="assert" content="When template element shouldn't be a foster parent then regular rules of foster parenting should be applied"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#foster-parent-addition"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + +test(function () { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '' + + '<div id="tmplParent">' + + '<template id="tmpl1">' + + '<div id="fosterParent">' + + '<table id="tbl">' + + '<tr><td>Cell 1</td></tr>' + + // Misplaced <div>. It should be foster parented + '<div id="orphanDiv">Orphan div content</div>' + + '<tr><td>Cell 2</td></tr>' + + '</table>' + + '</div>' + + '</template>' + + '</div>'; + + var template = doc.querySelector('#tmpl1'); + var fosterParent = template.content.querySelector('#fosterParent'); + var div = template.content.querySelector('#orphanDiv'); + + assert_equals(div.parentNode, fosterParent, 'Wrong foster parent element'); + +}, 'Template is not a foster parent element. ' + + 'Test the case when <template> is higher in stack of open elements'); + + + +test(function () { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '' + + '<div id="fosterParent">' + + '<table id="tbl">' + + '<tr><td><template id="tmpl1">Template content</template></td></tr>' + + // Misplaced <div>. It should be foster parented + '<div id="orphanDiv">Orphan div content</div>' + + '<tr><td>Cell 2</td></tr>' + + '</table>' + + '</div>' + + '</div>'; + + var t = doc.querySelector('#tmpl1'); + var fosterParent = doc.querySelector('#fosterParent'); + var div = doc.querySelector('#orphanDiv'); + + assert_equals(div.parentNode, fosterParent, 'Wrong foster parent element'); + +}, 'Template is not a foster parent element. ' + + 'Test the case when <template> is lower in stack of open elements'); + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/generating-of-implied-end-tags.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/generating-of-implied-end-tags.html new file mode 100644 index 0000000..6edce84 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/generating-of-implied-end-tags.html
@@ -0,0 +1,136 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: 'In body' insertion mode: when template end tag is met, implied end tags should be generated</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru"> +<meta name="assert" content="'In body' insertion mode: when template end tag is met, implied end tags should be generated"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + +test(function () { + var doc = newHTMLDocument(); + + //No end </td></tr></table> tags. Should be added implicitly + doc.body.innerHTML = '<template id="tpl">' + + '<table id="tbl"><tr id="tr"><td id="td"></template>'; + + var template = doc.querySelector('#tpl'); + + assert_not_equals(template, null, 'Template element must be parsed'); + + assert_equals(doc.querySelector('#tbl'), null, 'Table element should not be available'); + assert_equals(doc.querySelector('#tr'), null, 'TR element should not be available'); + assert_equals(doc.querySelector('#td'), null, 'TD element should not be available'); + + assert_not_equals(template.content.querySelector('#tbl'), null, + 'Template should contain table element'); + assert_not_equals(template.content.querySelector('#tr'), null, + 'Template should contain TR element'); + assert_not_equals(template.content.querySelector('#td'), null, + 'Template should contain TD element'); + +}, 'Generating of implied end tags. Test table elements'); + + + +test(function () { + var doc = newHTMLDocument(); + + //No end </div> tag. Should be added implicitly + doc.body.innerHTML = '<template id="tpl"><div id="dv">Div content</template>'; + + var template = doc.querySelector('#tpl'); + + assert_not_equals(template, null, 'Template element must be parsed'); + + assert_equals(doc.querySelector('#dv'), null, 'DIV element should not be available'); + + assert_not_equals(template.content.querySelector('#dv'), null, + 'Template should contain DIV element'); + +}, 'Generating of implied end tags. Test div element'); + + +test(function () { + var doc = newHTMLDocument(); + + //No end </div> tag. Should be added implicitly after text content + doc.body.innerHTML = '<template id="tpl">Template text<div id="dv">Div content</template>'; + + var template = doc.querySelector('#tpl'); + + assert_not_equals(template, null, 'Template element must be parsed'); + + assert_equals(doc.querySelector('#dv'), null, 'DIV element should not be available'); + + var div = template.content.querySelector('#dv'); + + assert_not_equals( div, null, 'Template should contain DIV element'); + assert_equals(div.textContent, 'Div content', 'Wrong template content inner text'); + +}, 'Generating of implied end tags. Test some text and DIV element'); + + +test(function () { + var doc = newHTMLDocument(); + + // Wrong end tag. Correct end tag must be added implicitly, wrong one ignored + doc.body.innerHTML = '<template id="tpl"><div id="dv">Div content</span></template>'; + + var template = doc.querySelector('#tpl'); + + assert_not_equals(template, null, 'Template element must be parsed'); + + assert_equals(template.content.childNodes.length, 1, + 'Wrong number of template\'s children'); + + assert_equals(doc.querySelector('#dv'), null, 'DIV element should not be available'); + + assert_not_equals(template.content.querySelector('#dv'), null, + 'Template should contain DIV element'); + assert_equals(template.content.querySelector('#dv').textContent, + 'Div content', 'Wrong template content inner text'); + +}, 'Generating of implied end tags. Test wrong end tag'); + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/template-contents-table-no-end-tag.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.body.querySelector('template'); + + assert_not_equals(template, null, 'Template element must be parsed'); + + assert_not_equals(template.content.querySelector('table'), null, + 'Template should contain table element'); + assert_not_equals(template.content.querySelector('tr'), null, + 'Template should contain TR element'); + assert_not_equals(template.content.querySelector('td'), null, + 'Template should contain TD element'); + +}, 'Generating of implied end tags. Test table elements. Loading of HTML document from a file'); + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/template-contents-div-no-end-tag.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.body.querySelector('template'); + + assert_not_equals(template, null, 'Template element must be parsed'); + + var div = template.content.querySelector('div'); + assert_not_equals(div, null, 'Template should contain div element'); + assert_equals(div.textContent, 'Hello, template\n ', 'Invalid div contents'); + +}, 'Generating of implied end tags. Test div element. Loading of HTML document from a file'); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-body-token.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-body-token.html new file mode 100644 index 0000000..4549f5f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-body-token.html
@@ -0,0 +1,132 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: In body insertion mode: parser should ignore BODY token</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<meta name="assert" content="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +/* + * According to http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-contents-insertion-mode + * when parser is in "template content" mode and meets <body> tag it should be switched to + * "in body" insertion mode. + * According to http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition + * this token (BODY) should be ignored + */ + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<body></body>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 0, + 'Template cannot contain BODY element'); + +}, 'Ignore BODY token. Test empty BODY element assigned to template innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<body><div>Some content</div></body>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 1, + 'Wrong number of template content children'); + assert_equals(template.content.firstChild.nodeName, 'DIV', + 'Template should contain children of ignored BODY element'); + +}, 'Ignore BODY token. Test not empty BODY element assigned to template innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<body><div <div id="div1">Some content</div></body><div id="div2">Some valid content</div>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 2, + 'Wrong number of template content children'); + assert_not_equals(template.content.querySelector('#div1'), null, + 'Template should contain children of the ignored BODY element'); + assert_not_equals(template.content.querySelector('#div2'), null, + 'Template should contain valid element'); + +}, 'Ignore BODY token. ' + + 'Test BODY element and some valid element after BODY tag assigned to template innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<div id="div1">Some valid content</div><body><div id="div2">Some content</div></body>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 2, + 'Template cannot contain BODY element'); + assert_not_equals(template.content.querySelector('#div1'), null, + 'Template should contain valid element'); + assert_not_equals(template.content.querySelector('#div2'), null, + 'Template should contain children of the ignored BODY element'); + +}, 'Ignore BODY token. ' + + 'Test BODY element and some valid element before BODY tag assigned to template innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<template id="t2"><body><span>Body!<span></body></template>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 1, + 'Template should contain nested template'); + assert_not_equals(template.content.querySelector('#t2'), null, + 'Template should contain nested element'); + + var nestedTemplate = template.content.querySelector('#t2'); + + assert_equals(nestedTemplate.content.childNodes.length, 1, + 'Template cannot contain BODY element'); + assert_equals(nestedTemplate.content.firstChild.nodeName, 'SPAN', + 'Template cannot contain BODY element'); + +}, 'Ignore BODY token. ' + + 'Test template with not empty BODY element inside assigned to another ' + + 'template\'s innerHTML'); + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/template-contents-body.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.body.querySelector('template'); + + assert_equals(template.content.childNodes.length, 0, + 'Template cannot contain BODY element'); + +}, 'Ignore BODY token. ' + + 'Test loading a HTML file with BODY tag inside template'); + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-frameset-token.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-frameset-token.html new file mode 100644 index 0000000..1211150 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-frameset-token.html
@@ -0,0 +1,125 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: In body insertion mode: parser should ignore FRAMESET token</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<meta name="assert" content="If parser is in 'in body' insertion mode and meets HTML token it should be ignored"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +/* + * According to http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-contents-insertion-mode + * when parser is in "template content" mode and meets <frameset> tag it should be switched to + * "in body" insertion mode. + * According to https://html.spec.whatwg.org/multipage/#parsing-main-inbody + * this token (FRAMESET) should be ignored + */ + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<frameset cols="25%,*,25%">' + + '<frame src="frame_a.htm">' + + '<frame src="frame_b.htm">' + '<frame src="frame_c.htm">' + + '</frameset>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 0, + 'Template cannot contain FRAMESET element'); + +}, 'Ignore frameset token. Test FRAMESET element assigned to template innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<div id="div1">Some text</div>' + + '<frameset cols="25%,*,25%">' + + '<frame src="frame_a.htm">' + + '<frame src="frame_b.htm">' + + '<frame src="frame_c.htm">' + + '</frameset>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 1, + 'Template cannot contain FRAMESET element'); + assert_not_equals(template.content.querySelector('#div1'), null, + 'Template should contain valid element'); + +}, 'Ignore frameset token. ' + + 'Test FRAMESET element and some valid element before it, assigned ' + + 'to the template\'s innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<frameset cols="25%,*,25%">' + + '<frame src="frame_a.htm">' + + '<frame src="frame_b.htm">' + + '<frame src="frame_c.htm">' + + '</frameset><div id="div1">Some text</div>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 1, + 'Template cannot contain FRAMESET element'); + assert_not_equals(template.content.querySelector('#div1'), null, + 'Template should contain valid element'); + +}, 'Ignore frameset token. ' + + 'Test FRAMESET element and some valid element after it, assigned ' + + 'to the template\'s innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<template id="t2">' + + '<frameset cols="25%,*,25%">' + + '<frame src="frame_a.htm">' + + '<frame src="frame_b.htm">' + + '<frame src="frame_c.htm">' + + '</frameset></template>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 1, + 'Template should contain nested template'); + assert_not_equals(template.content.querySelector('#t2'), null, + 'Template should contain nested element'); + + var nestedTemplate = template.content.querySelector('#t2'); + + assert_equals(nestedTemplate.content.childNodes.length, 0, + 'Template cannot contain FRAMESET element'); + +}, 'Ignore frameset token. ' + + 'Test FRAMESET tag inside template tag assigned to another template\'s innerHTML'); + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/template-contents-frameset.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.body.querySelector('template'); + + assert_equals(template.content.childNodes.length, 0, + 'Template cannot contain FRAMESET element'); +}, 'Ignore frameset token. Test loading a HTML file with FRAMESET tag inside template'); + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-head-token.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-head-token.html new file mode 100644 index 0000000..9b14df917 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-head-token.html
@@ -0,0 +1,129 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: In body insertion mode: parser should ignore HEAD token</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<meta name="assert" content="If parser is in 'in body' insertion mode and meets HEAD token it should be ignored"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +/* + * According to http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-contents-insertion-mode + * when parser is in "template content" mode and meets <head> tag it should be switched to + * "in body" insertion mode. + * According to https://html.spec.whatwg.org/multipage/#parsing-main-inbody + * this token (HEAD) should be ignored + */ + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<head></head>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 0, + 'Template cannot contain HEAD element'); + +}, 'Ignore HEAD token. Test empty HEAD element assigned to template innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<head><title>test</title></head>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 1, + 'Wrong number of template content children'); + assert_equals(template.content.firstChild.nodeName, 'TITLE', + 'Template should contain children of ignored HEAD element'); + +}, 'Ignore HEAD token. Test not empty HEAD element assigned to template innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<div id="div1">Some text</div><head><title>test</title></head>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 2, + 'Wrong number of template content children'); + assert_not_equals(template.content.querySelector('#div1'), null, + 'Template should contain valid element'); + assert_equals(template.content.lastChild.tagName, 'TITLE', + 'Template should contain children of ignored HEAD element'); + +}, 'Ignore HEAD token. ' + + 'Test HEAD element and some valid element before it, assigned to template innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<head><title>test</title></head><div id="div1">Some text</div>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 2, + 'Wrong number of template content children'); + assert_equals(template.content.firstChild.tagName, 'TITLE', + 'Template should contain children of ignored HEAD element'); + assert_not_equals(template.content.querySelector('#div1'), null, + 'Template should contain valid element'); + +}, 'Ignore HEAD token. ' + + 'Test HEAD element and some valid element after it, assigned to template innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<template id="t2"><head><title>test</title></head></template>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 1, + 'Template should contain nested template'); + assert_not_equals(template.content.querySelector('#t2'), null, + 'Template should contain nested element'); + + var nestedTemplate = template.content.querySelector('#t2'); + + assert_equals(nestedTemplate.content.childNodes.length, 1, + 'Wrong number of template content children'); + assert_equals(nestedTemplate.content.firstChild.tagName, 'TITLE', + 'Template should contain children of ignored HEAD element'); + +}, 'Ignore HEAD token. ' + + 'Test HEAD tag inside template tag assigned to another template\'s innerHTML'); + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/template-contents-head.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.body.querySelector('template'); + + assert_equals(template.content.childNodes.length, 0, + 'Template cannot contain HEAD element'); + +}, 'Ignore HEAD token. Test loading a HTML file with HEAD tag inside template'); + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-html-token.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-html-token.html new file mode 100644 index 0000000..5c53be8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-html-token.html
@@ -0,0 +1,158 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: In body insertion mode: parser should ignore HTML token</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<meta name="assert" content="If parser is in 'in body' insertion mode and meets HTML token it should be ignored"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +/* + * According to http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-contents-insertion-mode + * when parser is in "template content" mode and meets <html> tag it should be switched to + * "in body" insertion mode. + * According to https://html.spec.whatwg.org/multipage/#parsing-main-inbody + * this token (HTML) should be ignored + */ + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<html><body></body></html>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 0, + 'Template cannot contain HTML element'); + +}, 'Ignore HTML token. Test HTML element assigned to template innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<div id="div1">Some text</div><html><body></body></html>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 1, + 'Template cannot contain HTML element'); + assert_not_equals(template.content.querySelector('#div1'), null, + 'Template should contain valid element'); + +}, 'Ignore HTML token.' + + 'Test HTML element and some valid element before it, assigned to template innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<html><body></body></html><div id="div1">Some text</div>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 1, + 'Template cannot contain HTML element'); + assert_not_equals(template.content.querySelector('#div1'), null, + 'Template should contain valid element'); + +}, 'Ignore HTML token. ' + + 'Test HEAD element and some valid element after it, assigned to template innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<template id="t2"><html><body></body></html></template>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 1, + 'Template should contain nested template'); + assert_not_equals(template.content.querySelector('#t2'), null, + 'Template should contain nested element'); + + var nestedTemplate = template.content.querySelector('#t2'); + + assert_equals(nestedTemplate.content.childNodes.length, 0, + 'Template cannot contain HTML element'); + +}, 'Ignore HTML token. ' + + 'Test HTML tag inside template tag assigned to another template\'s innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<html><div id="div1">Some text</div></html>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 1, + 'Template cannot contain HTML element'); + assert_not_equals(template.content.querySelector('#div1'), null, + 'Template should contain a valid element'); + +}, 'Ignore HTML token. Test some valid element inside HTML element'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<html><body><div id="div1">Some text</div><body></html>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 1, + 'Template cannot contain HTML element'); + assert_not_equals(template.content.querySelector('#div1'), null, + 'Template should contain valid element'); + +}, 'Ignore HTML token. Test valid element inside HTML and BODY elements'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<html><span id="span1">Span</span><body><div id="div1">Some text</div><body></html>'; + + doc.body.appendChild(template); + + assert_equals(template.content.childNodes.length, 2, + 'Template cannot contain HTML element'); + assert_not_equals(template.content.querySelector('#div1'), null, + 'Template should contain valid DIV element'); + + assert_not_equals(template.content.querySelector('#span1'), null, + 'Template should contain valid SPAN element'); + +}, 'Ignore HTML token. Test valid element inside and between HTML and BODY elements'); + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/template-contents-html.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.body.querySelector('template'); + + assert_equals(template.content.childNodes.length, 0, + 'Template cannot contain HTML element'); + +}, 'Ignore HTML token. Test loading a HTML file with HTML tag inside template'); + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-body.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-body.html new file mode 100644 index 0000000..738c861 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-body.html
@@ -0,0 +1,97 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: In body insertion mode: Template contains a start tag whose tag name is body</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="assert" content="If the stack of open elements has a template element in html scope then ignore <body> the token. (fragment or template contents case)"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + +test(function () { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '<template id="tmpl"><body></template>'; + + var template = doc.querySelector('#tmpl'); + + assert_equals(template.content.childNodes.length, 0, 'Element must be ignored'); + +}, 'In body insertion mode: Template contains a start tag whose tag name is body.' + + 'Test <body> tag only'); + + + +test(function () { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '<template id="tmpl"><body>Body text content</body></template>'; + + var template = doc.querySelector('#tmpl'); + + assert_equals(template.content.querySelector('body'), null, + '<body> element must be ignored'); + assert_equals(template.content.childNodes.length, 1, 'Text shouldn\'t be ignored'); + assert_equals(template.content.firstChild.nodeType, Node.TEXT_NODE, + 'Text shouldn\'t be ignored'); + +}, 'In body insertion mode: Template contains a start tag whose tag name is body. ' + + 'Test <body> tag containing some text'); + + + +test(function () { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '<template id="tmpl"><body>' + + '<div id="div1">DIV 1</div>' + + '<div id="div2">DIV 2</div>' + + '</body></template>'; + + var template = doc.querySelector('#tmpl'); + + assert_equals(template.content.querySelector('body'), null, + '<body> element must be ignored'); + assert_equals(template.content.childNodes.length, 2, + 'Only body tag should be ignored'); + assert_not_equals(template.content.querySelector('#div1'), null, + 'Children of <body tag shouldn\'t be ignored'); + assert_not_equals(template.content.querySelector('#div2'), null, + 'Children of <body tag shouldn\'t be ignored'); + +}, 'In body insertion mode: Template contains a start tag whose tag name is body. ' + + 'Test <body> tag containing some other elements'); + + + +test(function () { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '<template id="tmpl1"><template id="tmpl2"><body>' + + '<div id="div1">DIV 1</div>' + + '<div id="div2">DIV 2</div>' + + '</body></template></template>'; + + var template = doc.querySelector('#tmpl1').content.querySelector('#tmpl2'); + + assert_equals(template.content.querySelector('body'), null, + '<body> element must be ignored'); + assert_equals(template.content.childNodes.length, 2, + 'Only body tag should be ignored'); + assert_not_equals(template.content.querySelector('#div1'), null, + 'Children of <body tag shouldn\'t be ignored'); + assert_not_equals(template.content.querySelector('#div2'), null, + 'Children of <body tag shouldn\'t be ignored'); + +}, 'In body insertion mode: Template contains a start tag whose tag name is body. ' + + 'Test nested template tag containing <body> tag with some other elements'); + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-html.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-html.html new file mode 100644 index 0000000..33c43cd --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-html.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: In body insertion mode: A start tag whose tag name is html</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="assert" content="If HTML parser is in 'in body' insertion mode and meets HTML start tag, then for each attribute on the token, check to see if the attribute is already present on the top element of the stack of open elements. If it is not, add the attribute and its corresponding value to that element"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +// test <template><html class="htmlClass"></html></template><html id="htmlId" tabindex="5"> +// id attribute should be added to root <html> element +// tabindex attribute should not be modified +//class attribute should be ignored +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/html-start-tag.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.body.querySelector('template'); + + var html = doc.documentElement; + + assert_equals(html.getAttribute('tabindex'), '5', 'Attribute should be accessible'); + assert_equals(html.getAttribute('id'), 'htmlId', + 'Attribute \'id\' should be added and accessible'); + assert_false(html.hasAttribute('class'), 'Attribute \'class\' should be ignored'); + assert_equals(template.content.childNodes.length, 0, 'Template should not contain HTML element'); + + +}, 'In body insertion mode: html start tag should add only absent attributes'); + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/template-end-tag-without-start-one.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/template-end-tag-without-start-one.html new file mode 100644 index 0000000..ca124ee --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/template-end-tag-without-start-one.html
@@ -0,0 +1,102 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: 'In body' insertion mode: Template end tag without start one. Element should be ignored</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru"> +<meta name="assert" content="If parser in 'in body' insertion mode meets template end tag and if the stack of open elements has no template element in html scope, then this is a parse error; ignore the token"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + +test(function () { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '</template>'; + + assert_equals(doc.body.childNodes.length, 0, 'Element must be ignored'); + +}, '</template> tag in HTML body without start one should be ignored'); + + + +test(function () { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '<template id="tmpl"></template></template>'; + + assert_equals(doc.body.childNodes.length, 1, 'Element must be ignored'); + assert_not_equals(doc.querySelector('#tmpl'), null, + 'Element should present it document body'); + +}, '</template> tag in HTML body without start one should be ignored. ' + + 'Test valid <template> element and </template> tag after it'); + + + +test(function () { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '</template><template id="tmpl"></template>'; + + assert_equals(doc.body.childNodes.length, 1, 'Element must be ignored'); + assert_not_equals(doc.querySelector('#tmpl'), null, + 'Element should present it document body'); + +}, '</template> tag in HTML body without start one should be ignored. ' + + 'Test valid <template> element and </template> tag before it'); + + + +test(function () { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '</template><template id="tmpl"></template><title></title>'; + + assert_equals(doc.body.childNodes.length, 2, 'Element must be ignored'); + assert_not_equals(doc.querySelector('#tmpl'), null, + 'Valid element should present it document body'); + assert_not_equals(doc.querySelector('title'), null, + 'Valid title element should present it document body'); + +}, '</template> tag in HTML body without start one should be ignored. ' + + 'Test valid <template> element, <title> element and </template> tag before them'); + + + +test(function () { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '<template id="tmpl"></template><title></title></template>'; + + assert_equals(doc.body.childNodes.length, 2, 'Element must be ignored'); + assert_not_equals(doc.querySelector('#tmpl'), null, + 'Valid element should present it document body'); + assert_not_equals(doc.querySelector('title'), null, + 'Valid title element should present it document body'); + +}, '</template> tag in HTML body without start one should be ignored. ' + + 'Test valid <template> element, <title> element and </template> tag after them'); + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-body.html', function(context) { + var doc = context.iframes[0].contentDocument; + + assert_equals(doc.body.querySelector('template'), null, + '</template> must be ignored'); + assert_not_equals(doc.body.querySelector('div'), null, + 'Valid element should present it document body'); + +}, '</template> tag in HTML body without start one should be ignored. ' + + 'Test HTML document loaded from file'); + + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset-expected.txt new file mode 100644 index 0000000..5b5821c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL <template> tag should be ignored in "in frameset" insertion mode assert_equals: Wrong number of frameset children elements expected 0 but got 1 +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset.html new file mode 100644 index 0000000..f03f5a30 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: additions to 'in frameset' insertion mode</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="assert" content="If parser is in 'in frameset' insertion mode then a start tag or an end tag whose name is 'template' is a parsing error"> +<link rel="help" href="https://www.w3.org/TR/2015/WD-html51-20151008/syntax.html#parsing-main-inframeset"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/frameset-end-tag.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var frameset = doc.querySelector('frameset'); + assert_equals(frameset.children.length, 0, 'Wrong number of frameset children elements'); + +}, '<template> tag should be ignored in "in frameset" insertion mode'); + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/generating-of-implied-end-tags.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/generating-of-implied-end-tags.html new file mode 100644 index 0000000..2f7e6f63 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/generating-of-implied-end-tags.html
@@ -0,0 +1,137 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: When template end tag is met, implied end tags should be generated</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru"> +<meta name="assert" content="When template end tag is met, implied end tags should be generated"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-head-addition"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + +test(function () { + var doc = newHTMLDocument(); + + //No end </td></tr></table> tags. Should be added implicitly + doc.head.innerHTML = '<template id="tpl">' + + '<table id="tbl"><tr id="tr"><td id="td"></template>'; + + var template = doc.querySelector('#tpl'); + + assert_not_equals(template, null, 'Template element must be parsed'); + + assert_equals(doc.querySelector('#tbl'), null, 'Table element should not be available'); + assert_equals(doc.querySelector('#tr'), null, 'TR element should not be available'); + assert_equals(doc.querySelector('#td'), null, 'TD element should not be available'); + + assert_not_equals(template.content.querySelector('#tbl'), null, + 'Template should contain table element'); + assert_not_equals(template.content.querySelector('#tr'), null, + 'Template should contain TR element'); + assert_not_equals(template.content.querySelector('#td'), null, + 'Template should contain TD element'); + +}, 'Generating of implied end tags. Test table elements'); + + + +test(function () { + var doc = newHTMLDocument(); + + //No end </div> tag. Should be added implicitly + doc.head.innerHTML = '<template id="tpl"><div id="dv">Div content</template>'; + + var template = doc.querySelector('#tpl'); + + assert_not_equals(template, null, 'Template element must be parsed'); + + assert_equals(doc.querySelector('#dv'), null, 'DIV element should not be available'); + + assert_not_equals(template.content.querySelector('#dv'), null, + 'Template should contain DIV element'); + +}, 'Generating of implied end tags. Test DIV element'); + + +test(function () { + var doc = newHTMLDocument(); + + //No end </div> tag. Should be added implicitly after text content + doc.head.innerHTML = '<template id="tpl">Template text<div id="dv">Div content</template>'; + + var template = doc.querySelector('#tpl'); + + assert_not_equals(template, null, 'Template element must be parsed'); + + assert_equals(doc.querySelector('#dv'), null, 'DIV element should not be available'); + + var div = template.content.querySelector('#dv'); + + assert_not_equals( div, null, 'Template should contain DIV element'); + assert_equals(div.textContent, 'Div content', 'Wrong template content inner text'); + +}, 'Generating of implied end tags. Test some text and DIV element'); + + +test(function () { + var doc = newHTMLDocument(); + + // Wrong end tag. Correct end tag must be added implicitly, wrong one ignored + doc.head.innerHTML = '<template id="tpl"><div id="dv">Div content</span></template>'; + + var template = doc.querySelector('#tpl'); + + assert_not_equals(template, null, 'Template element must be parsed'); + + assert_equals(template.content.childNodes.length, 1, + 'Wrong number of template\'s children'); + + assert_equals(doc.querySelector('#dv'), null, 'DIV element should not be available'); + + assert_not_equals(template.content.querySelector('#dv'), null, + 'Template should contain DIV element'); + assert_equals(template.content.querySelector('#dv').textContent, + 'Div content', 'Wrong template content inner text'); + +}, 'Generating of implied end tags. Test wrong end tag'); + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/head-template-contents-table-no-end-tag.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.head.querySelector('template'); + + assert_not_equals(template, null, + 'Template element must be parsed'); + + assert_not_equals(template.content.querySelector('table'), null, + 'Template should contain table element'); + assert_not_equals(template.content.querySelector('tr'), null, + 'Template should contain TR element'); + assert_not_equals(template.content.querySelector('td'), null, + 'Template should contain TD element'); + +}, 'Generating of implied end tags. Test table elements. Load HTML document from file'); + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/head-template-contents-div-no-end-tag.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.head.querySelector('template'); + + assert_not_equals(template, null, 'Template element must be parsed'); + + var div = template.content.querySelector('div'); + assert_not_equals(div, null, 'Template should contain div element'); + assert_equals(div.textContent, 'Hello, template\n ', 'Invalid div contents'); + +}, 'Generating of implied end tags. Test div element. Load HTML document from file'); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/template-end-tag-without-start-one.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/template-end-tag-without-start-one.html new file mode 100644 index 0000000..ccb4334 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/template-end-tag-without-start-one.html
@@ -0,0 +1,101 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Template end tag without start one. Element should be ignored</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru"> +<meta name="assert" content="If parser in 'in head' insertion mode meets template end tag and if the stack of open elements has no template element in html scope, then this is a parse error; ignore the token"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-head-addition"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + +test(function () { + var doc = newHTMLDocument(); + + doc.head.innerHTML = '</template>'; + + assert_equals(doc.head.childNodes.length, 0, 'Element must be ignored'); + +}, '</template> tag in HTML head without start one should be ignored'); + + + +test(function () { + var doc = newHTMLDocument(); + + doc.head.innerHTML = '<template id="tmpl"></template></template>'; + + assert_equals(doc.head.childNodes.length, 1, 'Element must be ignored'); + assert_not_equals(doc.querySelector('#tmpl'), null, + 'Element should present it document head'); + +}, '</template> tag in HTML head without start one should be ignored. ' + + 'Test valid <template> element and </template> tag after it'); + + + +test(function () { + var doc = newHTMLDocument(); + + doc.head.innerHTML = '</template><template id="tmpl"></template>'; + + assert_equals(doc.head.childNodes.length, 1, 'Element must be ignored'); + assert_not_equals(doc.querySelector('#tmpl'), null, + 'Element should present it document head'); + +}, '</template> tag in HTML head without start one should be ignored. ' + + 'Test valid <template> element and </template> tag before it'); + + + +test(function () { + var doc = newHTMLDocument(); + + doc.head.innerHTML = '</template><template id="tmpl"></template><title></title>'; + + assert_equals(doc.head.childNodes.length, 2, 'Element must be ignored'); + assert_not_equals(doc.querySelector('#tmpl'), null, + 'Valid element should present it document head'); + assert_not_equals(doc.querySelector('title'), null, + 'Valid title element should present it document head'); + +}, '</template> tag in HTML head without start one should be ignored. ' + + 'Test valid <template> element, <title> element and </template> tag before them'); + + + +test(function () { + var doc = newHTMLDocument(); + + doc.head.innerHTML = '<template id="tmpl"></template><title></title></template>'; + + assert_equals(doc.head.childNodes.length, 2, 'Element must be ignored'); + assert_not_equals(doc.querySelector('#tmpl'), null, + 'Valid element should present it document head'); + assert_not_equals(doc.querySelector('title'), null, + 'Valid title element should present it document head'); + +}, '</template> tag in HTML head without start one should be ignored. ' + + 'Test valid <template> element, <title> element and </template> tag after them'); + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-head.html', function(context) { + var doc = context.iframes[0].contentDocument; + + assert_equals(doc.head.querySelector('template'), null, '</template> must be ignored'); + assert_not_equals(doc.head.querySelector('title'), null, + 'Valid element should present it document head'); + +}, '</template> tag in HTML head without start one should be ignored. ' + + 'Test HTML document loaded from file'); + + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-table-insertion-mode/end-tag-table.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-table-insertion-mode/end-tag-table.html new file mode 100644 index 0000000..feb2eb10 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-table-insertion-mode/end-tag-table.html
@@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: 'In table' insertion mode: ignore TABLE end tag</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="assert" content="If parser is in 'in table' insertion mode and end tag table is met the ignore this token"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-table-addition"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + +test(function () { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '<table id="table">' + + '<template id="template">' + + '</table>' + + '</template>' + + '<tr><td></td></tr>' + + '</table>'; + + var table = doc.querySelector('#table'); + var template = table.querySelector('#template'); + + assert_equals(table.childNodes.length, 2, 'Wrong number of table children'); + assert_not_equals(template, null, 'Template element must be parsed'); + assert_equals(table.rows.length, 1, 'Wrong number of table rows'); + assert_equals(template.childNodes.length, 0, 'Wrong number of the template child nodes'); + assert_equals(template.content.childNodes.length, 0, + 'Wrong number of the template child nodes'); + + +}, 'In table insertion mode. Ignore </table> token'); + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/appending-to-a-template/template-child-nodes.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/appending-to-a-template/template-child-nodes.html new file mode 100644 index 0000000..6292c35 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/appending-to-a-template/template-child-nodes.html
@@ -0,0 +1,116 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: HTML parser appends child nodes only to the template contents node</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<meta name="assert" content="HTML parser must append template's child nodes only to the template contents node."> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#appending-to-a-template"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + +test(function () { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template id="tmpl1">' + + '<div id="div1">This is div inside template</div>' + + '<div id="div2">This is another div inside template</div>' + + '</template>'; + + var template = doc.querySelector('#tmpl1'); + + assert_equals(template.childNodes.length, 0, 'Wrong number of template child nodes'); + assert_equals(template.content.childNodes.length, 2, + 'Wrong number of template content child nodes'); + + assert_not_equals(template.content.querySelector('#div1'), null, + 'Element is absent in the template content'); + assert_not_equals(template.content.querySelector('#div2'), null, + 'Element is absent in the template content'); + +}, 'Template child nodes must be appended to template content node'); + + + +test(function () { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template id="tmpl1">' + + '<div id="div1">This is div inside template</div>' + + '<div id="div2">This is another div inside template</div>' + + '<template id="tmpl2">' + + '<div id="div3">This is div inside nested template</div>' + + '<div id="div4">This is another div inside nested template</div>' + + '</template>' + + '</template>'; + + var template = doc.querySelector('#tmpl1'); + + assert_equals(template.childNodes.length, 0, + 'Wrong number of template child nodes'); + assert_equals(template.content.childNodes.length, 3, + 'Wrong number of template content child nodes'); + + assert_not_equals(template.content.querySelector('#div1'), null, + 'Element is absent in the template content'); + assert_not_equals(template.content.querySelector('#div2'), null, + 'Element is absent in the template content'); + + var nestedTemplate = template.content.querySelector('#tmpl2'); + + assert_equals(nestedTemplate.childNodes.length, 0, + 'Wrong number of template child nodes'); + assert_equals(nestedTemplate.content.childNodes.length, 2, + 'Wrong number of nested template content child nodes'); + + assert_not_equals(nestedTemplate.content.querySelector('#div3'), null, + 'Element is absent in the template content'); + assert_not_equals(nestedTemplate.content.querySelector('#div4'), null, + 'Element is absent in the template content'); + +}, 'Template child nodes must be appended to template content. Test nested template'); + + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/template-contents.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.querySelector('template'); + + assert_equals(template.childNodes.length, 0, 'Wrong number of template child nodes'); + + assert_not_equals(template.content.querySelector('div'), null, + 'Element is absent in the template content'); + +}, 'Template child nodes must be appended to template content node. ' + + 'Load HTML document from a file'); + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/template-contents-nested.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.querySelector('template'); + + assert_equals(template.childNodes.length, 0, 'Wrong number of template child nodes'); + + var nestedTemplate = template.content.querySelector('template'); + + assert_not_equals(nestedTemplate, null, + 'Element is absent in the template content'); + + assert_equals(nestedTemplate.childNodes.length, 0, + 'Wrong number of template child nodes'); + + assert_not_equals(nestedTemplate.content.querySelector('div'), null, + 'Element is absent in the template content'); + +}, 'Template child nodes must be appended to nested template content node. ' + + 'Load HTML document from a file'); + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-body-context.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-body-context.html new file mode 100644 index 0000000..a150faa --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-body-context.html
@@ -0,0 +1,182 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Clearing stack back to a table body context</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="assert" content="Clearing the stack back to a table body context must be aborted if the current node is template"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#clearing-the-stack"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +function doTest(doc, tagToTest, templateInnerHTML, id, tagName, bodiesNum, footerIsNull, + footerId, headerIsNull, headerId) { + + doc.body.innerHTML = '' + + '<table id="tbl">' + + '<' + tagToTest + '>' + + '<template id="tmpl1">' + + // When parser meets <tr>, </tbody>, </tfoot>, </thead>, <caption>, <col>, + // <colgroup>, <tbody>, <tfoot>, <thead>, </table> + // stack must be cleared back to table body context. But <template> tag should + // abort this + templateInnerHTML + + '</template>' + + '<tr id="tr">' + + '<td id="td">' + + '</td>' + + '</tr>' + + '</' + tagToTest + '>' + + '</table>'; + + var table = doc.querySelector('#tbl'); + var tr = doc.querySelector('#tr'); + var td = doc.querySelector('#td'); + var template = doc.querySelector('#tmpl1'); + + assert_equals(table.rows.length, 1, 'Wrong number of table rows'); + assert_equals(table.rows[0].cells.length, 1, 'Wrong number of table cells'); + if (id !== null) { + assert_not_equals(template.content.querySelector('#' + id), null, + 'Element should present in the template content'); + } + if (tagName !== null) { + assert_equals(template.content.querySelector('#' + id).tagName, tagName, + 'Wrong element in the template content'); + } + + assert_equals(table.caption, null, 'Table should have no caption'); + + if (bodiesNum) { + assert_equals(table.tBodies.length, bodiesNum, 'Table should have ' + + bodiesNum + ' body'); + } + if (footerIsNull) { + assert_equals(table.tFoot, null, 'Table should have no footer'); + } + if (footerId) { + assert_not_equals(table.tFoot.id, footerId, + 'Table should have no footer with id="' + footerId + '"'); + } + if (headerIsNull) { + assert_equals(table.tHead, null, 'Table should have no header'); + } + if (headerId) { + assert_not_equals(table.tHead.id, headerId, + 'Table should have no header with id="' + headerId + '"'); + } +} + + + +var doc = newHTMLDocument(); +var parameters = [ + ['Clearing stack back to a table body context. Test <tr> in <tbody>', + doc, 'tbody', '<tr id="tr1"><td>Cell content</td></tr>', 'tr1', 'TR'], + + ['Clearing stack back to a table body context. Test <tr> in <thead>', + doc, 'thead', '<tr id="tr2"><td>Cell content</td></tr>', 'tr2', 'TR'], + + ['Clearing stack back to a table body context. Test <tr> in <tfoot>', + doc, 'tfoot', '<tr id="tr3"><td>Cell content</td></tr>', 'tr3', 'TR'], + + ['Clearing stack back to a table body context. Test </tbody>', + doc, 'tbody', '</tbody>', null, null], + + ['Clearing stack back to a table body context. Test </thead>', + doc, 'thead', '</thead>', null, null], + + ['Clearing stack back to a table body context. Test </tfoot>', + doc, 'tfoot', '</tfoot>', null, null], + + ['Clearing stack back to a table body context. Test <caption> in <tbody>', + doc, 'tbody', '<caption id="caption1">Table Caption</caption>', 'caption1', 'CAPTION'], + + ['Clearing stack back to a table body context. Test <caption> in <tfoot>', + doc, 'tfoot', '<caption id="caption2">Table Caption</caption>', 'caption2', 'CAPTION'], + + ['Clearing stack back to a table body context. Test <caption> in <thead>', + doc, 'thead', '<caption id="caption3">Table Caption</caption>', 'caption3', 'CAPTION'], + + ['Clearing stack back to a table body context. Test <col> in <tbody>', + doc, 'tbody', '<col id="col1" width="150"/>', 'col1', 'COL'], + + ['Clearing stack back to a table body context. Test <col> in <tfoot>', + doc, 'tfoot', '<col id="col2" width="150"/>', 'col2', 'COL'], + + ['Clearing stack back to a table body context. Test <col> in <thead>', + doc, 'thead', '<col id="col3" width="150"/>', 'col3', 'COL'], + + ['Clearing stack back to a table body context. Test <colgroup> in <tbody>', + doc, 'tbody', '<colgroup id="colgroup1" width="150"/>', 'colgroup1', 'COLGROUP'], + + ['Clearing stack back to a table body context. Test <colgroup> in <tfoot>', + doc, 'tfoot', '<colgroup id="colgroup2" width="150"/>', 'colgroup2', 'COLGROUP'], + + ['Clearing stack back to a table body context. Test <colgroup> in <thead>', + doc, 'thead', '<colgroup id="colgroup3" width="150"/>', 'colgroup3', 'COLGROUP'], + + ['Clearing stack back to a table body context. Test <tbody> in <tbody>', + doc, 'tbody', '<tbody id="tbody1"></tbody>', 'tbody1', 'TBODY', 1], + + ['Clearing stack back to a table body context. Test <tbody> in <tfoot>', + doc, 'tfoot', '<tbody id="tbody2"></tbody>', 'tbody2', 'TBODY', 0], + + ['Clearing stack back to a table body context. Test <tbody> in <thead>', + doc, 'thead', '<tbody id="tbody3"></tbody>', 'tbody3', 'TBODY', 0], + + ['Clearing stack back to a table body context. Test <tfoot> in <tbody>', + doc, 'tbody', '<tfoot id="tfoot1"></tfoot>', 'tfoot1', 'TFOOT', null, true], + + ['Clearing stack back to a table body context. Test <tfoot> in <tfoot>', + doc, 'tfoot', '<tfoot id="tfoot2"></tfoot>', 'tfoot2', 'TFOOT', null, false, 'tfoot2'], + + ['Clearing stack back to a table body context. Test <tfoot> in <thead>', + doc, 'thead', '<tfoot id="tfoot3"></tfoot>', 'tfoot3', 'TFOOT', null, true], + + ['Clearing stack back to a table body context. Test <thead> in <tbody>', + doc, 'tbody', '<thead id="thead1"></thead>', 'thead1', 'THEAD', null, false, null, true], + + ['Clearing stack back to a table body context. Test <thead> in <tfoot>', + doc, 'tfoot', '<thead id="thead2"></thead>', 'thead2', 'THEAD', null, false, null, true], + + ['Clearing stack back to a table body context. Test <thead> in <thead>', + doc, 'thead', '<thead id="thead3"></thead>', 'thead3', 'THEAD', null, false, null, false, 'thead3'], + + ['Clearing stack back to a table body context. Test </table> in <tbody>', + doc, 'tbody', '</table>', null, null, null, false, null, true], + + ['Clearing stack back to a table body context. Test </table> in <tfoot>', + doc, 'tfoot', '</table>', null, null, null, false, null, true], + + ['Clearing stack back to a table body context. Test </table> in <thead>', + doc, 'thead', '</table>', null, null], + + ['Clearing stack back to a table body context. Test </tbody> in <thead>', + doc, 'thead', '</tbody>', null, null], + + ['Clearing stack back to a table body context. Test </tbody> in <tfoot>', + doc, 'tfoot', '</tbody>', null, null], + + ['Clearing stack back to a table body context. Test </thead> in <tbody>', + doc, 'tbody', '</thead>', null, null], + + ['Clearing stack back to a table body context. Test </thead> in <tfoot>', + doc, 'tfoot', '</thead>', null, null], + + ['Clearing stack back to a table body context. Test </tfoot> in <thead>', + doc, 'thead', '</tfoot>', null, null], + + ['Clearing stack back to a table body context. Test </tfoot> in <tbody>', + doc, 'tbody', '</tfoot>', null, null] +]; + +generate_tests(doTest, parameters, 'Clearing stack back to a table body context.'); + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-context.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-context.html new file mode 100644 index 0000000..23a4e7b0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-context.html
@@ -0,0 +1,84 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Clearing stack back to a table context</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="assert" content="Clearing the stack back to a table context must be aborted if the current node is template"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#clearing-the-stack"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +function doTest(doc, templateInnerHTML, id, tagName, bodiesNum, footerIsNull, + headerIsNull) { + + doc.body.innerHTML = '' + + '<table id="tbl">' + + '<template id="tmpl1">' + + // When parser meets <caption>, <colgroup>, <tbody>, <tfoot>, <thead>, <col> + // stack must be cleared back to table context. + //But <template> tag should abort this process + templateInnerHTML + + '</template>' + + '<tr id="tr">' + + '<td id="td">' + + '</td>' + + '</tr>' + + '</table>'; + + var table = doc.querySelector('#tbl'); + var tr = doc.querySelector('#tr'); + var td = doc.querySelector('#td'); + var template = doc.querySelector('#tmpl1'); + + assert_equals(table.rows.length, 1, 'Wrong number of table rows'); + assert_equals(table.rows[0].cells.length, 1, 'Wrong number of table cells'); + assert_equals(template.parentNode, table, 'Wrong template parent'); + assert_not_equals(template.content.querySelector('#' + id), null, + 'Element should present in the template content'); + assert_equals(doc.querySelector('#tbl').caption, null, 'Table should have no caption'); + assert_equals(template.content.querySelector('#' + id).tagName, tagName, + 'Wrong element in the template content'); + if (bodiesNum) { + assert_equals(table.tBodies.length, bodiesNum, 'Table should have ' + + bodiesNum + ' body'); + } + if (footerIsNull) { + assert_equals(table.tFoot, null, 'Table should have no footer'); + } + if (headerIsNull) { + assert_equals(table.tHead, null, 'Table should have no header'); + } +} + + +var doc = newHTMLDocument(); +var parameters = [ + ['Clearing stack back to a table context. Test <caption>', + doc, '<caption id="caption1">Table caption</caption>', 'caption1', 'CAPTION'], + + ['Clearing stack back to a table context. Test <colgroup>', + doc, '<colgroup id="colgroup1" width="100%"/>', 'colgroup1', 'COLGROUP'], + + ['Clearing stack back to a table context. Test <tbody>', + doc, '<tbody id="tbody1"></tbody>', 'tbody1', 'TBODY', 1], + + ['Clearing stack back to a table context. Test <tfoot>', + doc, '<tfoot id="tfoot1"></tfoot>', 'tfoot1', 'TFOOT', null, true], + + ['Clearing stack back to a table context. Test <thead>', + doc, '<thead id="thead1"></thead>', 'thead1', 'THEAD', null, false, true], + + ['Clearing stack back to a table context. Test <col>', + doc, '<col id="col1" width="100%"/>', 'col1', 'COL'] +]; + +generate_tests(doTest, parameters, 'Clearing stack back to a table body context.'); + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-row-context.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-row-context.html new file mode 100644 index 0000000..2503916 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-row-context.html
@@ -0,0 +1,71 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Clearing stack back to a table row context</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="assert" content="Clearing the stack back to a table row context must be aborted if the current node is template"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#clearing-the-stack"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +function doTest(doc, templateInnerHTML, id, tagName, elementId) { + + doc.body.innerHTML = '' + + '<table id="tbl">' + + '<tr id="tr">' + + '<template id="tmpl1">' + + // When parser meets <th>, <td>, </tr>, stack must be cleared + // back to table row context. + // But <template> tag should abort this + templateInnerHTML + + '</template>' + + '<td id="td">' + + '</td>' + + '</tr>' + + '</table>'; + + var table = doc.querySelector('#tbl'); + var tr = doc.querySelector('#tr'); + var td = doc.querySelector('#td'); + var template = doc.querySelector('#tmpl1'); + + assert_equals(table.rows.length, 1, 'Wrong number of table rows'); + assert_equals(table.rows[0].cells.length, 1, 'Wrong number of table cells'); + assert_equals(template.parentNode, tr, 'Wrong template parent'); + if (id !== null) { + assert_not_equals(template.content.querySelector('#' + id), null, + 'Element should present in the template content'); + } + if (tagName !== null) { + assert_equals(template.content.querySelector('#' + id).tagName, tagName, + 'Wrong element in the template content'); + } + if (elementId) { + assert_equals(doc.querySelector('#' + elementId), null, + 'Table should have no element with ID ' + elementId); + } +} + + +var doc = newHTMLDocument(); +var parameters = [ + ['Clearing stack back to a table row context. Test <th>', + doc, '<th id="th1">Table header</th>', 'th1', 'TH', 'th1'], + + ['Clearing stack back to a table row context. Test <td>', + doc, '<td id="td1">Table cell</td>', 'td1', 'TD', 'td1'], + + ['Clearing stack back to a table row context. Test </tr>', + doc, '</tr>', null, null] +]; + +generate_tests(doTest, parameters, 'Clearing stack back to a table body context.'); + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/creating-an-element-for-the-token/template-owner-document.html b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/creating-an-element-for-the-token/template-owner-document.html new file mode 100644 index 0000000..e1f9995 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/creating-an-element-for-the-token/template-owner-document.html
@@ -0,0 +1,221 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: ownerDocument property of the element in template</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<meta name="assert" content="ownerDocument property of the element appended to template must be set to the template contents owner of the ownerDocument of the template element"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#creating-an-element-for-a-token"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/html/resources/common.js"></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + +test(function () { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<div><template id="tmpl1"><div id="div">DIV</div></template></div>'; + + var template = doc.querySelector('#tmpl1'); + + var div = template.content.querySelector('#div'); + + assert_equals(div.ownerDocument, template.content.ownerDocument, + 'Wrong ownerDocument of the element in template'); + +}, 'Test ownerDocument property of the element in a template. ' + + 'Current DOCUMENT has no browsing context. Test template element inside the div'); + + + +test(function () { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template id="tmpl1"><div id="div">DIV</div></template>'; + + var template = doc.querySelector('#tmpl1'); + + var div = template.content.querySelector('#div'); + + assert_equals(div.ownerDocument, template.content.ownerDocument, + 'Wrong ownerDocument of the element in template'); + +}, 'Test ownerDocument property of the element in a template. ' + + 'Current DOCUMENT has no browsing context. Test template element ' + + 'in the root of the body'); + + + +test(function () { + var doc = newHTMLDocument(); + doc.head.innerHTML = '<template id="tmpl1"><div id="div">DIV</div></template>'; + + var template = doc.querySelector('#tmpl1'); + + var div = template.content.querySelector('#div'); + + assert_equals(div.ownerDocument, template.content.ownerDocument, + 'Wrong ownerDocument of the element in template'); + +}, 'Test ownerDocument property of the element in a template. ' + + 'Current DOCUMENT has no browsing context. Test template element ' + + 'in the root of the head'); + + + +test(function () { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template id="tmpl1">' + + '<template id="tmpl2"><div id="div">DIV</div></template></template>'; + + var template = doc.querySelector('#tmpl1'); + + var nestedTemplate = template.content.querySelector('#tmpl2'); + + assert_equals(nestedTemplate.ownerDocument, template.content.ownerDocument, + 'Wrong nested template owner document'); + + var div = nestedTemplate.content.querySelector('#div'); + + assert_equals(div.ownerDocument, nestedTemplate.content.ownerDocument, + 'Wrong div ownerDocument'); + +}, 'Test ownerDocument property of the element in a nested template'); + + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/template-contents.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.querySelector('template'); + + var div = template.content.querySelector('div'); + + assert_equals(div.ownerDocument, template.content.ownerDocument, + 'Wrong ownerDocument of the element in template'); + +}, 'Test ownerDocument property of the element in a template. ' + + 'Load HTML document from a file, current DOCUMENT has browsing context'); + + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/template-contents-nested.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.querySelector('template'); + + var nestedTemplate = template.content.querySelector('template'); + + assert_equals(nestedTemplate.ownerDocument, template.content.ownerDocument, + 'Wrong nested template owner document'); + + var div = nestedTemplate.content.querySelector('div'); + + assert_equals(div.ownerDocument, nestedTemplate.content.ownerDocument, + 'Wrong div ownerDocument'); + +}, 'Test ownerDocument property of the element in a nested template. ' + + 'Load HTML document from a file, current DOCUMENT has browsing context'); + + + +testInIFrame('/html/semantics/scripting-1/the-template-element/resources/two-templates.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template1 = doc.querySelector('#template1'); + var div1 = template1.content.querySelector('div'); + var template2 = doc.querySelector('#template2'); + var div2 = template2.content.querySelector('div'); + + assert_equals(div1.ownerDocument, template1.content.ownerDocument, + 'Wrong ownerDocument of the element in template'); + assert_equals(div2.ownerDocument, template2.content.ownerDocument, + 'Wrong ownerDocument of the element in template'); + assert_equals(div1.ownerDocument, div2.ownerDocument, + 'Different elements in the same document should share the same template contents owner'); + +}, 'Test ownerDocument property of two elements in a template. ' + + 'Load HTML document from a file, current DOCUMENT has browsing context'); + + +var parameters = []; + +HTML5_ELEMENTS.forEach(function(value) { + if (value !== 'body' && value !== 'html' && value !== 'head' && value !== 'frameset') { + + var doc = newHTMLDocument(); + + if (isVoidElement(value)) { + doc.body.innerHTML = '<template><' + value + '/></template>'; + } else { + doc.body.innerHTML = '<template><' + value + '></' + value + '></template>'; + } + + var template = doc.querySelector('template'); + var element = template.content.querySelector(value); + + doc.body.appendChild(template); + + parameters.push([ + 'Test ownerDocument for the element ' + value + ' in the template', + element, + template + ]); + } +}); + +function compare_owners(element, template) { + assert_equals(element.ownerDocument, template.content.ownerDocument) +} + +generate_tests(compare_owners, parameters, + 'Test ownerDocument property of all HTML5 elements in a template. ' + + 'Current DOCUMENT has no browsing context.'); + +var context = newContext(); +parameters = []; + +try { + + HTML5_ELEMENTS.forEach(function(value) { + + if (value !== 'body' && value !== 'html' && value !== 'head' && value !== 'frameset') { + + var doc = newRenderedHTMLDocument(context); + + if (isVoidElement(value)) { + doc.body.innerHTML = '<template><' + value + '/></template>'; + } else { + doc.body.innerHTML = '<template><' + value + '></' + value + '></template>'; + } + + var template = doc.querySelector('template'); + var element = template.content.querySelector(value); + + doc.body.appendChild(template); + + parameters.push([ + 'Test ownerDocument for the element ' + value + ' in the template. ' + + 'Document has browsing context', + element, + template + ]); + } + }); + generate_tests(compare_owners, parameters, + 'Test ownerDocument property of all HTML5 elements in a template. ' + + 'Current DOCUMENT has browsing context.'); + +} finally { + try { + cleanContext(context); + } catch (e) { + //do nothing + } +} + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html new file mode 100644 index 0000000..1956a20 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html
@@ -0,0 +1,10 @@ +<!doctype html> +<meta charset=utf-8> +<title>NavigatorID</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src=NavigatorID.js></script> +<div id="log"></div> +<script> +run_test(); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/pointerevents/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/idlharness-expected.txt index 107597a1..d4573e8 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/pointerevents/idlharness-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/idlharness-expected.txt
@@ -1,4 +1,4 @@ -CONSOLE MESSAGE: line 236: callback not yet supported +CONSOLE MESSAGE: line 251: callback not yet supported This is a testharness.js-based test. PASS Window interface: attribute ongotpointercapture PASS Window interface: attribute onlostpointercapture
diff --git a/third_party/WebKit/LayoutTests/external/wpt/pointerevents/pointerevent_constructor.html b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/pointerevent_constructor.html index b2a779d..b8a97d1 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/pointerevents/pointerevent_constructor.html +++ b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/pointerevent_constructor.html
@@ -33,6 +33,8 @@ var testButton = 0; var testButtons = 1; var testPressure = 0.4; + var testTangentialPressure = 0.5; + var testTwist = 286; var testIsPrimary = true; on_event(target0, "pointerover", this.step_func(function(event) { @@ -50,10 +52,12 @@ ["custom clientY", event.clientY, testClientY], ["custom tiltX", event.tiltX, testTiltX], ["custom tiltY", event.tiltY, testTiltY], + ["custom twist", event.twist, testTwist], ["custom isPrimary", event.isPrimary, testIsPrimary] ]); test(function() { assert_approx_equals(event.pressure, testPressure, 0.00000001, "custom pressure: "); + assert_approx_equals(event.tangentialPressure, testTangentialPressure, 0.00000001, "custom tangential pressure: "); }, "custom pressure: "); })); @@ -66,6 +70,8 @@ ["default tiltX", event.tiltX, 0], ["default tiltY", event.tiltY, 0], ["default pressure", event.pressure, 0], + ["default tangentialPressure", event.tangentialPressure, 0], + ["default twist", event.twist, 0], ["default isPrimary", event.isPrimary, false] ]); })); @@ -87,6 +93,8 @@ button: testButton, buttons: testButtons, pressure: testPressure, + tangentialPressure: testTangentialPressure, + twist: testTwist, isPrimary: testIsPrimary }); // A PointerEvent created with a PointerEvent constructor must have all its attributes set to the corresponding values provided to the constructor.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js index 7d0abf4..da77fe7 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
@@ -49,14 +49,19 @@ (function(){ "use strict"; /// Helpers /// -function constValue (cnt) { +function constValue (cnt) +//@{ +{ if (cnt.type === "null") return null; if (cnt.type === "NaN") return NaN; if (cnt.type === "Infinity") return cnt.negative ? -Infinity : Infinity; return cnt.value; } -function minOverloadLength(overloads) { +//@} +function minOverloadLength(overloads) +//@{ +{ if (!overloads.length) { return 0; } @@ -69,7 +74,10 @@ .reduce(function(m, n) { return Math.min(m, n); }); } -function throwOrReject(a_test, operation, fn, obj, args, message, cb) { +//@} +function throwOrReject(a_test, operation, fn, obj, args, message, cb) +//@{ +{ if (operation.idlType.generic !== "Promise") { assert_throws(new TypeError(), function() { fn.apply(obj, args); @@ -87,7 +95,10 @@ } } -function awaitNCallbacks(n, cb, ctx) { +//@} +function awaitNCallbacks(n, cb, ctx) +//@{ +{ var counter = 0; return function() { counter++; @@ -97,7 +108,10 @@ }; } -var fround = (function(){ +//@} +var fround = +//@{ +(function(){ if (Math.fround) return Math.fround; var arr = new Float32Array(1); @@ -106,6 +120,7 @@ return arr[0]; }; })(); +//@} /// IdlArray /// // Entry point @@ -448,7 +463,7 @@ } if (type.generic === "Promise") { - assert_own_property(value, "then", "Attribute with a Promise type has a then property"); + assert_true("then" in value, "Attribute with a Promise type has a then property"); // TODO: Ideally, we would check on project fulfillment // that we get the right type // but that would require making the type check async @@ -650,7 +665,9 @@ IdlDictionary.prototype = Object.create(IdlObject.prototype); /// IdlInterface /// -function IdlInterface(obj, is_callback) { +function IdlInterface(obj, is_callback) +//@{ +{ /** * obj is an object produced by the WebIDLParser.js "interface" production. */ @@ -687,6 +704,7 @@ this._is_callback = is_callback; } +//@} IdlInterface.prototype = Object.create(IdlObject.prototype); IdlInterface.prototype.is_callback = function() //@{ @@ -783,8 +801,8 @@ if (this.is_callback()) { // "The internal [[Prototype]] property of an interface object for - // a callback interface MUST be the Object.prototype object." - assert_equals(Object.getPrototypeOf(self[this.name]), Object.prototype, + // a callback interface must be the Function.prototype object." + assert_equals(Object.getPrototypeOf(self[this.name]), Function.prototype, "prototype of self's property " + format_value(this.name) + " is not Object.prototype"); return; @@ -1117,10 +1135,12 @@ //@} IdlInterface.prototype.test_member_attribute = function(member) //@{ -{ - test(function() + { + var a_test = async_test(this.name + " interface: attribute " + member.name); + a_test.step(function() { if (this.is_callback() && !this.has_constants()) { + a_test.done() return; } @@ -1133,6 +1153,7 @@ assert_own_property(self[this.name], member.name, "The interface object must have a property " + format_value(member.name)); + a_test.done(); } else if (this.is_global()) { assert_own_property(self, member.name, "The global object must have a property " + @@ -1161,23 +1182,42 @@ "Gets on a global should not require an explicit this"); } - this.do_interface_attribute_asserts(self, member); + // do_interface_attribute_asserts must be the last thing we do, + // since it will call done() on a_test. + this.do_interface_attribute_asserts(self, member, a_test); } else { assert_true(member.name in self[this.name].prototype, "The prototype object must have a property " + format_value(member.name)); if (!member.has_extended_attribute("LenientThis")) { - assert_throws(new TypeError(), function() { - self[this.name].prototype[member.name]; - }.bind(this), "getting property on prototype object must throw TypeError"); + if (member.idlType.generic !== "Promise") { + assert_throws(new TypeError(), function() { + self[this.name].prototype[member.name]; + }.bind(this), "getting property on prototype object must throw TypeError"); + // do_interface_attribute_asserts must be the last thing we + // do, since it will call done() on a_test. + this.do_interface_attribute_asserts(self[this.name].prototype, member, a_test); + } else { + promise_rejects(a_test, new TypeError(), + self[this.name].prototype[member.name]) + .then(function() { + // do_interface_attribute_asserts must be the last + // thing we do, since it will call done() on a_test. + this.do_interface_attribute_asserts(self[this.name].prototype, + member, a_test); + }.bind(this)); + } } else { assert_equals(self[this.name].prototype[member.name], undefined, "getting property on prototype object must return undefined"); + // do_interface_attribute_asserts must be the last thing we do, + // since it will call done() on a_test. + this.do_interface_attribute_asserts(self[this.name].prototype, member, a_test); } - this.do_interface_attribute_asserts(self[this.name].prototype, member); + } - }.bind(this), this.name + " interface: attribute " + member.name); + }.bind(this)); }; //@} @@ -1316,6 +1356,46 @@ } //@} +IdlInterface.prototype.add_iterable_members = function(member) +//@{ +{ + this.members.push({type: "operation", name: "entries", idlType: "iterator", arguments: []}); + this.members.push({type: "operation", name: "keys", idlType: "iterator", arguments: []}); + this.members.push({type: "operation", name: "values", idlType: "iterator", arguments: []}); + this.members.push({type: "operation", name: "forEach", idlType: "void", arguments: + [{ name: "callback", idlType: {idlType: "function"}}, + { name: "thisValue", idlType: {idlType: "any"}, optional: true}]}); +}; + +//@} +IdlInterface.prototype.test_member_iterable = function(member) +//@{ +{ + var interfaceName = this.name; + var isPairIterator = member.idlType instanceof Array; + test(function() + { + var descriptor = Object.getOwnPropertyDescriptor(self[interfaceName].prototype, Symbol.iterator); + assert_true(descriptor.writable, "property is not writable"); + assert_true(descriptor.configurable, "property is not configurable"); + assert_false(descriptor.enumerable, "property is enumerable"); + assert_equals(self[interfaceName].prototype[Symbol.iterator].name, isPairIterator ? "entries" : "values", "@@iterator function does not have the right name"); + }, "Testing Symbol.iterator property of iterable interface " + interfaceName); + + if (isPairIterator) { + test(function() { + assert_equals(self[interfaceName].prototype["entries"], self[interfaceName].prototype[Symbol.iterator], "entries method is not the same as @@iterator"); + }, "Testing pair iterable interface " + interfaceName); + } else { + test(function() { + ["entries", "keys", "values", "forEach", Symbol.Iterator].forEach(function(property) { + assert_equals(self[interfaceName].prototype[property], Array.prototype[property], property + " function is not the same as Array one"); + }); + }, "Testing value iterable interface " + interfaceName); + } +}; + +//@} IdlInterface.prototype.test_member_stringifier = function(member) //@{ { @@ -1386,6 +1466,19 @@ for (var i = 0; i < this.members.length; i++) { var member = this.members[i]; + switch (member.type) { + case "iterable": + this.add_iterable_members(member); + break; + // TODO: add setlike and maplike handling. + default: + break; + } + } + + for (var i = 0; i < this.members.length; i++) + { + var member = this.members[i]; if (member.untested) { continue; } @@ -1422,6 +1515,9 @@ } break; + case "iterable": + this.test_member_iterable(member); + break; default: // TODO: check more member types. break; @@ -1522,12 +1618,13 @@ var member = this.members[i]; if (member.type == "attribute" && member.isUnforgeable) { - test(function() - { + var a_test = async_test(this.name + " interface: " + desc + ' must have own property "' + member.name + '"'); + a_test.step(function() { assert_equals(exception, null, "Unexpected exception when evaluating object"); assert_equals(typeof obj, expected_typeof, "wrong typeof object"); - this.do_interface_attribute_asserts(obj, member); - }.bind(this), this.name + " interface: " + desc + ' must have own property "' + member.name + '"'); + // Call do_interface_attribute_asserts last, since it will call a_test.done() + this.do_interface_attribute_asserts(obj, member, a_test); + }.bind(this)); } else if (member.type == "operation" && member.name && @@ -1646,7 +1743,7 @@ }; //@} -IdlInterface.prototype.do_interface_attribute_asserts = function(obj, member) +IdlInterface.prototype.do_interface_attribute_asserts = function(obj, member, a_test) //@{ { // This function tests WebIDL as of 2015-01-27. @@ -1656,6 +1753,8 @@ // it is not a global, and the global otherwise, and by test_interface_of() // with the object as obj. + var pendingPromises = []; + // "For each exposed attribute of the interface, whether it was declared on // the interface itself or one of its consequential interfaces, there MUST // exist a corresponding property. The characteristics of this property are @@ -1695,9 +1794,15 @@ // attribute, then return undefined. // "Otherwise, throw a TypeError." if (!member.has_extended_attribute("LenientThis")) { - assert_throws(new TypeError(), function() { - desc.get.call({}); - }.bind(this), "calling getter on wrong object type must throw TypeError"); + if (member.idlType.generic !== "Promise") { + assert_throws(new TypeError(), function() { + desc.get.call({}); + }.bind(this), "calling getter on wrong object type must throw TypeError"); + } else { + pendingPromises.push( + promise_rejects(a_test, new TypeError(), desc.get.call({}), + "calling getter on wrong object type must reject the return promise with TypeError")); + } } else { assert_equals(desc.get.call({}), undefined, "calling getter on wrong object type must return undefined"); @@ -1748,6 +1853,8 @@ // value 1." assert_equals(desc.set.length, 1, "setter length must be 1"); } + + Promise.all(pendingPromises).then(a_test.done.bind(a_test)); } //@}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/testharness.js b/third_party/WebKit/LayoutTests/external/wpt/resources/testharness.js index 49e38675..a6e7913 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/testharness.js +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/testharness.js
@@ -389,7 +389,7 @@ self.addEventListener("connect", function(message_event) { this_obj._add_message_port(message_event.source); - }); + }, false); } SharedWorkerTestEnvironment.prototype = Object.create(WorkerTestEnvironment.prototype); @@ -430,7 +430,7 @@ this_obj._add_message_port(event.source); } } - }); + }, false); // The oninstall event is received after the service worker script and // all imported scripts have been fetched and executed. It's the @@ -586,7 +586,7 @@ }); for (var i = 0; i < eventTypes.length; i++) { - watchedNode.addEventListener(eventTypes[i], eventHandler); + watchedNode.addEventListener(eventTypes[i], eventHandler, false); } /** @@ -611,7 +611,7 @@ function stop_watching() { for (var i = 0; i < eventTypes.length; i++) { - watchedNode.removeEventListener(eventTypes[i], eventHandler); + watchedNode.removeEventListener(eventTypes[i], eventHandler, false); } }; @@ -2669,7 +2669,7 @@ var tests = new Tests(); - addEventListener("error", function(e) { + var error_handler = function(e) { if (tests.file_is_test) { var test = tests.tests[0]; if (test.phase >= test.phases.HAS_RESULT) { @@ -2684,7 +2684,10 @@ tests.status.message = e.message; tests.status.stack = e.stack; } - }); + }; + + addEventListener("error", error_handler, false); + addEventListener("unhandledrejection", function(e){ error_handler(e.reason); }, false); test_environment.on_tests_ready();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/testharnessreport.js b/third_party/WebKit/LayoutTests/external/wpt/resources/testharnessreport.js deleted file mode 100644 index c95506ea..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/testharnessreport.js +++ /dev/null
@@ -1,425 +0,0 @@ -/* global add_completion_callback */ -/* global setup */ - -/* - * This file is intended for vendors to implement - * code needed to integrate testharness.js tests with their own test systems. - * - * The default implementation extracts metadata from the tests and validates - * it against the cached version that should be present in the test source - * file. If the cache is not found or is out of sync, source code suitable for - * caching the metadata is optionally generated. - * - * The cached metadata is present for extraction by test processing tools that - * are unable to execute javascript. - * - * Metadata is attached to tests via the properties parameter in the test - * constructor. See testharness.js for details. - * - * Typically test system integration will attach callbacks when each test has - * run, using add_result_callback(callback(test)), or when the whole test file - * has completed, using - * add_completion_callback(callback(tests, harness_status)). - * - * For more documentation about the callback functions and the - * parameters they are called with see testharness.js - */ - -var metadata_generator = { - - currentMetadata: {}, - cachedMetadata: false, - metadataProperties: ['help', 'assert', 'author'], - - error: function(message) { - var messageElement = document.createElement('p'); - messageElement.setAttribute('class', 'error'); - this.appendText(messageElement, message); - - var summary = document.getElementById('summary'); - if (summary) { - summary.parentNode.insertBefore(messageElement, summary); - } - else { - document.body.appendChild(messageElement); - } - }, - - /** - * Ensure property value has contact information - */ - validateContact: function(test, propertyName) { - var result = true; - var value = test.properties[propertyName]; - var values = Array.isArray(value) ? value : [value]; - for (var index = 0; index < values.length; index++) { - value = values[index]; - var re = /(\S+)(\s*)<(.*)>(.*)/; - if (! re.test(value)) { - re = /(\S+)(\s+)(http[s]?:\/\/)(.*)/; - if (! re.test(value)) { - this.error('Metadata property "' + propertyName + - '" for test: "' + test.name + - '" must have name and contact information ' + - '("name <email>" or "name http(s)://")'); - result = false; - } - } - } - return result; - }, - - /** - * Extract metadata from test object - */ - extractFromTest: function(test) { - var testMetadata = {}; - // filter out metadata from other properties in test - for (var metaIndex = 0; metaIndex < this.metadataProperties.length; - metaIndex++) { - var meta = this.metadataProperties[metaIndex]; - if (test.properties.hasOwnProperty(meta)) { - if ('author' == meta) { - this.validateContact(test, meta); - } - testMetadata[meta] = test.properties[meta]; - } - } - return testMetadata; - }, - - /** - * Compare cached metadata to extracted metadata - */ - validateCache: function() { - for (var testName in this.currentMetadata) { - if (! this.cachedMetadata.hasOwnProperty(testName)) { - return false; - } - var testMetadata = this.currentMetadata[testName]; - var cachedTestMetadata = this.cachedMetadata[testName]; - delete this.cachedMetadata[testName]; - - for (var metaIndex = 0; metaIndex < this.metadataProperties.length; - metaIndex++) { - var meta = this.metadataProperties[metaIndex]; - if (cachedTestMetadata.hasOwnProperty(meta) && - testMetadata.hasOwnProperty(meta)) { - if (Array.isArray(cachedTestMetadata[meta])) { - if (! Array.isArray(testMetadata[meta])) { - return false; - } - if (cachedTestMetadata[meta].length == - testMetadata[meta].length) { - for (var index = 0; - index < cachedTestMetadata[meta].length; - index++) { - if (cachedTestMetadata[meta][index] != - testMetadata[meta][index]) { - return false; - } - } - } - else { - return false; - } - } - else { - if (Array.isArray(testMetadata[meta])) { - return false; - } - if (cachedTestMetadata[meta] != testMetadata[meta]) { - return false; - } - } - } - else if (cachedTestMetadata.hasOwnProperty(meta) || - testMetadata.hasOwnProperty(meta)) { - return false; - } - } - } - for (var testName in this.cachedMetadata) { - return false; - } - return true; - }, - - appendText: function(elemement, text) { - elemement.appendChild(document.createTextNode(text)); - }, - - jsonifyArray: function(arrayValue, indent) { - var output = '['; - - if (1 == arrayValue.length) { - output += JSON.stringify(arrayValue[0]); - } - else { - for (var index = 0; index < arrayValue.length; index++) { - if (0 < index) { - output += ',\n ' + indent; - } - output += JSON.stringify(arrayValue[index]); - } - } - output += ']'; - return output; - }, - - jsonifyObject: function(objectValue, indent) { - var output = '{'; - var value; - - var count = 0; - for (var property in objectValue) { - ++count; - if (Array.isArray(objectValue[property]) || - ('object' == typeof(value))) { - ++count; - } - } - if (1 == count) { - for (var property in objectValue) { - output += ' "' + property + '": ' + - JSON.stringify(objectValue[property]) + - ' '; - } - } - else { - var first = true; - for (var property in objectValue) { - if (! first) { - output += ','; - } - first = false; - output += '\n ' + indent + '"' + property + '": '; - value = objectValue[property]; - if (Array.isArray(value)) { - output += this.jsonifyArray(value, indent + - ' '.substr(0, 5 + property.length)); - } - else if ('object' == typeof(value)) { - output += this.jsonifyObject(value, indent + ' '); - } - else { - output += JSON.stringify(value); - } - } - if (1 < output.length) { - output += '\n' + indent; - } - } - output += '}'; - return output; - }, - - /** - * Generate javascript source code for captured metadata - * Metadata is in pretty-printed JSON format - */ - generateSource: function() { - /* "\/" is used instead of a plain forward slash so that the contents - of testharnessreport.js can (for convenience) be copy-pasted into a - script tag without issue. Otherwise, the HTML parser would think that - the script ended in the middle of that string literal. */ - var source = - '<script id="metadata_cache">/*\n' + - this.jsonifyObject(this.currentMetadata, '') + '\n' + - '*/<\/script>\n'; - return source; - }, - - /** - * Add element containing metadata source code - */ - addSourceElement: function(event) { - var sourceWrapper = document.createElement('div'); - sourceWrapper.setAttribute('id', 'metadata_source'); - - var instructions = document.createElement('p'); - if (this.cachedMetadata) { - this.appendText(instructions, - 'Replace the existing <script id="metadata_cache"> element ' + - 'in the test\'s <head> with the following:'); - } - else { - this.appendText(instructions, - 'Copy the following into the <head> element of the test ' + - 'or the test\'s metadata sidecar file:'); - } - sourceWrapper.appendChild(instructions); - - var sourceElement = document.createElement('pre'); - this.appendText(sourceElement, this.generateSource()); - - sourceWrapper.appendChild(sourceElement); - - var messageElement = document.getElementById('metadata_issue'); - messageElement.parentNode.insertBefore(sourceWrapper, - messageElement.nextSibling); - messageElement.parentNode.removeChild(messageElement); - - (event.preventDefault) ? event.preventDefault() : - event.returnValue = false; - }, - - /** - * Extract the metadata cache from the cache element if present - */ - getCachedMetadata: function() { - var cacheElement = document.getElementById('metadata_cache'); - - if (cacheElement) { - var cacheText = cacheElement.firstChild.nodeValue; - var openBrace = cacheText.indexOf('{'); - var closeBrace = cacheText.lastIndexOf('}'); - if ((-1 < openBrace) && (-1 < closeBrace)) { - cacheText = cacheText.slice(openBrace, closeBrace + 1); - try { - this.cachedMetadata = JSON.parse(cacheText); - } - catch (exc) { - this.cachedMetadata = 'Invalid JSON in Cached metadata. '; - } - } - else { - this.cachedMetadata = 'Metadata not found in cache element. '; - } - } - }, - - /** - * Main entry point, extract metadata from tests, compare to cached version - * if present. - * If cache not present or differs from extrated metadata, generate an error - */ - process: function(tests) { - for (var index = 0; index < tests.length; index++) { - var test = tests[index]; - if (this.currentMetadata.hasOwnProperty(test.name)) { - this.error('Duplicate test name: ' + test.name); - } - else { - this.currentMetadata[test.name] = this.extractFromTest(test); - } - } - - this.getCachedMetadata(); - - var message = null; - var messageClass = 'warning'; - var showSource = false; - - if (0 === tests.length) { - if (this.cachedMetadata) { - message = 'Cached metadata present but no tests. '; - } - } - else if (1 === tests.length) { - if (this.cachedMetadata) { - message = 'Single test files should not have cached metadata. '; - } - else { - var testMetadata = this.currentMetadata[tests[0].name]; - for (var meta in testMetadata) { - if (testMetadata.hasOwnProperty(meta)) { - message = 'Single tests should not have metadata. ' + - 'Move metadata to <head>. '; - break; - } - } - } - } - else { - if (this.cachedMetadata) { - messageClass = 'error'; - if ('string' == typeof(this.cachedMetadata)) { - message = this.cachedMetadata; - showSource = true; - } - else if (! this.validateCache()) { - message = 'Cached metadata out of sync. '; - showSource = true; - } - } - } - - if (message) { - var messageElement = document.createElement('p'); - messageElement.setAttribute('id', 'metadata_issue'); - messageElement.setAttribute('class', messageClass); - this.appendText(messageElement, message); - - if (showSource) { - var link = document.createElement('a'); - this.appendText(link, 'Click for source code.'); - link.setAttribute('href', '#'); - link.setAttribute('onclick', - 'metadata_generator.addSourceElement(event)'); - messageElement.appendChild(link); - } - - var summary = document.getElementById('summary'); - if (summary) { - summary.parentNode.insertBefore(messageElement, summary); - } - else { - var log = document.getElementById('log'); - if (log) { - log.appendChild(messageElement); - } - } - } - }, - - setup: function() { - add_completion_callback( - function (tests, harness_status) { - metadata_generator.process(tests, harness_status); - dump_test_results(tests, harness_status); - }); - } -}; - -function dump_test_results(tests, status) { - var results_element = document.createElement("script"); - results_element.type = "text/json"; - results_element.id = "__testharness__results__"; - var test_results = tests.map(function(x) { - return {name:x.name, status:x.status, message:x.message, stack:x.stack} - }); - var data = {test:window.location.href, - tests:test_results, - status: status.status, - message: status.message, - stack: status.stack}; - results_element.textContent = JSON.stringify(data); - - // To avoid a HierarchyRequestError with XML documents, ensure that 'results_element' - // is inserted at a location that results in a valid document. - var parent = document.body - ? document.body // <body> is required in XHTML documents - : document.documentElement; // fallback for optional <body> in HTML5, SVG, etc. - - parent.appendChild(results_element); -} - -metadata_generator.setup(); - -/* If the parent window has a testharness_properties object, - * we use this to provide the test settings. This is used by the - * default in-browser runner to configure the timeout and the - * rendering of results - */ -try { - if (window.opener && "testharness_properties" in window.opener) { - /* If we pass the testharness_properties object as-is here without - * JSON stringifying and reparsing it, IE fails & emits the message - * "Could not complete the operation due to error 80700019". - */ - setup(JSON.parse(JSON.stringify(window.opener.testharness_properties))); - } -} catch (e) { -} -// vim: set expandtab shiftwidth=4 tabstop=4:
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/serviceworker/cache-add.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/serviceworker/cache-add.https-expected.txt index e28fdf3..7c119fd 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/serviceworker/cache-add.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/serviceworker/cache-add.https-expected.txt
@@ -1,4 +1,5 @@ This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Partial response (status code 206) is unsupported PASS Cache.add and Cache.addAll PASS Cache.add called with no arguments PASS Cache.add called with relative URL specified as a string
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/window/cache-add.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/window/cache-add.https-expected.txt index 309462b..68f3697 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/window/cache-add.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/window/cache-add.https-expected.txt
@@ -1,5 +1,6 @@ CONSOLE ERROR: Uncaught (in promise) TypeError: Partial response (status code 206) is unsupported This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Partial response (status code 206) is unsupported PASS Cache.add called with no arguments PASS Cache.add called with relative URL specified as a string PASS Cache.add called with non-HTTP/HTTPS URL
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/worker/cache-add.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/worker/cache-add.https-expected.txt index 309462b..68f3697 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/worker/cache-add.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/worker/cache-add.https-expected.txt
@@ -1,5 +1,6 @@ CONSOLE ERROR: Uncaught (in promise) TypeError: Partial response (status code 206) is unsupported This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Partial response (status code 206) is unsupported PASS Cache.add called with no arguments PASS Cache.add called with relative URL specified as a string PASS Cache.add called with non-HTTP/HTTPS URL
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/byte-length-queuing-strategy.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/byte-length-queuing-strategy.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/byte-length-queuing-strategy.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/byte-length-queuing-strategy.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/byte-length-queuing-strategy.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/byte-length-queuing-strategy.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/byte-length-queuing-strategy.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/byte-length-queuing-strategy.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/count-queuing-strategy.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/count-queuing-strategy.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/count-queuing-strategy.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/count-queuing-strategy.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/count-queuing-strategy.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/count-queuing-strategy.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/count-queuing-strategy.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/count-queuing-strategy.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/generate-test-wrappers.js b/third_party/WebKit/LayoutTests/external/wpt/streams/generate-test-wrappers.js index 0803eef..d81f06ef 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/streams/generate-test-wrappers.js +++ b/third_party/WebKit/LayoutTests/external/wpt/streams/generate-test-wrappers.js
@@ -31,7 +31,7 @@ const noExtension = path.basename(jsFilename, '.js'); const outputs = { - https: `<!DOCTYPE html> + '.html': `<!DOCTYPE html> <meta charset="utf-8"> <title>${basename} browser context wrapper file</title> @@ -42,7 +42,7 @@ <script src="${basename}"></script> `, - dedicatedworker: `<!DOCTYPE html> + '.dedicatedworker.html': `<!DOCTYPE html> <meta charset="utf-8"> <title>${basename} dedicated worker wrapper file</title> @@ -54,7 +54,7 @@ fetch_tests_from_worker(new Worker('${basename}')); </script> `, - sharedworker: `<!DOCTYPE html> + '.sharedworker.html': `<!DOCTYPE html> <meta charset="utf-8"> <title>${basename} shared worker wrapper file</title> @@ -66,7 +66,7 @@ fetch_tests_from_worker(new SharedWorker('${basename}')); </script> `, - serviceworker: `<!DOCTYPE html> + '.serviceworker.https.html': `<!DOCTYPE html> <meta charset="utf-8"> <title>${basename} service worker wrapper file</title> @@ -82,7 +82,7 @@ }; for (const [key, value] of Object.entries(outputs)) { - const destFilename = path.resolve(path.dirname(jsFilename), `${noExtension}.${key}.html`); + const destFilename = path.resolve(path.dirname(jsFilename), `${noExtension}${key}`); fs.writeFileSync(destFilename, value, { encoding: 'utf-8' }); } }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-backward.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-backward.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-backward.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-backward.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-backward.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-backward.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-backward.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-backward.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-forward.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-forward.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-forward.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-forward.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-forward.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-forward.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-forward.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/close-propagation-forward.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-backward.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-backward.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-backward.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-backward.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-backward.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-backward.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-backward.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-backward.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-forward.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-forward.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-forward.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-forward.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-forward.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-forward.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-forward.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/error-propagation-forward.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/flow-control.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/flow-control.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/flow-control.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/flow-control.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/flow-control.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/flow-control.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/flow-control.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/flow-control.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/general.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/general.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/general.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/general.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/general.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/general.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/general.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/general.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation.https-expected.txt rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation-expected.txt
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation.serviceworker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation.serviceworker.https-expected.txt new file mode 100644 index 0000000..7c3b316 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation.serviceworker.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = The stream has been aborted +PASS Service worker test setup +PASS Piping from an errored readable stream to an errored writable stream +PASS Piping from an errored readable stream to an errored writable stream; preventAbort = true +FAIL Piping from an errored readable stream to a closed writable stream assert_array_equals: lengths differ, expected 1 got 2 +PASS Piping from a closed readable stream to an errored writable stream +PASS Piping from a closed readable stream to a closed writable stream +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/multiple-propagation.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through-expected.txt new file mode 100644 index 0000000..c055ee5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through-expected.txt
@@ -0,0 +1,10 @@ +CONSOLE ERROR: line 44: Uncaught (in promise) Error: this rejection should not be reported as unhandled +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = this rejection should not be reported as unhandled +PASS Piping through a duck-typed pass-through transform stream should work +PASS Piping through a transform errored on the writable end does not cause an unhandled promise rejection +PASS pipeThrough generically calls pipeTo with the appropriate args +PASS pipeThrough can handle calling a pipeTo that returns a non-promise object +PASS pipeThrough can handle calling a pipeTo that returns a non-promise thenable object +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.dedicatedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.dedicatedworker-expected.txt new file mode 100644 index 0000000..c055ee5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.dedicatedworker-expected.txt
@@ -0,0 +1,10 @@ +CONSOLE ERROR: line 44: Uncaught (in promise) Error: this rejection should not be reported as unhandled +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = this rejection should not be reported as unhandled +PASS Piping through a duck-typed pass-through transform stream should work +PASS Piping through a transform errored on the writable end does not cause an unhandled promise rejection +PASS pipeThrough generically calls pipeTo with the appropriate args +PASS pipeThrough can handle calling a pipeTo that returns a non-promise object +PASS pipeThrough can handle calling a pipeTo that returns a non-promise thenable object +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.serviceworker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.serviceworker.https-expected.txt new file mode 100644 index 0000000..1ef1fed5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.serviceworker.https-expected.txt
@@ -0,0 +1,10 @@ +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = this rejection should not be reported as unhandled +PASS Service worker test setup +PASS Piping through a duck-typed pass-through transform stream should work +PASS Piping through a transform errored on the writable end does not cause an unhandled promise rejection +PASS pipeThrough generically calls pipeTo with the appropriate args +PASS pipeThrough can handle calling a pipeTo that returns a non-promise object +PASS pipeThrough can handle calling a pipeTo that returns a non-promise thenable object +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.sharedworker-expected.txt new file mode 100644 index 0000000..423e104 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/pipe-through.sharedworker-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = this rejection should not be reported as unhandled +PASS Piping through a duck-typed pass-through transform stream should work +PASS Piping through a transform errored on the writable end does not cause an unhandled promise rejection +PASS pipeThrough generically calls pipeTo with the appropriate args +PASS pipeThrough can handle calling a pipeTo that returns a non-promise object +PASS pipeThrough can handle calling a pipeTo that returns a non-promise thenable object +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams.https-expected.txt rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams-expected.txt
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams.serviceworker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams.serviceworker.https-expected.txt new file mode 100644 index 0000000..384f434 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams.serviceworker.https-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +PASS Service worker test setup +FAIL Piping through an identity transform stream should close the destination when the source closes TransformStream is not defined +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/piping/transform-streams.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.https-expected.txt rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general-expected.txt
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.serviceworker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.serviceworker.https-expected.txt new file mode 100644 index 0000000..218a38b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.serviceworker.https-expected.txt
@@ -0,0 +1,72 @@ +This is a testharness.js-based test. +PASS Service worker test setup +PASS getReader({mode: "byob"}) throws on non-bytes streams +FAIL ReadableStream with byte source can be constructed with no errors bytes type is not yet implemented +FAIL ReadableStream with byte source: Construct and expect start and pull being called bytes type is not yet implemented +FAIL ReadableStream with byte source: No automatic pull call if start doesn't finish bytes type is not yet implemented +FAIL ReadableStream with byte source: Construct with highWaterMark of 0 bytes type is not yet implemented +FAIL ReadableStream with byte source: getReader(), then releaseLock() bytes type is not yet implemented +FAIL ReadableStream with byte source: getReader() with mode set to byob, then releaseLock() bytes type is not yet implemented +FAIL ReadableStream with byte source: Test that closing a stream does not release a reader automatically bytes type is not yet implemented +FAIL ReadableStream with byte source: Test that closing a stream does not release a BYOB reader automatically bytes type is not yet implemented +FAIL ReadableStream with byte source: Test that erroring a stream does not release a reader automatically bytes type is not yet implemented +FAIL ReadableStream with byte source: Test that erroring a stream does not release a BYOB reader automatically bytes type is not yet implemented +FAIL ReadableStream with byte source: releaseLock() on ReadableStreamReader with pending read() must throw bytes type is not yet implemented +FAIL ReadableStream with byte source: Automatic pull() after start() bytes type is not yet implemented +FAIL ReadableStream with byte source: Automatic pull() after start() and read() bytes type is not yet implemented +FAIL ReadableStream with byte source: autoAllocateChunkSize bytes type is not yet implemented +FAIL ReadableStream with byte source: Mix of auto allocate and BYOB bytes type is not yet implemented +FAIL ReadableStream with byte source: Automatic pull() after start() and read(view) bytes type is not yet implemented +FAIL ReadableStream with byte source: enqueue(), getReader(), then read() bytes type is not yet implemented +FAIL ReadableStream with byte source: Push source that doesn't understand pull signal bytes type is not yet implemented +FAIL ReadableStream with byte source: read(), but pull() function is not callable bytes type is not yet implemented +FAIL ReadableStream with byte source: read(view), but pull() function is not callable bytes type is not yet implemented +FAIL ReadableStream with byte source: enqueue() with Uint16Array, getReader(), then read() bytes type is not yet implemented +FAIL ReadableStream with byte source: enqueue(), read(view) partially, then read() bytes type is not yet implemented +FAIL ReadableStream with byte source: getReader(), enqueue(), close(), then read() bytes type is not yet implemented +FAIL ReadableStream with byte source: enqueue(), close(), getReader(), then read() bytes type is not yet implemented +FAIL ReadableStream with byte source: Respond to pull() by enqueue() bytes type is not yet implemented +FAIL ReadableStream with byte source: Respond to pull() by enqueue() asynchronously bytes type is not yet implemented +FAIL ReadableStream with byte source: read(view), then respond() bytes type is not yet implemented +FAIL ReadableStream with byte source: read(view), then respond() with a transferred ArrayBuffer bytes type is not yet implemented +FAIL ReadableStream with byte source: read(view), then respond() with too big value bytes type is not yet implemented +FAIL ReadableStream with byte source: respond(3) to read(view) with 2 element Uint16Array enqueues the 1 byte remainder bytes type is not yet implemented +FAIL ReadableStream with byte source: enqueue(), getReader(), then read(view) bytes type is not yet implemented +FAIL ReadableStream with byte source: enqueue(), getReader(), then cancel() (mode = not BYOB) bytes type is not yet implemented +FAIL ReadableStream with byte source: enqueue(), getReader(), then cancel() (mode = BYOB) bytes type is not yet implemented +FAIL ReadableStream with byte source: getReader(), read(view), then cancel() bytes type is not yet implemented +FAIL ReadableStream with byte source: cancel() with partially filled pending pull() request bytes type is not yet implemented +FAIL ReadableStream with byte source: enqueue(), getReader(), then read(view) where view.buffer is not fully covered by view bytes type is not yet implemented +FAIL ReadableStream with byte source: Multiple enqueue(), getReader(), then read(view) bytes type is not yet implemented +FAIL ReadableStream with byte source: enqueue(), getReader(), then read(view) with a bigger view bytes type is not yet implemented +FAIL ReadableStream with byte source: enqueue(), getReader(), then read(view) with a smaller views bytes type is not yet implemented +FAIL ReadableStream with byte source: enqueue() 1 byte, getReader(), then read(view) with Uint16Array bytes type is not yet implemented +FAIL ReadableStream with byte source: enqueue() 3 byte, getReader(), then read(view) with 2-element Uint16Array bytes type is not yet implemented +FAIL ReadableStream with byte source: read(view) with Uint16Array on close()-d stream with 1 byte enqueue()-d must fail bytes type is not yet implemented +FAIL ReadableStream with byte source: A stream must be errored if close()-d before fulfilling read(view) with Uint16Array bytes type is not yet implemented +FAIL ReadableStream with byte source: Throw if close()-ed more than once bytes type is not yet implemented +FAIL ReadableStream with byte source: Throw on enqueue() after close() bytes type is not yet implemented +FAIL ReadableStream with byte source: read(view), then respond() and close() in pull() bytes type is not yet implemented +FAIL ReadableStream with byte source: read(view) with Uint32Array, then fill it by multiple respond() calls bytes type is not yet implemented +FAIL ReadableStream with byte source: read() twice, then enqueue() twice bytes type is not yet implemented +FAIL ReadableStream with byte source: Multiple read(view), close() and respond() bytes type is not yet implemented +FAIL ReadableStream with byte source: Multiple read(view), big enqueue() bytes type is not yet implemented +FAIL ReadableStream with byte source: Multiple read(view) and multiple enqueue() bytes type is not yet implemented +FAIL ReadableStream with byte source: read(view) with passing undefined as view must fail bytes type is not yet implemented +FAIL ReadableStream with byte source: read(view) with zero-length view must fail bytes type is not yet implemented +FAIL ReadableStream with byte source: read(view) with passing an empty object as view must fail bytes type is not yet implemented +FAIL ReadableStream with byte source: Even read(view) with passing ArrayBufferView like object as view must fail bytes type is not yet implemented +FAIL ReadableStream with byte source: read() on an errored stream bytes type is not yet implemented +FAIL ReadableStream with byte source: read(), then error() bytes type is not yet implemented +FAIL ReadableStream with byte source: read(view) on an errored stream bytes type is not yet implemented +FAIL ReadableStream with byte source: read(view), then error() bytes type is not yet implemented +FAIL ReadableStream with byte source: Throwing in pull function must error the stream bytes type is not yet implemented +FAIL ReadableStream with byte source: Throwing in pull in response to read() must be ignored if the stream is errored in it bytes type is not yet implemented +FAIL ReadableStream with byte source: Throwing in pull in response to read(view) function must error the stream bytes type is not yet implemented +FAIL ReadableStream with byte source: Throwing in pull in response to read(view) must be ignored if the stream is errored in it bytes type is not yet implemented +FAIL ReadableStreamBYOBReader can be constructed directly bytes type is not yet implemented +FAIL ReadableStreamBYOBReader constructor requires a ReadableStream argument bytes type is not yet implemented +FAIL ReadableStreamBYOBReader constructor requires an unlocked ReadableStream bytes type is not yet implemented +FAIL ReadableStreamBYOBReader constructor requires a ReadableStream with type "bytes" bytes type is not yet implemented +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-byte-streams/general.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-strategies.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-strategies.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-strategies.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-strategies.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-strategies.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-strategies.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-strategies.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-strategies.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-underlying-sources.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-underlying-sources.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-underlying-sources.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-underlying-sources.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-underlying-sources.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-underlying-sources.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-underlying-sources.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/bad-underlying-sources.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/brand-checks.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/brand-checks.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/brand-checks.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/brand-checks.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/brand-checks.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/brand-checks.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/brand-checks.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/brand-checks.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/cancel.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/cancel.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/cancel.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/cancel.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/cancel.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/cancel.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/cancel.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/cancel.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/count-queuing-strategy-integration.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/count-queuing-strategy-integration.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/count-queuing-strategy-integration.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/count-queuing-strategy-integration.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/count-queuing-strategy-integration.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/count-queuing-strategy-integration.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/count-queuing-strategy-integration.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/count-queuing-strategy-integration.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/garbage-collection.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/garbage-collection.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/garbage-collection.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/garbage-collection.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/garbage-collection.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/garbage-collection.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/garbage-collection.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/garbage-collection.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/general.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/general.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/general.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/general.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/general.serviceworker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/general.serviceworker.https-expected.txt new file mode 100644 index 0000000..09889cf2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/general.serviceworker.https-expected.txt
@@ -0,0 +1,39 @@ +This is a testharness.js-based test. +PASS Service worker test setup +PASS ReadableStream can be constructed with no errors +PASS ReadableStream can't be constructed with garbage +PASS ReadableStream can't be constructed with an invalid type +PASS ReadableStream instances should have the correct list of properties +PASS ReadableStream constructor should throw for non-function start arguments +PASS ReadableStream constructor can get initial garbage as cancel argument +PASS ReadableStream constructor can get initial garbage as pull argument +FAIL ReadableStream start should be called with the proper parameters assert_equals: constructor should have 4 parameter expected 4 but got 5 +PASS ReadableStream start controller parameter should be extensible +PASS ReadableStream should be able to call start method within prototype chain of its source +PASS ReadableStream start should be able to return a promise +PASS ReadableStream start should be able to return a promise and reject it +PASS ReadableStream should be able to enqueue different objects. +PASS ReadableStream: if pull rejects, it should error the stream +PASS ReadableStream: should only call pull once upon starting the stream +PASS ReadableStream: should call pull when trying to read from a started, empty stream +PASS ReadableStream: should only call pull once on a non-empty stream read from before start fulfills +PASS ReadableStream: should only call pull once on a non-empty stream read from after start fulfills +PASS ReadableStream: should call pull in reaction to read()ing the last chunk, if not draining +PASS ReadableStream: should not call pull() in reaction to read()ing the last chunk, if draining +PASS ReadableStream: should not call pull until the previous pull call's promise fulfills +PASS ReadableStream: should pull after start, and after every read +PASS ReadableStream: should not call pull after start if the stream is now closed +PASS ReadableStream: should call pull after enqueueing from inside pull (with no read requests), if strategy allows +PASS ReadableStream pull should be able to close a stream. +PASS ReadableStream pull should be able to error a stream. +PASS ReadableStream pull should be able to error a stream and throw. +PASS ReadableStream: enqueue should throw when the stream is readable but draining +PASS ReadableStream: enqueue should throw when the stream is closed +PASS ReadableStream: should call underlying source methods as methods +PASS ReadableStream strategies: the default strategy should give desiredSize of 1 to start, decreasing by 1 per enqueue +PASS ReadableStream strategies: the default strategy should continue giving desiredSize of 1 if the chunks are read immediately +PASS ReadableStream integration test: adapting a random push source +PASS ReadableStream integration test: adapting a sync pull source +PASS ReadableStream integration test: adapting an async pull source +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/general.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/general.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/general.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/general.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/pipe-through.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/pipe-through.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/pipe-through.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/pipe-through.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/pipe-through.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/pipe-through.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/pipe-through.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/pipe-through.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/readable-stream-reader.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/readable-stream-reader.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/readable-stream-reader.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/readable-stream-reader.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/readable-stream-reader.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/readable-stream-reader.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/readable-stream-reader.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/readable-stream-reader.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/tee.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/tee.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/tee.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/tee.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/tee.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/tee.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/tee.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/tee.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/templated.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/templated.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/templated.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/templated.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/templated.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/templated.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/templated.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/readable-streams/templated.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-strategies.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-strategies.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-strategies.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-strategies.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-strategies.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-strategies.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-strategies.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-strategies.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-underlying-sinks.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-underlying-sinks.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-underlying-sinks.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-underlying-sinks.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-underlying-sinks.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-underlying-sinks.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-underlying-sinks.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/bad-underlying-sinks.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/brand-checks.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/brand-checks.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/brand-checks.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/brand-checks.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/brand-checks.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/brand-checks.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/brand-checks.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/brand-checks.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/byte-length-queuing-strategy.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/byte-length-queuing-strategy.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/byte-length-queuing-strategy.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/byte-length-queuing-strategy.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/byte-length-queuing-strategy.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/byte-length-queuing-strategy.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/byte-length-queuing-strategy.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/byte-length-queuing-strategy.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/count-queuing-strategy.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/count-queuing-strategy.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/count-queuing-strategy.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/count-queuing-strategy.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/count-queuing-strategy.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/count-queuing-strategy.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/count-queuing-strategy.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/count-queuing-strategy.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/general.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/general.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/general.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/general.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/general.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/general.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/general.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/general.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/start.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/start.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/start.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/start.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/start.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/start.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/start.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/start.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/write.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/write.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/write.https.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/write.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/write.serviceworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/write.serviceworker.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/write.serviceworker.html rename to third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/write.serviceworker.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/svg/interfaces-expected.txt index 85ff741..30ef2f5 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/svg/interfaces-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/interfaces-expected.txt
@@ -1,6 +1,6 @@ -CONSOLE MESSAGE: line 236: callback not yet supported -CONSOLE MESSAGE: line 236: callback not yet supported -CONSOLE MESSAGE: line 236: callback not yet supported +CONSOLE MESSAGE: line 251: callback not yet supported +CONSOLE MESSAGE: line 251: callback not yet supported +CONSOLE MESSAGE: line 251: callback not yet supported This is a testharness.js-based test. PASS Document interface: attribute rootElement PASS SVGElement interface: existence and properties of interface object
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/rtcpeerconnection/rtcpeerconnection-idl-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/rtcpeerconnection/rtcpeerconnection-idl-expected.txt index e9e9576d..1531ad1 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/rtcpeerconnection/rtcpeerconnection-idl-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/rtcpeerconnection/rtcpeerconnection-idl-expected.txt
@@ -1,12 +1,12 @@ -CONSOLE ERROR: line 75: Uncaught (in promise) TypeError: Failed to execute 'createOffer' on 'RTCPeerConnection': Illegal invocation -CONSOLE ERROR: line 75: Uncaught (in promise) TypeError: Failed to execute 'setLocalDescription' on 'RTCPeerConnection': Illegal invocation -CONSOLE ERROR: line 75: Uncaught (in promise) TypeError: Failed to execute 'createAnswer' on 'RTCPeerConnection': Illegal invocation -CONSOLE ERROR: line 75: Uncaught (in promise) TypeError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Illegal invocation -CONSOLE ERROR: line 75: Uncaught (in promise) TypeError: Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Illegal invocation -CONSOLE ERROR: line 75: Uncaught (in promise) TypeError: Failed to execute 'getStats' on 'RTCPeerConnection': Illegal invocation -CONSOLE ERROR: line 75: Uncaught (in promise) TypeError: Failed to execute 'setLocalDescription' on 'RTCPeerConnection': 1 argument required, but only 0 present. -CONSOLE ERROR: line 75: Uncaught (in promise) TypeError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': 1 argument required, but only 0 present. -CONSOLE ERROR: line 75: Uncaught (in promise) TypeError: Failed to execute 'addIceCandidate' on 'RTCPeerConnection': 1 argument required, but only 0 present. +CONSOLE ERROR: line 83: Uncaught (in promise) TypeError: Failed to execute 'createOffer' on 'RTCPeerConnection': Illegal invocation +CONSOLE ERROR: line 83: Uncaught (in promise) TypeError: Failed to execute 'setLocalDescription' on 'RTCPeerConnection': Illegal invocation +CONSOLE ERROR: line 83: Uncaught (in promise) TypeError: Failed to execute 'createAnswer' on 'RTCPeerConnection': Illegal invocation +CONSOLE ERROR: line 83: Uncaught (in promise) TypeError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Illegal invocation +CONSOLE ERROR: line 83: Uncaught (in promise) TypeError: Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Illegal invocation +CONSOLE ERROR: line 83: Uncaught (in promise) TypeError: Failed to execute 'getStats' on 'RTCPeerConnection': Illegal invocation +CONSOLE ERROR: line 83: Uncaught (in promise) TypeError: Failed to execute 'setLocalDescription' on 'RTCPeerConnection': 1 argument required, but only 0 present. +CONSOLE ERROR: line 83: Uncaught (in promise) TypeError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': 1 argument required, but only 0 present. +CONSOLE ERROR: line 83: Uncaught (in promise) TypeError: Failed to execute 'addIceCandidate' on 'RTCPeerConnection': 1 argument required, but only 0 present. This is a testharness.js-based test. PASS EventTarget interface: existence and properties of interface object PASS EventTarget interface object length
diff --git a/third_party/WebKit/LayoutTests/fast/dom/promise-rejection-events-attached-in-event-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/promise-rejection-events-attached-in-event-expected.txt new file mode 100644 index 0000000..9e12039 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/dom/promise-rejection-events-attached-in-event-expected.txt
@@ -0,0 +1,6 @@ +CONSOLE ERROR: line 8: Uncaught (in promise) Error: e +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = e +PASS Attaching a handler in unhandledrejection should not trigger rejectionhandled. +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/fast/dom/promise-rejection-events-console-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/promise-rejection-events-console-expected.txt new file mode 100644 index 0000000..c1ad6fbb --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/dom/promise-rejection-events-console-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = e +PASS evt.preventDefault() should suppress console output. +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/fast/dom/promise-rejection-events-lifetime-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/promise-rejection-events-lifetime-expected.txt new file mode 100644 index 0000000..4574831 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/dom/promise-rejection-events-lifetime-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = +PASS evt.promise and evt.reason should live at least as long as evt +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/register-link-element-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/register-link-element-expected.txt new file mode 100644 index 0000000..3bcff44 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/register-link-element-expected.txt
@@ -0,0 +1,41 @@ +CONSOLE ERROR: Uncaught (in promise) TypeError: Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script. +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script. +PASS Registering normal scope +PASS Registering scope with fragment +PASS Registering same scope as the script directory +PASS Registering same scope as the script directory without the last slash +PASS Registration scope outside the script directory +PASS Registering scope outside domain +PASS Registering script outside domain +PASS Registering non-existent script +PASS Registering invalid chunked encoding script +PASS Registering invalid chunked encoding script with flush +PASS Registering script with no MIME type +PASS Registering script with bad MIME type +PASS Registering redirected script +PASS Registering script including parse error +PASS Registering script including undefined error +PASS Registering script including uncaught exception +PASS Registering script including caught exception +PASS Registering script importing malformed script +PASS Registering script importing non-existent script +PASS Scope including URL-encoded multibyte characters +PASS Scope including non-escaped multibyte characters +PASS Script URL including URL-encoded slash +PASS Script URL including uppercase URL-encoded slash +PASS Scope including URL-encoded slash +PASS Script URL including URL-encoded backslash +PASS Script URL including uppercase URL-encoded backslash +PASS Scope including URL-encoded backslash +PASS Script URL including self-reference +PASS Scope including self-reference +PASS Script URL including parent-reference +PASS Scope including parent-reference +PASS Scope including parent-reference and not under the script directory +PASS Script URL including consecutive slashes +PASS Scope including consecutive slashes +PASS Script URL is same-origin filesystem: URL +PASS Scope URL is same-origin filesystem: URL +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/registration-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/registration-expected.txt new file mode 100644 index 0000000..3bcff44 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/registration-expected.txt
@@ -0,0 +1,41 @@ +CONSOLE ERROR: Uncaught (in promise) TypeError: Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script. +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script. +PASS Registering normal scope +PASS Registering scope with fragment +PASS Registering same scope as the script directory +PASS Registering same scope as the script directory without the last slash +PASS Registration scope outside the script directory +PASS Registering scope outside domain +PASS Registering script outside domain +PASS Registering non-existent script +PASS Registering invalid chunked encoding script +PASS Registering invalid chunked encoding script with flush +PASS Registering script with no MIME type +PASS Registering script with bad MIME type +PASS Registering redirected script +PASS Registering script including parse error +PASS Registering script including undefined error +PASS Registering script including uncaught exception +PASS Registering script including caught exception +PASS Registering script importing malformed script +PASS Registering script importing non-existent script +PASS Scope including URL-encoded multibyte characters +PASS Scope including non-escaped multibyte characters +PASS Script URL including URL-encoded slash +PASS Script URL including uppercase URL-encoded slash +PASS Scope including URL-encoded slash +PASS Script URL including URL-encoded backslash +PASS Script URL including uppercase URL-encoded backslash +PASS Scope including URL-encoded backslash +PASS Script URL including self-reference +PASS Scope including self-reference +PASS Script URL including parent-reference +PASS Scope including parent-reference +PASS Scope including parent-reference and not under the script directory +PASS Script URL including consecutive slashes +PASS Scope including consecutive slashes +PASS Script URL is same-origin filesystem: URL +PASS Scope URL is same-origin filesystem: URL +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/resources/import-tests.js b/third_party/WebKit/LayoutTests/http/tests/worklet/resources/import-tests.js index 90bd4e9..ea341b8 100644 --- a/third_party/WebKit/LayoutTests/http/tests/worklet/resources/import-tests.js +++ b/third_party/WebKit/LayoutTests/http/tests/worklet/resources/import-tests.js
@@ -8,39 +8,38 @@ promise_test(function() { return worklet.import(path + 'resources/empty-worklet-script.js').then(function(undefined_arg) { assert_equals(undefined_arg, undefined, 'Promise should resolve with no arguments.'); - }).catch(function(error) { - assert_unreached('unexpected rejection: ' + error); }); - }, 'Importing a script resolves the given promise.'); promise_test(function() { + return Promise.all([ + worklet.import(path + 'resources/empty-worklet-script.js?1'), + worklet.import(path + 'resources/empty-worklet-script.js?2'), + worklet.import(path + 'resources/empty-worklet-script.js?3') + ]).then(function(undefined_args) { + assert_array_equals(undefined_args, [undefined, undefined, undefined], 'Promise should resolve with no arguments.'); + }); + }, 'Importing scripts resolves all the given promises.'); + promise_test(function() { return worklet.import(path + 'resources/throwing-worklet-script.js').then(function(undefined_arg) { assert_equals(undefined_arg, undefined, 'Promise should resolve with no arguments.'); - }).catch(function(error) { - assert_unreached('unexpected rejection: ' + error); }); - }, 'Importing a script which throws should still resolve the given promise.'); promise_test(function() { - return worklet.import(path + 'non-existant-worklet-script.js').then(function() { assert_unreached('import should fail.'); }).catch(function(error) { assert_equals(error.name, 'NetworkError', 'error should be a NetworkError.'); }); - }, 'Importing a non-existant script rejects the given promise with a NetworkError.'); promise_test(function() { - return worklet.import('http://invalid:123$').then(function() { assert_unreached('import should fail.'); }).catch(function(error) { assert_equals(error.name, 'SyntaxError', 'error should be a SyntaxError.'); }); - }, 'Attempting to resolve an invalid URL should reject the given promise with a SyntaxError.'); }
diff --git a/third_party/WebKit/LayoutTests/media/video-display-none-crash-expected.txt b/third_party/WebKit/LayoutTests/media/video-display-none-crash-expected.txt new file mode 100644 index 0000000..0b158f4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/media/video-display-none-crash-expected.txt
@@ -0,0 +1,6 @@ +CONSOLE ERROR: Uncaught (in promise) AbortError: The play() request was interrupted by a call to pause(). +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = The play() request was interrupted by a call to pause(). +PASS Test that pause() after changing display to "none" doesn't cause a crash. +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/media/video-play-pause-events-expected.txt b/third_party/WebKit/LayoutTests/media/video-play-pause-events-expected.txt new file mode 100644 index 0000000..5222de8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/media/video-play-pause-events-expected.txt
@@ -0,0 +1,6 @@ +CONSOLE ERROR: Uncaught (in promise) AbortError: The play() request was interrupted by a call to pause(). +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = The play() request was interrupted by a call to pause(). +PASS Test that calling play() and pause() triggers async play, timeupdate and pause events. +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/media/video-play-require-user-gesture-expected.txt b/third_party/WebKit/LayoutTests/media/video-play-require-user-gesture-expected.txt new file mode 100644 index 0000000..1c81d4b --- /dev/null +++ b/third_party/WebKit/LayoutTests/media/video-play-require-user-gesture-expected.txt
@@ -0,0 +1,7 @@ +CONSOLE WARNING: line 18: Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture. +CONSOLE ERROR: line 18: Uncaught (in promise) NotAllowedError: play() can only be initiated by a user gesture. +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = play() can only be initiated by a user gesture. +PASS Test that video play does not work unless a user gesture is involved in playing a video. +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/nfc/watch-expected.txt b/third_party/WebKit/LayoutTests/nfc/watch-expected.txt new file mode 100644 index 0000000..2d8375aee --- /dev/null +++ b/third_party/WebKit/LayoutTests/nfc/watch-expected.txt
@@ -0,0 +1,16 @@ +CONSOLE ERROR: Uncaught (in promise) NotFoundError: Invalid NFC watch Id was provided. +CONSOLE ERROR: Uncaught (in promise) NotFoundError: Invalid NFC watch Id was provided. +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Invalid NFC watch Id was provided. +PASS Test that nfc.watch succeeds if NFC hardware is enabled. +PASS Test that nfc.watch fails if NFC hardware is disabled. +PASS Test that nfc.watch fails if NFC hardware is not supported. +PASS Test that default NFCWatchOptions values are set correctly. +PASS Test that NFCWatchOptions values are correctly converted. +PASS Test that nfc.cancelWatch fails if invalid watch ID is provided. +PASS Test that nfc.cancelWatch fails if there are no active watchers. +PASS Test that nfc.cancelWatch succeeds if correct watch id is provided. +PASS Test that nfc.cancelWatch succeeds if there are active watchers. +PASS Test that watch callback is triggered with valid NFCMessage. +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/platform/linux/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt new file mode 100644 index 0000000..74e60e3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +PASS appCodeName +PASS appName +PASS appVersion +PASS platform +PASS product +PASS productSub +PASS userAgent type +FAIL userAgent value assert_equals: userAgent should return the value sent in the User-Agent header expected "{\"error\": {\"message\": \"\", \"code\": 404}}" but got "user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.77.34.5 Safari/537.36\n" +PASS vendor +PASS vendorSub +PASS taintEnabled +PASS oscpu +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt new file mode 100644 index 0000000..ea157644 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +PASS appCodeName +PASS appName +PASS appVersion +PASS platform +PASS product +PASS productSub +PASS userAgent type +FAIL userAgent value assert_equals: userAgent should return the value sent in the User-Agent header expected "{\"error\": {\"message\": \"\", \"code\": 404}}" but got "user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.77.34.5 Safari/537.36\n" +PASS vendor +PASS vendorSub +PASS taintEnabled +PASS oscpu +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt new file mode 100644 index 0000000..2e06406 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +PASS appCodeName +PASS appName +PASS appVersion +PASS platform +PASS product +PASS productSub +PASS userAgent type +FAIL userAgent value assert_equals: userAgent should return the value sent in the User-Agent header expected "{\"error\": {\"message\": \"\", \"code\": 404}}" but got "user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.77.34.5 Safari/537.36\n" +PASS vendor +PASS vendorSub +PASS taintEnabled +PASS oscpu +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-retina/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt new file mode 100644 index 0000000..ef3655e --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-retina/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +PASS appCodeName +PASS appName +PASS appVersion +PASS platform +PASS product +PASS productSub +PASS userAgent type +FAIL userAgent value assert_equals: userAgent should return the value sent in the User-Agent header expected "{\"error\": {\"message\": \"\", \"code\": 404}}" but got "user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.77.34.5 Safari/537.36\n" +PASS vendor +PASS vendorSub +PASS taintEnabled +PASS oscpu +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/mojo-loading/http/tests/security/xss-DENIED-window-name-navigator-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/mojo-loading/http/tests/security/xss-DENIED-window-name-navigator-expected.txt new file mode 100644 index 0000000..315a063 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/mojo-loading/http/tests/security/xss-DENIED-window-name-navigator-expected.txt
@@ -0,0 +1,4 @@ +CONSOLE MESSAGE: line 7: SecurityError: Blocked a frame with origin "null" from accessing a cross-origin frame. +CONSOLE MESSAGE: line 15: SecurityError: Blocked a frame with origin "null" from accessing a cross-origin frame. +CONSOLE MESSAGE: line 7: SecurityError: Blocked a frame with origin "null" from accessing a cross-origin frame. +
diff --git a/third_party/WebKit/LayoutTests/platform/mac/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt new file mode 100644 index 0000000..5891d2f --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +PASS appCodeName +PASS appName +PASS appVersion +PASS platform +PASS product +PASS productSub +PASS userAgent type +FAIL userAgent value assert_equals: userAgent should return the value sent in the User-Agent header expected "{\"error\": {\"message\": \"\", \"code\": 404}}" but got "user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.77.34.5 Safari/537.36\n" +PASS vendor +PASS vendorSub +PASS taintEnabled +PASS oscpu +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/platform/win/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt b/third_party/WebKit/LayoutTests/platform/win/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt new file mode 100644 index 0000000..e7b489c --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +PASS appCodeName +PASS appName +PASS appVersion +PASS platform +PASS product +PASS productSub +PASS userAgent type +FAIL userAgent value assert_equals: userAgent should return the value sent in the User-Agent header expected "{\"error\": {\"message\": \"\", \"code\": 404}}" but got "user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.77.34.5 Safari/537.36\n" +PASS vendor +PASS vendorSub +PASS taintEnabled +PASS oscpu +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/platform/win7/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt new file mode 100644 index 0000000..bf89f63 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win7/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +PASS appCodeName +PASS appName +PASS appVersion +PASS platform +PASS product +PASS productSub +PASS userAgent type +FAIL userAgent value assert_equals: userAgent should return the value sent in the User-Agent header expected "{\"error\": {\"message\": \"\", \"code\": 404}}" but got "user-agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.77.34.5 Safari/537.36\n" +PASS vendor +PASS vendorSub +PASS taintEnabled +PASS oscpu +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/resources/idlharness.js b/third_party/WebKit/LayoutTests/resources/idlharness.js index 7d0abf4..da77fe7 100644 --- a/third_party/WebKit/LayoutTests/resources/idlharness.js +++ b/third_party/WebKit/LayoutTests/resources/idlharness.js
@@ -49,14 +49,19 @@ (function(){ "use strict"; /// Helpers /// -function constValue (cnt) { +function constValue (cnt) +//@{ +{ if (cnt.type === "null") return null; if (cnt.type === "NaN") return NaN; if (cnt.type === "Infinity") return cnt.negative ? -Infinity : Infinity; return cnt.value; } -function minOverloadLength(overloads) { +//@} +function minOverloadLength(overloads) +//@{ +{ if (!overloads.length) { return 0; } @@ -69,7 +74,10 @@ .reduce(function(m, n) { return Math.min(m, n); }); } -function throwOrReject(a_test, operation, fn, obj, args, message, cb) { +//@} +function throwOrReject(a_test, operation, fn, obj, args, message, cb) +//@{ +{ if (operation.idlType.generic !== "Promise") { assert_throws(new TypeError(), function() { fn.apply(obj, args); @@ -87,7 +95,10 @@ } } -function awaitNCallbacks(n, cb, ctx) { +//@} +function awaitNCallbacks(n, cb, ctx) +//@{ +{ var counter = 0; return function() { counter++; @@ -97,7 +108,10 @@ }; } -var fround = (function(){ +//@} +var fround = +//@{ +(function(){ if (Math.fround) return Math.fround; var arr = new Float32Array(1); @@ -106,6 +120,7 @@ return arr[0]; }; })(); +//@} /// IdlArray /// // Entry point @@ -448,7 +463,7 @@ } if (type.generic === "Promise") { - assert_own_property(value, "then", "Attribute with a Promise type has a then property"); + assert_true("then" in value, "Attribute with a Promise type has a then property"); // TODO: Ideally, we would check on project fulfillment // that we get the right type // but that would require making the type check async @@ -650,7 +665,9 @@ IdlDictionary.prototype = Object.create(IdlObject.prototype); /// IdlInterface /// -function IdlInterface(obj, is_callback) { +function IdlInterface(obj, is_callback) +//@{ +{ /** * obj is an object produced by the WebIDLParser.js "interface" production. */ @@ -687,6 +704,7 @@ this._is_callback = is_callback; } +//@} IdlInterface.prototype = Object.create(IdlObject.prototype); IdlInterface.prototype.is_callback = function() //@{ @@ -783,8 +801,8 @@ if (this.is_callback()) { // "The internal [[Prototype]] property of an interface object for - // a callback interface MUST be the Object.prototype object." - assert_equals(Object.getPrototypeOf(self[this.name]), Object.prototype, + // a callback interface must be the Function.prototype object." + assert_equals(Object.getPrototypeOf(self[this.name]), Function.prototype, "prototype of self's property " + format_value(this.name) + " is not Object.prototype"); return; @@ -1117,10 +1135,12 @@ //@} IdlInterface.prototype.test_member_attribute = function(member) //@{ -{ - test(function() + { + var a_test = async_test(this.name + " interface: attribute " + member.name); + a_test.step(function() { if (this.is_callback() && !this.has_constants()) { + a_test.done() return; } @@ -1133,6 +1153,7 @@ assert_own_property(self[this.name], member.name, "The interface object must have a property " + format_value(member.name)); + a_test.done(); } else if (this.is_global()) { assert_own_property(self, member.name, "The global object must have a property " + @@ -1161,23 +1182,42 @@ "Gets on a global should not require an explicit this"); } - this.do_interface_attribute_asserts(self, member); + // do_interface_attribute_asserts must be the last thing we do, + // since it will call done() on a_test. + this.do_interface_attribute_asserts(self, member, a_test); } else { assert_true(member.name in self[this.name].prototype, "The prototype object must have a property " + format_value(member.name)); if (!member.has_extended_attribute("LenientThis")) { - assert_throws(new TypeError(), function() { - self[this.name].prototype[member.name]; - }.bind(this), "getting property on prototype object must throw TypeError"); + if (member.idlType.generic !== "Promise") { + assert_throws(new TypeError(), function() { + self[this.name].prototype[member.name]; + }.bind(this), "getting property on prototype object must throw TypeError"); + // do_interface_attribute_asserts must be the last thing we + // do, since it will call done() on a_test. + this.do_interface_attribute_asserts(self[this.name].prototype, member, a_test); + } else { + promise_rejects(a_test, new TypeError(), + self[this.name].prototype[member.name]) + .then(function() { + // do_interface_attribute_asserts must be the last + // thing we do, since it will call done() on a_test. + this.do_interface_attribute_asserts(self[this.name].prototype, + member, a_test); + }.bind(this)); + } } else { assert_equals(self[this.name].prototype[member.name], undefined, "getting property on prototype object must return undefined"); + // do_interface_attribute_asserts must be the last thing we do, + // since it will call done() on a_test. + this.do_interface_attribute_asserts(self[this.name].prototype, member, a_test); } - this.do_interface_attribute_asserts(self[this.name].prototype, member); + } - }.bind(this), this.name + " interface: attribute " + member.name); + }.bind(this)); }; //@} @@ -1316,6 +1356,46 @@ } //@} +IdlInterface.prototype.add_iterable_members = function(member) +//@{ +{ + this.members.push({type: "operation", name: "entries", idlType: "iterator", arguments: []}); + this.members.push({type: "operation", name: "keys", idlType: "iterator", arguments: []}); + this.members.push({type: "operation", name: "values", idlType: "iterator", arguments: []}); + this.members.push({type: "operation", name: "forEach", idlType: "void", arguments: + [{ name: "callback", idlType: {idlType: "function"}}, + { name: "thisValue", idlType: {idlType: "any"}, optional: true}]}); +}; + +//@} +IdlInterface.prototype.test_member_iterable = function(member) +//@{ +{ + var interfaceName = this.name; + var isPairIterator = member.idlType instanceof Array; + test(function() + { + var descriptor = Object.getOwnPropertyDescriptor(self[interfaceName].prototype, Symbol.iterator); + assert_true(descriptor.writable, "property is not writable"); + assert_true(descriptor.configurable, "property is not configurable"); + assert_false(descriptor.enumerable, "property is enumerable"); + assert_equals(self[interfaceName].prototype[Symbol.iterator].name, isPairIterator ? "entries" : "values", "@@iterator function does not have the right name"); + }, "Testing Symbol.iterator property of iterable interface " + interfaceName); + + if (isPairIterator) { + test(function() { + assert_equals(self[interfaceName].prototype["entries"], self[interfaceName].prototype[Symbol.iterator], "entries method is not the same as @@iterator"); + }, "Testing pair iterable interface " + interfaceName); + } else { + test(function() { + ["entries", "keys", "values", "forEach", Symbol.Iterator].forEach(function(property) { + assert_equals(self[interfaceName].prototype[property], Array.prototype[property], property + " function is not the same as Array one"); + }); + }, "Testing value iterable interface " + interfaceName); + } +}; + +//@} IdlInterface.prototype.test_member_stringifier = function(member) //@{ { @@ -1386,6 +1466,19 @@ for (var i = 0; i < this.members.length; i++) { var member = this.members[i]; + switch (member.type) { + case "iterable": + this.add_iterable_members(member); + break; + // TODO: add setlike and maplike handling. + default: + break; + } + } + + for (var i = 0; i < this.members.length; i++) + { + var member = this.members[i]; if (member.untested) { continue; } @@ -1422,6 +1515,9 @@ } break; + case "iterable": + this.test_member_iterable(member); + break; default: // TODO: check more member types. break; @@ -1522,12 +1618,13 @@ var member = this.members[i]; if (member.type == "attribute" && member.isUnforgeable) { - test(function() - { + var a_test = async_test(this.name + " interface: " + desc + ' must have own property "' + member.name + '"'); + a_test.step(function() { assert_equals(exception, null, "Unexpected exception when evaluating object"); assert_equals(typeof obj, expected_typeof, "wrong typeof object"); - this.do_interface_attribute_asserts(obj, member); - }.bind(this), this.name + " interface: " + desc + ' must have own property "' + member.name + '"'); + // Call do_interface_attribute_asserts last, since it will call a_test.done() + this.do_interface_attribute_asserts(obj, member, a_test); + }.bind(this)); } else if (member.type == "operation" && member.name && @@ -1646,7 +1743,7 @@ }; //@} -IdlInterface.prototype.do_interface_attribute_asserts = function(obj, member) +IdlInterface.prototype.do_interface_attribute_asserts = function(obj, member, a_test) //@{ { // This function tests WebIDL as of 2015-01-27. @@ -1656,6 +1753,8 @@ // it is not a global, and the global otherwise, and by test_interface_of() // with the object as obj. + var pendingPromises = []; + // "For each exposed attribute of the interface, whether it was declared on // the interface itself or one of its consequential interfaces, there MUST // exist a corresponding property. The characteristics of this property are @@ -1695,9 +1794,15 @@ // attribute, then return undefined. // "Otherwise, throw a TypeError." if (!member.has_extended_attribute("LenientThis")) { - assert_throws(new TypeError(), function() { - desc.get.call({}); - }.bind(this), "calling getter on wrong object type must throw TypeError"); + if (member.idlType.generic !== "Promise") { + assert_throws(new TypeError(), function() { + desc.get.call({}); + }.bind(this), "calling getter on wrong object type must throw TypeError"); + } else { + pendingPromises.push( + promise_rejects(a_test, new TypeError(), desc.get.call({}), + "calling getter on wrong object type must reject the return promise with TypeError")); + } } else { assert_equals(desc.get.call({}), undefined, "calling getter on wrong object type must return undefined"); @@ -1748,6 +1853,8 @@ // value 1." assert_equals(desc.set.length, 1, "setter length must be 1"); } + + Promise.all(pendingPromises).then(a_test.done.bind(a_test)); } //@}
diff --git a/third_party/WebKit/LayoutTests/resources/testharness.js b/third_party/WebKit/LayoutTests/resources/testharness.js index 49e38675..a6e7913 100644 --- a/third_party/WebKit/LayoutTests/resources/testharness.js +++ b/third_party/WebKit/LayoutTests/resources/testharness.js
@@ -389,7 +389,7 @@ self.addEventListener("connect", function(message_event) { this_obj._add_message_port(message_event.source); - }); + }, false); } SharedWorkerTestEnvironment.prototype = Object.create(WorkerTestEnvironment.prototype); @@ -430,7 +430,7 @@ this_obj._add_message_port(event.source); } } - }); + }, false); // The oninstall event is received after the service worker script and // all imported scripts have been fetched and executed. It's the @@ -586,7 +586,7 @@ }); for (var i = 0; i < eventTypes.length; i++) { - watchedNode.addEventListener(eventTypes[i], eventHandler); + watchedNode.addEventListener(eventTypes[i], eventHandler, false); } /** @@ -611,7 +611,7 @@ function stop_watching() { for (var i = 0; i < eventTypes.length; i++) { - watchedNode.removeEventListener(eventTypes[i], eventHandler); + watchedNode.removeEventListener(eventTypes[i], eventHandler, false); } }; @@ -2669,7 +2669,7 @@ var tests = new Tests(); - addEventListener("error", function(e) { + var error_handler = function(e) { if (tests.file_is_test) { var test = tests.tests[0]; if (test.phase >= test.phases.HAS_RESULT) { @@ -2684,7 +2684,10 @@ tests.status.message = e.message; tests.status.stack = e.stack; } - }); + }; + + addEventListener("error", error_handler, false); + addEventListener("unhandledrejection", function(e){ error_handler(e.reason); }, false); test_environment.on_tests_ready();
diff --git a/third_party/WebKit/LayoutTests/vr/resources/mock-vr-service.js b/third_party/WebKit/LayoutTests/vr/resources/mock-vr-service.js index fc1be18e..d40e9e4 100644 --- a/third_party/WebKit/LayoutTests/vr/resources/mock-vr-service.js +++ b/third_party/WebKit/LayoutTests/vr/resources/mock-vr-service.js
@@ -13,6 +13,7 @@ this.displayClient_ = new vr_service.VRDisplayClientPtr(); this.displayInfo_ = displayInfo; this.service_ = service; + this.vsync_provider_ = new MockVRVSyncProvider(); interfaceProvider.addInterfaceOverrideForTesting( vr_service.VRDisplay.name, @@ -27,6 +28,8 @@ return Promise.resolve({success: true}); } + getVRVSyncProvider(request) { this.vsync_provider_.bind(request); } + forceActivate(reason) { this.displayClient_.onActivate(reason); } @@ -43,6 +46,26 @@ } } + class MockVRVSyncProvider { + constructor() { + this.timeDelta_ = 0; + this.binding_ = new bindings.Binding(vr_service.VRVSyncProvider, this); + } + bind(request) { + this.binding_.close(); + this.binding_.bind(request); + } + getVSync() { + this.timeDelta_ += 1000.0 / 60.0; + return Promise.resolve({ + pose: null, + time: { + microseconds: this.timeDelta_, + }, + }); + } + } + class MockVRService { constructor(interfaceProvider) { this.bindingSet_ = new bindings.BindingSet(vr_service.VRService);
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-ready-promise-expected.txt b/third_party/WebKit/LayoutTests/web-animations-api/animation-ready-promise-expected.txt new file mode 100644 index 0000000..58e3f773 --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-ready-promise-expected.txt
@@ -0,0 +1,13 @@ +CONSOLE ERROR: line 29: Uncaught (in promise) AbortError: The user aborted a request. +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = The user aborted a request. +PASS The ready attribute should be a Promise +PASS The ready promise should be resolved when an animation is in the idle play state +PASS The ready promise should be replaced when the animation is cancelled +PASS The ready promise should be replaced when the animation enters the pending state +PASS A pending ready promise should be rejected when the animation is cancelled +PASS A pending ready promise should be resolved and not replaced when the animation enters the running state +PASS A pending ready promise should be resolved and not replaced when the animation enters the finished state +PASS A pending ready promise should be resolved and not replaced when the animation enters the paused state +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/Source/core/dom/SynchronousMutationObserver.h b/third_party/WebKit/Source/core/dom/SynchronousMutationObserver.h index ad0311ca..62373f7 100644 --- a/third_party/WebKit/Source/core/dom/SynchronousMutationObserver.h +++ b/third_party/WebKit/Source/core/dom/SynchronousMutationObserver.h
@@ -23,7 +23,7 @@ // // TODO(yosin): Following classes should be derived from this class to // simplify Document class. -// - DragCaretController +// - DragCaret // - DocumentMarkerController // - EventHandler // - FrameCaret
diff --git a/third_party/WebKit/Source/core/editing/BUILD.gn b/third_party/WebKit/Source/core/editing/BUILD.gn index 96c70ce..6f8cd005 100644 --- a/third_party/WebKit/Source/core/editing/BUILD.gn +++ b/third_party/WebKit/Source/core/editing/BUILD.gn
@@ -13,8 +13,8 @@ "CompositionUnderline.h", "DOMSelection.cpp", "DOMSelection.h", - "DragCaretController.cpp", - "DragCaretController.h", + "DragCaret.cpp", + "DragCaret.h", "EditingBehavior.cpp", "EditingBehavior.h", "EditingStrategy.cpp",
diff --git a/third_party/WebKit/Source/core/editing/DragCaretController.cpp b/third_party/WebKit/Source/core/editing/DragCaret.cpp similarity index 80% rename from third_party/WebKit/Source/core/editing/DragCaretController.cpp rename to third_party/WebKit/Source/core/editing/DragCaret.cpp index 01eb293..75480d7b 100644 --- a/third_party/WebKit/Source/core/editing/DragCaretController.cpp +++ b/third_party/WebKit/Source/core/editing/DragCaret.cpp
@@ -23,7 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "core/editing/DragCaretController.h" +#include "core/editing/DragCaret.h" #include "core/editing/EditingUtilities.h" #include "core/frame/Settings.h" @@ -32,15 +32,15 @@ namespace blink { -DragCaretController::DragCaretController() : m_caretBase(new CaretBase()) {} +DragCaret::DragCaret() : m_caretBase(new CaretBase()) {} -DragCaretController::~DragCaretController() = default; +DragCaret::~DragCaret() = default; -DragCaretController* DragCaretController::create() { - return new DragCaretController; +DragCaret* DragCaret::create() { + return new DragCaret; } -bool DragCaretController::hasCaretIn(const LayoutBlock& layoutBlock) const { +bool DragCaret::hasCaretIn(const LayoutBlock& layoutBlock) const { Node* node = m_position.anchorNode(); if (!node) return false; @@ -49,13 +49,12 @@ return rootEditableElementOf(m_position.position()); } -bool DragCaretController::isContentRichlyEditable() const { +bool DragCaret::isContentRichlyEditable() const { return isRichlyEditablePosition(m_position.position()); } -void DragCaretController::invalidateCaretRect( - Node* node, - const LayoutRect& caretLocalRect) { +void DragCaret::invalidateCaretRect(Node* node, + const LayoutRect& caretLocalRect) { // TODO(editing-dev): The use of updateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. // In the long term we should use idle time spell checker to prevent @@ -66,8 +65,7 @@ m_caretBase->invalidateLocalCaretRect(node, caretLocalRect); } -void DragCaretController::setCaretPosition( - const PositionWithAffinity& position) { +void DragCaret::setCaretPosition(const PositionWithAffinity& position) { // for querying Layer::compositingState() // This code is probably correct, since it doesn't occur in a stack that // involves updating compositing state. @@ -91,7 +89,7 @@ } } -void DragCaretController::nodeChildrenWillBeRemoved(ContainerNode& container) { +void DragCaret::nodeChildrenWillBeRemoved(ContainerNode& container) { if (!hasCaret() || !container.inActiveDocument()) return; Node* const anchorNode = m_position.position().anchorNode(); @@ -103,7 +101,7 @@ clear(); } -void DragCaretController::nodeWillBeRemoved(Node& node) { +void DragCaret::nodeWillBeRemoved(Node& node) { if (!hasCaret() || !node.inActiveDocument()) return; Node* const anchorNode = m_position.position().anchorNode(); @@ -115,14 +113,14 @@ clear(); } -DEFINE_TRACE(DragCaretController) { +DEFINE_TRACE(DragCaret) { visitor->trace(m_position); SynchronousMutationObserver::trace(visitor); } -void DragCaretController::paintDragCaret(LocalFrame* frame, - GraphicsContext& context, - const LayoutPoint& paintOffset) const { +void DragCaret::paintDragCaret(LocalFrame* frame, + GraphicsContext& context, + const LayoutPoint& paintOffset) const { if (m_position.anchorNode()->document().frame() == frame) { m_caretBase->paintCaret(m_position.anchorNode(), context, m_caretLocalRect, paintOffset, DisplayItem::kDragCaret);
diff --git a/third_party/WebKit/Source/core/editing/DragCaretController.h b/third_party/WebKit/Source/core/editing/DragCaret.h similarity index 84% rename from third_party/WebKit/Source/core/editing/DragCaretController.h rename to third_party/WebKit/Source/core/editing/DragCaret.h index 6d6df7b..ccb47f5 100644 --- a/third_party/WebKit/Source/core/editing/DragCaretController.h +++ b/third_party/WebKit/Source/core/editing/DragCaret.h
@@ -24,8 +24,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DragCaretController_h -#define DragCaretController_h +#ifndef DragCaret_h +#define DragCaret_h #include "core/dom/SynchronousMutationObserver.h" #include "core/editing/CaretBase.h" @@ -33,16 +33,15 @@ namespace blink { -class DragCaretController final - : public GarbageCollectedFinalized<DragCaretController>, - public SynchronousMutationObserver { - WTF_MAKE_NONCOPYABLE(DragCaretController); - USING_GARBAGE_COLLECTED_MIXIN(DragCaretController); +class DragCaret final : public GarbageCollectedFinalized<DragCaret>, + public SynchronousMutationObserver { + WTF_MAKE_NONCOPYABLE(DragCaret); + USING_GARBAGE_COLLECTED_MIXIN(DragCaret); public: - static DragCaretController* create(); + static DragCaret* create(); - virtual ~DragCaretController(); + virtual ~DragCaret(); void paintDragCaret(LocalFrame*, GraphicsContext&, const LayoutPoint&) const; @@ -57,7 +56,7 @@ DECLARE_TRACE(); private: - DragCaretController(); + DragCaret(); void invalidateCaretRect(Node*, const LayoutRect&); @@ -74,4 +73,4 @@ } // namespace blink -#endif // DragCaretController_h +#endif // DragCaret_h
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp index df74a2f..4d5dac1 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp +++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -111,13 +111,13 @@ } const Document& FrameSelection::document() const { - DCHECK(m_document); - return *m_document; + DCHECK(lifecycleContext()); + return *lifecycleContext(); } Document& FrameSelection::document() { - DCHECK(m_document); - return *m_document; + DCHECK(lifecycleContext()); + return *lifecycleContext(); } // TODO(yosin): To avoid undefined symbols in clang, we explicitly @@ -710,8 +710,6 @@ void FrameSelection::documentAttached(Document* document) { DCHECK(document); - DCHECK(!m_document) << "FrameSelection is already attached to " << m_document; - m_document = document; m_useSecureKeyboardEntryWhenActive = false; m_selectionEditor->documentAttached(document); m_frameCaret->documentAttached(document); @@ -719,8 +717,6 @@ } void FrameSelection::contextDestroyed(Document* document) { - DCHECK_EQ(m_document, document); - m_document = nullptr; m_granularity = CharacterGranularity; LayoutViewItem view = m_frame->contentLayoutItem(); @@ -1303,7 +1299,6 @@ #endif DEFINE_TRACE(FrameSelection) { - visitor->trace(m_document); visitor->trace(m_frame); visitor->trace(m_pendingSelection); visitor->trace(m_selectionEditor);
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.h b/third_party/WebKit/Source/core/editing/FrameSelection.h index a6b7517..0ff79f1 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelection.h +++ b/third_party/WebKit/Source/core/editing/FrameSelection.h
@@ -99,7 +99,7 @@ return static_cast<EUserTriggered>(options & UserTriggered); } - bool isAvailable() const { return m_document; } + bool isAvailable() const { return lifecycleContext(); } // You should not call |document()| when |!isAvailable()|. const Document& document() const; Document& document(); @@ -339,7 +339,6 @@ bool shouldPaintCaretForTesting() const; bool isPreviousCaretDirtyForTesting() const; - Member<Document> m_document; Member<LocalFrame> m_frame; const Member<PendingSelection> m_pendingSelection; const Member<SelectionEditor> m_selectionEditor;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp index eb6fc76..1aba392 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
@@ -29,7 +29,7 @@ #include "core/dom/Element.h" #include "core/dom/StyleEngine.h" #include "core/dom/shadow/ShadowRoot.h" -#include "core/editing/DragCaretController.h" +#include "core/editing/DragCaret.h" #include "core/editing/EditingUtilities.h" #include "core/editing/FrameSelection.h" #include "core/frame/FrameView.h" @@ -1847,9 +1847,8 @@ bool LayoutBlock::hasDragCaret() const { LocalFrame* frame = this->frame(); - DragCaretController& dragCaretController = - frame->page()->dragCaretController(); - return dragCaretController.hasCaretIn(*this); + DragCaret& dragCaret = frame->page()->dragCaret(); + return dragCaret.hasCaretIn(*this); } LayoutRect LayoutBlock::localCaretRect(InlineBox* inlineBox,
diff --git a/third_party/WebKit/Source/core/page/DragController.cpp b/third_party/WebKit/Source/core/page/DragController.cpp index 90e76ca..c9eef0f9 100644 --- a/third_party/WebKit/Source/core/page/DragController.cpp +++ b/third_party/WebKit/Source/core/page/DragController.cpp
@@ -39,7 +39,7 @@ #include "core/dom/Node.h" #include "core/dom/Text.h" #include "core/dom/shadow/ShadowRoot.h" -#include "core/editing/DragCaretController.h" +#include "core/editing/DragCaret.h" #include "core/editing/EditingUtilities.h" #include "core/editing/Editor.h" #include "core/editing/FrameSelection.h" @@ -199,13 +199,13 @@ // FIXME: This method is poorly named. We're just clearing the selection from // the document this drag is exiting. void DragController::cancelDrag() { - m_page->dragCaretController().clear(); + m_page->dragCaret().clear(); } void DragController::dragEnded() { m_dragInitiator = nullptr; m_didInitiateDrag = false; - m_page->dragCaretController().clear(); + m_page->dragCaret().clear(); } void DragController::dragExited(DragData* dragData, LocalFrame& localRoot) { @@ -374,7 +374,7 @@ return false; if (isHandlingDrag) { - m_page->dragCaretController().clear(); + m_page->dragCaret().clear(); return true; } @@ -393,7 +393,7 @@ } if (!m_fileInputElementUnderMouse) { - m_page->dragCaretController().setCaretPosition( + m_page->dragCaret().setCaretPosition( m_documentUnderMouse->frame()->positionForPoint(point)); } @@ -430,7 +430,7 @@ // We are not over an editable region. Make sure we're clearing any prior drag // cursor. - m_page->dragCaretController().clear(); + m_page->dragCaret().clear(); if (m_fileInputElementUnderMouse) m_fileInputElementUnderMouse->setCanReceiveDroppedFiles(false); m_fileInputElementUnderMouse = nullptr; @@ -479,12 +479,12 @@ DragData* dragData) { // Layout should be clean due to a hit test performed in |elementUnderMouse|. DCHECK(!innerFrame->document()->needsLayoutTreeUpdate()); - DCHECK(m_page->dragCaretController().hasCaret()); - String text = m_page->dragCaretController().isContentRichlyEditable() + DCHECK(m_page->dragCaret().hasCaret()); + String text = m_page->dragCaret().isContentRichlyEditable() ? "" : dragData->asPlainText(); const PositionWithAffinity& caretPosition = - m_page->dragCaretController().caretPosition(); + m_page->dragCaret().caretPosition(); DCHECK(caretPosition.isConnected()) << caretPosition; Element* target = innerFrame->editor().findEventTargetFrom(createVisibleSelection( @@ -513,7 +513,7 @@ LocalFrame* innerFrame = element->ownerDocument()->frame(); DCHECK(innerFrame); - if (m_page->dragCaretController().hasCaret() && + if (m_page->dragCaret().hasCaret() && dispatchTextInputEventFor(innerFrame, dragData) != DispatchEventResult::NotCanceled) return true; @@ -532,14 +532,14 @@ // TODO(paulmeyer): Isn't |m_page->dragController()| the same as |this|? if (!m_page->dragController().canProcessDrag(dragData, *innerFrame->localFrameRoot())) { - m_page->dragCaretController().clear(); + m_page->dragCaret().clear(); return false; } - if (m_page->dragCaretController().hasCaret()) { + if (m_page->dragCaret().hasCaret()) { // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets // needs to be audited. See http://crbug.com/590369 for more details. - m_page->dragCaretController() + m_page->dragCaret() .caretPosition() .position() .document() @@ -547,16 +547,16 @@ } const PositionWithAffinity& caretPosition = - m_page->dragCaretController().caretPosition(); + m_page->dragCaret().caretPosition(); if (!caretPosition.isConnected()) { // "editing/pasteboard/drop-text-events-sideeffect-crash.html" and // "editing/pasteboard/drop-text-events-sideeffect.html" reach here. - m_page->dragCaretController().clear(); + m_page->dragCaret().clear(); return false; } VisibleSelection dragCaret = createVisibleSelection( SelectionInDOMTree::Builder().collapse(caretPosition).build()); - m_page->dragCaretController().clear(); + m_page->dragCaret().clear(); // |innerFrame| can be removed by event handler called by // |dispatchTextInputEventFor()|. if (!innerFrame->selection().isAvailable()) {
diff --git a/third_party/WebKit/Source/core/page/Page.cpp b/third_party/WebKit/Source/core/page/Page.cpp index 6557e088..4e1bc08 100644 --- a/third_party/WebKit/Source/core/page/Page.cpp +++ b/third_party/WebKit/Source/core/page/Page.cpp
@@ -27,7 +27,7 @@ #include "core/dom/StyleChangeReason.h" #include "core/dom/StyleEngine.h" #include "core/dom/VisitedLinkState.h" -#include "core/editing/DragCaretController.h" +#include "core/editing/DragCaret.h" #include "core/editing/markers/DocumentMarkerController.h" #include "core/events/Event.h" #include "core/frame/DOMTimer.h" @@ -116,7 +116,7 @@ m_animator(PageAnimator::create(*this)), m_autoscrollController(AutoscrollController::create(*this)), m_chromeClient(pageClients.chromeClient), - m_dragCaretController(DragCaretController::create()), + m_dragCaret(DragCaret::create()), m_dragController(DragController::create(this)), m_focusController(FocusController::create(this)), m_contextMenuController( @@ -494,7 +494,7 @@ visitor->trace(m_animator); visitor->trace(m_autoscrollController); visitor->trace(m_chromeClient); - visitor->trace(m_dragCaretController); + visitor->trace(m_dragCaret); visitor->trace(m_dragController); visitor->trace(m_focusController); visitor->trace(m_contextMenuController);
diff --git a/third_party/WebKit/Source/core/page/Page.h b/third_party/WebKit/Source/core/page/Page.h index c23e07a..d5721803f 100644 --- a/third_party/WebKit/Source/core/page/Page.h +++ b/third_party/WebKit/Source/core/page/Page.h
@@ -52,7 +52,7 @@ class ContextMenuClient; class ContextMenuController; class Document; -class DragCaretController; +class DragCaret; class DragController; class EditorClient; class FocusController; @@ -155,9 +155,7 @@ AutoscrollController& autoscrollController() const { return *m_autoscrollController; } - DragCaretController& dragCaretController() const { - return *m_dragCaretController; - } + DragCaret& dragCaret() const { return *m_dragCaret; } DragController& dragController() const { return *m_dragController; } FocusController& focusController() const { return *m_focusController; } ContextMenuController& contextMenuController() const { @@ -247,7 +245,7 @@ Member<PageAnimator> m_animator; const Member<AutoscrollController> m_autoscrollController; Member<ChromeClient> m_chromeClient; - const Member<DragCaretController> m_dragCaretController; + const Member<DragCaret> m_dragCaret; const Member<DragController> m_dragController; const Member<FocusController> m_focusController; const Member<ContextMenuController> m_contextMenuController;
diff --git a/third_party/WebKit/Source/core/paint/BlockPainter.cpp b/third_party/WebKit/Source/core/paint/BlockPainter.cpp index a6154a5..c075bb1 100644 --- a/third_party/WebKit/Source/core/paint/BlockPainter.cpp +++ b/third_party/WebKit/Source/core/paint/BlockPainter.cpp
@@ -4,7 +4,7 @@ #include "core/paint/BlockPainter.h" -#include "core/editing/DragCaretController.h" +#include "core/editing/DragCaret.h" #include "core/editing/FrameSelection.h" #include "core/layout/LayoutFlexibleBox.h" #include "core/layout/LayoutInline.h" @@ -259,9 +259,10 @@ if (m_layoutBlock.hasCursorCaret()) frame->selection().paintCaret(paintInfo.context, paintOffset); - if (m_layoutBlock.hasDragCaret()) - frame->page()->dragCaretController().paintDragCaret( - frame, paintInfo.context, paintOffset); + if (m_layoutBlock.hasDragCaret()) { + frame->page()->dragCaret().paintDragCaret(frame, paintInfo.context, + paintOffset); + } } DISABLE_CFI_PERF
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp index 5063ae6..71ca7ff 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
@@ -66,12 +66,23 @@ bool PaintLayerPainter::paintedOutputInvisible( const PaintLayerPaintingInfo& paintingInfo) { - if (m_paintLayer.layoutObject()->hasBackdropFilter()) + const LayoutObject& layoutObject = *m_paintLayer.layoutObject(); + if (layoutObject.hasBackdropFilter()) return false; - if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && - m_paintLayer.layoutObject()->styleRef().opacity()) - return false; + if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { + if (layoutObject.styleRef().opacity()) + return false; + + const EffectPaintPropertyNode* effect = + layoutObject.paintProperties()->effect(); + const TransformPaintPropertyNode* transform = + layoutObject.paintProperties()->transform(); + if ((effect && effect->requiresCompositingForAnimation()) || + (transform && transform->requiresCompositingForAnimation())) { + return false; + } + } // 0.0004f < 1/2048. With 10-bit color channels (only available on the // newest Macs; otherwise it's 8-bit), we see that an alpha of 1/2048 or @@ -79,8 +90,7 @@ // not visible. static const float kMinimumVisibleOpacity = 0.0004f; if (m_paintLayer.paintsWithTransparency(paintingInfo.getGlobalPaintFlags())) { - if (m_paintLayer.layoutObject()->styleRef().opacity() < - kMinimumVisibleOpacity) { + if (layoutObject.styleRef().opacity() < kMinimumVisibleOpacity) { return true; } }
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.h b/third_party/WebKit/Source/core/paint/PaintLayerPainter.h index 207ebdea..4a245c4 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.h +++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.h
@@ -154,6 +154,10 @@ FRIEND_TEST_ALL_PREFIXES(PaintLayerPainterTest, DoPaintWithCompositedTinyOpacity); FRIEND_TEST_ALL_PREFIXES(PaintLayerPainterTest, DoPaintWithNonTinyOpacity); + FRIEND_TEST_ALL_PREFIXES(PaintLayerPainterTest, + DoPaintWithEffectAnimationZeroOpacity); + FRIEND_TEST_ALL_PREFIXES(PaintLayerPainterTest, + DoPaintWithTransformAnimationZeroOpacity); }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp index 5d9d39d..69ea1ba 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp
@@ -1060,4 +1060,49 @@ PaintLayerPainter(*targetLayer).paintedOutputInvisible(paintingInfo)); } +TEST_P(PaintLayerPainterTest, DoPaintWithEffectAnimationZeroOpacity) { + setBodyInnerHTML( + "<style> " + "div { " + " width: 100px; " + " height: 100px; " + " animation-name: example; " + " animation-duration: 4s; " + "} " + "@keyframes example { " + " from { opacity: 0.0;} " + " to { opacity: 1.0;} " + "} " + "</style> " + "<div id='target'></div>"); + PaintLayer* targetLayer = + toLayoutBox(getLayoutObjectByElementId("target"))->layer(); + PaintLayerPaintingInfo paintingInfo(nullptr, LayoutRect(), + GlobalPaintNormalPhase, LayoutSize()); + EXPECT_FALSE( + PaintLayerPainter(*targetLayer).paintedOutputInvisible(paintingInfo)); +} + +TEST_P(PaintLayerPainterTest, DoPaintWithTransformAnimationZeroOpacity) { + setBodyInnerHTML( + "<style> " + "div#target { " + " animation-name: example; " + " animation-duration: 4s; " + " opacity: 0.0; " + "} " + "@keyframes example { " + " from { transform: translate(0px, 0px); } " + " to { transform: translate(3em, 0px); } " + "} " + "</style> " + "<div id='target'>x</div></div>"); + PaintLayer* targetLayer = + toLayoutBox(getLayoutObjectByElementId("target"))->layer(); + PaintLayerPaintingInfo paintingInfo(nullptr, LayoutRect(), + GlobalPaintNormalPhase, LayoutSize()); + EXPECT_FALSE( + PaintLayerPainter(*targetLayer).paintedOutputInvisible(paintingInfo)); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp index 926cb5a..716a2d0 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -509,10 +509,11 @@ // We should generate a special clip node to represent this expansion. } - CompositingReasons compositingReasons = - CompositingReasonFinder::requiresCompositingForEffectAnimation(style); - if (compositingReasons != CompositingReasonNone) + CompositingReasons compositingReasons = CompositingReasonNone; + if (CompositingReasonFinder::requiresCompositingForEffectAnimation(style)) { + compositingReasons = CompositingReasonActiveAnimation; effectNodeNeeded = true; + } CompositorElementId compositorElementId = (style.hasCurrentOpacityAnimation() ||
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp index 24ea040e..9014db1 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -3118,6 +3118,7 @@ EXPECT_TRUE(properties->transform()); EXPECT_NE(CompositorElementId(), properties->transform()->compositorElementId()); + EXPECT_TRUE(properties->transform()->requiresCompositingForAnimation()); } TEST_P(PaintPropertyTreeBuilderTest, EffectNodeAnimatedHasCompositorElementId) { @@ -3125,6 +3126,7 @@ const ObjectPaintProperties* properties = paintPropertiesForElement("target"); EXPECT_TRUE(properties->effect()); EXPECT_NE(CompositorElementId(), properties->effect()->compositorElementId()); + EXPECT_TRUE(properties->effect()->requiresCompositingForAnimation()); } TEST_P(PaintPropertyTreeBuilderTest, FloatUnderInline) {
diff --git a/third_party/WebKit/Source/core/workers/Worklet.cpp b/third_party/WebKit/Source/core/workers/Worklet.cpp index da888b1..67a822c 100644 --- a/third_party/WebKit/Source/core/workers/Worklet.cpp +++ b/third_party/WebKit/Source/core/workers/Worklet.cpp
@@ -4,29 +4,24 @@ #include "core/workers/Worklet.h" -#include "bindings/core/v8/ScriptPromiseResolver.h" #include "bindings/core/v8/ScriptSourceCode.h" #include "bindings/core/v8/V8Binding.h" #include "core/dom/DOMException.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" #include "core/frame/LocalFrame.h" -#include "core/loader/DocumentLoader.h" -#include "core/loader/FrameFetchContext.h" #include "core/workers/WorkletGlobalScopeProxy.h" -#include "core/workers/WorkletScriptLoader.h" -#include "platform/loader/fetch/FetchInitiatorTypeNames.h" +#include "wtf/WTF.h" namespace blink { Worklet::Worklet(LocalFrame* frame) - : ContextLifecycleObserver(frame->document()), - m_fetcher(frame->loader().documentLoader()->fetcher()) {} + : ContextLifecycleObserver(frame->document()), m_frame(frame) {} ScriptPromise Worklet::import(ScriptState* scriptState, const String& url) { - if (!isInitialized()) { + DCHECK(isMainThread()); + if (!isInitialized()) initialize(); - } KURL scriptURL = getExecutionContext()->completeURL(url); if (!scriptURL.isValid()) { @@ -35,42 +30,45 @@ DOMException::create(SyntaxError, "'" + url + "' is not a valid URL.")); } - ResourceRequest resourceRequest(scriptURL); - resourceRequest.setRequestContext(WebURLRequest::RequestContextScript); - FetchRequest request(resourceRequest, FetchInitiatorTypeNames::internal); - ScriptResource* resource = ScriptResource::fetch(request, fetcher()); - ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); - if (resource) { - WorkletScriptLoader* workletLoader = - WorkletScriptLoader::create(resolver, this, resource); - m_scriptLoaders.insert(workletLoader); - } else { - resolver->reject(DOMException::create(NetworkError)); - } + + WorkletScriptLoader* scriptLoader = + WorkletScriptLoader::create(m_frame->document()->fetcher(), this); + m_loaderAndResolvers.set(scriptLoader, resolver); + scriptLoader->fetchScript(scriptURL); return promise; } -void Worklet::notifyFinished(WorkletScriptLoader* scriptLoader) { - workletGlobalScopeProxy()->evaluateScript( - ScriptSourceCode(scriptLoader->resource())); - m_scriptLoaders.remove(scriptLoader); +void Worklet::notifyWorkletScriptLoadingFinished( + WorkletScriptLoader* scriptLoader, + const ScriptSourceCode& sourceCode) { + DCHECK(isMainThread()); + ScriptPromiseResolver* resolver = m_loaderAndResolvers.get(scriptLoader); + m_loaderAndResolvers.remove(scriptLoader); + + if (!scriptLoader->wasScriptLoadSuccessful()) { + resolver->reject(DOMException::create(NetworkError)); + return; + } + + workletGlobalScopeProxy()->evaluateScript(sourceCode); + resolver->resolve(); } void Worklet::contextDestroyed(ExecutionContext*) { - if (isInitialized()) { + DCHECK(isMainThread()); + if (isInitialized()) workletGlobalScopeProxy()->terminateWorkletGlobalScope(); - } - - for (const auto& scriptLoader : m_scriptLoaders) { + for (const auto& scriptLoader : m_loaderAndResolvers.keys()) scriptLoader->cancel(); - } + m_loaderAndResolvers.clear(); + m_frame = nullptr; } DEFINE_TRACE(Worklet) { - visitor->trace(m_fetcher); - visitor->trace(m_scriptLoaders); + visitor->trace(m_frame); + visitor->trace(m_loaderAndResolvers); ContextLifecycleObserver::trace(visitor); }
diff --git a/third_party/WebKit/Source/core/workers/Worklet.h b/third_party/WebKit/Source/core/workers/Worklet.h index ebd8d1e..fca8f5e8 100644 --- a/third_party/WebKit/Source/core/workers/Worklet.h +++ b/third_party/WebKit/Source/core/workers/Worklet.h
@@ -6,20 +6,21 @@ #define Worklet_h #include "bindings/core/v8/ScriptPromise.h" +#include "bindings/core/v8/ScriptPromiseResolver.h" #include "bindings/core/v8/ScriptWrappable.h" #include "core/CoreExport.h" #include "core/dom/ContextLifecycleObserver.h" -#include "core/loader/resource/ScriptResource.h" +#include "core/workers/WorkletScriptLoader.h" #include "platform/heap/Handle.h" +#include "platform/loader/fetch/ResourceFetcher.h" namespace blink { class LocalFrame; -class ResourceFetcher; class WorkletGlobalScopeProxy; -class WorkletScriptLoader; class CORE_EXPORT Worklet : public GarbageCollectedFinalized<Worklet>, + public WorkletScriptLoader::Client, public ScriptWrappable, public ContextLifecycleObserver { DEFINE_WRAPPERTYPEINFO(); @@ -27,7 +28,7 @@ WTF_MAKE_NONCOPYABLE(Worklet); public: - virtual ~Worklet() {} + virtual ~Worklet() = default; virtual void initialize() {} virtual bool isInitialized() const { return true; } @@ -37,7 +38,9 @@ // Worklet ScriptPromise import(ScriptState*, const String& url); - void notifyFinished(WorkletScriptLoader*); + // WorkletScriptLoader::Client + void notifyWorkletScriptLoadingFinished(WorkletScriptLoader*, + const ScriptSourceCode&) final; // ContextLifecycleObserver void contextDestroyed(ExecutionContext*) final; @@ -49,10 +52,9 @@ explicit Worklet(LocalFrame*); private: - ResourceFetcher* fetcher() const { return m_fetcher.get(); } - - Member<ResourceFetcher> m_fetcher; - HeapHashSet<Member<WorkletScriptLoader>> m_scriptLoaders; + Member<LocalFrame> m_frame; + HeapHashMap<Member<WorkletScriptLoader>, Member<ScriptPromiseResolver>> + m_loaderAndResolvers; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkletScriptLoader.cpp b/third_party/WebKit/Source/core/workers/WorkletScriptLoader.cpp index f20af72..b9ec6b51 100644 --- a/third_party/WebKit/Source/core/workers/WorkletScriptLoader.cpp +++ b/third_party/WebKit/Source/core/workers/WorkletScriptLoader.cpp
@@ -4,39 +4,65 @@ #include "core/workers/WorkletScriptLoader.h" -#include "core/dom/DOMException.h" -#include "core/dom/ExceptionCode.h" -#include "core/workers/Worklet.h" +#include "bindings/core/v8/ScriptSourceCode.h" +#include "core/loader/FrameFetchContext.h" +#include "platform/loader/fetch/FetchInitiatorTypeNames.h" +#include "wtf/WTF.h" namespace blink { -WorkletScriptLoader::WorkletScriptLoader(ScriptPromiseResolver* resolver, - Worklet* worklet, - ScriptResource* resource) - : m_resolver(resolver), m_host(worklet) { +WorkletScriptLoader::WorkletScriptLoader(ResourceFetcher* fetcher, + Client* client) + : m_fetcher(fetcher), m_client(client) {} + +void WorkletScriptLoader::fetchScript(const String& scriptURL) { + DCHECK(isMainThread()); + DCHECK(!resource()); + DCHECK(!m_wasScriptLoadComplete); + + ResourceRequest resourceRequest(scriptURL); + resourceRequest.setRequestContext(WebURLRequest::RequestContextScript); + FetchRequest request(resourceRequest, FetchInitiatorTypeNames::internal); + ScriptResource* resource = ScriptResource::fetch(request, m_fetcher); + if (!resource) { + notifyFinished(nullptr); + return; + } setResource(resource); + // notifyFinished() will be called later. } void WorkletScriptLoader::cancel() { - clearResource(); + DCHECK(isMainThread()); + if (!resource() || m_wasScriptLoadComplete) + return; + notifyFinished(nullptr); } void WorkletScriptLoader::notifyFinished(Resource* resource) { - DCHECK(this->resource() == resource); - - m_host->notifyFinished(this); - if (resource->errorOccurred()) { - m_resolver->reject(DOMException::create(NetworkError)); - } else { - DCHECK(resource->isLoaded()); - m_resolver->resolve(); - } + DCHECK(isMainThread()); + DCHECK(!m_wasScriptLoadComplete); clearResource(); + m_wasScriptLoadComplete = true; + if (!resource || resource->errorOccurred()) { + m_client->notifyWorkletScriptLoadingFinished(this, ScriptSourceCode()); + } else { + m_wasScriptLoadSuccessful = true; + m_client->notifyWorkletScriptLoadingFinished( + this, ScriptSourceCode(static_cast<ScriptResource*>(resource))); + } + m_fetcher = nullptr; + m_client = nullptr; +} + +bool WorkletScriptLoader::wasScriptLoadSuccessful() const { + DCHECK(m_wasScriptLoadComplete); + return m_wasScriptLoadSuccessful; } DEFINE_TRACE(WorkletScriptLoader) { - visitor->trace(m_resolver); - visitor->trace(m_host); + visitor->trace(m_fetcher); + visitor->trace(m_client); ResourceOwner<ScriptResource, ScriptResourceClient>::trace(visitor); }
diff --git a/third_party/WebKit/Source/core/workers/WorkletScriptLoader.h b/third_party/WebKit/Source/core/workers/WorkletScriptLoader.h index 6291fff..6da3040 100644 --- a/third_party/WebKit/Source/core/workers/WorkletScriptLoader.h +++ b/third_party/WebKit/Source/core/workers/WorkletScriptLoader.h
@@ -5,17 +5,20 @@ #ifndef WorkletScriptLoader_h #define WorkletScriptLoader_h -#include "bindings/core/v8/ScriptPromiseResolver.h" +#include "core/CoreExport.h" #include "core/loader/resource/ScriptResource.h" #include "platform/loader/fetch/ResourceClient.h" #include "platform/loader/fetch/ResourceOwner.h" namespace blink { -class Worklet; +class ResourceFetcher; +class ScriptSourceCode; -// Class that is responsible for processing {@code resource} that is associated -// with worklet's import promise. +// This class is responsible for fetching and loading a worklet script as a +// classic script. You can access this class only on the main thread. +// A client of this class receives notifications via Client interface. +// TODO(nhiroki): Switch to module script loading (https://crbug.com/627945) class WorkletScriptLoader final : public GarbageCollectedFinalized<WorkletScriptLoader>, public ResourceOwner<ScriptResource, ScriptResourceClient> { @@ -23,38 +26,48 @@ WTF_MAKE_NONCOPYABLE(WorkletScriptLoader); public: - static WorkletScriptLoader* create( - ScriptPromiseResolver* scriptPromiseResolver, - Worklet* worklet, - ScriptResource* resource) { - return new WorkletScriptLoader(scriptPromiseResolver, worklet, resource); + class CORE_EXPORT Client : public GarbageCollectedMixin { + public: + // Called when resource loading is completed. If loading is failed or + // canceled, an empty ScriptSourceCode is passed. You can check if loading + // is successfully completed by wasScriptLoadSuccessful(). + virtual void notifyWorkletScriptLoadingFinished( + WorkletScriptLoader*, + const ScriptSourceCode&) = 0; + }; + + static WorkletScriptLoader* create(ResourceFetcher* fetcher, Client* client) { + return new WorkletScriptLoader(fetcher, client); } ~WorkletScriptLoader() override = default; - // Cancels loading of {@code m_resource}. - // - // Typically it gets called when WorkletScriptLoader's host is about to be - // disposed off. + // Fetches an URL and loads it as a classic script. Synchronously calls + // Client::notifyWorkletScriptLoadingFinished() if there is an error. + void fetchScript(const String& scriptURL); + + // Cancels resource loading and synchronously calls + // Client::notifyWorkletScriptLoadingFinished(). void cancel(); + // Returns true if a script was successfully loaded. This should be called + // after Client::notifyWorkletScriptLoadingFinished() is called. + bool wasScriptLoadSuccessful() const; + DECLARE_TRACE(); private: - // Default constructor. - // - // @param resolver Promise resolver that is used to reject/resolve the promise - // on ScriptResourceClient::notifyFinished event. - // @param host Host that needs be notified when the resource is downloaded. - // @param resource that needs to be downloaded. - WorkletScriptLoader(ScriptPromiseResolver*, Worklet* host, ScriptResource*); + WorkletScriptLoader(ResourceFetcher*, Client*); // ResourceClient void notifyFinished(Resource*) final; String debugName() const final { return "WorkletLoader"; } - Member<ScriptPromiseResolver> m_resolver; - Member<Worklet> m_host; + Member<ResourceFetcher> m_fetcher; + Member<Client> m_client; + + bool m_wasScriptLoadSuccessful = false; + bool m_wasScriptLoadComplete = false; }; } // namespace blink
diff --git a/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js b/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js index 20d5b22a..33ebb13 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js
@@ -11,7 +11,7 @@ * @param {!SDK.RemoteObject} object * @return {!Promise<!Components.FrameworkEventListenersObject>} */ -SDK.EventListener.frameworkEventListeners = function(object) { +Components.frameworkEventListeners = function(object) { if (!object.target().hasDOMCapability()) { // TODO(kozyatinskiy): figure out how this should work for |window|. return Promise.resolve(
diff --git a/third_party/WebKit/Source/devtools/front_end/components/EventListenersView.js b/third_party/WebKit/Source/devtools/front_end/components/EventListenersView.js index 76e8ca1..9fca52a1 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/EventListenersView.js +++ b/third_party/WebKit/Source/devtools/front_end/components/EventListenersView.js
@@ -57,7 +57,7 @@ var promises = []; promises.push(object.eventListeners().then(storeEventListeners)); - promises.push(SDK.EventListener.frameworkEventListeners(object).then(storeFrameworkEventListenersObject)); + promises.push(Components.frameworkEventListeners(object).then(storeFrameworkEventListenersObject)); return Promise.all(promises).then(markInternalEventListeners).then(addEventListeners.bind(this)); /**
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkConfigView.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkConfigView.js index 9ecb71a..58668809 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkConfigView.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkConfigView.js
@@ -7,6 +7,10 @@ Network.NetworkConfigView = class extends UI.VBox { constructor() { super(true); + /** @type {!Element} */ + this._autoCheckbox; + /** @type {!{input: !Element, select: !Element}} */ + this._customSelectAndInput; this.registerRequiredCSS('network/networkConfigView.css'); this.contentElement.classList.add('network-config');
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js index e5444aaf..161b1d3 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
@@ -183,6 +183,12 @@ */ constructor(parentView, request) { super(parentView); + /** @type {?Element} */ + this._nameCell = null; + /** @type {?Element} */ + this._initiatorCell = null; + /** @type {?Element} */ + this._linkifiedInitiatorAnchor = null; this._request = request; this._isNavigationRequest = false; this.selectable = true;
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js index 8ca3e4f5..25bef3f 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
@@ -346,7 +346,7 @@ /** * @param {!SDK.NetworkRequest} request - * @return {?Network.NetworkNode} + * @return {?Network.NetworkRequestNode} */ nodeForRequest(request) { return this._nodesByRequestId.get(request.requestId());
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js index 7d2e6ad13..6e60ef2 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
@@ -151,8 +151,11 @@ var node = this._waterfallColumn.getNodeFromPoint(event.offsetX, event.offsetY); if (!node) return; + var request = node.request(); + if (!request) + return; var contextMenu = new UI.ContextMenu(event); - this._networkLogView.handleContextMenuForRequest(contextMenu, node.request()); + this._networkLogView.handleContextMenuForRequest(contextMenu, request); contextMenu.show(); } }
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkOverview.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkOverview.js index f8d0296..1b9fecaa 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkOverview.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkOverview.js
@@ -7,6 +7,7 @@ Network.NetworkOverview = class extends PerfUI.TimelineOverviewBase { constructor() { super(); + this._selectedFilmStripTime = -1; this.element.classList.add('network-overview'); /** @type {number} */
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js index cfe3a2e..92bc783 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js
@@ -633,6 +633,8 @@ * @param {!PerfUI.FilmStripView} filmStripView */ constructor(timeCalculator, filmStripView) { + /** @type {?SDK.Target} */ + this._target = null; this._timeCalculator = timeCalculator; this._filmStripView = filmStripView; } @@ -656,7 +658,7 @@ * @override */ tracingComplete() { - if (!this._tracingModel) + if (!this._tracingModel || !this._target) return; this._tracingModel.tracingComplete(); SDK.targetManager.resumeReload(this._target);
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkTimeCalculator.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkTimeCalculator.js index 26006cd5..05ceea8 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkTimeCalculator.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkTimeCalculator.js
@@ -58,6 +58,8 @@ constructor(startAtZero) { super(); this.startAtZero = startAtZero; + this._minimumBoundary = -1; + this._maximumBoundary = -1; this._boundryChangedEventThrottler = new Common.Throttler(0); /** @type {?Network.NetworkTimeBoundary} */ this._window = null; @@ -143,8 +145,8 @@ } reset() { - delete this._minimumBoundary; - delete this._maximumBoundary; + this._minimumBoundary = -1; + this._maximumBoundary = -1; this._boundaryChanged(); } @@ -296,7 +298,7 @@ var previousMinimumBoundary = this._minimumBoundary; var previousMaximumBoundary = this._maximumBoundary; const minOffset = Network.NetworkTimeCalculator._minimumSpread; - if (typeof this._minimumBoundary === 'undefined' || typeof this._maximumBoundary === 'undefined') { + if (this._minimumBoundary === -1 || this._maximumBoundary === -1) { this._minimumBoundary = timestamp; this._maximumBoundary = timestamp + minOffset; } else {
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkWaterfallColumn.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkWaterfallColumn.js index b314070..6eeb0ba 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkWaterfallColumn.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkWaterfallColumn.js
@@ -30,6 +30,11 @@ this._headerHeight = 0; this._calculator = calculator; + this._offsetWidth = 0; + this._offsetHeight = 0; + this._startTime = this._calculator.minimumBoundary(); + this._endTime = this._calculator.maximumBoundary(); + this._popoverHelper = new UI.PopoverHelper(this.element); this._popoverHelper.initializeCallbacks(this._getPopoverAnchor.bind(this), this._showPopover.bind(this)); this._popoverHelper.setTimeout(300, 300); @@ -214,8 +219,10 @@ } if (eventDividers !== undefined) this._eventDividers = eventDividers; - this.element.window().cancelAnimationFrame(this._updateRequestID); - this._updateRequestID = null; + if (this._updateRequestID) { + this.element.window().cancelAnimationFrame(this._updateRequestID); + delete this._updateRequestID; + } this._startTime = this._calculator.minimumBoundary(); this._endTime = this._calculator.maximumBoundary();
diff --git a/third_party/WebKit/Source/devtools/front_end/network/RequestHeadersView.js b/third_party/WebKit/Source/devtools/front_end/network/RequestHeadersView.js index 742ab30..7b3231ed 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/RequestHeadersView.js +++ b/third_party/WebKit/Source/devtools/front_end/network/RequestHeadersView.js
@@ -216,15 +216,16 @@ * @this {Network.RequestHeadersView} */ function toggleViewSource(event) { - paramsTreeElement._viewSource = !paramsTreeElement._viewSource; + paramsTreeElement[Network.RequestHeadersView._viewSourceSymbol] = + !paramsTreeElement[Network.RequestHeadersView._viewSourceSymbol]; this._refreshParams(title, params, sourceText, paramsTreeElement); event.consume(); } - paramsTreeElement.listItemElement.appendChild( - this._createViewSourceToggle(paramsTreeElement._viewSource, toggleViewSource.bind(this))); + paramsTreeElement.listItemElement.appendChild(this._createViewSourceToggle( + paramsTreeElement[Network.RequestHeadersView._viewSourceSymbol], toggleViewSource.bind(this))); - if (paramsTreeElement._viewSource) { + if (paramsTreeElement[Network.RequestHeadersView._viewSourceSymbol]) { this._populateTreeElementWithSourceText(paramsTreeElement, sourceText); return; } @@ -270,13 +271,15 @@ * @this {Network.RequestHeadersView} */ function toggleViewSource(event) { - treeElement._viewSource = !treeElement._viewSource; + treeElement[Network.RequestHeadersView._viewSourceSymbol] = + !treeElement[Network.RequestHeadersView._viewSourceSymbol]; this._refreshRequestJSONPayload(parsedObject, sourceText); event.consume(); } - listItem.appendChild(this._createViewSourceToggle(treeElement._viewSource, toggleViewSource.bind(this))); - if (treeElement._viewSource) { + listItem.appendChild(this._createViewSourceToggle( + treeElement[Network.RequestHeadersView._viewSourceSymbol], toggleViewSource.bind(this))); + if (treeElement[Network.RequestHeadersView._viewSourceSymbol]) { this._populateTreeElementWithSourceText(this._requestPayloadCategory, sourceText); } else { var object = SDK.RemoteObject.fromLocalObject(parsedObject); @@ -496,6 +499,8 @@ } }; +Network.RequestHeadersView._viewSourceSymbol = Symbol('ViewSource'); + /** * @unrestricted */
diff --git a/third_party/WebKit/Source/devtools/front_end/network/networkConfigView.css b/third_party/WebKit/Source/devtools/front_end/network/networkConfigView.css index 5580678..df43e5a 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/networkConfigView.css +++ b/third_party/WebKit/Source/devtools/front_end/network/networkConfigView.css
@@ -57,11 +57,7 @@ line-height: 20px; } -.network-config-ua label[is="dt-radio"].checked > * { - display: none -} - -.network-config-ua input:not(.dt-radio-button) { +.network-config-ua input { display: block; width: calc(100% - 20px); max-width: 250px; @@ -93,10 +89,6 @@ max-width: 250px; } -.network-config-ua label[is="dt-radio"] { - display: block; -} - .network-config-ua-auto, .network-config-ua-custom { opacity: 0.5; }
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js index 221b59e..1d2517d3 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -790,6 +790,7 @@ this._delegate = delegate; this._filters.push.apply(this._filters, this._filtersControl.filters()); this._dataGrid.markColumnAsSortedBy('startTime', DataGrid.DataGrid.Order.Ascending); + this._splitWidget.showBoth(); } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js index 1dc35d8..cea913c 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
@@ -1354,10 +1354,9 @@ * @this {Element} */ createdCallback: function() { - this.radioElement = this.createChild('input', 'dt-radio-button'); - this.radioElement.type = 'radio'; var root = UI.createShadowRootWithCoreStyles(this, 'ui/radioButton.css'); - root.createChild('content').select = '.dt-radio-button'; + this.radioElement = root.createChild('input', 'dt-radio-button'); + this.radioElement.type = 'radio'; root.createChild('content'); this.addEventListener('click', radioClickHandler, false); },
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/radioButton.css b/third_party/WebKit/Source/devtools/front_end/ui/radioButton.css index 47f4775b..f0e77c6 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/radioButton.css +++ b/third_party/WebKit/Source/devtools/front_end/ui/radioButton.css
@@ -4,7 +4,7 @@ * found in the LICENSE file. */ -::content .dt-radio-button { +.dt-radio-button { height: 17px; width: 17px; min-width: 17px; @@ -16,16 +16,16 @@ margin: 0 5px 5px 0; } -::content .dt-radio-button:active:not(:disabled) { +.dt-radio-button:active:not(:disabled) { background-image: linear-gradient(to bottom, rgb(194, 194, 194), rgb(239, 239, 239)); } -::content .dt-radio-button:checked { +.dt-radio-button:checked { background: url(Images/radioDot.png) center no-repeat, linear-gradient(to bottom, rgb(252, 252, 252), rgb(223, 223, 223)); } -::content .dt-radio-button:checked:active { +.dt-radio-button:checked:active { background: url(Images/radioDot.png) center no-repeat, linear-gradient(to bottom, rgb(194, 194, 194), rgb(239, 239, 239)); }
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.cpp index e4e2d87f..e8bfd645 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.cpp +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.cpp
@@ -71,6 +71,10 @@ std::move(descriptor), characteristic); } +bool BluetoothDevice::isValidDescriptor(const String& descriptorInstanceId) { + return m_attributeInstanceMap->containsDescriptor(descriptorInstanceId); +} + void BluetoothDevice::dispose() { disconnectGATTIfConnected(); }
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.h b/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.h index faaee31..30876f7 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.h +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.h
@@ -61,6 +61,7 @@ BluetoothRemoteGATTDescriptor* getOrCreateBluetoothRemoteGATTDescriptor( mojom::blink::WebBluetoothRemoteGATTDescriptorPtr, BluetoothRemoteGATTCharacteristic*); + bool isValidDescriptor(const String& descriptorInstanceId); // We should disconnect from the device in all of the following cases: // 1. When the object gets GarbageCollected e.g. it went out of scope.
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothError.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothError.cpp index 7868d5a..383649d 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothError.cpp +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothError.cpp
@@ -28,6 +28,8 @@ "GATT Service no longer exists."); MAP_ERROR(CHARACTERISTIC_NO_LONGER_EXISTS, InvalidStateError, "GATT Characteristic no longer exists."); + MAP_ERROR(DESCRIPTOR_NO_LONGER_EXISTS, InvalidStateError, + "GATT Descriptor no longer exists."); // NetworkErrors: MAP_ERROR(CONNECT_ALREADY_IN_PROGRESS, NetworkError,
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp index f40038d..1de9bc3 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp
@@ -101,8 +101,7 @@ resolver->getExecutionContext()->isContextDestroyed()) return; - // If the resolver is not in the set of ActiveAlgorithms then the frame - // disconnected so we reject. + // If the device is disconnected, reject. if (!getGatt()->RemoveFromActiveAlgorithms(resolver)) { resolver->reject(BluetoothRemoteGATTUtils::CreateDOMException( BluetoothRemoteGATTUtils::ExceptionType::kGATTServerDisconnected)); @@ -122,7 +121,6 @@ ScriptPromise BluetoothRemoteGATTCharacteristic::readValue( ScriptState* scriptState) { - // We always check that the device is connected. if (!getGatt()->connected()) { return ScriptPromise::rejectWithDOMException( scriptState, @@ -160,8 +158,7 @@ resolver->getExecutionContext()->isContextDestroyed()) return; - // If the resolver is not in the set of ActiveAlgorithms then the frame - // disconnected so we reject. + // If the device is disconnected, reject. if (!getGatt()->RemoveFromActiveAlgorithms(resolver)) { resolver->reject(BluetoothRemoteGATTUtils::CreateDOMException( BluetoothRemoteGATTUtils::ExceptionType::kGATTServerDisconnected)); @@ -179,7 +176,6 @@ ScriptPromise BluetoothRemoteGATTCharacteristic::writeValue( ScriptState* scriptState, const DOMArrayPiece& value) { - // We always check that the device is connected. if (!getGatt()->connected()) { return ScriptPromise::rejectWithDOMException( scriptState, @@ -231,8 +227,7 @@ resolver->getExecutionContext()->isContextDestroyed()) return; - // If the resolver is not in the set of ActiveAlgorithms then the frame - // disconnected so we reject. + // If the device is disconnected, reject. if (!getGatt()->RemoveFromActiveAlgorithms(resolver)) { resolver->reject(BluetoothRemoteGATTUtils::CreateDOMException( BluetoothRemoteGATTUtils::ExceptionType::kGATTServerDisconnected)); @@ -248,7 +243,6 @@ ScriptPromise BluetoothRemoteGATTCharacteristic::startNotifications( ScriptState* scriptState) { - // We always check that the device is connected. if (!getGatt()->connected()) { return ScriptPromise::rejectWithDOMException( scriptState, @@ -280,7 +274,6 @@ ScriptPromise BluetoothRemoteGATTCharacteristic::stopNotifications( ScriptState* scriptState) { - // We always check that the device is connected. if (!getGatt()->connected()) { return ScriptPromise::rejectWithDOMException( scriptState, @@ -392,8 +385,7 @@ resolver->getExecutionContext()->isContextDestroyed()) return; - // If the resolver is not in the set of ActiveAlgorithms then the frame - // disconnected so we reject. + // If the device is disconnected, reject. if (!service()->device()->gatt()->RemoveFromActiveAlgorithms(resolver)) { resolver->reject(BluetoothRemoteGATTUtils::CreateDOMException( BluetoothRemoteGATTUtils::ExceptionType::kGATTServerDisconnected));
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp index 4184c2d..8b0ca46 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp
@@ -4,8 +4,13 @@ #include "modules/bluetooth/BluetoothRemoteGATTDescriptor.h" +#include "bindings/core/v8/ScriptPromise.h" +#include "bindings/core/v8/ScriptPromiseResolver.h" #include "core/dom/DOMException.h" +#include "modules/bluetooth/Bluetooth.h" +#include "modules/bluetooth/BluetoothError.h" #include "modules/bluetooth/BluetoothRemoteGATTService.h" +#include "modules/bluetooth/BluetoothRemoteGATTUtils.h" #include <memory> namespace blink { @@ -24,14 +29,61 @@ return result; } +void BluetoothRemoteGATTDescriptor::ReadValueCallback( + ScriptPromiseResolver* resolver, + mojom::blink::WebBluetoothResult result, + const Optional<Vector<uint8_t>>& value) { + if (!resolver->getExecutionContext() || + resolver->getExecutionContext()->isContextDestroyed()) + return; + + // If the device is disconnected, reject. + if (!getGatt()->RemoveFromActiveAlgorithms(resolver)) { + resolver->reject(BluetoothRemoteGATTUtils::CreateDOMException( + BluetoothRemoteGATTUtils::ExceptionType::kGATTServerDisconnected)); + return; + } + + if (result == mojom::blink::WebBluetoothResult::SUCCESS) { + DCHECK(value); + DOMDataView* domDataView = + BluetoothRemoteGATTUtils::ConvertWTFVectorToDataView(value.value()); + m_value = domDataView; + resolver->resolve(domDataView); + } else { + resolver->reject(BluetoothError::take(resolver, result)); + } +} + ScriptPromise BluetoothRemoteGATTDescriptor::readValue( ScriptState* scriptState) { - // TODO(668837): Implement WebBluetooth descriptor.readValue() - return ScriptPromise::rejectWithDOMException( - scriptState, - DOMException::create(NotSupportedError, - "descriptor readValue is not implemented " - "yet. See https://goo.gl/J6ASzs")); + if (!getGatt()->connected()) { + return ScriptPromise::rejectWithDOMException( + scriptState, + BluetoothRemoteGATTUtils::CreateDOMException( + BluetoothRemoteGATTUtils::ExceptionType::kGATTServerNotConnected)); + } + + if (!getGatt()->device()->isValidDescriptor(m_descriptor->instance_id)) { + return ScriptPromise::rejectWithDOMException( + scriptState, + BluetoothRemoteGATTUtils::CreateDOMException( + BluetoothRemoteGATTUtils::ExceptionType::kInvalidDescriptor)); + } + + ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + getGatt()->AddToActiveAlgorithms(resolver); + + mojom::blink::WebBluetoothService* service = + m_characteristic->m_device->bluetooth()->service(); + service->RemoteDescriptorReadValue( + m_descriptor->instance_id, + convertToBaseCallback( + WTF::bind(&BluetoothRemoteGATTDescriptor::ReadValueCallback, + wrapPersistent(this), wrapPersistent(resolver)))); + + return promise; } ScriptPromise BluetoothRemoteGATTDescriptor::writeValue(
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.h b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.h index 6a2fc29..b491c1d 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.h +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.h
@@ -55,6 +55,10 @@ BluetoothRemoteGATTServer* getGatt() { return m_characteristic->getGatt(); } + void ReadValueCallback(ScriptPromiseResolver*, + mojom::blink::WebBluetoothResult, + const Optional<Vector<uint8_t>>&); + mojom::blink::WebBluetoothRemoteGATTDescriptorPtr m_descriptor; Member<BluetoothRemoteGATTCharacteristic> m_characteristic; Member<DOMDataView> m_value;
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp index 34717ac..8697c84 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp
@@ -105,8 +105,7 @@ resolver->getExecutionContext()->isContextDestroyed()) return; - // If the resolver is not in the set of ActiveAlgorithms then the frame - // disconnected so we reject. + // If the device is disconnected, reject. if (!RemoveFromActiveAlgorithms(resolver)) { resolver->reject( DOMException::create(NetworkError, kGATTServerDisconnected)); @@ -174,7 +173,6 @@ ScriptState* scriptState, mojom::blink::WebBluetoothGATTQueryQuantity quantity, String servicesUUID) { - // We always check that the device is connected. if (!connected()) { return ScriptPromise::rejectWithDOMException( scriptState,
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTService.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTService.cpp index e9da959b..cfcd631 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTService.cpp +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTService.cpp
@@ -57,8 +57,7 @@ resolver->getExecutionContext()->isContextDestroyed()) return; - // If the resolver is not in the set of ActiveAlgorithms then the frame - // disconnected so we reject. + // If the device is disconnected, reject. if (!device()->gatt()->RemoveFromActiveAlgorithms(resolver)) { resolver->reject( DOMException::create(NetworkError, kGATTServerDisconnected)); @@ -129,7 +128,6 @@ ScriptState* scriptState, mojom::blink::WebBluetoothGATTQueryQuantity quantity, const String& characteristicsUUID) { - // We always check that the device is connected. if (!device()->gatt()->connected()) { return ScriptPromise::rejectWithDOMException( scriptState,
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTUtils.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTUtils.cpp index 7e586e6e..f417871 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTUtils.cpp +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTUtils.cpp
@@ -35,6 +35,12 @@ "Characteristic is no longer valid. Remember to retrieve the " "characteristic again after reconnecting."); + case ExceptionType::kInvalidDescriptor: + return DOMException::create( + InvalidStateError, + "Descriptor is no longer valid. Remember to retrieve the " + "Descriptor again after reconnecting."); + default: NOTREACHED(); return nullptr;
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTUtils.h b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTUtils.h index bc8fa22..de176f3ba 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTUtils.h +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTUtils.h
@@ -18,7 +18,8 @@ enum ExceptionType { kGATTServerDisconnected, kGATTServerNotConnected, - kInvalidCharacteristic + kInvalidCharacteristic, + kInvalidDescriptor }; static DOMException* CreateDOMException(ExceptionType);
diff --git a/third_party/WebKit/Source/modules/presentation/ExistingPresentationConnectionCallbacks.cpp b/third_party/WebKit/Source/modules/presentation/ExistingPresentationConnectionCallbacks.cpp index 7d7a69e..c0c8fac 100644 --- a/third_party/WebKit/Source/modules/presentation/ExistingPresentationConnectionCallbacks.cpp +++ b/third_party/WebKit/Source/modules/presentation/ExistingPresentationConnectionCallbacks.cpp
@@ -40,4 +40,9 @@ NOTREACHED(); } +WebPresentationConnection* +ExistingPresentationConnectionCallbacks::getConnection() { + return m_connection.get(); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/modules/presentation/ExistingPresentationConnectionCallbacks.h b/third_party/WebKit/Source/modules/presentation/ExistingPresentationConnectionCallbacks.h index 055de84f..7a94e65 100644 --- a/third_party/WebKit/Source/modules/presentation/ExistingPresentationConnectionCallbacks.h +++ b/third_party/WebKit/Source/modules/presentation/ExistingPresentationConnectionCallbacks.h
@@ -7,6 +7,7 @@ #include "platform/heap/Handle.h" #include "public/platform/WebCallbacks.h" +#include "public/platform/modules/presentation/WebPresentationConnectionCallbacks.h" #include "wtf/Noncopyable.h" namespace blink { @@ -20,17 +21,22 @@ // underlying promise. It takes the PresentationConnection object that // originated the call in its constructor and will resolve underlying promise // with that object. +// TODO(crbug.com/684111): Combine ExistingPresentationConnectionCallbacks with +// PresentationConnectionCallbacks class ExistingPresentationConnectionCallbacks final - : public WebCallbacks<const WebPresentationSessionInfo&, - const WebPresentationError&> { + : public WebPresentationConnectionCallbacks { public: ExistingPresentationConnectionCallbacks(ScriptPromiseResolver*, PresentationConnection*); ~ExistingPresentationConnectionCallbacks() override = default; + // WebCallbacks implementation void onSuccess(const WebPresentationSessionInfo&) override; void onError(const WebPresentationError&) override; + // WebPresentationConnectionCallbacks implementation + WebPresentationConnection* getConnection() override; + private: Persistent<ScriptPromiseResolver> m_resolver; Persistent<PresentationConnection> m_connection;
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp b/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp index 404deb1c..dc336a1 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp
@@ -153,12 +153,22 @@ m_id(id), m_url(url), m_state(WebPresentationConnectionState::Connecting), - m_binaryType(BinaryTypeBlob) {} + m_binaryType(BinaryTypeBlob), + m_proxy(nullptr) {} PresentationConnection::~PresentationConnection() { ASSERT(!m_blobLoader); } +void PresentationConnection::bindProxy( + std::unique_ptr<WebPresentationConnectionProxy> proxy) { + DCHECK(proxy); + // TODO(zhaobin): Restore to DCHECK(!m_proxy) when reconnect() is properly + // implemented. + if (!m_proxy) + m_proxy = std::move(proxy); +} + // static PresentationConnection* PresentationConnection::take( ScriptPromiseResolver* resolver, @@ -308,20 +318,21 @@ void PresentationConnection::handleMessageQueue() { WebPresentationClient* client = presentationClient(getExecutionContext()); - if (!client) + if (!client || !m_proxy) return; while (!m_messages.isEmpty() && !m_blobLoader) { Message* message = m_messages.first().get(); switch (message->type) { case MessageTypeText: - client->sendString(m_url, m_id, message->text); + client->sendString(m_url, m_id, message->text, m_proxy.get()); m_messages.removeFirst(); break; case MessageTypeArrayBuffer: - client->sendArrayBuffer(m_url, m_id, static_cast<const uint8_t*>( - message->arrayBuffer->data()), - message->arrayBuffer->byteLength()); + client->sendArrayBuffer( + m_url, m_id, + static_cast<const uint8_t*>(message->arrayBuffer->data()), + message->arrayBuffer->byteLength(), m_proxy.get()); m_messages.removeFirst(); break; case MessageTypeBlob: @@ -355,7 +366,7 @@ ASSERT_NOT_REACHED(); } -void PresentationConnection::didReceiveTextMessage(const String& message) { +void PresentationConnection::didReceiveTextMessage(const WebString& message) { if (m_state != WebPresentationConnectionState::Connected) return; @@ -459,10 +470,11 @@ ASSERT(buffer && buffer->buffer()); // Send the loaded blob immediately here and continue processing the queue. WebPresentationClient* client = presentationClient(getExecutionContext()); - if (client) + if (client) { client->sendBlobData(m_url, m_id, static_cast<const uint8_t*>(buffer->data()), - buffer->byteLength()); + buffer->byteLength(), m_proxy.get()); + } m_messages.removeFirst(); m_blobLoader.clear();
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationConnection.h b/third_party/WebKit/Source/modules/presentation/PresentationConnection.h index 72fe6730..804d109e 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationConnection.h +++ b/third_party/WebKit/Source/modules/presentation/PresentationConnection.h
@@ -11,6 +11,8 @@ #include "core/fileapi/FileError.h" #include "platform/heap/Handle.h" #include "platform/weborigin/KURL.h" +#include "public/platform/modules/presentation/WebPresentationConnection.h" +#include "public/platform/modules/presentation/WebPresentationConnectionProxy.h" #include "public/platform/modules/presentation/WebPresentationController.h" #include "public/platform/modules/presentation/WebPresentationSessionInfo.h" #include "wtf/text/WTFString.h" @@ -29,7 +31,8 @@ class PresentationRequest; class PresentationConnection final : public EventTargetWithInlineData, - public ContextClient { + public ContextClient, + public WebPresentationConnection { USING_GARBAGE_COLLECTED_MIXIN(PresentationConnection); DEFINE_WRAPPERTYPEINFO(); @@ -78,15 +81,14 @@ // |url|. bool matches(const String& id, const KURL&) const; - // Notifies the connection about its state change. - void didChangeState(WebPresentationConnectionState); - // Notifies the connection about its state change to 'closed'. void didClose(WebPresentationConnectionCloseReason, const String& message); - // Notifies the presentation about new message. - void didReceiveTextMessage(const String& message); - void didReceiveBinaryMessage(const uint8_t* data, size_t length); + // WebPresentationConnection implementation. + void bindProxy(std::unique_ptr<WebPresentationConnectionProxy>) override; + void didReceiveTextMessage(const WebString& message) override; + void didReceiveBinaryMessage(const uint8_t* data, size_t length) override; + void didChangeState(WebPresentationConnectionState) override; WebPresentationConnectionState getState(); @@ -133,6 +135,8 @@ HeapDeque<Member<Message>> m_messages; BinaryType m_binaryType; + + std::unique_ptr<WebPresentationConnectionProxy> m_proxy; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.cpp b/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.cpp index 30c89bb1..88980d1d 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.cpp
@@ -18,7 +18,7 @@ PresentationConnectionCallbacks::PresentationConnectionCallbacks( ScriptPromiseResolver* resolver, PresentationRequest* request) - : m_resolver(resolver), m_request(request) { + : m_resolver(resolver), m_request(request), m_connection(nullptr) { ASSERT(m_resolver); ASSERT(m_request); } @@ -29,16 +29,24 @@ m_resolver->getExecutionContext()->isContextDestroyed()) { return; } - m_resolver->resolve( - PresentationConnection::take(m_resolver.get(), sessionInfo, m_request)); + + m_connection = + PresentationConnection::take(m_resolver.get(), sessionInfo, m_request); + m_resolver->resolve(m_connection); } void PresentationConnectionCallbacks::onError( const WebPresentationError& error) { if (!m_resolver->getExecutionContext() || - m_resolver->getExecutionContext()->isContextDestroyed()) + m_resolver->getExecutionContext()->isContextDestroyed()) { return; + } m_resolver->reject(PresentationError::take(error)); + m_connection = nullptr; +} + +WebPresentationConnection* PresentationConnectionCallbacks::getConnection() { + return m_connection ? m_connection.get() : nullptr; } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.h b/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.h index 79b33160..a54018c2 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.h +++ b/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.h
@@ -7,10 +7,12 @@ #include "platform/heap/Handle.h" #include "public/platform/WebCallbacks.h" +#include "public/platform/modules/presentation/WebPresentationConnectionCallbacks.h" #include "wtf/Noncopyable.h" namespace blink { +class PresentationConnection; class PresentationRequest; class ScriptPromiseResolver; struct WebPresentationSessionInfo; @@ -21,18 +23,22 @@ // the PresentationRequest object that originated the call in its constructor // and will pass it to the created PresentationConnection. class PresentationConnectionCallbacks final - : public WebCallbacks<const WebPresentationSessionInfo&, - const WebPresentationError&> { + : public WebPresentationConnectionCallbacks { public: PresentationConnectionCallbacks(ScriptPromiseResolver*, PresentationRequest*); ~PresentationConnectionCallbacks() override = default; + // WebCallbacks implementation void onSuccess(const WebPresentationSessionInfo&) override; void onError(const WebPresentationError&) override; + // WebPresentationConnectionCallbacks implementation + WebPresentationConnection* getConnection() override; + private: Persistent<ScriptPromiseResolver> m_resolver; Persistent<PresentationRequest> m_request; + WeakPersistent<PresentationConnection> m_connection; WTF_MAKE_NONCOPYABLE(PresentationConnectionCallbacks); };
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationController.cpp b/third_party/WebKit/Source/modules/presentation/PresentationController.cpp index 8f1646e6..fbceef7 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationController.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationController.cpp
@@ -66,12 +66,13 @@ ContextLifecycleObserver::trace(visitor); } -void PresentationController::didStartDefaultSession( +WebPresentationConnection* PresentationController::didStartDefaultSession( const WebPresentationSessionInfo& sessionInfo) { if (!m_presentation || !m_presentation->defaultRequest()) - return; - PresentationConnection::take(this, sessionInfo, - m_presentation->defaultRequest()); + return nullptr; + + return PresentationConnection::take(this, sessionInfo, + m_presentation->defaultRequest()); } void PresentationController::didChangeSessionState(
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationController.h b/third_party/WebKit/Source/modules/presentation/PresentationController.h index a6ac96d..88afa40 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationController.h +++ b/third_party/WebKit/Source/modules/presentation/PresentationController.h
@@ -45,7 +45,8 @@ DECLARE_VIRTUAL_TRACE(); // Implementation of WebPresentationController. - void didStartDefaultSession(const WebPresentationSessionInfo&) override; + WebPresentationConnection* didStartDefaultSession( + const WebPresentationSessionInfo&) override; void didChangeSessionState(const WebPresentationSessionInfo&, WebPresentationConnectionState) override; void didCloseConnection(const WebPresentationSessionInfo&,
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationReceiver.cpp b/third_party/WebKit/Source/modules/presentation/PresentationReceiver.cpp index aa15f675..d7097b9 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationReceiver.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationReceiver.cpp
@@ -39,7 +39,7 @@ return m_connectionListProperty->promise(scriptState->world()); } -void PresentationReceiver::onReceiverConnectionAvailable( +WebPresentationConnection* PresentationReceiver::onReceiverConnectionAvailable( const WebPresentationSessionInfo& sessionInfo) { // take() will call PresentationReceiver::registerConnection() // and register the connection. @@ -47,7 +47,7 @@ // receiver.connectionList property not accessed if (!m_connectionListProperty) - return; + return nullptr; if (m_connectionListProperty->getState() == ScriptPromisePropertyBase::Pending) @@ -55,6 +55,8 @@ else if (m_connectionListProperty->getState() == ScriptPromisePropertyBase::Resolved) m_connectionList->dispatchConnectionAvailableEvent(connection); + + return connection; } void PresentationReceiver::registerConnection(
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationReceiver.h b/third_party/WebKit/Source/modules/presentation/PresentationReceiver.h index c59d67c..60d9c00 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationReceiver.h +++ b/third_party/WebKit/Source/modules/presentation/PresentationReceiver.h
@@ -43,7 +43,7 @@ ScriptPromise connectionList(ScriptState*); // Implementation of WebPresentationController. - void onReceiverConnectionAvailable( + WebPresentationConnection* onReceiverConnectionAvailable( const WebPresentationSessionInfo&) override; void registerConnection(PresentationConnection*);
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationReceiverTest.cpp b/third_party/WebKit/Source/modules/presentation/PresentationReceiverTest.cpp index 6d6dc95..a57a899b 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationReceiverTest.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationReceiverTest.cpp
@@ -8,9 +8,12 @@ #include "bindings/core/v8/V8BindingForTesting.h" #include "core/frame/LocalFrame.h" #include "core/testing/DummyPageHolder.h" +#include "modules/presentation/PresentationConnection.h" #include "modules/presentation/PresentationConnectionList.h" #include "platform/testing/URLTestHelpers.h" #include "public/platform/modules/presentation/WebPresentationClient.h" +#include "public/platform/modules/presentation/WebPresentationConnectionCallbacks.h" +#include "public/platform/modules/presentation/WebPresentationConnectionProxy.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include <memory> @@ -32,13 +35,13 @@ class MockWebPresentationClient : public WebPresentationClient { void startSession( const WebVector<WebURL>& presentationUrls, - std::unique_ptr<WebPresentationConnectionCallback> callbacks) override { + std::unique_ptr<WebPresentationConnectionCallbacks> callbacks) override { return startSession_(presentationUrls, callbacks); } void joinSession( const WebVector<WebURL>& presentationUrls, const WebString& presentationId, - std::unique_ptr<WebPresentationConnectionCallback> callbacks) override { + std::unique_ptr<WebPresentationConnectionCallbacks> callbacks) override { return joinSession_(presentationUrls, presentationId, callbacks); } @@ -55,29 +58,32 @@ MOCK_METHOD2(startSession_, void(const WebVector<WebURL>& presentationUrls, - std::unique_ptr<WebPresentationConnectionCallback>&)); + std::unique_ptr<WebPresentationConnectionCallbacks>&)); MOCK_METHOD3(joinSession_, void(const WebVector<WebURL>& presentationUrls, const WebString& presentationId, - std::unique_ptr<WebPresentationConnectionCallback>&)); + std::unique_ptr<WebPresentationConnectionCallbacks>&)); - MOCK_METHOD3(sendString, + MOCK_METHOD4(sendString, void(const WebURL& presentationUrl, const WebString& presentationId, - const WebString& message)); + const WebString& message, + const WebPresentationConnectionProxy* proxy)); - MOCK_METHOD4(sendArrayBuffer, + MOCK_METHOD5(sendArrayBuffer, void(const WebURL& presentationUrl, const WebString& presentationId, const uint8_t* data, - size_t length)); + size_t length, + const WebPresentationConnectionProxy* proxy)); - MOCK_METHOD4(sendBlobData, + MOCK_METHOD5(sendBlobData, void(const WebURL& presentationUrl, const WebString& presentationId, const uint8_t* data, - size_t length)); + size_t length, + const WebPresentationConnectionProxy* proxy)); MOCK_METHOD2(closeSession, void(const WebURL& presentationUrl,
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp index 900b0a2..829d1de2 100644 --- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp +++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
@@ -29,6 +29,7 @@ #include "platform/UserGestureIndicator.h" #include "public/platform/Platform.h" #include "wtf/AutoReset.h" +#include "wtf/Time.h" #include <array> @@ -48,33 +49,6 @@ return VREyeNone; } -class VRDisplayFrameRequestCallback : public FrameRequestCallback { - public: - VRDisplayFrameRequestCallback(VRDisplay* vrDisplay) : m_vrDisplay(vrDisplay) { - m_useLegacyTimeBase = true; - } - ~VRDisplayFrameRequestCallback() override {} - void handleEvent(double highResTimeMs) override { - Document* doc = m_vrDisplay->document(); - if (!doc) - return; - - // Need to divide by 1000 here because serviceScriptedAnimations expects - // time to be given in seconds. - m_vrDisplay->serviceScriptedAnimations( - doc->loader()->timing().pseudoWallTimeToMonotonicTime(highResTimeMs / - 1000.0)); - } - - DEFINE_INLINE_VIRTUAL_TRACE() { - visitor->trace(m_vrDisplay); - - FrameRequestCallback::trace(visitor); - } - - Member<VRDisplay> m_vrDisplay; -}; - } // namespace VRDisplay::VRDisplay(NavigatorVR* navigatorVR, @@ -82,25 +56,16 @@ device::mojom::blink::VRDisplayClientRequest request) : ContextLifecycleObserver(navigatorVR->document()), m_navigatorVR(navigatorVR), - m_isConnected(false), - m_isPresenting(false), - m_isValidDeviceForPresenting(true), - m_canUpdateFramePose(true), m_capabilities(new VRDisplayCapabilities()), m_eyeParametersLeft(new VREyeParameters()), m_eyeParametersRight(new VREyeParameters()), - m_depthNear(0.01), - m_depthFar(10000.0), m_fullscreenCheckTimer( TaskRunnerHelper::get(TaskType::UnspecedTimer, navigatorVR->document()->frame()), this, &VRDisplay::onFullscreenCheck), - m_contextGL(nullptr), - m_animationCallbackRequested(false), - m_inAnimationFrame(false), m_display(std::move(display)), - m_binding(this, std::move(request)) {} + m_displayClientBinding(this, std::move(request)) {} VRDisplay::~VRDisplay() {} @@ -149,9 +114,7 @@ } bool VRDisplay::getFrameData(VRFrameData* frameData) { - updatePose(); - - if (!m_framePose) + if (!m_framePose || m_displayBlurred) return false; if (!frameData) @@ -165,9 +128,7 @@ } VRPose* VRDisplay::getPose() { - updatePose(); - - if (!m_framePose) + if (!m_framePose || m_displayBlurred) return nullptr; VRPose* pose = VRPose::create(); @@ -175,23 +136,6 @@ return pose; } -void VRDisplay::updatePose() { - if (m_displayBlurred) { - // WebVR spec says to return a null pose when the display is blurred. - m_framePose = nullptr; - return; - } - if (m_canUpdateFramePose) { - if (!m_display) - return; - device::mojom::blink::VRPosePtr pose; - m_display->GetPose(&pose); - m_framePose = std::move(pose); - if (m_isPresenting) - m_canUpdateFramePose = false; - } -} - void VRDisplay::resetPose() { if (!m_display) return; @@ -214,12 +158,13 @@ Document* doc = this->document(); if (!doc) return 0; - - if (!m_animationCallbackRequested) { - doc->requestAnimationFrame(new VRDisplayFrameRequestCallback(this)); - m_animationCallbackRequested = true; + m_pendingRaf = true; + if (!m_vrVSyncProvider.is_bound()) { + ConnectVSyncProvider(); + } else if (!m_displayBlurred) { + m_vrVSyncProvider->GetVSync(convertToBaseCallback( + WTF::bind(&VRDisplay::OnVSync, wrapWeakPersistent(this)))); } - callback->m_useLegacyTimeBase = false; return ensureScriptedAnimationController(doc).registerCallback(callback); } @@ -232,44 +177,18 @@ void VRDisplay::OnBlur() { m_displayBlurred = true; - + m_vrVSyncProvider.reset(); m_navigatorVR->enqueueVREvent(VRDisplayEvent::create( EventTypeNames::vrdisplayblur, true, false, this, "")); } void VRDisplay::OnFocus() { m_displayBlurred = false; - // Restart our internal doc requestAnimationFrame callback, if it fired while - // the display was blurred. - // TODO(bajones): Don't use doc->requestAnimationFrame() at all. Animation - // frames should be tied to the presenting VR display (e.g. should be serviced - // by GVR library callbacks on Android), and not the doc frame rate. - if (!m_animationCallbackRequested) { - Document* doc = this->document(); - if (!doc) - return; - doc->requestAnimationFrame(new VRDisplayFrameRequestCallback(this)); - } + ConnectVSyncProvider(); m_navigatorVR->enqueueVREvent(VRDisplayEvent::create( EventTypeNames::vrdisplayfocus, true, false, this, "")); } -void VRDisplay::serviceScriptedAnimations(double monotonicAnimationStartTime) { - if (!m_scriptedAnimationController) - return; - AutoReset<bool> animating(&m_inAnimationFrame, true); - m_animationCallbackRequested = false; - - // We use an internal rAF callback to run the animation loop at the display - // speed, and run the user's callback after our internal callback fires. - // However, when the display is blurred, we want to pause the animation loop, - // so we don't fire the user's callback until the display is focused. - if (m_displayBlurred) - return; - m_scriptedAnimationController->serviceScriptedAnimations( - monotonicAnimationStartTime); -} - void ReportPresentationResult(PresentationResult result) { // Note that this is called twice for each call to requestPresent - // one to declare that requestPresent was called, and one for the @@ -655,7 +574,6 @@ m_renderingContext->restoreClearColor(); m_display->SubmitFrame(m_framePose.Clone()); - m_canUpdateFramePose = true; } Document* VRDisplay::document() { @@ -700,6 +618,47 @@ EventTypeNames::vrdisplaydeactivate, true, false, this, reason)); } +void VRDisplay::OnVSync(device::mojom::blink::VRPosePtr pose, + mojo::common::mojom::blink::TimeDeltaPtr time) { + WTF::TimeDelta timeDelta = + WTF::TimeDelta::FromMicroseconds(time->microseconds); + // The VSync provider cannot shut down before replying to pending callbacks, + // so it will send a null pose with no timestamp to be ignored. + if (pose.is_null() && timeDelta.is_zero()) { + // We need to keep the VSync loop going because we haven't responded to the + // previous rAF yet. + m_vrVSyncProvider->GetVSync(convertToBaseCallback( + WTF::bind(&VRDisplay::OnVSync, wrapWeakPersistent(this)))); + return; + } + if (m_displayBlurred) + return; + if (!m_scriptedAnimationController) + return; + Document* doc = this->document(); + if (!doc) + return; + + // Ensure a consistent timebase with document rAF. + if (m_timebase < 0) { + m_timebase = WTF::monotonicallyIncreasingTime() - timeDelta.InSecondsF(); + } + + AutoReset<bool> animating(&m_inAnimationFrame, true); + m_framePose = std::move(pose); + m_pendingRaf = false; + m_scriptedAnimationController->serviceScriptedAnimations( + m_timebase + timeDelta.InSecondsF()); +} + +void VRDisplay::ConnectVSyncProvider() { + m_display->GetVRVSyncProvider(mojo::MakeRequest(&m_vrVSyncProvider)); + if (m_pendingRaf && !m_displayBlurred) { + m_vrVSyncProvider->GetVSync(convertToBaseCallback( + WTF::bind(&VRDisplay::OnVSync, wrapWeakPersistent(this)))); + } +} + void VRDisplay::onFullscreenCheck(TimerBase*) { if (!m_isPresenting) { m_fullscreenCheckTimer.stop(); @@ -745,7 +704,8 @@ } void VRDisplay::dispose() { - m_binding.Close(); + m_displayClientBinding.Close(); + m_vrVSyncProvider.reset(); } ExecutionContext* VRDisplay::getExecutionContext() const {
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.h b/third_party/WebKit/Source/modules/vr/VRDisplay.h index 92cc1f4..a3b8adc 100644 --- a/third_party/WebKit/Source/modules/vr/VRDisplay.h +++ b/third_party/WebKit/Source/modules/vr/VRDisplay.h
@@ -72,7 +72,6 @@ int requestAnimationFrame(FrameRequestCallback*); void cancelAnimationFrame(int id); - void serviceScriptedAnimations(double monotonicAnimationStartTime); ScriptPromise requestPresent(ScriptState*, const HeapVector<VRLayer>& layers); ScriptPromise exitPresent(ScriptState*); @@ -131,41 +130,46 @@ void OnActivate(device::mojom::blink::VRDisplayEventReason) override; void OnDeactivate(device::mojom::blink::VRDisplayEventReason) override; + void OnVSync(device::mojom::blink::VRPosePtr, + mojo::common::mojom::blink::TimeDeltaPtr); + void ConnectVSyncProvider(); + ScriptedAnimationController& ensureScriptedAnimationController(Document*); Member<NavigatorVR> m_navigatorVR; - unsigned m_displayId; + unsigned m_displayId = 0; String m_displayName; - bool m_isConnected; - bool m_isPresenting; - bool m_isValidDeviceForPresenting; - bool m_canUpdateFramePose; + bool m_isConnected = false; + bool m_isPresenting = false; + bool m_isValidDeviceForPresenting = true; Member<VRDisplayCapabilities> m_capabilities; Member<VRStageParameters> m_stageParameters; Member<VREyeParameters> m_eyeParametersLeft; Member<VREyeParameters> m_eyeParametersRight; device::mojom::blink::VRPosePtr m_framePose; VRLayer m_layer; - double m_depthNear; - double m_depthFar; + double m_depthNear = 0.01; + double m_depthFar = 10000.0; void dispose(); TaskRunnerTimer<VRDisplay> m_fullscreenCheckTimer; String m_fullscreenOrigWidth; String m_fullscreenOrigHeight; - gpu::gles2::GLES2Interface* m_contextGL; + gpu::gles2::GLES2Interface* m_contextGL = nullptr; Member<WebGLRenderingContextBase> m_renderingContext; Member<ScriptedAnimationController> m_scriptedAnimationController; - bool m_animationCallbackRequested; - bool m_inAnimationFrame; - bool m_displayBlurred; - bool m_reenteredFullscreen; + bool m_pendingRaf = false; + bool m_inAnimationFrame = false; + bool m_displayBlurred = false; + bool m_reenteredFullscreen = false; + double m_timebase = -1; device::mojom::blink::VRDisplayPtr m_display; - mojo::Binding<device::mojom::blink::VRDisplayClient> m_binding; + mojo::Binding<device::mojom::blink::VRDisplayClient> m_displayClientBinding; + device::mojom::blink::VRVSyncProviderPtr m_vrVSyncProvider; HeapDeque<Member<ScriptPromiseResolver>> m_pendingPresentResolvers; };
diff --git a/third_party/WebKit/Source/modules/vr/VRFrameData.cpp b/third_party/WebKit/Source/modules/vr/VRFrameData.cpp index 6395e5d6..83627ca 100644 --- a/third_party/WebKit/Source/modules/vr/VRFrameData.cpp +++ b/third_party/WebKit/Source/modules/vr/VRFrameData.cpp
@@ -180,9 +180,6 @@ VREyeParameters* rightEye, float depthNear, float depthFar) { - if (!pose) - return false; - m_timestamp = pose->timestamp; // Build the projection matrices
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index 6cc8afe..c10e4d05 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -554,6 +554,8 @@ "exported/WebPrerender.cpp", "exported/WebPrerenderingSupport.cpp", "exported/WebPresentationAvailabilityObserver.cpp", + "exported/WebPresentationConnection.cpp", + "exported/WebPresentationConnectionCallbacks.cpp", "exported/WebPresentationController.cpp", "exported/WebPresentationReceiver.cpp", "exported/WebRTCAnswerOptions.cpp",
diff --git a/third_party/WebKit/Source/platform/exported/WebPresentationConnection.cpp b/third_party/WebKit/Source/platform/exported/WebPresentationConnection.cpp new file mode 100644 index 0000000..f220d6f --- /dev/null +++ b/third_party/WebKit/Source/platform/exported/WebPresentationConnection.cpp
@@ -0,0 +1,11 @@ +// 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 "public/platform/modules/presentation/WebPresentationConnection.h" + +// This WebPresentationConnection.cpp, which includes only +// WebPresentationConnection.h, should be in Source/platform/exported, +// because WebPresentationController is not compiled without this cpp. +// So if we don't have this cpp, we will see unresolved symbol error +// when constructor/destructor's address is required.
diff --git a/third_party/WebKit/Source/platform/exported/WebPresentationConnectionCallbacks.cpp b/third_party/WebKit/Source/platform/exported/WebPresentationConnectionCallbacks.cpp new file mode 100644 index 0000000..1a639f5b --- /dev/null +++ b/third_party/WebKit/Source/platform/exported/WebPresentationConnectionCallbacks.cpp
@@ -0,0 +1,11 @@ +// 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 "public/platform/modules/presentation/WebPresentationConnectionCallbacks.h" + +// This WebPresentationConnectionCallbacks.cpp, which includes only +// WebPresentationConnectionCallbacks.h, should be in Source/platform/exported, +// because WebPresentationConnectionCallbacks is not compiled without this cpp. +// So if we don't have this cpp, we will see unresolved symbol error +// when constructor/destructor's address is required.
diff --git a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h index b9c9d19e..f62059d 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h +++ b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h
@@ -113,6 +113,10 @@ return m_directCompositingReasons != CompositingReasonNone; } + bool requiresCompositingForAnimation() const { + return m_directCompositingReasons & CompositingReasonActiveAnimation; + } + const CompositorElementId& compositorElementId() const { return m_compositorElementId; }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h index 265f63fe..1a525b8 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h +++ b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
@@ -100,6 +100,10 @@ return m_directCompositingReasons != CompositingReasonNone; } + bool requiresCompositingForAnimation() const { + return m_directCompositingReasons & CompositingReasonActiveAnimation; + } + const CompositorElementId& compositorElementId() const { return m_compositorElementId; }
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index 1f250b1f..84776230d 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -361,6 +361,9 @@ "platform/modules/permissions/WebPermissionType.h", "platform/modules/presentation/WebPresentationAvailabilityObserver.h", "platform/modules/presentation/WebPresentationClient.h", + "platform/modules/presentation/WebPresentationConnection.h", + "platform/modules/presentation/WebPresentationConnectionCallbacks.h", + "platform/modules/presentation/WebPresentationConnectionProxy.h", "platform/modules/presentation/WebPresentationController.h", "platform/modules/presentation/WebPresentationError.h", "platform/modules/presentation/WebPresentationReceiver.h",
diff --git a/third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom b/third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom index 148e756e..ed1adc8 100644 --- a/third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom +++ b/third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom
@@ -103,6 +103,7 @@ REQUEST_DEVICE_WITH_BLOCKLISTED_UUID, REQUEST_DEVICE_FROM_CROSS_ORIGIN_IFRAME, REQUEST_DEVICE_WITHOUT_FRAME, + DESCRIPTOR_NO_LONGER_EXISTS, }; struct WebBluetoothScanFilter { @@ -239,6 +240,16 @@ bluetooth.mojom.UUID? descriptor_uuid) => ( WebBluetoothResult result, array<WebBluetoothRemoteGATTDescriptor>? descriptors); + + // Reads the value for the descriptor identified by + // |descriptor_instance_id|. If the value is successfully read the callback + // will be run with WebBluetoothResult::SUCCESS and the descriptor's value. If + // the value is not successfully read the callback with be run with the + // corresponding error and nullptr for value + RemoteDescriptorReadValue( + string descriptor_instance_id) => ( + WebBluetoothResult result, + array<uint8>? value); }; // Classes should implement this interface and pass an associated pointer
diff --git a/third_party/WebKit/public/platform/modules/presentation/WebPresentationClient.h b/third_party/WebKit/public/platform/modules/presentation/WebPresentationClient.h index 77dc785f..d92088b 100644 --- a/third_party/WebKit/public/platform/modules/presentation/WebPresentationClient.h +++ b/third_party/WebKit/public/platform/modules/presentation/WebPresentationClient.h
@@ -15,20 +15,14 @@ class WebPresentationAvailabilityObserver; class WebPresentationController; struct WebPresentationError; +class WebPresentationConnectionCallbacks; +class WebPresentationConnectionProxy; class WebPresentationReceiver; -struct WebPresentationSessionInfo; class WebString; class WebURL; template <typename T> class WebVector; -// If session was created, callback's onSuccess() is invoked with the -// information about the presentation session created by the embedder. -// Otherwise, onError() is invoked with the error code and message. -using WebPresentationConnectionCallback = - WebCallbacks<const WebPresentationSessionInfo&, - const WebPresentationError&>; - // Callback for .getAvailability(). using WebPresentationAvailabilityCallbacks = WebCallbacks<bool, const WebPresentationError&>; @@ -48,33 +42,42 @@ // Called when the frame requests to start a new session. virtual void startSession( const WebVector<WebURL>& presentationUrls, - std::unique_ptr<WebPresentationConnectionCallback>) = 0; + std::unique_ptr<WebPresentationConnectionCallbacks>) = 0; // Called when the frame requests to join an existing session. virtual void joinSession( const WebVector<WebURL>& presentationUrls, const WebString& presentationId, - std::unique_ptr<WebPresentationConnectionCallback>) = 0; + std::unique_ptr<WebPresentationConnectionCallbacks>) = 0; // Called when the frame requests to send String message to an existing // session. + // |proxy|: proxy of blink connection object initiating send String message + // request. Does not pass ownership. virtual void sendString(const WebURL& presentationUrl, const WebString& presentationId, - const WebString& message) = 0; + const WebString& message, + const WebPresentationConnectionProxy*) = 0; // Called when the frame requests to send ArrayBuffer/View data to an existing // session. Embedder copies the |data| and the ownership is not transferred. + // |proxy|: proxy of blink connection object initiating send ArrayBuffer + // request. Does not pass ownership. virtual void sendArrayBuffer(const WebURL& presentationUrl, const WebString& presentationId, const uint8_t* data, - size_t length) = 0; + size_t length, + const WebPresentationConnectionProxy*) = 0; // Called when the frame requests to send Blob data to an existing session. // Embedder copies the |data| and the ownership is not transferred. + // |proxy|: proxy of blink connection object initiating send Blob data + // request. Does not pass ownership. virtual void sendBlobData(const WebURL& presentationUrl, const WebString& presentationId, const uint8_t* data, - size_t length) = 0; + size_t length, + const WebPresentationConnectionProxy*) = 0; // Called when the frame requests to close an existing session. virtual void closeSession(const WebURL& presentationUrl,
diff --git a/third_party/WebKit/public/platform/modules/presentation/WebPresentationConnection.h b/third_party/WebKit/public/platform/modules/presentation/WebPresentationConnection.h new file mode 100644 index 0000000..69460de --- /dev/null +++ b/third_party/WebKit/public/platform/modules/presentation/WebPresentationConnection.h
@@ -0,0 +1,37 @@ +// 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 WebPresentationConnection_h +#define WebPresentationConnection_h + +#include "public/platform/WebCommon.h" + +#include <memory> + +namespace blink { + +enum class WebPresentationConnectionState; +class WebPresentationConnectionProxy; +class WebString; + +// Implemented by the embedder for a PresentationConnection. +class WebPresentationConnection { + public: + virtual ~WebPresentationConnection() = default; + + // Takes ownership of |proxy| and stores it in connection object. Should be + // called only once. + virtual void bindProxy(std::unique_ptr<WebPresentationConnectionProxy>) = 0; + + // Notifies the presentation about new message. + virtual void didReceiveTextMessage(const WebString& message) = 0; + virtual void didReceiveBinaryMessage(const uint8_t* data, size_t length) = 0; + + // Notifies the connection about its state change. + virtual void didChangeState(WebPresentationConnectionState) = 0; +}; + +} // namespace blink + +#endif // WebPresentationConnection_h
diff --git a/third_party/WebKit/public/platform/modules/presentation/WebPresentationConnectionCallbacks.h b/third_party/WebKit/public/platform/modules/presentation/WebPresentationConnectionCallbacks.h new file mode 100644 index 0000000..d24220f0 --- /dev/null +++ b/third_party/WebKit/public/platform/modules/presentation/WebPresentationConnectionCallbacks.h
@@ -0,0 +1,31 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebPresentationConnectionCallbacks_h +#define WebPresentationConnectionCallbacks_h + +#include "public/platform/WebCallbacks.h" +#include "public/platform/WebCommon.h" + +namespace blink { + +class WebPresentationConnection; +struct WebPresentationError; +struct WebPresentationSessionInfo; + +// If session was created, callback's onSuccess() is invoked with the +// information about the presentation session created by the embedder. +// Otherwise, onError() is invoked with the error code and message. +class WebPresentationConnectionCallbacks + : public WebCallbacks<const WebPresentationSessionInfo&, + const WebPresentationError&> { + public: + // Returns newly created PresentationConnection object if + // WebCallbacks::onSuccess() has been called. + virtual WebPresentationConnection* getConnection() = 0; +}; + +} // namespace blink + +#endif // WebPresentationConnectionCallbacks_h
diff --git a/third_party/WebKit/public/platform/modules/presentation/WebPresentationConnectionProxy.h b/third_party/WebKit/public/platform/modules/presentation/WebPresentationConnectionProxy.h new file mode 100644 index 0000000..6340179 --- /dev/null +++ b/third_party/WebKit/public/platform/modules/presentation/WebPresentationConnectionProxy.h
@@ -0,0 +1,20 @@ +// 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 WebPresentationConnectionProxy_h +#define WebPresentationConnectionProxy_h + +namespace blink { + +// The implementation the embedder has to provide for the Presentation API to +// work. This class is used to send messages to a PresentationConnection hosted +// in a different frame. +class WebPresentationConnectionProxy { + public: + virtual ~WebPresentationConnectionProxy() = default; +}; + +} // namespace blink + +#endif // WebPresentationConnectionProxy_h
diff --git a/third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h b/third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h index e59c632..297e07ff 100644 --- a/third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h +++ b/third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h
@@ -10,6 +10,7 @@ namespace blink { struct WebPresentationSessionInfo; +class WebPresentationConnection; class WebString; enum class WebPresentationConnectionCloseReason { Error = 0, Closed, WentAway }; @@ -28,7 +29,8 @@ // Called when the presentation session is started by the embedder using // the default presentation URL and id. - virtual void didStartDefaultSession(const WebPresentationSessionInfo&) = 0; + virtual WebPresentationConnection* didStartDefaultSession( + const WebPresentationSessionInfo&) = 0; // Called when the state of a session changes. virtual void didChangeSessionState(const WebPresentationSessionInfo&,
diff --git a/third_party/WebKit/public/platform/modules/presentation/WebPresentationReceiver.h b/third_party/WebKit/public/platform/modules/presentation/WebPresentationReceiver.h index 15593441..0443b0e 100644 --- a/third_party/WebKit/public/platform/modules/presentation/WebPresentationReceiver.h +++ b/third_party/WebKit/public/platform/modules/presentation/WebPresentationReceiver.h
@@ -10,6 +10,7 @@ namespace blink { struct WebPresentationSessionInfo; +class WebPresentationConnection; // The delegate Blink provides to WebPresentationReceiverClient in order to get // updates. @@ -18,7 +19,7 @@ virtual ~WebPresentationReceiver() = default; // Called when receiver page gets an incoming connection. - virtual void onReceiverConnectionAvailable( + virtual WebPresentationConnection* onReceiverConnectionAvailable( const WebPresentationSessionInfo&) = 0; };
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index c1c8b66f..47e4ad8 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -28097,6 +28097,13 @@ </summary> </histogram> +<histogram name="MobileStartup.ToolbarInflationTime" units="ms"> + <owner>mariakhomenko@chromium.org</owner> + <summary> + Android: The time spent performing toolbar layout inflation. + </summary> +</histogram> + <histogram name="ModuleIntegrityVerification.BytesModified" units="bytes"> <owner>anthonyvd@chromium.org</owner> <summary> @@ -78926,6 +78933,8 @@ <int value="5" label="AVG_BAD_EXT_ID"/> <int value="6" label="AVG_NULL_AVG"/> <int value="7" label="ESWMF_INVALID_DECREMENT_ACTIVITY"/> + <int value="8" label="EFD_BAD_MESSAGE"/> + <int value="9" label="EFD_BAD_MESSAGE_WORKER"/> </enum> <enum name="BadMessageReasonNaCl" type="int"> @@ -87549,6 +87558,8 @@ <int value="1157" label="NETWORKINGPRIVATE_GETGLOBALPOLICY"/> <int value="1158" label="DIAL_FETCHDEVICEDESCRIPTION"/> <int value="1159" label="SYSTEM_DISPLAY_STARTCUSTOMTOUCHCALIBRATION"/> + <int value="1160" label="AUDIO_GETMUTE"/> + <int value="1161" label="AUDIO_SETMUTE"/> </enum> <enum name="ExtensionIconState" type="int"> @@ -111094,6 +111105,7 @@ label="Activity launched with a CUSTOM TAB on Android"/> <affected-histogram name="MobileStartup.ToolbarFirstDrawTime"/> <affected-histogram name="MobileStartup.ToolbarFirstFocusTime"/> + <affected-histogram name="MobileStartup.ToolbarInflationTime"/> </histogram_suffixes> <histogram_suffixes name="ChromeOS.MachineIdRegen.AgeSeconds">
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc index a047acbd..2086222 100644 --- a/ui/views/controls/label.cc +++ b/ui/views/controls/label.cc
@@ -513,6 +513,8 @@ if (!GetRenderTextForSelectionController()) return false; + const bool had_focus = HasFocus(); + // RequestFocus() won't work when the label has FocusBehavior::NEVER. Hence // explicitly set the focused view. // TODO(karandeepb): If a widget with a label having FocusBehavior::NEVER as @@ -521,16 +523,18 @@ // when the widget gets focus again. Fix this. // Tracked in https://crbug.com/630365. if ((event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) && - GetFocusManager()) { + GetFocusManager() && !had_focus) { GetFocusManager()->SetFocusedView(this); } #if defined(OS_LINUX) && !defined(OS_CHROMEOS) - if (event.IsOnlyMiddleMouseButton() && GetFocusManager()) + if (event.IsOnlyMiddleMouseButton() && GetFocusManager() && !had_focus) GetFocusManager()->SetFocusedView(this); #endif - return selection_controller_->OnMousePressed(event, false); + return selection_controller_->OnMousePressed( + event, false, had_focus ? SelectionController::FOCUSED + : SelectionController::UNFOCUSED); } bool Label::OnMouseDragged(const ui::MouseEvent& event) {
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc index d15a3e3..3a417b19 100644 --- a/ui/views/controls/textfield/textfield.cc +++ b/ui/views/controls/textfield/textfield.cc
@@ -575,19 +575,23 @@ } bool Textfield::OnMousePressed(const ui::MouseEvent& event) { + const bool had_focus = HasFocus(); bool handled = controller_ && controller_->HandleMouseEvent(this, event); if (!handled && (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton())) { - RequestFocus(); + if (!had_focus) + RequestFocus(); ShowImeIfNeeded(); } #if defined(OS_LINUX) && !defined(OS_CHROMEOS) - if (!handled && !HasFocus() && event.IsOnlyMiddleMouseButton()) + if (!handled && !had_focus && event.IsOnlyMiddleMouseButton()) RequestFocus(); #endif - return selection_controller_.OnMousePressed(event, handled); + return selection_controller_.OnMousePressed( + event, handled, had_focus ? SelectionController::FOCUSED + : SelectionController::UNFOCUSED); } bool Textfield::OnMouseDragged(const ui::MouseEvent& event) {
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc index 858e7d5..d292e972 100644 --- a/ui/views/controls/textfield/textfield_unittest.cc +++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -1463,7 +1463,7 @@ } // Tests text selection behavior on a right click. -TEST_F(TextfieldTest, SelectWordOnRightClick) { +TEST_F(TextfieldTest, SelectionOnRightClick) { InitTextfield(); textfield_->SetText(ASCIIToUTF16("hello world")); @@ -1478,10 +1478,23 @@ // Verify right clicking outside the selection, selects the word under the // cursor on platforms where this is expected. MoveMouseTo(gfx::Point(GetCursorPositionX(8), cursor_y)); - const char* expected_right_click = + const char* expected_right_click_word = PlatformStyle::kSelectWordOnRightClick ? "world" : "ello"; ClickRightMouseButton(); - EXPECT_STR_EQ(expected_right_click, textfield_->GetSelectedText()); + EXPECT_STR_EQ(expected_right_click_word, textfield_->GetSelectedText()); + + // Verify right clicking inside an unfocused textfield selects all the text on + // platforms where this is expected. Else the older selection is retained. + widget_->GetFocusManager()->ClearFocus(); + EXPECT_FALSE(textfield_->HasFocus()); + MoveMouseTo(gfx::Point(GetCursorPositionX(0), cursor_y)); + ClickRightMouseButton(); + EXPECT_TRUE(textfield_->HasFocus()); + const char* expected_right_click_unfocused = + PlatformStyle::kSelectAllOnRightClickWhenUnfocused + ? "hello world" + : expected_right_click_word; + EXPECT_STR_EQ(expected_right_click_unfocused, textfield_->GetSelectedText()); } TEST_F(TextfieldTest, DragToSelect) {
diff --git a/ui/views/selection_controller.cc b/ui/views/selection_controller.cc index 9aecd74..fdf9924 100644 --- a/ui/views/selection_controller.cc +++ b/ui/views/selection_controller.cc
@@ -27,8 +27,10 @@ DCHECK(delegate); } -bool SelectionController::OnMousePressed(const ui::MouseEvent& event, - bool handled) { +bool SelectionController::OnMousePressed( + const ui::MouseEvent& event, + bool handled, + InitialFocusStateOnMousePress initial_focus_state) { gfx::RenderText* render_text = GetRenderText(); DCHECK(render_text); @@ -61,23 +63,22 @@ break; case 2: // Select all the text on a triple click. - delegate_->OnBeforePointerAction(); - render_text->SelectAll(false); - delegate_->OnAfterPointerAction(false, true); + SelectAll(); break; default: NOTREACHED(); } } - // TODO(crbug.com/676296): Right clicking an unfocused text view should select - // all its text on Mac. - const bool select_word_on_right_click = - event.IsOnlyRightMouseButton() && - PlatformStyle::kSelectWordOnRightClick && - !render_text->IsPointInSelection(event.location()); - if (select_word_on_right_click) - SelectWord(event.location()); + if (event.IsOnlyRightMouseButton()) { + if (PlatformStyle::kSelectAllOnRightClickWhenUnfocused && + initial_focus_state == InitialFocusStateOnMousePress::UNFOCUSED) { + SelectAll(); + } else if (PlatformStyle::kSelectWordOnRightClick && + !render_text->IsPointInSelection(event.location())) { + SelectWord(event.location()); + } + } if (handles_selection_clipboard_ && event.IsOnlyMiddleMouseButton()) { if (render_text->IsPointInSelection(event.location())) { @@ -186,6 +187,14 @@ delegate_->OnAfterPointerAction(false, true); } +void SelectionController::SelectAll() { + gfx::RenderText* render_text = GetRenderText(); + DCHECK(render_text); + delegate_->OnBeforePointerAction(); + render_text->SelectAll(false); + delegate_->OnAfterPointerAction(false, true); +} + gfx::RenderText* SelectionController::GetRenderText() { return delegate_->GetRenderTextForSelectionController(); }
diff --git a/ui/views/selection_controller.h b/ui/views/selection_controller.h index 8a410e9..3a2279be 100644 --- a/ui/views/selection_controller.h +++ b/ui/views/selection_controller.h
@@ -28,6 +28,13 @@ // TODO(karandeepb): Also make this class handle gesture events. class VIEWS_EXPORT SelectionController { public: + // Describes whether the view managing the delegate was initially focused when + // the mouse press was received. + enum InitialFocusStateOnMousePress { + FOCUSED, + UNFOCUSED, + }; + // |delegate| must be non-null. explicit SelectionController(SelectionControllerDelegate* delegate); @@ -35,7 +42,9 @@ // the event has already been handled by the |delegate_|. If |handled| is // true, the mouse event is just used to update the internal state without // updating the state of the associated RenderText instance. - bool OnMousePressed(const ui::MouseEvent& event, bool handled); + bool OnMousePressed(const ui::MouseEvent& event, + bool handled, + InitialFocusStateOnMousePress initial_focus_state); bool OnMouseDragged(const ui::MouseEvent& event); void OnMouseReleased(const ui::MouseEvent& event); void OnMouseCaptureLost(); @@ -56,6 +65,9 @@ // Selects the word at the given |point|. void SelectWord(const gfx::Point& point); + // Selects all the text. + void SelectAll(); + // Returns the associated render text instance via the |delegate_|. gfx::RenderText* GetRenderText();
diff --git a/ui/views/style/platform_style.cc b/ui/views/style/platform_style.cc index d2188c9..b744302 100644 --- a/ui/views/style/platform_style.cc +++ b/ui/views/style/platform_style.cc
@@ -42,6 +42,7 @@ const bool PlatformStyle::kDefaultLabelButtonHasBoldFont = true; const bool PlatformStyle::kDialogDefaultButtonCanBeCancel = true; const bool PlatformStyle::kSelectWordOnRightClick = false; +const bool PlatformStyle::kSelectAllOnRightClickWhenUnfocused = false; const CustomButton::NotifyAction PlatformStyle::kMenuNotifyActivationAction = CustomButton::NOTIFY_ON_RELEASE; const CustomButton::KeyClickAction PlatformStyle::kKeyClickActionOnSpace =
diff --git a/ui/views/style/platform_style.h b/ui/views/style/platform_style.h index 5f945147..93b8c84 100644 --- a/ui/views/style/platform_style.h +++ b/ui/views/style/platform_style.h
@@ -43,6 +43,9 @@ // Whether right clicking on text, selects the word under cursor. static const bool kSelectWordOnRightClick; + // Whether right clicking inside an unfocused text view selects all the text. + static const bool kSelectAllOnRightClickWhenUnfocused; + // The menu button's action to show the menu. static const CustomButton::NotifyAction kMenuNotifyActivationAction;
diff --git a/ui/views/style/platform_style_mac.mm b/ui/views/style/platform_style_mac.mm index c5e0814..3785d83 100644 --- a/ui/views/style/platform_style_mac.mm +++ b/ui/views/style/platform_style_mac.mm
@@ -24,6 +24,7 @@ const bool PlatformStyle::kDefaultLabelButtonHasBoldFont = false; const bool PlatformStyle::kDialogDefaultButtonCanBeCancel = false; const bool PlatformStyle::kSelectWordOnRightClick = true; +const bool PlatformStyle::kSelectAllOnRightClickWhenUnfocused = true; const bool PlatformStyle::kTreeViewHasFocusRing = true; const bool PlatformStyle::kTreeViewSelectionPaintsEntireRow = true; const bool PlatformStyle::kUseRipples = false;