diff --git a/DEPS b/DEPS index 9aa8ddf..28054b1 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'fc4ee229a653d0e9d71f828e513c9d458c1eab57', + 'skia_revision': '8abb9f45379823f417371d3e99f42629fbccd579', # 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': '1115d8724ce832a77e1a85e0ba3fbee527ea7eb0', + 'v8_revision': 'a47a2b11cb904b87c10c50ad2ff54668042d62ee', # 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. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '21dd189fe50d297dd1224c06319e166c1ac6bae2', + 'pdfium_revision': '3a4ebcc7c490eba0c22892ab04d1730c350fd0c0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # 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': 'ebf00ecf2e8397f7774dcd90c73f40fcba8097d5', + 'catapult_revision': 'af47a939971b50a8f4c7b2e234ec7069ca196841', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -199,7 +199,7 @@ Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0', 'src/third_party/webgl/src': - Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '5e57726d6fe2833c957b5a33cd0aed19d67a4fa9', + Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '72eda82d069da578af04e5c4e8e411ae006b6a18', 'src/third_party/webdriver/pylib': Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc index 5c9301b5..734516a 100644 --- a/ash/display/display_manager_unittest.cc +++ b/ash/display/display_manager_unittest.cc
@@ -64,10 +64,7 @@ public display::DisplayObserver, public aura::WindowObserver { public: - DisplayManagerTest() - : removed_count_(0U), - root_window_destroyed_(false), - changed_metrics_(0U) {} + DisplayManagerTest() {} ~DisplayManagerTest() override {} void SetUp() override { @@ -86,14 +83,15 @@ uint32_t changed_metrics() const { return changed_metrics_; } string GetCountSummary() const { - return StringPrintf("%" PRIuS " %" PRIuS " %" PRIuS, changed_.size(), - added_.size(), removed_count_); + return StringPrintf("%" PRIuS " %" PRIuS " %" PRIuS " %" PRIuS " %" PRIuS, + changed_.size(), added_.size(), removed_count_, + will_process_count_, did_process_count_); } void reset() { changed_.clear(); added_.clear(); - removed_count_ = 0U; + removed_count_ = will_process_count_ = did_process_count_ = 0U; changed_metrics_ = 0U; root_window_destroyed_ = false; } @@ -118,6 +116,8 @@ } // aura::DisplayObserver overrides: + void OnWillProcessDisplayChanges() override { ++will_process_count_; } + void OnDidProcessDisplayChanges() override { ++did_process_count_; } void OnDisplayMetricsChanged(const display::Display& display, uint32_t changed_metrics) override { changed_.push_back(display); @@ -139,9 +139,11 @@ private: vector<display::Display> changed_; vector<display::Display> added_; - size_t removed_count_; - bool root_window_destroyed_; - uint32_t changed_metrics_; + size_t removed_count_ = 0u; + size_t will_process_count_ = 0u; + size_t did_process_count_ = 0u; + bool root_window_destroyed_ = false; + uint32_t changed_metrics_ = 0u; DISALLOW_COPY_AND_ASSIGN(DisplayManagerTest); }; @@ -155,7 +157,7 @@ EXPECT_EQ("0,0 500x500", display_manager()->GetDisplayAt(0).bounds().ToString()); - EXPECT_EQ("2 1 0", GetCountSummary()); + EXPECT_EQ("2 1 0 1 1", GetCountSummary()); EXPECT_EQ(display_manager()->GetDisplayAt(1).id(), changed()[0].id()); EXPECT_EQ(display_manager()->GetDisplayAt(0).id(), changed()[1].id()); EXPECT_EQ(display_manager()->GetDisplayAt(1).id(), added()[0].id()); @@ -169,12 +171,12 @@ // Delete secondary. UpdateDisplay("100+0-500x500"); - EXPECT_EQ("0 0 1", GetCountSummary()); + EXPECT_EQ("0 0 1 1 1", GetCountSummary()); reset(); // Change primary. UpdateDisplay("1+1-1000x600"); - EXPECT_EQ("1 0 0", GetCountSummary()); + EXPECT_EQ("1 0 0 1 1", GetCountSummary()); EXPECT_EQ(display_manager()->GetDisplayAt(0).id(), changed()[0].id()); EXPECT_EQ("0,0 1000x600", changed()[0].bounds().ToString()); reset(); @@ -182,7 +184,7 @@ // Add secondary. UpdateDisplay("1+1-1000x600,1002+0-600x400"); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); - EXPECT_EQ("1 1 0", GetCountSummary()); + EXPECT_EQ("1 1 0 1 1", GetCountSummary()); EXPECT_EQ(display_manager()->GetDisplayAt(1).id(), changed()[0].id()); EXPECT_EQ(display_manager()->GetDisplayAt(1).id(), added()[0].id()); // Secondary display is on right. @@ -194,7 +196,7 @@ // Secondary removed, primary changed. UpdateDisplay("1+1-800x300"); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); - EXPECT_EQ("1 0 1", GetCountSummary()); + EXPECT_EQ("1 0 1 1 1", GetCountSummary()); EXPECT_EQ(display_manager()->GetDisplayAt(0).id(), changed()[0].id()); EXPECT_EQ("0,0 800x300", changed()[0].bounds().ToString()); reset(); @@ -203,7 +205,9 @@ const vector<display::ManagedDisplayInfo> empty; display_manager()->OnNativeDisplaysChanged(empty); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); - EXPECT_EQ("0 0 0", GetCountSummary()); + // Going to 0 displays doesn't actually change the list and is effectively + // ignored. + EXPECT_EQ("0 0 0 0 0", GetCountSummary()); EXPECT_FALSE(root_window_destroyed()); // Display configuration stays the same EXPECT_EQ("0,0 800x300", @@ -213,7 +217,7 @@ // Connect to display again UpdateDisplay("100+100-500x400"); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); - EXPECT_EQ("1 0 0", GetCountSummary()); + EXPECT_EQ("1 0 0 1 1", GetCountSummary()); EXPECT_FALSE(root_window_destroyed()); EXPECT_EQ("0,0 500x400", changed()[0].bounds().ToString()); EXPECT_EQ("100,100 500x400", @@ -240,7 +244,7 @@ // Changing primary will update secondary as well. UpdateDisplay("0+0-800x600,1000+1000-600x400"); - EXPECT_EQ("2 0 0", GetCountSummary()); + EXPECT_EQ("2 0 0 1 1", GetCountSummary()); reset(); EXPECT_EQ("0,0 800x600", display_manager()->GetDisplayAt(0).bounds().ToString()); @@ -263,17 +267,17 @@ display_manager()->AddRemoveDisplay(); // Update primary and add seconary. EXPECT_EQ(2U, display_manager()->GetNumDisplays()); - EXPECT_EQ("1 1 0", GetCountSummary()); + EXPECT_EQ("1 1 0 1 1", GetCountSummary()); reset(); display_manager()->AddRemoveDisplay(); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); - EXPECT_EQ("0 0 1", GetCountSummary()); + EXPECT_EQ("0 0 1 1 1", GetCountSummary()); reset(); display_manager()->AddRemoveDisplay(); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); - EXPECT_EQ("1 1 0", GetCountSummary()); + EXPECT_EQ("1 1 0 1 1", GetCountSummary()); } // Tests support for 3 displays. @@ -292,7 +296,7 @@ EXPECT_EQ("960,0 400x300", display_manager()->GetDisplayAt(2).bounds().ToString()); - EXPECT_EQ("3 2 0", GetCountSummary()); + EXPECT_EQ("3 2 0 1 1", GetCountSummary()); EXPECT_EQ(display_manager()->GetDisplayAt(1).id(), changed()[0].id()); EXPECT_EQ(display_manager()->GetDisplayAt(2).id(), changed()[1].id()); EXPECT_EQ(display_manager()->GetDisplayAt(0).id(), changed()[2].id()); @@ -1199,11 +1203,11 @@ EXPECT_EQ(1, host->compositor()->device_scale_factor()); EXPECT_EQ("1000x600", Shell::GetPrimaryRootWindow()->bounds().size().ToString()); - EXPECT_EQ("1 0 0", GetCountSummary()); + EXPECT_EQ("1 0 0 1 1", GetCountSummary()); UpdateDisplay("1000x600*2"); EXPECT_EQ(2, host->compositor()->device_scale_factor()); - EXPECT_EQ("2 0 0", GetCountSummary()); + EXPECT_EQ("2 0 0 2 2", GetCountSummary()); EXPECT_EQ("500x300", Shell::GetPrimaryRootWindow()->bounds().size().ToString()); } @@ -1596,7 +1600,7 @@ EXPECT_EQ("400x300", GetDisplayInfoAt(1).size_in_pixel().ToString()); reset(); UpdateDisplay("100x200/b,300x400"); - EXPECT_EQ("2 0 0", GetCountSummary()); + EXPECT_EQ("2 0 0 1 1", GetCountSummary()); reset(); EXPECT_EQ("1,1 100x200", GetDisplayInfoAt(0).bounds_in_native().ToString()); @@ -1607,30 +1611,31 @@ // Just Rotating display will change the bounds on both display. UpdateDisplay("100x200/l,300x400"); - EXPECT_EQ("2 0 0", GetCountSummary()); + EXPECT_EQ("2 0 0 1 1", GetCountSummary()); reset(); - // Updating to the same configuration should report no changes. + // Updating to the same configuration should report no changes. A will/did + // change is still sent. UpdateDisplay("100x200/l,300x400"); - EXPECT_EQ("0 0 0", GetCountSummary()); + EXPECT_EQ("0 0 0 1 1", GetCountSummary()); reset(); // Rotating 180 degrees should report one change. UpdateDisplay("100x200/r,300x400"); - EXPECT_EQ("1 0 0", GetCountSummary()); + EXPECT_EQ("1 0 0 1 1", GetCountSummary()); reset(); UpdateDisplay("200x200"); - EXPECT_EQ("1 0 1", GetCountSummary()); + EXPECT_EQ("1 0 1 1 1", GetCountSummary()); reset(); // Rotating 180 degrees should report one change. UpdateDisplay("200x200/u"); - EXPECT_EQ("1 0 0", GetCountSummary()); + EXPECT_EQ("1 0 0 1 1", GetCountSummary()); reset(); UpdateDisplay("200x200/l"); - EXPECT_EQ("1 0 0", GetCountSummary()); + EXPECT_EQ("1 0 0 1 1", GetCountSummary()); // Having the internal display deactivated should restore user rotation. Newly // set rotations should be applied.
diff --git a/ash/display/window_tree_host_manager.cc b/ash/display/window_tree_host_manager.cc index e5d787ef..2605bd4 100644 --- a/ash/display/window_tree_host_manager.cc +++ b/ash/display/window_tree_host_manager.cc
@@ -606,14 +606,15 @@ // unified and non unified, but I'm keeping them separated to minimize // the risk in M44. I'll consolidate this in M45. DCHECK(window_tree_hosts_.empty()); - primary_display_id = display.id(); - window_tree_hosts_[display.id()] = primary_tree_host_for_replace_; - GetRootWindowSettings(GetWindow(primary_tree_host_for_replace_)) - ->display_id = display.id(); + AshWindowTreeHost* ash_host = primary_tree_host_for_replace_; primary_tree_host_for_replace_ = nullptr; + primary_display_id = display.id(); + window_tree_hosts_[display.id()] = ash_host; + GetRootWindowSettings(GetWindow(ash_host))->display_id = display.id(); + for (auto& observer : observers_) + observer.OnWindowTreeHostReusedForDisplay(ash_host, display); const display::ManagedDisplayInfo& display_info = GetDisplayManager()->GetDisplayInfo(display.id()); - AshWindowTreeHost* ash_host = window_tree_hosts_[display.id()]; ash_host->AsWindowTreeHost()->SetBoundsInPixels( display_info.bounds_in_native()); SetDisplayPropertiesOnHost(ash_host, display);
diff --git a/ash/display/window_tree_host_manager.h b/ash/display/window_tree_host_manager.h index 545ae6e..50e930c9 100644 --- a/ash/display/window_tree_host_manager.h +++ b/ash/display/window_tree_host_manager.h
@@ -68,6 +68,13 @@ // Invoked in WindowTreeHostManager::Shutdown(). virtual void OnWindowTreeHostManagerShutdown() {} + // Invoked when an existing AshWindowTreeHost is reused for a new display. + // This happens when all displays are removed, and then a new display is + // added. + virtual void OnWindowTreeHostReusedForDisplay( + AshWindowTreeHost* window_tree_host, + const display::Display& display) {} + protected: virtual ~Observer() {} };
diff --git a/ash/laser/laser_segment_utils.cc b/ash/laser/laser_segment_utils.cc index 189f51b..52d85d7 100644 --- a/ash/laser/laser_segment_utils.cc +++ b/ash/laser/laser_segment_utils.cc
@@ -4,6 +4,7 @@ #include "ash/laser/laser_segment_utils.h" +#include <cmath> #include <limits> #include "base/logging.h" @@ -67,8 +68,8 @@ gfx::PointF* second_projection) { // If the slope is NaN, the y-intercept should be NaN too. The line is thus // vertical and projections will be projected straight up/down from |point|. - if (isnan(line_slope)) { - DCHECK(isnan(line_y_intercept)); + if (std::isnan(line_slope)) { + DCHECK(std::isnan(line_y_intercept)); *first_projection = gfx::PointF(point.x(), point.y() + round(projection_distance));
diff --git a/ash/mus/DEPS b/ash/mus/DEPS index b39c35c..7d88d9a0 100644 --- a/ash/mus/DEPS +++ b/ash/mus/DEPS
@@ -20,6 +20,10 @@ "+mash/quick_launch/public", ], + "display_synchronizer.cc": [ + "+ash/host/ash_window_tree_host.h", + ], + "non_client_frame_controller_unittest.cc": [ # These tests inspect the DrawQuads in the CompositorFrame generated by the # compositor. So this needs to explicitly depend on cc.
diff --git a/ash/mus/display_synchronizer.cc b/ash/mus/display_synchronizer.cc index ca00f7c..8aa12a5 100644 --- a/ash/mus/display_synchronizer.cc +++ b/ash/mus/display_synchronizer.cc
@@ -4,8 +4,11 @@ #include "ash/mus/display_synchronizer.h" +#include "ash/host/ash_window_tree_host.h" #include "ash/shell.h" +#include "services/ui/public/interfaces/window_manager_constants.mojom.h" #include "ui/aura/mus/window_manager_delegate.h" +#include "ui/aura/mus/window_tree_host_mus.h" #include "ui/display/manager/display_manager.h" #include "ui/display/manager/managed_display_info.h" @@ -25,6 +28,9 @@ } void DisplaySynchronizer::SendDisplayConfigurationToServer() { + if (processing_display_changes_) + return; + display::DisplayManager* display_manager = Shell::Get()->display_manager(); const size_t display_count = display_manager->GetNumDisplays(); if (display_count == 0) @@ -58,6 +64,38 @@ SendDisplayConfigurationToServer(); } +void DisplaySynchronizer::OnWindowTreeHostReusedForDisplay( + AshWindowTreeHost* window_tree_host, + const display::Display& display) { + aura::WindowTreeHostMus* window_tree_host_mus = + static_cast<aura::WindowTreeHostMus*>( + window_tree_host->AsWindowTreeHost()); + if (window_tree_host_mus->display_id() == display.id()) + return; + const display::ManagedDisplayInfo& display_info = + Shell::Get()->display_manager()->GetDisplayInfo(display.id()); + ui::mojom::WmViewportMetricsPtr viewport_metrics = + ui::mojom::WmViewportMetrics::New(); + viewport_metrics->bounds_in_pixels = display_info.bounds_in_native(); + viewport_metrics->device_scale_factor = display.device_scale_factor(); + viewport_metrics->ui_scale_factor = display_info.configured_ui_scale(); + window_manager_client_->AddDisplayReusingWindowTreeHost( + static_cast<aura::WindowTreeHostMus*>( + window_tree_host->AsWindowTreeHost()), + display, std::move(viewport_metrics)); +} + +void DisplaySynchronizer::OnWillProcessDisplayChanges() { + DCHECK(!processing_display_changes_); + processing_display_changes_ = true; +} + +void DisplaySynchronizer::OnDidProcessDisplayChanges() { + DCHECK(processing_display_changes_); + processing_display_changes_ = false; + SendDisplayConfigurationToServer(); +} + void DisplaySynchronizer::OnDisplayMetricsChanged( const display::Display& display, uint32_t changed_metrics) {
diff --git a/ash/mus/display_synchronizer.h b/ash/mus/display_synchronizer.h index 3428cc5..b38a286 100644 --- a/ash/mus/display_synchronizer.h +++ b/ash/mus/display_synchronizer.h
@@ -31,8 +31,13 @@ // WindowTreeHostManager::Observer: void OnDisplaysInitialized() override; void OnDisplayConfigurationChanged() override; + void OnWindowTreeHostReusedForDisplay( + AshWindowTreeHost* window_tree_host, + const display::Display& display) override; // display::DisplayObserver: + void OnWillProcessDisplayChanges() override; + void OnDidProcessDisplayChanges() override; void OnDisplayMetricsChanged(const display::Display& display, uint32_t changed_metrics) override; @@ -40,6 +45,16 @@ bool sent_initial_config_ = false; + // Set to true when OnWillProcessDisplayChanges() is called and false in + // OnDidProcessDisplayChanges(). DisplayManager calls out while the list of + // displays contains both newly added displays and displays that have been + // removed. This means if we attempt to access the list of displays during + // this time we may get the wrong state (SendDisplayConfigurationToServer() + // would send a bogus display to the window server). By only processing the + // change after DisplayManager has updated its internal state we ensure we + // don't send a bad config. + bool processing_display_changes_ = false; + DISALLOW_COPY_AND_ASSIGN(DisplaySynchronizer); };
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn index 9e5568b..961f0dd 100644 --- a/ash/resources/vector_icons/BUILD.gn +++ b/ash/resources/vector_icons/BUILD.gn
@@ -82,6 +82,8 @@ "palette_tray_icon_magnify.icon", "palette_tray_icon_metalayer.1x.icon", "palette_tray_icon_metalayer.icon", + "shelf_back.1x.icon", + "shelf_back.icon", "shelf_keyboard.1x.icon", "shelf_keyboard.icon", "shelf_logout.1x.icon",
diff --git a/ash/resources/vector_icons/shelf_back.1x.icon b/ash/resources/vector_icons/shelf_back.1x.icon new file mode 100644 index 0000000..0eb4554 --- /dev/null +++ b/ash/resources/vector_icons/shelf_back.1x.icon
@@ -0,0 +1,24 @@ +// 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. + +CANVAS_DIMENSIONS, 16, +MOVE_TO, 0, 0, +R_H_LINE_TO, 16, +R_V_LINE_TO, 16, +H_LINE_TO, 0, +CLOSE, +NEW_PATH, +PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF, +MOVE_TO, 5.2f, 7, +H_LINE_TO, 15, +R_V_LINE_TO, 2, +H_LINE_TO, 5.2f, +R_LINE_TO, 4.8f, 4.8f, +LINE_TO, 8.9f, 15, +LINE_TO, 2, 8, +R_LINE_TO, 6.9f, -7, +LINE_TO, 10, 2.2f, +LINE_TO, 5.2f, 7, +CLOSE, +END
diff --git a/ash/resources/vector_icons/shelf_back.icon b/ash/resources/vector_icons/shelf_back.icon new file mode 100644 index 0000000..c8ca33f --- /dev/null +++ b/ash/resources/vector_icons/shelf_back.icon
@@ -0,0 +1,23 @@ +// 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. + +CANVAS_DIMENSIONS, 32, +MOVE_TO, 0, 0, +R_H_LINE_TO, 32, +R_V_LINE_TO, 32, +H_LINE_TO, 0, +CLOSE, +NEW_PATH, +PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF, +MOVE_TO, 8.56f, 17.99f, +R_LINE_TO, 9.65f, 9.98f, +LINE_TO, 16.18f, 30, +LINE_TO, 3, 16.49f, +LINE_TO, 16.18f, 3, +R_LINE_TO, 2.03f, 2, +R_LINE_TO, -9.86f, 9.99f, +H_LINE_TO, 29, +R_V_LINE_TO, 3, +CLOSE, +END
diff --git a/ash/shelf/app_list_button.cc b/ash/shelf/app_list_button.cc index 82948a84..fdc86e4 100644 --- a/ash/shelf/app_list_button.cc +++ b/ash/shelf/app_list_button.cc
@@ -17,20 +17,24 @@ #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/tray/tray_popup_utils.h" +#include "ash/wm/maximize_mode/maximize_mode_controller.h" #include "base/command_line.h" #include "base/memory/ptr_util.h" #include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics_action.h" #include "base/timer/timer.h" #include "chromeos/chromeos_switches.h" +#include "third_party/skia/include/core/SkPath.h" #include "ui/accessibility/ax_node_data.h" #include "ui/app_list/presenter/app_list.h" +#include "ui/aura/window_tree_host.h" #include "ui/base/l10n/l10n_util.h" #include "ui/compositor/layer_animation_element.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/layer_animation_sequence.h" #include "ui/compositor/paint_context.h" #include "ui/compositor/paint_recorder.h" +#include "ui/events/event_sink.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/canvas_image_source.h" #include "ui/gfx/image/image_skia.h" @@ -44,7 +48,35 @@ namespace ash { namespace { + constexpr int kVoiceInteractionAnimationDelayMs = 200; + +// Generate and send a VKEY_BROWSER_BACK key event when the back button portion +// is clicked or tapped. +void GenerateAndSendBackEvent(const ui::LocatedEvent& original_event) { + ui::EventType event_type; + switch (original_event.type()) { + case ui::ET_MOUSE_PRESSED: + case ui::ET_GESTURE_TAP_DOWN: + event_type = ui::ET_KEY_PRESSED; + break; + case ui::ET_MOUSE_RELEASED: + case ui::ET_GESTURE_TAP: + event_type = ui::ET_KEY_RELEASED; + break; + default: + return; + } + + ui::KeyEvent key_event(event_type, ui::VKEY_BROWSER_BACK, ui::EF_NONE); + aura::Window* target = static_cast<aura::Window*>(original_event.target()); + aura::Window* target_root = target->GetRootWindow() + ? target->GetRootWindow() + : Shell::Get()->GetPrimaryRootWindow(); + ignore_result( + target_root->GetHost()->event_sink()->OnEventFromSource(&key_event)); +} + } // namespace constexpr uint8_t kVoiceInteractionRunningAlpha = 255; // 100% alpha @@ -106,6 +138,28 @@ } void AppListButton::OnGestureEvent(ui::GestureEvent* event) { + last_event_is_back_event_ = IsBackEvent(event->location()); + // Handle gesture events that are on the back button. + if (last_event_is_back_event_) { + switch (event->type()) { + case ui::ET_GESTURE_TAP: + AnimateInkDrop(views::InkDropState::ACTION_TRIGGERED, event); + GenerateAndSendBackEvent(*event); + break; + case ui::ET_GESTURE_TAP_CANCEL: + AnimateInkDrop(views::InkDropState::HIDDEN, event); + break; + case ui::ET_GESTURE_TAP_DOWN: + AnimateInkDrop(views::InkDropState::ACTION_PENDING, event); + GenerateAndSendBackEvent(*event); + break; + default: + break; + } + return; + } + + // Handle gesture events that are on the app list circle. switch (event->type()) { case ui::ET_GESTURE_SCROLL_BEGIN: AnimateInkDrop(views::InkDropState::HIDDEN, event); @@ -172,14 +226,26 @@ } bool AppListButton::OnMousePressed(const ui::MouseEvent& event) { - ImageButton::OnMousePressed(event); - shelf_view_->PointerPressedOnButton(this, ShelfView::MOUSE, event); + last_event_is_back_event_ = IsBackEvent(event.location()); + if (last_event_is_back_event_) { + AnimateInkDrop(views::InkDropState::ACTION_PENDING, &event); + GenerateAndSendBackEvent(*event.AsLocatedEvent()); + } else { + ImageButton::OnMousePressed(event); + shelf_view_->PointerPressedOnButton(this, ShelfView::MOUSE, event); + } return true; } void AppListButton::OnMouseReleased(const ui::MouseEvent& event) { - ImageButton::OnMouseReleased(event); - shelf_view_->PointerReleasedOnButton(this, ShelfView::MOUSE, false); + last_event_is_back_event_ = IsBackEvent(event.location()); + if (last_event_is_back_event_) { + AnimateInkDrop(views::InkDropState::ACTION_TRIGGERED, &event); + GenerateAndSendBackEvent(*event.AsLocatedEvent()); + } else { + ImageButton::OnMouseReleased(event); + shelf_view_->PointerReleasedOnButton(this, ShelfView::MOUSE, false); + } } void AppListButton::OnMouseCaptureLost() { @@ -200,7 +266,8 @@ std::unique_ptr<views::InkDropRipple> AppListButton::CreateInkDropRipple() const { - gfx::Point center = GetCenterPoint(); + gfx::Point center = last_event_is_back_event_ ? GetBackButtonCenterPoint() + : GetAppListButtonCenterPoint(); gfx::Rect bounds(center.x() - kAppListButtonRadius, center.y() - kAppListButtonRadius, 2 * kAppListButtonRadius, 2 * kAppListButtonRadius); @@ -232,22 +299,81 @@ } std::unique_ptr<views::InkDropMask> AppListButton::CreateInkDropMask() const { - return base::MakeUnique<views::CircleInkDropMask>(size(), GetCenterPoint(), - kAppListButtonRadius); + return base::MakeUnique<views::CircleInkDropMask>( + size(), + last_event_is_back_event_ ? GetBackButtonCenterPoint() + : GetAppListButtonCenterPoint(), + kAppListButtonRadius); } void AppListButton::PaintButtonContents(gfx::Canvas* canvas) { - gfx::PointF circle_center(GetCenterPoint()); + const bool is_maximize_mode = Shell::Get() + ->maximize_mode_controller() + ->IsMaximizeModeWindowManagerEnabled(); + gfx::PointF circle_center(GetAppListButtonCenterPoint()); // Paint the circular background. cc::PaintFlags bg_flags; bg_flags.setColor(background_color_); bg_flags.setAntiAlias(true); bg_flags.setStyle(cc::PaintFlags::kFill_Style); - canvas->DrawCircle(circle_center, kAppListButtonRadius, bg_flags); - // Paint a white ring as the foreground. The ceil/dsf math assures that the - // ring draws sharply and is centered at all scale factors. + if (is_maximize_mode) { + // Draw the maximize mode app list background. It will look something like + // [1] when the shelf is horizontal and [2] when the shelf is vertical, + // where 1. is the back button and 2. is the app launcher circle. + // _____ + // [1] _______________ [2] / 1. \ + // / \ | | + // | 1. 2. | | 2. | + // \_______________/ \_____/ + + // Calculate the rectangular bounds of the path. The primary axis will be + // the distance between the back button and app circle centers and the + // secondary axis will be 2 * |kAppListButtonRadius|. The origin will be + // situated such that the back button center and app circle center are + // located equal distance from the sides parallel to the primary axis. See + // diagrams below; (1) is the back button and (2) is the app circle. + // + // ___________ ____(1)____ + // | | | | + // (1) (2) | | + // |_________| | | + // |___(2)___| + gfx::PointF back_center(GetBackButtonCenterPoint()); + gfx::RectF background_bounds( + shelf_->PrimaryAxisValue(back_center.x(), + back_center.x() - kAppListButtonRadius), + shelf_->PrimaryAxisValue(back_center.y() - kAppListButtonRadius, + back_center.y()), + shelf_->PrimaryAxisValue(circle_center.x() - back_center.x(), + 2 * kAppListButtonRadius), + shelf_->PrimaryAxisValue(2 * kAppListButtonRadius, + circle_center.y() - back_center.y())); + + // Create the path by drawing two circles, one around the back button and + // one around the app list circle. Join them with the rectangle calculated + // previously. + SkPath path; + path.addCircle(circle_center.x(), circle_center.y(), kAppListButtonRadius); + path.addCircle(back_center.x(), back_center.y(), kAppListButtonRadius); + path.addRect(background_bounds.x(), background_bounds.y(), + background_bounds.right(), background_bounds.bottom()); + canvas->DrawPath(path, bg_flags); + + // Draw the back button icon. + // TODO(sammiequon): Check if the back button should be flipped in RTL. + gfx::ImageSkia back_button = + CreateVectorIcon(kShelfBackIcon, SK_ColorTRANSPARENT); + canvas->DrawImageInt(back_button, back_center.x() - back_button.width() / 2, + back_center.y() - back_button.height() / 2); + } else { + canvas->DrawCircle(circle_center, kAppListButtonRadius, bg_flags); + } + + // Paint a white ring as the foreground for the app list circle. The ceil/dsf + // math assures that the ring draws sharply and is centered at all scale + // factors. float ring_outer_radius_dp = 7.f; float ring_thickness_dp = 1.5f; if (chromeos::switches::IsVoiceInteractionEnabled()) { @@ -286,26 +412,55 @@ } } -gfx::Point AppListButton::GetCenterPoint() const { +gfx::Point AppListButton::GetAppListButtonCenterPoint() const { // For a bottom-aligned shelf, the button bounds could have a larger height - // than width (in the case of touch-dragging the shelf updwards) or a larger + // than width (in the case of touch-dragging the shelf upwards) or a larger // width than height (in the case of a shelf hide/show animation), so adjust // the y-position of the circle's center to ensure correct layout. Similarly - // adjust the x-position for a left- or right-aligned shelf. + // adjust the x-position for a left- or right-aligned shelf. In maximized + // mode, the button will increase it's primary axis size to accomodate the + // back button arrow in addition to the app list button circle. const int x_mid = width() / 2.f; const int y_mid = height() / 2.f; + const bool is_maximize_mode = Shell::Get() + ->maximize_mode_controller() + ->IsMaximizeModeWindowManagerEnabled(); + ShelfAlignment alignment = shelf_->alignment(); if (alignment == SHELF_ALIGNMENT_BOTTOM || alignment == SHELF_ALIGNMENT_BOTTOM_LOCKED) { + if (is_maximize_mode) { + return gfx::Point(width() - kShelfButtonSize / 2.f, + kShelfButtonSize / 2.f); + } return gfx::Point(x_mid, x_mid); } else if (alignment == SHELF_ALIGNMENT_RIGHT) { + if (is_maximize_mode) { + return gfx::Point(kShelfButtonSize / 2.f, + height() - kShelfButtonSize / 2.f); + } return gfx::Point(y_mid, y_mid); } else { DCHECK_EQ(alignment, SHELF_ALIGNMENT_LEFT); + if (is_maximize_mode) { + return gfx::Point(width() - kShelfButtonSize / 2.f, + height() - kShelfButtonSize / 2.f); + } return gfx::Point(width() - y_mid, y_mid); } } +gfx::Point AppListButton::GetBackButtonCenterPoint() const { + DCHECK(Shell::Get() + ->maximize_mode_controller() + ->IsMaximizeModeWindowManagerEnabled()); + + if (shelf_->alignment() == SHELF_ALIGNMENT_LEFT) + return gfx::Point(width() - kShelfButtonSize / 2.f, kShelfButtonSize / 2.f); + + return gfx::Point(kShelfButtonSize / 2.f, kShelfButtonSize / 2.f); +} + void AppListButton::OnAppListVisibilityChanged(bool shown, aura::Window* root_window) { if (shelf_ != Shelf::ForWindow(root_window)) @@ -322,4 +477,15 @@ SchedulePaint(); } +bool AppListButton::IsBackEvent(const gfx::Point& location) { + if (!Shell::Get() + ->maximize_mode_controller() + ->IsMaximizeModeWindowManagerEnabled()) { + return false; + } + + return (location - GetBackButtonCenterPoint()).LengthSquared() < + (location - GetAppListButtonCenterPoint()).LengthSquared(); +} + } // namespace ash
diff --git a/ash/shelf/app_list_button.h b/ash/shelf/app_list_button.h index 6ad53960..67a644b 100644 --- a/ash/shelf/app_list_button.h +++ b/ash/shelf/app_list_button.h
@@ -40,15 +40,18 @@ // Updates background and schedules a paint. void UpdateShelfItemBackground(SkColor color); - // views::ImageButton overrides: + // views::ImageButton: void OnGestureEvent(ui::GestureEvent* event) override; - // Get the center point of the app list button used to draw its background and - // ink drops. - gfx::Point GetCenterPoint() const; + // Get the center point of the app list button circle used to draw its + // background and ink drops. + gfx::Point GetAppListButtonCenterPoint() const; + // Get the center point of the app list button back arrow. Returns an empty + // gfx::Point if the back arrow is not shown. + gfx::Point GetBackButtonCenterPoint() const; protected: - // views::ImageButton overrides: + // views::ImageButton: bool OnMousePressed(const ui::MouseEvent& event) override; void OnMouseReleased(const ui::MouseEvent& event) override; void OnMouseCaptureLost() override; @@ -62,11 +65,16 @@ void PaintButtonContents(gfx::Canvas* canvas) override; private: - // ShellObserver overrides: + // ShellObserver: void OnAppListVisibilityChanged(bool shown, aura::Window* root_window) override; void OnVoiceInteractionStatusChanged(bool running) override; + // Helper function to determine whether and event at |location| should be + // handled by the back button or the app list circle. Returns false if we are + // not in maximized mode (there is no back button). + bool IsBackEvent(const gfx::Point& location); + // True if the app list is currently showing for this display. // This is useful because other IsApplistVisible functions aren't per-display. bool is_showing_app_list_; @@ -83,6 +91,10 @@ bool voice_interaction_running_ = false; + // Flag that gets set each time we receive a mouse or gesture event. It is + // then used to render the ink drop in the right location. + bool last_event_is_back_event_ = false; + DISALLOW_COPY_AND_ASSIGN(AppListButton); };
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index acbef66d..e9d4938b 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -28,6 +28,7 @@ #include "ash/shell_delegate.h" #include "ash/shell_port.h" #include "ash/strings/grit/ash_strings.h" +#include "ash/wm/maximize_mode/maximize_mode_controller.h" #include "ash/wm/root_window_finder.h" #include "base/auto_reset.h" #include "base/memory/ptr_util.h" @@ -755,15 +756,31 @@ int w = shelf_->PrimaryAxisValue(kShelfButtonSize, width()); int h = shelf_->PrimaryAxisValue(height(), kShelfButtonSize); + + const bool is_maximize_mode = Shell::Get()->maximize_mode_controller() + ? Shell::Get() + ->maximize_mode_controller() + ->IsMaximizeModeWindowManagerEnabled() + : false; + for (int i = 0; i < view_model_->view_size(); ++i) { if (i < first_visible_index_) { view_model_->set_ideal_bounds(i, gfx::Rect(x, y, 0, 0)); continue; } - view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h)); - x = shelf_->PrimaryAxisValue(x + w + kShelfButtonSpacing, x); - y = shelf_->PrimaryAxisValue(y, y + h + kShelfButtonSpacing); + int width = w; + int height = h; + // If this is the app list button and we are in maximize/tablet mode, make + // space for the back button (which is part of the app list button). + if (i == 0 && is_maximize_mode) { + width = shelf_->PrimaryAxisValue(2 * w + kShelfButtonSpacing, w); + height = shelf_->PrimaryAxisValue(h, 2 * h + kShelfButtonSpacing); + } + + view_model_->set_ideal_bounds(i, gfx::Rect(x, y, width, height)); + x = shelf_->PrimaryAxisValue(x + width + kShelfButtonSpacing, x); + y = shelf_->PrimaryAxisValue(y, y + height + kShelfButtonSpacing); } if (is_overflow_mode()) {
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index c18c2140..e18ab969 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -35,6 +35,7 @@ #include "ash/test/test_shell_delegate.h" #include "ash/test/wallpaper_controller_test_api.h" #include "ash/wallpaper/wallpaper_controller.h" +#include "ash/wm/maximize_mode/maximize_mode_controller.h" #include "base/i18n/rtl.h" #include "base/macros.h" #include "base/memory/ptr_util.h" @@ -2568,6 +2569,129 @@ namespace { +// Test fixture to run app list button ink drop tests for both mouse and touch +// events. +class AppListButtonInkDropTest + : public ShelfViewInkDropTest, + public testing::WithParamInterface<ui::EventPointerType> { + public: + AppListButtonInkDropTest() : pointer_type_(GetParam()) {} + + ~AppListButtonInkDropTest() override {} + + void MovePointerTo(const gfx::Point& point) { + if (pointer_type_ == ui::EventPointerType::POINTER_TYPE_MOUSE) + GetEventGenerator().MoveMouseTo(point); + else if (pointer_type_ == ui::EventPointerType::POINTER_TYPE_TOUCH) + GetEventGenerator().MoveTouch(point); + } + + void PressPointer() { + if (pointer_type_ == ui::EventPointerType::POINTER_TYPE_MOUSE) + GetEventGenerator().PressLeftButton(); + else if (pointer_type_ == ui::EventPointerType::POINTER_TYPE_TOUCH) + GetEventGenerator().PressTouch(); + } + + void ReleasePointer() { + if (pointer_type_ == ui::EventPointerType::POINTER_TYPE_MOUSE) + GetEventGenerator().ReleaseLeftButton(); + else if (pointer_type_ == ui::EventPointerType::POINTER_TYPE_TOUCH) + GetEventGenerator().ReleaseTouch(); + } + + private: + ui::EventPointerType pointer_type_; + + DISALLOW_COPY_AND_ASSIGN(AppListButtonInkDropTest); +}; + +const ui::EventPointerType kPointerTypes[] = { + ui::EventPointerType::POINTER_TYPE_MOUSE, + ui::EventPointerType::POINTER_TYPE_TOUCH}; + +} // namespace + +// Tests that clicking/tapping on the app list button in maximized mode (when +// it has two functionalities), transitions the ink drop state correctly. +TEST_P(AppListButtonInkDropTest, AppListButtonInMaximizedMode) { + // TODO: investigate failure in mash, http://crbug.com/695751. + if (Shell::GetAshConfig() == Config::MASH) + return; + + InitAppListButtonInkDrop(); + + // Verify the app list button bounds change when we enter maximized mode. + const gfx::Rect old_bounds = app_list_button_->GetBoundsInScreen(); + Shell::Get()->maximize_mode_controller()->EnableMaximizeModeWindowManager( + true); + gfx::Rect new_bounds = app_list_button_->GetBoundsInScreen(); + EXPECT_EQ(new_bounds.height(), old_bounds.height()); + EXPECT_GT(new_bounds.width(), old_bounds.width()); + + gfx::Point point_on_circle = app_list_button_->GetAppListButtonCenterPoint(); + views::View::ConvertPointToScreen(app_list_button_, &point_on_circle); + gfx::Point point_on_back_button = + app_list_button_->GetBackButtonCenterPoint(); + views::View::ConvertPointToScreen(app_list_button_, &point_on_back_button); + + // Verify the ink drop state transitions as expected when we press and + // release on the app list circle part of the app list button. Taps on the + // app list circle, which shows the app list, should end up in the activated + // state. + MovePointerTo(point_on_circle); + PressPointer(); + EXPECT_EQ(views::InkDropState::ACTION_PENDING, + app_list_button_ink_drop_->GetTargetInkDropState()); + EXPECT_THAT(app_list_button_ink_drop_->GetAndResetRequestedStates(), + ElementsAre(views::InkDropState::ACTION_PENDING)); + ReleasePointer(); + + // Trigger a mock button notification that the app list was shown. + app_list_button_->OnAppListShown(); + FinishAppListVisibilityChange(); + EXPECT_EQ(views::InkDropState::ACTIVATED, + app_list_button_ink_drop_->GetTargetInkDropState()); + EXPECT_THAT(app_list_button_ink_drop_->GetAndResetRequestedStates(), + ElementsAre(views::InkDropState::ACTIVATED)); + + // Trigger a mock button notification that the app list was dismissed. + app_list_button_->OnAppListDismissed(); + FinishAppListVisibilityChange(); + EXPECT_EQ(views::InkDropState::HIDDEN, + app_list_button_ink_drop_->GetTargetInkDropState()); + EXPECT_THAT(app_list_button_ink_drop_->GetAndResetRequestedStates(), + ElementsAre(views::InkDropState::DEACTIVATED)); + + // Verify the ink drop state transitions as expected when we tap on the back + // button part of the app list button. + MovePointerTo(point_on_back_button); + PressPointer(); + EXPECT_EQ(views::InkDropState::ACTION_PENDING, + app_list_button_ink_drop_->GetTargetInkDropState()); + EXPECT_THAT(app_list_button_ink_drop_->GetAndResetRequestedStates(), + ElementsAre(views::InkDropState::ACTION_PENDING)); + ReleasePointer(); + EXPECT_EQ(views::InkDropState::HIDDEN, + app_list_button_ink_drop_->GetTargetInkDropState()); + EXPECT_THAT(app_list_button_ink_drop_->GetAndResetRequestedStates(), + ElementsAre(views::InkDropState::ACTION_TRIGGERED)); + + // Verify when we leave maximized mode, the bounds should return to be the + // same as they were before we entered maximized mode. + Shell::Get()->maximize_mode_controller()->EnableMaximizeModeWindowManager( + false); + new_bounds = app_list_button_->GetBoundsInScreen(); + EXPECT_EQ(new_bounds, old_bounds); +} + +INSTANTIATE_TEST_CASE_P( + /* prefix intentionally left blank due to only one parameterization */, + AppListButtonInkDropTest, + ::testing::ValuesIn(kPointerTypes)); + +namespace { + // An empty menu model for shell context menu just to have a menu. class TestShellMenuModel : public ui::SimpleMenuModel, public ui::SimpleMenuModel::Delegate {
diff --git a/ash/shelf/voice_interaction_overlay.cc b/ash/shelf/voice_interaction_overlay.cc index e50c738..a9b87711 100644 --- a/ash/shelf/voice_interaction_overlay.cc +++ b/ash/shelf/voice_interaction_overlay.cc
@@ -193,7 +193,7 @@ kRippleCircleStartRadiusDip / kRippleCircleInitRadiusDip; gfx::Transform transform; - const gfx::Point center = host_view_->GetCenterPoint(); + const gfx::Point center = host_view_->GetAppListButtonCenterPoint(); transform.Translate(center.x() - kRippleCircleStartRadiusDip, center.y() - kRippleCircleStartRadiusDip); transform.Scale(scale_factor, scale_factor); @@ -311,7 +311,7 @@ void VoiceInteractionOverlay::BurstAnimation() { is_bursting_ = true; - gfx::Point center = host_view_->GetCenterPoint(); + gfx::Point center = host_view_->GetAppListButtonCenterPoint(); // Setup ripple animations. { @@ -364,7 +364,7 @@ kRippleCircleStartRadiusDip / kRippleCircleInitRadiusDip; gfx::Transform transform; - const gfx::Point center = host_view_->GetCenterPoint(); + const gfx::Point center = host_view_->GetAppListButtonCenterPoint(); transform.Translate(center.x() - kRippleCircleStartRadiusDip, center.y() - kRippleCircleStartRadiusDip); transform.Scale(scale_factor, scale_factor);
diff --git a/base/numerics/clamped_math.h b/base/numerics/clamped_math.h index 799043a..620bfd8 100644 --- a/base/numerics/clamped_math.h +++ b/base/numerics/clamped_math.h
@@ -176,6 +176,11 @@ value_); } + // This method extracts the raw integer value without saturating it to the + // destination type as the conversion operator does. This is useful when + // e.g. assigning to an auto type or passing as a deduced template parameter. + constexpr T RawValue() const { return value_; } + private: T value_;
diff --git a/base/numerics/saturated_arithmetic.h b/base/numerics/saturated_arithmetic.h index 74fbba80..504fcd8f 100644 --- a/base/numerics/saturated_arithmetic.h +++ b/base/numerics/saturated_arithmetic.h
@@ -22,46 +22,6 @@ namespace base { -ALWAYS_INLINE int32_t SaturatedAddition(int32_t a, int32_t b) { - uint32_t ua = a; - uint32_t ub = b; - uint32_t result = ua + ub; - - // Can only overflow if the signed bit of the two values match. If the - // signed bit of the result and one of the values differ it overflowed. - // The branch compiles to a CMOVNS instruction on x86. - if (~(ua ^ ub) & (result ^ ua) & (1 << 31)) - return std::numeric_limits<int>::max() + (ua >> 31); - - return result; -} - -ALWAYS_INLINE int32_t SaturatedSubtraction(int32_t a, int32_t b) { - uint32_t ua = a; - uint32_t ub = b; - uint32_t result = ua - ub; - - // Can only overflow if the signed bit of the two input values differ. If - // the signed bit of the result and the first value differ it overflowed. - // The branch compiles to a CMOVNS instruction on x86. - if ((ua ^ ub) & (result ^ ua) & (1 << 31)) - return std::numeric_limits<int>::max() + (ua >> 31); - - return result; -} - -ALWAYS_INLINE int32_t SaturatedNegative(int32_t a) { - if (UNLIKELY(a == std::numeric_limits<int>::min())) - return std::numeric_limits<int>::max(); - return -a; -} - -ALWAYS_INLINE int32_t SaturatedAbsolute(int32_t a) { - if (a >= 0) - return a; - return SaturatedNegative(a); -} - ALWAYS_INLINE int GetMaxSaturatedSetResultForTesting(int fractional_shift) { // For C version the set function maxes out to max int, this differs from // the ARM asm version, see saturated_arithmetic_arm.h for the equivalent asm
diff --git a/base/numerics/saturated_arithmetic_arm.h b/base/numerics/saturated_arithmetic_arm.h index 732f5f2..21701aa 100644 --- a/base/numerics/saturated_arithmetic_arm.h +++ b/base/numerics/saturated_arithmetic_arm.h
@@ -9,36 +9,6 @@ namespace base { -inline int32_t SaturatedAddition(int32_t a, int32_t b) { - int32_t result; - - asm("qadd %[output],%[first],%[second]" - : [output] "=r"(result) - : [first] "r"(a), [second] "r"(b)); - - return result; -} - -inline int32_t SaturatedSubtraction(int32_t a, int32_t b) { - int32_t result; - - asm("qsub %[output],%[first],%[second]" - : [output] "=r"(result) - : [first] "r"(a), [second] "r"(b)); - - return result; -} - -inline int32_t SaturatedNegative(int32_t a) { - return SaturatedSubtraction(0, a); -} - -inline int32_t SaturatedAbsolute(int32_t a) { - if (a >= 0) - return a; - return SaturatedNegative(a); -} - inline int GetMaxSaturatedSetResultForTesting(int fractional_shift) { // For ARM Asm version the set function maxes out to the biggest // possible integer part with the fractional part zero'd out.
diff --git a/base/numerics/saturated_arithmetic_unittest.cc b/base/numerics/saturated_arithmetic_unittest.cc index 498f5b7..aa323c2 100644 --- a/base/numerics/saturated_arithmetic_unittest.cc +++ b/base/numerics/saturated_arithmetic_unittest.cc
@@ -12,78 +12,6 @@ namespace base { -TEST(SaturatedArithmeticTest, Addition) { - int int_max = std::numeric_limits<int>::max(); - int int_min = std::numeric_limits<int>::min(); - - EXPECT_EQ(0, SaturatedAddition(0, 0)); - EXPECT_EQ(1, SaturatedAddition(0, 1)); - EXPECT_EQ(100, SaturatedAddition(0, 100)); - EXPECT_EQ(150, SaturatedAddition(100, 50)); - - EXPECT_EQ(-1, SaturatedAddition(0, -1)); - EXPECT_EQ(0, SaturatedAddition(1, -1)); - EXPECT_EQ(50, SaturatedAddition(100, -50)); - EXPECT_EQ(-50, SaturatedAddition(50, -100)); - - EXPECT_EQ(int_max - 1, SaturatedAddition(int_max - 1, 0)); - EXPECT_EQ(int_max, SaturatedAddition(int_max - 1, 1)); - EXPECT_EQ(int_max, SaturatedAddition(int_max - 1, 2)); - EXPECT_EQ(int_max - 1, SaturatedAddition(0, int_max - 1)); - EXPECT_EQ(int_max, SaturatedAddition(1, int_max - 1)); - EXPECT_EQ(int_max, SaturatedAddition(2, int_max - 1)); - EXPECT_EQ(int_max, SaturatedAddition(int_max - 1, int_max - 1)); - EXPECT_EQ(int_max, SaturatedAddition(int_max, int_max)); - - EXPECT_EQ(int_min, SaturatedAddition(int_min, 0)); - EXPECT_EQ(int_min + 1, SaturatedAddition(int_min + 1, 0)); - EXPECT_EQ(int_min + 2, SaturatedAddition(int_min + 1, 1)); - EXPECT_EQ(int_min + 3, SaturatedAddition(int_min + 1, 2)); - EXPECT_EQ(int_min, SaturatedAddition(int_min + 1, -1)); - EXPECT_EQ(int_min, SaturatedAddition(int_min + 1, -2)); - EXPECT_EQ(int_min + 1, SaturatedAddition(0, int_min + 1)); - EXPECT_EQ(int_min, SaturatedAddition(-1, int_min + 1)); - EXPECT_EQ(int_min, SaturatedAddition(-2, int_min + 1)); - - EXPECT_EQ(int_max / 2 + 10000, SaturatedAddition(int_max / 2, 10000)); - EXPECT_EQ(int_max, SaturatedAddition(int_max / 2 + 1, int_max / 2 + 1)); - EXPECT_EQ(-1, SaturatedAddition(int_min, int_max)); -} - -TEST(SaturatedArithmeticTest, Subtraction) { - int int_max = std::numeric_limits<int>::max(); - int int_min = std::numeric_limits<int>::min(); - - EXPECT_EQ(0, SaturatedSubtraction(0, 0)); - EXPECT_EQ(-1, SaturatedSubtraction(0, 1)); - EXPECT_EQ(-100, SaturatedSubtraction(0, 100)); - EXPECT_EQ(50, SaturatedSubtraction(100, 50)); - - EXPECT_EQ(1, SaturatedSubtraction(0, -1)); - EXPECT_EQ(2, SaturatedSubtraction(1, -1)); - EXPECT_EQ(150, SaturatedSubtraction(100, -50)); - EXPECT_EQ(150, SaturatedSubtraction(50, -100)); - - EXPECT_EQ(int_max, SaturatedSubtraction(int_max, 0)); - EXPECT_EQ(int_max - 1, SaturatedSubtraction(int_max, 1)); - EXPECT_EQ(int_max - 1, SaturatedSubtraction(int_max - 1, 0)); - EXPECT_EQ(int_max, SaturatedSubtraction(int_max - 1, -1)); - EXPECT_EQ(int_max, SaturatedSubtraction(int_max - 1, -2)); - EXPECT_EQ(-int_max + 1, SaturatedSubtraction(0, int_max - 1)); - EXPECT_EQ(-int_max, SaturatedSubtraction(-1, int_max - 1)); - EXPECT_EQ(-int_max - 1, SaturatedSubtraction(-2, int_max - 1)); - EXPECT_EQ(-int_max - 1, SaturatedSubtraction(-3, int_max - 1)); - - EXPECT_EQ(int_min, SaturatedSubtraction(int_min, 0)); - EXPECT_EQ(int_min + 1, SaturatedSubtraction(int_min + 1, 0)); - EXPECT_EQ(int_min, SaturatedSubtraction(int_min + 1, 1)); - EXPECT_EQ(int_min, SaturatedSubtraction(int_min + 1, 2)); - - EXPECT_EQ(0, SaturatedSubtraction(int_min, int_min)); - EXPECT_EQ(0, SaturatedSubtraction(int_max, int_max)); - EXPECT_EQ(int_max, SaturatedSubtraction(int_max, int_min)); -} - TEST(SaturatedArithmeticTest, SetSigned) { int int_max = std::numeric_limits<int>::max(); int int_min = std::numeric_limits<int>::min();
diff --git a/base/trace_event/heap_profiler_event_writer.cc b/base/trace_event/heap_profiler_event_writer.cc index 23fe761f..c09a1e2 100644 --- a/base/trace_event/heap_profiler_event_writer.cc +++ b/base/trace_event/heap_profiler_event_writer.cc
@@ -17,6 +17,7 @@ #include "base/trace_event/heap_profiler_string_deduplicator.h" #include "base/trace_event/heap_profiler_type_name_deduplicator.h" #include "base/trace_event/sharded_allocation_register.h" +#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" namespace base { @@ -44,6 +45,7 @@ std::unique_ptr<TracedValue> SerializeHeapDump( const ShardedAllocationRegister& allocation_register, HeapProfilerSerializationState* serialization_state) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("memory-infra"), "SerializeHeapDump"); // Aggregate allocations by {backtrace_id, type_id} key. using MetricsMap = std::unordered_map<AggregationKey, AllocationMetrics, AggregationKey::Hasher>; @@ -67,9 +69,13 @@ metrics.size += allocation.size; metrics.count += 1; }; - allocation_register.VisitAllocations(base::BindRepeating( - visit_allocation, base::Unretained(serialization_state), - base::Unretained(&metrics_by_key))); + { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("memory-infra"), + "SerializeHeapDump.VisitAllocations"); + allocation_register.VisitAllocations(base::BindRepeating( + visit_allocation, base::Unretained(serialization_state), + base::Unretained(&metrics_by_key))); + } auto traced_value = MakeUnique<TracedValue>(); @@ -101,6 +107,8 @@ std::unique_ptr<TracedValue> SerializeHeapProfileEventData( const SerializedHeapDumpsMap& heap_dumps, HeapProfilerSerializationState* serialization_state) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("memory-infra"), + "SerializeHeapProfileEventData"); auto traced_value = MakeUnique<TracedValue>(); // See brief description of the format in the header file.
diff --git a/base/trace_event/heap_profiler_stack_frame_deduplicator.cc b/base/trace_event/heap_profiler_stack_frame_deduplicator.cc index 5e314984..a7dac9c5 100644 --- a/base/trace_event/heap_profiler_stack_frame_deduplicator.cc +++ b/base/trace_event/heap_profiler_stack_frame_deduplicator.cc
@@ -13,6 +13,7 @@ #include "base/strings/stringprintf.h" #include "base/trace_event/heap_profiler_string_deduplicator.h" #include "base/trace_event/memory_usage_estimator.h" +#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "base/trace_event/trace_event_memory_overhead.h" @@ -80,6 +81,8 @@ } void StackFrameDeduplicator::SerializeIncrementally(TracedValue* traced_value) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("memory-infra"), + "StackFrameDeduplicator::SerializeIncrementally"); std::string stringify_buffer; for (; last_exported_index_ < frames_.size(); ++last_exported_index_) {
diff --git a/base/trace_event/heap_profiler_string_deduplicator.cc b/base/trace_event/heap_profiler_string_deduplicator.cc index bf035a1..5938e30 100644 --- a/base/trace_event/heap_profiler_string_deduplicator.cc +++ b/base/trace_event/heap_profiler_string_deduplicator.cc
@@ -38,6 +38,8 @@ } void StringDeduplicator::SerializeIncrementally(TracedValue* traced_value) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("memory-infra"), + "StringDeduplicator::SerializeIncrementally"); for (; last_serialized_index_ != strings_.size(); ++last_serialized_index_) { traced_value->BeginDictionary(); traced_value->SetInteger("id", last_serialized_index_);
diff --git a/base/trace_event/heap_profiler_type_name_deduplicator.cc b/base/trace_event/heap_profiler_type_name_deduplicator.cc index 0f01165..8224b5a9 100644 --- a/base/trace_event/heap_profiler_type_name_deduplicator.cc +++ b/base/trace_event/heap_profiler_type_name_deduplicator.cc
@@ -87,6 +87,8 @@ } void TypeNameDeduplicator::SerializeIncrementally(TracedValue* traced_value) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("memory-infra"), + "TypeNameDeduplicator::SerializeIncrementally"); for (const auto* name_and_id : new_type_ids_) { traced_value->BeginDictionary();
diff --git a/cc/base/rtree.h b/cc/base/rtree.h index a29a7b8..4a48643 100644 --- a/cc/base/rtree.h +++ b/cc/base/rtree.h
@@ -13,7 +13,7 @@ #include <vector> #include "base/logging.h" -#include "base/numerics/saturated_arithmetic.h" +#include "base/numerics/clamped_math.h" #include "ui/gfx/geometry/rect.h" namespace cc { @@ -258,8 +258,8 @@ ++node->num_children; ++current_branch; } - branch.bounds.SetRect(x, y, base::SaturatedSubtraction(right, x), - base::SaturatedSubtraction(bottom, y)); + branch.bounds.SetRect(x, y, base::ClampSub(right, x), + base::ClampSub(bottom, y)); DCHECK_LT(new_branch_index, current_branch); (*branches)[new_branch_index] = std::move(branch);
diff --git a/cc/ipc/cc_param_traits_macros.h b/cc/ipc/cc_param_traits_macros.h index ba065ea..c91c95a 100644 --- a/cc/ipc/cc_param_traits_macros.h +++ b/cc/ipc/cc_param_traits_macros.h
@@ -144,6 +144,7 @@ IPC_STRUCT_TRAITS_MEMBER(mailbox_holder) IPC_STRUCT_TRAITS_MEMBER(read_lock_fences_enabled) IPC_STRUCT_TRAITS_MEMBER(is_software) + IPC_STRUCT_TRAITS_MEMBER(shared_bitmap_sequence_number) IPC_STRUCT_TRAITS_MEMBER(is_overlay_candidate) IPC_STRUCT_TRAITS_MEMBER(color_space) #if defined(OS_ANDROID)
diff --git a/cc/ipc/shared_bitmap_allocation_notifier.mojom b/cc/ipc/shared_bitmap_allocation_notifier.mojom index 1648625..a10eff2 100644 --- a/cc/ipc/shared_bitmap_allocation_notifier.mojom +++ b/cc/ipc/shared_bitmap_allocation_notifier.mojom
@@ -8,10 +8,6 @@ // This interface is used when allocating shared bitmaps to be shared with a // display compositor. -// This interface needs to be associated with the channel used to submit -// CompositorFrames, to prevent running into message ordering issues (the -// display compositor trying to access shared memory before the registration -// message below made it to the display compositor). interface SharedBitmapAllocationNotifier { // Informs the display compositor that the child allocated a shared bitmap. DidAllocateSharedBitmap(handle<shared_buffer> buffer, gpu.mojom.Mailbox id);
diff --git a/cc/ipc/struct_traits_unittest.cc b/cc/ipc/struct_traits_unittest.cc index 5bffa458..59fc43b 100644 --- a/cc/ipc/struct_traits_unittest.cc +++ b/cc/ipc/struct_traits_unittest.cc
@@ -1135,6 +1135,7 @@ const uint32_t texture_target = 1337; const bool read_lock_fences_enabled = true; const bool is_software = false; + const uint32_t shared_bitmap_sequence_number = 123456; const bool is_overlay_candidate = true; gpu::MailboxHolder mailbox_holder; @@ -1151,6 +1152,7 @@ input.mailbox_holder = mailbox_holder; input.read_lock_fences_enabled = read_lock_fences_enabled; input.is_software = is_software; + input.shared_bitmap_sequence_number = shared_bitmap_sequence_number; input.is_overlay_candidate = is_overlay_candidate; mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy(); TransferableResource output; @@ -1165,6 +1167,8 @@ output.mailbox_holder.texture_target); EXPECT_EQ(read_lock_fences_enabled, output.read_lock_fences_enabled); EXPECT_EQ(is_software, output.is_software); + EXPECT_EQ(shared_bitmap_sequence_number, + output.shared_bitmap_sequence_number); EXPECT_EQ(is_overlay_candidate, output.is_overlay_candidate); }
diff --git a/cc/ipc/transferable_resource.mojom b/cc/ipc/transferable_resource.mojom index ea20a63..81696f6 100644 --- a/cc/ipc/transferable_resource.mojom +++ b/cc/ipc/transferable_resource.mojom
@@ -23,12 +23,13 @@ struct TransferableResource { uint32 id; ResourceFormat format; - gfx.mojom.BufferFormat buffer_format; + gfx.mojom.BufferFormat buffer_format; uint32 filter; gfx.mojom.Size size; gpu.mojom.MailboxHolder mailbox_holder; bool read_lock_fences_enabled; bool is_software; + uint32 shared_bitmap_sequence_number; bool is_overlay_candidate; bool is_backed_by_surface_texture; bool wants_promotion_hint;
diff --git a/cc/ipc/transferable_resource_struct_traits.cc b/cc/ipc/transferable_resource_struct_traits.cc index 60aedc8..d53c823 100644 --- a/cc/ipc/transferable_resource_struct_traits.cc +++ b/cc/ipc/transferable_resource_struct_traits.cc
@@ -25,6 +25,7 @@ out->filter = data.filter(); out->read_lock_fences_enabled = data.read_lock_fences_enabled(); out->is_software = data.is_software(); + out->shared_bitmap_sequence_number = data.shared_bitmap_sequence_number(); out->is_overlay_candidate = data.is_overlay_candidate(); #if defined(OS_ANDROID) out->is_backed_by_surface_texture = data.is_backed_by_surface_texture();
diff --git a/cc/ipc/transferable_resource_struct_traits.h b/cc/ipc/transferable_resource_struct_traits.h index e9964c6..526a7e1 100644 --- a/cc/ipc/transferable_resource_struct_traits.h +++ b/cc/ipc/transferable_resource_struct_traits.h
@@ -50,6 +50,11 @@ return resource.is_software; } + static uint32_t shared_bitmap_sequence_number( + const cc::TransferableResource& resource) { + return resource.shared_bitmap_sequence_number; + } + static bool is_overlay_candidate(const cc::TransferableResource& resource) { return resource.is_overlay_candidate; }
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index 23a8640d..6c0383e 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc
@@ -1729,6 +1729,12 @@ if (source->type == RESOURCE_TYPE_BITMAP) { resource->mailbox_holder.mailbox = source->shared_bitmap_id; resource->is_software = true; + if (source->shared_bitmap) { + resource->shared_bitmap_sequence_number = + source->shared_bitmap->sequence_number(); + } else { + resource->shared_bitmap_sequence_number = 0; + } } else { DCHECK(source->mailbox().IsValid()); DCHECK(source->mailbox().IsTexture());
diff --git a/cc/resources/transferable_resource.cc b/cc/resources/transferable_resource.cc index d64a0670..d305971 100644 --- a/cc/resources/transferable_resource.cc +++ b/cc/resources/transferable_resource.cc
@@ -14,6 +14,7 @@ filter(0), read_lock_fences_enabled(false), is_software(false), + shared_bitmap_sequence_number(0), #if defined(OS_ANDROID) is_backed_by_surface_texture(false), wants_promotion_hint(false),
diff --git a/cc/resources/transferable_resource.h b/cc/resources/transferable_resource.h index a4e497c..7fcd0d8 100644 --- a/cc/resources/transferable_resource.h +++ b/cc/resources/transferable_resource.h
@@ -38,6 +38,7 @@ gpu::MailboxHolder mailbox_holder; bool read_lock_fences_enabled; bool is_software; + uint32_t shared_bitmap_sequence_number; #if defined(OS_ANDROID) bool is_backed_by_surface_texture; bool wants_promotion_hint;
diff --git a/cc/test/test_shared_bitmap_manager.cc b/cc/test/test_shared_bitmap_manager.cc index 900aaaa..bc30dd5d 100644 --- a/cc/test/test_shared_bitmap_manager.cc +++ b/cc/test/test_shared_bitmap_manager.cc
@@ -17,7 +17,9 @@ public: OwnedSharedBitmap(std::unique_ptr<base::SharedMemory> shared_memory, const viz::SharedBitmapId& id) - : viz::SharedBitmap(static_cast<uint8_t*>(shared_memory->memory()), id), + : viz::SharedBitmap(static_cast<uint8_t*>(shared_memory->memory()), + id, + 0 /* sequence_number */), shared_memory_(std::move(shared_memory)) {} ~OwnedSharedBitmap() override {} @@ -34,7 +36,7 @@ class UnownedSharedBitmap : public viz::SharedBitmap { public: UnownedSharedBitmap(uint8_t* pixels, const viz::SharedBitmapId& id) - : viz::SharedBitmap(pixels, id) {} + : viz::SharedBitmap(pixels, id, 0 /* sequence_number */) {} // viz::SharedBitmap: base::SharedMemoryHandle GetSharedMemoryHandle() const override {
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 9b433783..29e26b1 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -409,7 +409,7 @@ </activity> <activity android:name="org.chromium.chrome.browser.firstrun.LightweightFirstRunActivity" android:theme="@style/SimpleDialog" - android:launchMode="singleTop" + android:launchMode="singleInstance" android:autoRemoveFromRecents="true" android:windowSoftInputMode="stateHidden|adjustPan" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize">
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java index c68b61e..1d275ba 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
@@ -34,7 +34,10 @@ private static final String DISABLE_SEARCH_TERM_RESOLUTION = "disable_search_term_resolution"; private static final String WAIT_AFTER_TAP_DELAY_MS = "wait_after_tap_delay_ms"; - // Translation. All these members are private, except for usage by testing. + // ------------ + // Translation. + // ------------ + // All these members are private, except for usage by testing. // Master switch, needed to disable all translate code for Contextual Search in case of an // emergency. @VisibleForTesting @@ -44,6 +47,9 @@ static final String ENABLE_ENGLISH_TARGET_TRANSLATION = "enable_english_target_translation"; + // --------------------------------------------- + // Features for suppression or machine learning. + // --------------------------------------------- // TODO(donnd): remove all supporting code once short-lived data collection is done. private static final String SCREEN_TOP_SUPPRESSION_DPS = "screen_top_suppression_dps"; private static final String ENABLE_BAR_OVERLAP_COLLECTION = "enable_bar_overlap_collection"; @@ -54,20 +60,25 @@ "enable_not_long_word_suppression"; @VisibleForTesting static final String NOT_AN_ENTITY_SUPPRESSION_ENABLED = "enable_not_an_entity_suppression"; + // The threshold for tap suppression based on duration. + private static final String TAP_DURATION_THRESHOLD_MS = "tap_duration_threshold_ms"; private static final String MINIMUM_SELECTION_LENGTH = "minimum_selection_length"; + // ----------------- + // Disable switches. + // ----------------- // Safety switch for disabling online-detection. Also used to disable detection when running // tests. @VisibleForTesting static final String ONLINE_DETECTION_DISABLED = "disable_online_detection"; - private static final String DISABLE_AMP_AS_SEPARATE_TAB = "disable_amp_as_separate_tab"; - - // Machine Learning + // Disable logging for Machine Learning private static final String DISABLE_RANKER_LOGGING = "disable_ranker_logging"; - // Privacy-related flags + // ---------------------- + // Privacy-related flags. + // ---------------------- private static final String DISABLE_SEND_HOME_COUNTRY = "disable_send_home_country"; private static final String DISABLE_PAGE_CONTENT_NOTIFICATION = "disable_page_content_notification"; @@ -98,6 +109,7 @@ private static Boolean sContextualSearchUrlActionsEnabled; private static Boolean sIsRankerLoggingDisabled; private static Integer sWaitAfterTapDelayMs; + private static Integer sTapDurationThresholdMs; /** * Don't instantiate. @@ -375,6 +387,18 @@ return sWaitAfterTapDelayMs.intValue(); } + /** + * Gets a threshold for the duration of a tap gesture for categorization as brief or lengthy. + * @return The maximum amount of time in milliseconds for a tap gesture that's still considered + * a very brief duration tap. + */ + static int getTapDurationThresholdMs() { + if (sTapDurationThresholdMs == null) { + sTapDurationThresholdMs = getIntParamValueOrDefault(TAP_DURATION_THRESHOLD_MS, 0); + } + return sTapDurationThresholdMs.intValue(); + } + // --------------------------- // Feature-controlled Switches // ---------------------------
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java index 8fe0f7e..db4ad34 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java
@@ -4,8 +4,6 @@ package org.chromium.chrome.browser.contextualsearch; -import org.chromium.chrome.browser.contextualsearch.ContextualSearchRankerLogger.Feature; - import java.net.URL; import java.util.Collections; import java.util.HashMap;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java index 6060aea..eabeb55 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java
@@ -46,6 +46,8 @@ // Max selection length must be limited or the entire request URL can go past the 2K limit. private static final int MAX_SELECTION_LENGTH = 100; + private static final int INVALID_DURATION = -1; + private final ChromeActivity mActivity; private final ContextualSearchSelectionHandler mHandler; private final float mPxToDp; @@ -71,6 +73,9 @@ // When the last tap gesture happened. private long mTapTimeNanoseconds; + // The duration of the last tap gesture in milliseconds, or 0 if not set. + private int mTapDurationMs = INVALID_DURATION; + private class ContextualSearchGestureStateListener extends GestureStateListener { @Override public void onScrollStarted(int scrollOffsetY, int scrollExtentY) { @@ -89,13 +94,9 @@ mLastScrollTimeNs = System.nanoTime(); } - // TODO(donnd): Remove this once we get notification of the selection changing - // after a tap-select gets a subsequent tap nearby. Currently there's no - // notification in this case. - // See crbug.com/444114. @Override - public void onSingleTap(boolean consumed) { - // TODO(donnd): remove completely! + public void onTouchDown() { + mTapTimeNanoseconds = System.nanoTime(); } } @@ -292,6 +293,7 @@ mLastTapState = null; mLastScrollTimeNs = 0; mTapTimeNanoseconds = 0; + mTapDurationMs = INVALID_DURATION; mDidExpandSelection = false; } @@ -322,9 +324,11 @@ mWasTapGestureDetected = false; // TODO(donnd): refactor to avoid needing a new handler API method as suggested by Pedro. if (mSelectionType != SelectionType.LONG_PRESS) { + assert mTapTimeNanoseconds != 0 : "mTapTimeNanoseconds not set!"; + mTapDurationMs = (int) ((System.nanoTime() - mTapTimeNanoseconds) + / ContextualSearchHeuristic.NANOSECONDS_IN_A_MILLISECOND); mWasTapGestureDetected = true; mSelectionType = SelectionType.TAP; - mTapTimeNanoseconds = System.nanoTime(); mX = x; mY = y; mHandler.handleValidTap(); @@ -353,8 +357,9 @@ ChromePreferenceManager prefs = ChromePreferenceManager.getInstance(); int adjustedTapsSinceOpen = prefs.getContextualSearchTapCount() - prefs.getContextualSearchTapQuickAnswerCount(); - TapSuppressionHeuristics tapHeuristics = new TapSuppressionHeuristics( - this, mLastTapState, x, y, adjustedTapsSinceOpen, contextualSearchContext); + assert mTapDurationMs != INVALID_DURATION : "mTapDurationMs not set!"; + TapSuppressionHeuristics tapHeuristics = new TapSuppressionHeuristics(this, mLastTapState, + x, y, adjustedTapsSinceOpen, contextualSearchContext, mTapDurationMs); // TODO(donnd): Move to be called when the panel closes to work with states that change. tapHeuristics.logConditionState();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java index a49e129..5206970 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
@@ -803,6 +803,44 @@ } /** + * Logs whether results were seen based on the duration of the Tap, for both short and long + * durations. + * @param wasSearchContentViewSeen If the panel was opened. + * @param isTapShort Whether this tap was "short" in duration. + */ + public static void logTapDurationSeen(boolean wasSearchContentViewSeen, boolean isTapShort) { + if (isTapShort) { + RecordHistogram.recordEnumeratedHistogram("Search.ContextualSearchTapShortDurationSeen", + wasSearchContentViewSeen ? RESULTS_SEEN : RESULTS_NOT_SEEN, + RESULTS_SEEN_BOUNDARY); + } else { + RecordHistogram.recordEnumeratedHistogram("Search.ContextualSearchTapLongDurationSeen", + wasSearchContentViewSeen ? RESULTS_SEEN : RESULTS_NOT_SEEN, + RESULTS_SEEN_BOUNDARY); + } + } + + /** + * Logs the duration of a Tap in ms into custom histograms to profile the duration of seen + * and not seen taps. + * @param wasPanelSeen Whether the panel was seen. + * @param durationMs The duration of the tap gesture. + */ + public static void logTapDuration(boolean wasPanelSeen, int durationMs) { + int min = 1; + int max = 1000; + int numBuckets = 100; + + if (wasPanelSeen) { + RecordHistogram.recordCustomCountHistogram( + "Search.ContextualSearchTapDurationSeen", durationMs, min, max, numBuckets); + } else { + RecordHistogram.recordCustomCountHistogram( + "Search.ContextualSearchTapDurationNotSeen", durationMs, min, max, numBuckets); + } + } + + /** * Log whether results were seen due to a Tap on a short word. * @param wasSearchContentViewSeen If the panel was opened. * @param isTapOnShortWord Whether this tap was on a "short" word.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapDurationSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapDurationSuppression.java new file mode 100644 index 0000000..3d71153 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapDurationSuppression.java
@@ -0,0 +1,58 @@ +// 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. + +package org.chromium.chrome.browser.contextualsearch; + +/** + * Provides a signal for the duration of a Tap being either brief or lengthy. + * This signal could be used for suppression of taps below some threshold, so we aggregate-log too. + * We log CTR to UMA for Taps shorter and longer than the threshold. + */ +class TapDurationSuppression extends ContextualSearchHeuristic { + private static final int DEFAULT_TAP_DURATION_THRESHOLD_MS = 70; + + private final int mTapDurationMs; + private final int mTapDurationThresholdMs; + private final boolean mIsTapDurationConditionSatisfied; + + /** + * Constructs a heuristic to categorize the Tap based on duration as either short or long. + * @param tapDurationMs The duration of the tap in milliseconds. + */ + TapDurationSuppression(int tapDurationMs) { + mTapDurationMs = tapDurationMs; + mTapDurationThresholdMs = ContextualSearchFieldTrial.getTapDurationThresholdMs(); + int tapDurationThreshold = mTapDurationThresholdMs != 0 ? mTapDurationThresholdMs + : DEFAULT_TAP_DURATION_THRESHOLD_MS; + mIsTapDurationConditionSatisfied = tapDurationMs < tapDurationThreshold; + } + + @Override + protected boolean isConditionSatisfiedAndEnabled() { + return mIsTapDurationConditionSatisfied && mTapDurationThresholdMs != 0; + } + + @Override + protected void logResultsSeen(boolean wasSearchContentViewSeen, boolean wasActivatedByTap) { + if (wasActivatedByTap) { + ContextualSearchUma.logTapDurationSeen( + wasSearchContentViewSeen, mIsTapDurationConditionSatisfied); + + // TODO(donnd): remove when logging to Ranker is done! + ContextualSearchUma.logTapDuration(wasSearchContentViewSeen, mTapDurationMs); + } + } + + // TODO(donnd): Log the actual tap duration to Ranker once we have privacy-approval! + + @Override + protected boolean shouldAggregateLogForTapSuppression() { + return true; + } + + @Override + protected boolean isConditionSatisfiedForAggregateLogging() { + return mIsTapDurationConditionSatisfied; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapSuppressionHeuristics.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapSuppressionHeuristics.java index ab9358fc..b0eef111 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapSuppressionHeuristics.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapSuppressionHeuristics.java
@@ -20,13 +20,14 @@ */ TapSuppressionHeuristics(ContextualSearchSelectionController selectionController, ContextualSearchTapState previousTapState, int x, int y, int tapsSinceOpen, - ContextualSearchContext contextualSearchContext) { + ContextualSearchContext contextualSearchContext, int tapDurationMs) { super(); mCtrSuppression = new CtrSuppression(); mHeuristics.add(mCtrSuppression); mHeuristics.add(new RecentScrollTapSuppression(selectionController)); mHeuristics.add( new TapFarFromPreviousSuppression(selectionController, previousTapState, x, y)); + mHeuristics.add(new TapDurationSuppression(tapDurationMs)); mHeuristics.add(new TapWordLengthSuppression(contextualSearchContext)); mHeuristics.add(new TapWordEdgeSuppression(contextualSearchContext)); mHeuristics.add(new ContextualSearchEntityHeuristic(contextualSearchContext));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java index de4082e..8fcca29 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
@@ -376,17 +376,10 @@ List<WeakReference<Activity>> activities = ApplicationStatus.getRunningActivities(); for (WeakReference<Activity> weakActivity : activities) { Activity activity = weakActivity.get(); - if (activity == null) { - continue; - } else if (activity instanceof LightweightFirstRunActivity) { - // A Generic or a new Lightweight First Run Experience will be launched - // below, so finish the old Lightweight First Run Experience. - activity.setResult(Activity.RESULT_CANCELED); - activity.finish(); - continue; - } else if (activity instanceof FirstRunActivity) { + if (activity instanceof FirstRunActivity + && !(activity instanceof LightweightFirstRunActivity)) { isGenericFreActive = true; - continue; + break; } }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index ebabaca5..a407dd6 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -263,6 +263,7 @@ "java/src/org/chromium/chrome/browser/contextualsearch/QuickAnswersHeuristic.java", "java/src/org/chromium/chrome/browser/contextualsearch/RecentScrollTapSuppression.java", "java/src/org/chromium/chrome/browser/contextualsearch/SwipeRecognizer.java", + "java/src/org/chromium/chrome/browser/contextualsearch/TapDurationSuppression.java", "java/src/org/chromium/chrome/browser/contextualsearch/TapFarFromPreviousSuppression.java", "java/src/org/chromium/chrome/browser/contextualsearch/TapSuppression.java", "java/src/org/chromium/chrome/browser/contextualsearch/TapSuppressionHeuristics.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java index 0b23f5bd..cb1ceb7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java
@@ -203,6 +203,7 @@ ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { + mContextualSearchManager.getGestureStateListener().onTouchDown(); mContextualSearchClient.showUnhandledTapUIIfNeeded(0, 0); } });
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 4f6bd5ea..51d0c55 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1299,8 +1299,6 @@ "ssl/chrome_ssl_host_state_delegate_factory.h", "ssl/common_name_mismatch_handler.cc", "ssl/common_name_mismatch_handler.h", - "ssl/ignore_errors_cert_verifier.cc", - "ssl/ignore_errors_cert_verifier.h", "ssl/security_state_tab_helper.cc", "ssl/security_state_tab_helper.h", "ssl/ssl_blocking_page.cc", @@ -3405,6 +3403,8 @@ "resource_coordinator/tab_manager.h", "resource_coordinator/tab_manager_delegate_chromeos.cc", "resource_coordinator/tab_manager_delegate_chromeos.h", + "resource_coordinator/tab_manager_grc_tab_signal_observer.cc", + "resource_coordinator/tab_manager_grc_tab_signal_observer.h", "resource_coordinator/tab_manager_observer.cc", "resource_coordinator/tab_manager_observer.h", "resource_coordinator/tab_manager_web_contents_data.cc",
diff --git a/chrome/browser/android/download/download_manager_service.cc b/chrome/browser/android/download/download_manager_service.cc index 84a39b50..b99c229 100644 --- a/chrome/browser/android/download/download_manager_service.cc +++ b/chrome/browser/android/download/download_manager_service.cc
@@ -46,10 +46,10 @@ void UpdateNotifier( DownloadManagerService* service, content::DownloadManager* manager, - std::unique_ptr<content::AllDownloadItemNotifier>& notifier) { + std::unique_ptr<download::AllDownloadItemNotifier>& notifier) { if (manager) { if (!notifier || notifier->GetManager() != manager) - notifier.reset(new content::AllDownloadItemNotifier(manager, service)); + notifier.reset(new download::AllDownloadItemNotifier(manager, service)); } else { notifier.reset(nullptr); }
diff --git a/chrome/browser/android/download/download_manager_service.h b/chrome/browser/android/download/download_manager_service.h index cb66aad..7f241c63 100644 --- a/chrome/browser/android/download/download_manager_service.h +++ b/chrome/browser/android/download/download_manager_service.h
@@ -16,7 +16,7 @@ #include "base/memory/singleton.h" #include "chrome/browser/android/download/download_controller.h" #include "chrome/browser/download/download_history.h" -#include "content/public/browser/all_download_item_notifier.h" +#include "components/download/content/public/all_download_item_notifier.h" #include "content/public/browser/download_manager.h" using base::android::JavaParamRef; @@ -28,7 +28,7 @@ // Native side of DownloadManagerService.java. The native object is owned by its // Java object. class DownloadManagerService - : public content::AllDownloadItemNotifier::Observer, + : public download::AllDownloadItemNotifier::Observer, public DownloadHistory::Observer { public: // JNI registration. @@ -176,8 +176,8 @@ ResumeCallback resume_callback_for_testing_; - std::unique_ptr<content::AllDownloadItemNotifier> original_notifier_; - std::unique_ptr<content::AllDownloadItemNotifier> off_the_record_notifier_; + std::unique_ptr<download::AllDownloadItemNotifier> original_notifier_; + std::unique_ptr<download::AllDownloadItemNotifier> off_the_record_notifier_; DISALLOW_COPY_AND_ASSIGN(DownloadManagerService); };
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 5652731..d5a988f 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -74,6 +74,7 @@ "//components/crx_file", "//components/cryptauth", "//components/device_event_log", + "//components/download/content/public", "//components/drive", "//components/drive:drive_chromeos", "//components/exo",
diff --git a/chrome/browser/chromeos/drive/download_handler.cc b/chrome/browser/chromeos/drive/download_handler.cc index fde753a..7cb6663 100644 --- a/chrome/browser/chromeos/drive/download_handler.cc +++ b/chrome/browser/chromeos/drive/download_handler.cc
@@ -171,7 +171,7 @@ if (download_manager) { notifier_.reset( - new content::AllDownloadItemNotifier(download_manager, this)); + new download::AllDownloadItemNotifier(download_manager, this)); // Remove any persisted Drive DownloadItem. crbug.com/171384 DownloadManager::DownloadVector downloads; download_manager->GetAllDownloads(&downloads); @@ -185,7 +185,7 @@ void DownloadHandler::ObserveIncognitoDownloadManager( DownloadManager* download_manager) { notifier_incognito_.reset( - new content::AllDownloadItemNotifier(download_manager, this)); + new download::AllDownloadItemNotifier(download_manager, this)); } void DownloadHandler::SubstituteDriveDownloadPath(
diff --git a/chrome/browser/chromeos/drive/download_handler.h b/chrome/browser/chromeos/drive/download_handler.h index f2f54a1..b48dc49 100644 --- a/chrome/browser/chromeos/drive/download_handler.h +++ b/chrome/browser/chromeos/drive/download_handler.h
@@ -10,8 +10,8 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "components/download/content/public/all_download_item_notifier.h" #include "components/drive/file_errors.h" -#include "content/public/browser/all_download_item_notifier.h" #include "content/public/browser/download_manager_delegate.h" class Profile; @@ -27,7 +27,7 @@ // Observes downloads to temporary local drive folder. Schedules these // downloads for upload to drive service. -class DownloadHandler : public content::AllDownloadItemNotifier::Observer { +class DownloadHandler : public download::AllDownloadItemNotifier::Observer { public: explicit DownloadHandler(FileSystemInterface* file_system); ~DownloadHandler() override; @@ -122,8 +122,8 @@ FileSystemInterface* file_system_; // Owned by DriveIntegrationService. // Observe the DownloadManager for new downloads. - std::unique_ptr<content::AllDownloadItemNotifier> notifier_; - std::unique_ptr<content::AllDownloadItemNotifier> notifier_incognito_; + std::unique_ptr<download::AllDownloadItemNotifier> notifier_; + std::unique_ptr<download::AllDownloadItemNotifier> notifier_incognito_; // Temporary download location directory. base::FilePath drive_tmp_download_path_;
diff --git a/chrome/browser/download/download_history.h b/chrome/browser/download/download_history.h index 20d6667..8598e6a 100644 --- a/chrome/browser/download/download_history.h +++ b/chrome/browser/download/download_history.h
@@ -14,8 +14,8 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" +#include "components/download/content/public/all_download_item_notifier.h" #include "components/history/core/browser/history_service.h" -#include "content/public/browser/all_download_item_notifier.h" #include "content/public/browser/download_item.h" #include "content/public/browser/download_manager.h" @@ -25,7 +25,7 @@ // Observes a single DownloadManager and all its DownloadItems, keeping the // DownloadDatabase up to date. -class DownloadHistory : public content::AllDownloadItemNotifier::Observer { +class DownloadHistory : public download::AllDownloadItemNotifier::Observer { public: typedef std::set<uint32_t> IdSet; @@ -133,7 +133,7 @@ // Removes all |removing_ids_| from |history_|. void RemoveDownloadsBatch(); - content::AllDownloadItemNotifier notifier_; + download::AllDownloadItemNotifier notifier_; std::unique_ptr<HistoryAdapter> history_;
diff --git a/chrome/browser/download/download_status_updater.cc b/chrome/browser/download/download_status_updater.cc index ce23b5e..d5730e3 100644 --- a/chrome/browser/download/download_status_updater.cc +++ b/chrome/browser/download/download_status_updater.cc
@@ -92,7 +92,7 @@ void DownloadStatusUpdater::AddManager(content::DownloadManager* manager) { notifiers_.push_back( - base::MakeUnique<content::AllDownloadItemNotifier>(manager, this)); + base::MakeUnique<download::AllDownloadItemNotifier>(manager, this)); content::DownloadManager::DownloadVector items; manager->GetAllDownloads(&items); for (auto* item : items)
diff --git a/chrome/browser/download/download_status_updater.h b/chrome/browser/download/download_status_updater.h index bed04e73..c22d852 100644 --- a/chrome/browser/download/download_status_updater.h +++ b/chrome/browser/download/download_status_updater.h
@@ -9,13 +9,13 @@ #include <set> #include "base/macros.h" -#include "content/public/browser/all_download_item_notifier.h" +#include "components/download/content/public/all_download_item_notifier.h" #include "content/public/browser/download_item.h" #include "content/public/browser/download_manager.h" // Keeps track of download progress for the entire browser. class DownloadStatusUpdater - : public content::AllDownloadItemNotifier::Observer { + : public download::AllDownloadItemNotifier::Observer { public: DownloadStatusUpdater(); ~DownloadStatusUpdater() override; @@ -47,7 +47,7 @@ virtual void UpdateAppIconDownloadProgress(content::DownloadItem* download); private: - std::vector<std::unique_ptr<content::AllDownloadItemNotifier>> notifiers_; + std::vector<std::unique_ptr<download::AllDownloadItemNotifier>> notifiers_; DISALLOW_COPY_AND_ASSIGN(DownloadStatusUpdater); };
diff --git a/chrome/browser/download/download_status_updater_unittest.cc b/chrome/browser/download/download_status_updater_unittest.cc index e11b25a..532c9b5 100644 --- a/chrome/browser/download/download_status_updater_unittest.cc +++ b/chrome/browser/download/download_status_updater_unittest.cc
@@ -87,6 +87,7 @@ while (manager_observers_.size() <= static_cast<size_t>(i)) { manager_observers_.push_back(nullptr); } + EXPECT_CALL(*mgr, IsManagerInitialized()); EXPECT_CALL(*mgr, AddObserver(_)) .WillOnce(WithArg<0>(Invoke( this, &DownloadStatusUpdaterTest::SetObserver)));
diff --git a/chrome/browser/download/download_ui_controller.h b/chrome/browser/download/download_ui_controller.h index 43bf314..a3934e3 100644 --- a/chrome/browser/download/download_ui_controller.h +++ b/chrome/browser/download/download_ui_controller.h
@@ -9,13 +9,14 @@ #include <set> #include "base/macros.h" -#include "content/public/browser/all_download_item_notifier.h" +#include "components/download/content/public/all_download_item_notifier.h" // This class handles the task of observing a single DownloadManager for // notifying the UI when a new download should be displayed in the UI. // It invokes the OnNewDownloadReady() method of hte Delegate when the // target path is available for a new download. -class DownloadUIController : public content::AllDownloadItemNotifier::Observer { +class DownloadUIController + : public download::AllDownloadItemNotifier::Observer { public: // The delegate is responsible for figuring out how to notify the UI. class Delegate { @@ -45,7 +46,7 @@ void OnDownloadUpdated(content::DownloadManager* manager, content::DownloadItem* item) override; - content::AllDownloadItemNotifier download_notifier_; + download::AllDownloadItemNotifier download_notifier_; std::unique_ptr<Delegate> delegate_;
diff --git a/chrome/browser/download/download_ui_controller_unittest.cc b/chrome/browser/download/download_ui_controller_unittest.cc index 87af5bd..0df2161 100644 --- a/chrome/browser/download/download_ui_controller_unittest.cc +++ b/chrome/browser/download/download_ui_controller_unittest.cc
@@ -170,6 +170,7 @@ ChromeRenderViewHostTestHarness::SetUp(); manager_.reset(new testing::StrictMock<MockDownloadManager>()); + EXPECT_CALL(*manager_, IsManagerInitialized()).Times(AnyNumber()); EXPECT_CALL(*manager_, AddObserver(_)) .WillOnce(SaveArg<0>(&download_history_manager_observer_)); EXPECT_CALL(*manager_,
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index 07509f3..c8e7637a 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -831,6 +831,7 @@ "//components/cryptauth", "//components/data_reduction_proxy/core/browser", "//components/dom_distiller/core", + "//components/download/content/public", "//components/drive", "//components/favicon/content", "//components/feedback",
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.h b/chrome/browser/extensions/api/downloads/downloads_api.h index a253325..084d39b 100644 --- a/chrome/browser/extensions/api/downloads/downloads_api.h +++ b/chrome/browser/extensions/api/downloads/downloads_api.h
@@ -17,7 +17,7 @@ #include "chrome/browser/download/download_path_reservation_tracker.h" #include "chrome/browser/extensions/chrome_extension_function.h" #include "chrome/common/extensions/api/downloads.h" -#include "content/public/browser/all_download_item_notifier.h" +#include "components/download/content/public/all_download_item_notifier.h" #include "content/public/browser/download_manager.h" #include "extensions/browser/event_router.h" #include "extensions/browser/extension_registry_observer.h" @@ -299,7 +299,7 @@ class ExtensionDownloadsEventRouter : public extensions::EventRouter::Observer, public extensions::ExtensionRegistryObserver, - public content::AllDownloadItemNotifier::Observer { + public download::AllDownloadItemNotifier::Observer { public: typedef base::Callback<void( const base::FilePath& changed_filename, @@ -391,7 +391,7 @@ extensions::UnloadedExtensionReason reason) override; Profile* profile_; - content::AllDownloadItemNotifier notifier_; + download::AllDownloadItemNotifier notifier_; std::set<const extensions::Extension*> shelf_disabling_extensions_; base::Time last_checked_removal_;
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc b/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc index a2b8a6b..1351c63 100644 --- a/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc +++ b/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc
@@ -69,6 +69,7 @@ ExtensionApiUnittest::SetUp(); manager_.reset(new testing::StrictMock<MockDownloadManager>()); + EXPECT_CALL(*manager_, IsManagerInitialized()); EXPECT_CALL(*manager_, AddObserver(testing::_)) .WillOnce(testing::SaveArg<0>(&download_history_manager_observer_)); EXPECT_CALL(*manager_, RemoveObserver(testing::Eq(testing::ByRef(
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 9dcd7f0..be6e9b6 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc
@@ -41,7 +41,6 @@ #include "chrome/browser/net/dns_probe_service.h" #include "chrome/browser/net/proxy_service_factory.h" #include "chrome/browser/net/sth_distributor_provider.h" -#include "chrome/browser/ssl/ignore_errors_cert_verifier.h" #include "chrome/common/channel_info.h" #include "chrome/common/chrome_content_client.h" #include "chrome/common/chrome_switches.h" @@ -63,6 +62,7 @@ #include "components/variations/variations_associated_data.h" #include "components/version_info/version_info.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/ignore_errors_cert_verifier.h" #include "content/public/browser/network_quality_observer_factory.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" @@ -819,18 +819,21 @@ builder->set_host_resolver(std::move(host_resolver)); + std::unique_ptr<net::CertVerifier> cert_verifier; #if defined(OS_CHROMEOS) // Creates a CertVerifyProc that doesn't allow any profile-provided certs. - builder->SetCertVerifier(base::MakeUnique<net::CachingCertVerifier>( + cert_verifier = base::MakeUnique<net::CachingCertVerifier>( base::MakeUnique<net::MultiThreadedCertVerifier>( - new chromeos::CertVerifyProcChromeOS()))); + new chromeos::CertVerifyProcChromeOS())); #else - builder->SetCertVerifier(IgnoreErrorsCertVerifier::MaybeWrapCertVerifier( - command_line, net::CertVerifier::CreateDefault())); + cert_verifier = net::CertVerifier::CreateDefault(); +#endif + builder->SetCertVerifier( + content::IgnoreErrorsCertVerifier::MaybeWrapCertVerifier( + command_line, switches::kUserDataDir, std::move(cert_verifier))); UMA_HISTOGRAM_BOOLEAN( "Net.Certificate.IgnoreCertificateErrorsSPKIListPresent", command_line.HasSwitch(switches::kIgnoreCertificateErrorsSPKIList)); -#endif std::unique_ptr<net::MultiLogCTVerifier> ct_verifier = base::MakeUnique<net::MultiLogCTVerifier>();
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.cc b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.cc index 1ad648b..022649b 100644 --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.cc +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.cc
@@ -8,7 +8,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/common/media_router/discovery/media_sink_internal.h" #include "components/cast_channel/cast_socket_service.h" -#include "components/cast_channel/cast_socket_service_factory.h" #include "components/net_log/chrome_net_log.h" #include "content/public/common/content_client.h" #include "net/base/host_port_pair.h" @@ -16,8 +15,6 @@ namespace { -constexpr char kObserverId[] = "browser_observer_id"; - enum ErrorType { NONE, NOT_CAST_DEVICE, @@ -90,10 +87,9 @@ CastMediaSinkService::CastMediaSinkService( const OnSinksDiscoveredCallback& callback, content::BrowserContext* browser_context) - : MediaSinkServiceBase(callback) { + : MediaSinkServiceBase(callback), + cast_socket_service_(cast_channel::CastSocketService::GetInstance()) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - cast_socket_service_ = cast_channel::CastSocketServiceFactory::GetInstance() - ->GetForBrowserContext(browser_context); DCHECK(cast_socket_service_); } @@ -169,17 +165,14 @@ void CastMediaSinkService::OpenChannelOnIOThread( const DnsSdService& service, const net::IPEndPoint& ip_endpoint) { - auto* observer = cast_socket_service_->GetObserver(kObserverId); - if (!observer) { - observer = new CastSocketObserver(); - cast_socket_service_->AddObserver(kObserverId, base::WrapUnique(observer)); - } + if (!observer_) + observer_.reset(new CastSocketObserver()); cast_socket_service_->OpenSocket( ip_endpoint, g_browser_process->net_log(), base::Bind(&CastMediaSinkService::OnChannelOpenedOnIOThread, this, service), - observer); + observer_.get()); } void CastMediaSinkService::OnChannelOpenedOnIOThread( @@ -228,7 +221,9 @@ } CastMediaSinkService::CastSocketObserver::CastSocketObserver() {} -CastMediaSinkService::CastSocketObserver::~CastSocketObserver() {} +CastMediaSinkService::CastSocketObserver::~CastSocketObserver() { + cast_channel::CastSocketService::GetInstance()->RemoveObserver(this); +} void CastMediaSinkService::CastSocketObserver::OnError( const cast_channel::CastSocket& socket,
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.h b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.h index 2030c05..df6e60e 100644 --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.h +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.h
@@ -16,6 +16,7 @@ #include "chrome/browser/media/router/discovery/media_sink_service_base.h" #include "components/cast_channel/cast_channel_enum.h" #include "components/cast_channel/cast_socket.h" +#include "content/public/browser/browser_thread.h" #include "net/base/ip_endpoint.h" namespace cast_channel { @@ -119,8 +120,13 @@ // Service list from current round of discovery. DnsSdRegistry::DnsSdServiceList current_services_; - // Service managing creating and removing cast channels. - scoped_refptr<cast_channel::CastSocketService> cast_socket_service_; + // Raw pointer of leaky singleton CastSocketService, which manages creating + // and removing Cast sockets. + cast_channel::CastSocketService* const cast_socket_service_; + + std::unique_ptr<cast_channel::CastSocket::Observer, + content::BrowserThread::DeleteOnIOThread> + observer_; THREAD_CHECKER(thread_checker_);
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_unittest.cc b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_unittest.cc index 7e12a975..963a24e 100644 --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_unittest.cc +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_unittest.cc
@@ -68,23 +68,10 @@ namespace media_router { -class MockCastSocketService : public cast_channel::CastSocketService { - public: - MOCK_METHOD4(OpenSocket, - int(const net::IPEndPoint& ip_endpoint, - net::NetLog* net_log, - const cast_channel::CastSocket::OnOpenCallback& open_cb, - cast_channel::CastSocket::Observer* observer)); - MOCK_CONST_METHOD1(GetSocket, cast_channel::CastSocket*(int channel_id)); - - private: - ~MockCastSocketService() {} -}; - class CastMediaSinkServiceTest : public ::testing::Test { public: CastMediaSinkServiceTest() - : mock_cast_socket_service_(new MockCastSocketService()), + : mock_cast_socket_service_(new cast_channel::MockCastSocketService()), media_sink_service_( new CastMediaSinkService(mock_sink_discovered_cb_.Get(), mock_cast_socket_service_.get())), @@ -103,7 +90,8 @@ base::MockCallback<MediaSinkService::OnSinksDiscoveredCallback> mock_sink_discovered_cb_; - scoped_refptr<MockCastSocketService> mock_cast_socket_service_; + std::unique_ptr<cast_channel::MockCastSocketService> + mock_cast_socket_service_; scoped_refptr<CastMediaSinkService> media_sink_service_; MockDnsSdRegistry test_dns_sd_registry_; base::MockTimer* mock_timer_;
diff --git a/chrome/browser/printing/pdf_to_emf_converter.cc b/chrome/browser/printing/pdf_to_emf_converter.cc index 427d73b..4356ae3d 100644 --- a/chrome/browser/printing/pdf_to_emf_converter.cc +++ b/chrome/browser/printing/pdf_to_emf_converter.cc
@@ -228,7 +228,8 @@ std::unique_ptr<base::File, content::BrowserThread::DeleteOnFileThread> temp_file) { if (settings_.mode == PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2 || - settings_.mode == PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3) { + settings_.mode == PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3 || + settings_.mode == PdfRenderSettings::Mode::TEXTONLY) { return base::MakeUnique<PostScriptMetaFile>(temp_dir_, std::move(temp_file)); }
diff --git a/chrome/browser/printing/print_job.cc b/chrome/browser/printing/print_job.cc index d5e81cd..d9535550 100644 --- a/chrome/browser/printing/print_job.cc +++ b/chrome/browser/printing/print_job.cc
@@ -318,6 +318,21 @@ base::Bind(&PrintJob::OnPdfPageConverted, this)); } +void PrintJob::StartPdfToTextConversion( + const scoped_refptr<base::RefCountedMemory>& bytes, + const gfx::Size& page_size) { + DCHECK(!pdf_conversion_state_); + pdf_conversion_state_ = + base::MakeUnique<PdfConversionState>(gfx::Size(), gfx::Rect()); + const int kPrinterDpi = settings().dpi(); + gfx::Rect page_area = gfx::Rect(0, 0, page_size.width(), page_size.height()); + PdfRenderSettings settings(page_area, gfx::Point(0, 0), kPrinterDpi, + /*autorotate=*/true, + PdfRenderSettings::Mode::TEXTONLY); + pdf_conversion_state_->Start( + bytes, settings, base::Bind(&PrintJob::OnPdfConversionStarted, this)); +} + void PrintJob::StartPdfToPostScriptConversion( const scoped_refptr<base::RefCountedMemory>& bytes, const gfx::Rect& content_area,
diff --git a/chrome/browser/printing/print_job.h b/chrome/browser/printing/print_job.h index aa293c8..6a189d6 100644 --- a/chrome/browser/printing/print_job.h +++ b/chrome/browser/printing/print_job.h
@@ -105,6 +105,10 @@ const gfx::Rect& content_area, const gfx::Point& physical_offset, bool ps_level2); + + void StartPdfToTextConversion( + const scoped_refptr<base::RefCountedMemory>& bytes, + const gfx::Size& page_size); #endif // defined(OS_WIN) protected:
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc index d7f5ec8..9d81a019 100644 --- a/chrome/browser/printing/print_view_manager_base.cc +++ b/chrome/browser/printing/print_view_manager_base.cc
@@ -189,8 +189,11 @@ document->DebugDumpData(bytes.get(), FILE_PATH_LITERAL(".pdf")); const auto& settings = document->settings(); - if ((settings.printer_is_ps2() || settings.printer_is_ps3()) && - !base::FeatureList::IsEnabled(features::kDisablePostScriptPrinting)) { + if (settings.printer_is_textonly()) { + print_job_->StartPdfToTextConversion(bytes, params.page_size); + } else if ((settings.printer_is_ps2() || settings.printer_is_ps3()) && + !base::FeatureList::IsEnabled( + features::kDisablePostScriptPrinting)) { print_job_->StartPdfToPostScriptConversion(bytes, params.content_area, params.physical_offsets, settings.printer_is_ps2());
diff --git a/chrome/browser/resource_coordinator/tab_manager.cc b/chrome/browser/resource_coordinator/tab_manager.cc index 7e3f0c7..1b84c5f 100644 --- a/chrome/browser/resource_coordinator/tab_manager.cc +++ b/chrome/browser/resource_coordinator/tab_manager.cc
@@ -30,6 +30,8 @@ #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" #include "chrome/browser/memory/oom_memory_details.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.h" +#include "chrome/browser/resource_coordinator/tab_manager_grc_tab_signal_observer.h" #include "chrome/browser/resource_coordinator/tab_manager_observer.h" #include "chrome/browser/resource_coordinator/tab_manager_web_contents_data.h" #include "chrome/browser/sessions/session_restore.h" @@ -51,6 +53,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h" #include "content/public/common/page_importance_signals.h" +#include "services/resource_coordinator/public/cpp/resource_coordinator_features.h" #if defined(OS_CHROMEOS) #include "ash/multi_profile_uma.h" @@ -149,6 +152,9 @@ #endif browser_tab_strip_tracker_.Init(); session_restore_observer_.reset(new TabManagerSessionRestoreObserver(this)); + if (resource_coordinator::IsResourceCoordinatorEnabled()) { + grc_tab_signal_observer_.reset(new GRCTabSignalObserver()); + } } TabManager::~TabManager() { @@ -848,6 +854,16 @@ content::WebContents* contents, int index, bool foreground) { + // Gets CoordinationUnitID for this WebContents and adds it to + // GRCTabSignalObserver. + if (grc_tab_signal_observer_) { + auto* tab_resource_coordinator = + ResourceCoordinatorWebContentsObserver::FromWebContents(contents) + ->tab_resource_coordinator(); + grc_tab_signal_observer_->AssociateCoordinationUnitIDWithWebContents( + tab_resource_coordinator->id(), contents); + } + // Only interested in background tabs, as foreground tabs get taken care of by // ActiveTabChanged. if (foreground) @@ -861,6 +877,20 @@ GetTimeToPurge(min_time_to_purge_, max_time_to_purge_)); } +void TabManager::TabClosingAt(TabStripModel* tab_strip_model, + content::WebContents* contents, + int index) { + // Gets CoordinationUnitID for this WebContents and removes it from + // GRCTabSignalObserver. + if (!grc_tab_signal_observer_) + return; + auto* tab_resource_coordinator = + ResourceCoordinatorWebContentsObserver::FromWebContents(contents) + ->tab_resource_coordinator(); + grc_tab_signal_observer_->RemoveCoordinationUnitID( + tab_resource_coordinator->id()); +} + void TabManager::OnBrowserSetLastActive(Browser* browser) { // Reload the active tab in |browser| if it is discarded. content::WebContents* contents =
diff --git a/chrome/browser/resource_coordinator/tab_manager.h b/chrome/browser/resource_coordinator/tab_manager.h index 6600088..aa5deb5f 100644 --- a/chrome/browser/resource_coordinator/tab_manager.h +++ b/chrome/browser/resource_coordinator/tab_manager.h
@@ -72,6 +72,8 @@ class TabManager : public TabStripModelObserver, public chrome::BrowserListObserver { public: + // Forward declaration of tab signal observer. + class GRCTabSignalObserver; // Needs to be public for DEFINE_WEB_CONTENTS_USER_DATA_KEY. class WebContentsData; @@ -326,6 +328,9 @@ content::WebContents* contents, int index, bool foreground) override; + void TabClosingAt(TabStripModel* tab_strip_model, + content::WebContents* contents, + int index) override; // BrowserListObserver overrides. void OnBrowserSetLastActive(Browser* browser) override; @@ -468,6 +473,9 @@ // is brought to foreground. std::set<content::WebContents*> loading_contents_; + // GRC tab signal observer, receives tab scoped signal from GRC. + std::unique_ptr<GRCTabSignalObserver> grc_tab_signal_observer_; + // Weak pointer factory used for posting delayed tasks. base::WeakPtrFactory<TabManager> weak_ptr_factory_;
diff --git a/chrome/browser/resource_coordinator/tab_manager_grc_tab_signal_observer.cc b/chrome/browser/resource_coordinator/tab_manager_grc_tab_signal_observer.cc new file mode 100644 index 0000000..53a8638 --- /dev/null +++ b/chrome/browser/resource_coordinator/tab_manager_grc_tab_signal_observer.cc
@@ -0,0 +1,54 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/resource_coordinator/tab_manager_grc_tab_signal_observer.h" + +#include "chrome/browser/resource_coordinator/tab_manager_web_contents_data.h" +#include "content/public/common/service_manager_connection.h" +#include "services/resource_coordinator/public/cpp/coordination_unit_id.h" +#include "services/resource_coordinator/public/interfaces/service_constants.mojom.h" +#include "services/service_manager/public/cpp/connector.h" + +namespace resource_coordinator { + +TabManager::GRCTabSignalObserver::GRCTabSignalObserver() : binding_(this) { + service_manager::Connector* connector = + content::ServiceManagerConnection::GetForProcess()->GetConnector(); + mojom::TabSignalGeneratorPtr tab_signal_generator_ptr; + connector->BindInterface(mojom::kServiceName, + mojo::MakeRequest(&tab_signal_generator_ptr)); + + mojom::TabSignalObserverPtr tab_signal_observer_ptr; + binding_.Bind(mojo::MakeRequest(&tab_signal_observer_ptr)); + tab_signal_generator_ptr->AddObserver(std::move(tab_signal_observer_ptr)); +} + +TabManager::GRCTabSignalObserver::~GRCTabSignalObserver() = default; + +void TabManager::GRCTabSignalObserver::OnEventReceived( + const CoordinationUnitID& cu_id, + mojom::TabEvent event) { + if (event == mojom::TabEvent::kDoneLoading) { + auto web_contents_iter = cu_id_web_contents_map_.find(cu_id); + if (web_contents_iter == cu_id_web_contents_map_.end()) + return; + auto* web_contents_data = + TabManager::WebContentsData::FromWebContents(web_contents_iter->second); + web_contents_data->DoneLoading(); + } +} + +void TabManager::GRCTabSignalObserver:: + AssociateCoordinationUnitIDWithWebContents( + const CoordinationUnitID& cu_id, + content::WebContents* web_contents) { + cu_id_web_contents_map_[cu_id] = web_contents; +} + +void TabManager::GRCTabSignalObserver::RemoveCoordinationUnitID( + const CoordinationUnitID& cu_id) { + cu_id_web_contents_map_.erase(cu_id); +} + +} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_manager_grc_tab_signal_observer.h b/chrome/browser/resource_coordinator/tab_manager_grc_tab_signal_observer.h new file mode 100644 index 0000000..b4e019a --- /dev/null +++ b/chrome/browser/resource_coordinator/tab_manager_grc_tab_signal_observer.h
@@ -0,0 +1,46 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_GRC_TAB_SIGNAL_OBSERVER_H_ +#define CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_GRC_TAB_SIGNAL_OBSERVER_H_ + +#include "base/macros.h" +#include "chrome/browser/resource_coordinator/tab_manager.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "services/resource_coordinator/public/interfaces/tab_signal.mojom.h" + +namespace content { +class WebContents; +} + +namespace resource_coordinator { + +// Implementation of resource_coordinator::mojom::TabSignalObserver, +// observer constructs a mojo channel to TabSignalGenerator in GRC, passes an +// interface pointer to TabSignalGenerator, and receives tab scoped signals from +// TabSignalGenerator once a signal is generated. +class TabManager::GRCTabSignalObserver : public mojom::TabSignalObserver { + public: + GRCTabSignalObserver(); + ~GRCTabSignalObserver() override; + + // mojom::TabSignalObserver implementation. + void OnEventReceived(const CoordinationUnitID& cu_id, + mojom::TabEvent event) override; + + void AssociateCoordinationUnitIDWithWebContents( + const CoordinationUnitID& cu_id, + content::WebContents* web_contents); + + void RemoveCoordinationUnitID(const CoordinationUnitID& cu_id); + + private: + mojo::Binding<mojom::TabSignalObserver> binding_; + std::map<CoordinationUnitID, content::WebContents*> cu_id_web_contents_map_; + DISALLOW_COPY_AND_ASSIGN(GRCTabSignalObserver); +}; + +} // namespace resource_coordinator + +#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_GRC_TAB_SIGNAL_OBSERVER_H_
diff --git a/chrome/browser/resource_coordinator/tab_manager_web_contents_data.h b/chrome/browser/resource_coordinator/tab_manager_web_contents_data.h index 8cbe85b..379b46b 100644 --- a/chrome/browser/resource_coordinator/tab_manager_web_contents_data.h +++ b/chrome/browser/resource_coordinator/tab_manager_web_contents_data.h
@@ -61,6 +61,9 @@ content::NavigationHandle* navigation_handle) override; void WebContentsDestroyed() override; + // Tab signal received from GRC. + void DoneLoading() {} + // Returns true if the tab has been discarded to save memory. bool IsDiscarded();
diff --git a/chrome/browser/subresource_filter/subresource_filter_test_harness.cc b/chrome/browser/subresource_filter/subresource_filter_test_harness.cc new file mode 100644 index 0000000..0feb38e --- /dev/null +++ b/chrome/browser/subresource_filter/subresource_filter_test_harness.cc
@@ -0,0 +1,163 @@ +// 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/feature_list.h" +#include "base/memory/ptr_util.h" +#include "base/run_loop.h" +#include "base/test/scoped_feature_list.h" +#include "base/threading/thread_task_runner_handle.h" +#include "chrome/browser/after_startup_task_utils.h" +#include "chrome/browser/content_settings/tab_specific_content_settings.h" +#include "chrome/browser/infobars/infobar_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/safe_browsing/test_safe_browsing_service.h" +#include "chrome/browser/subresource_filter/chrome_subresource_filter_client.h" +#include "chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h" +#include "chrome/browser/subresource_filter/subresource_filter_profile_context.h" +#include "chrome/browser/subresource_filter/subresource_filter_profile_context_factory.h" +#include "chrome/browser/subresource_filter/subresource_filter_test_harness.h" +#include "chrome/browser/subresource_filter/test_ruleset_publisher.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "components/safe_browsing_db/v4_protocol_manager_util.h" +#include "components/subresource_filter/content/browser/content_ruleset_service.h" +#include "components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h" +#include "components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h" +#include "components/subresource_filter/core/browser/ruleset_service.h" +#include "components/subresource_filter/core/common/activation_decision.h" +#include "components/subresource_filter/core/common/activation_level.h" +#include "components/subresource_filter/core/common/activation_list.h" +#include "components/subresource_filter/core/common/test_ruleset_creator.h" +#include "content/public/browser/navigation_throttle.h" +#include "content/public/test/navigation_simulator.h" +#include "content/public/test/test_renderer_host.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +constexpr char const SubresourceFilterTestHarness::kDefaultDisallowedUrl[]; + +SubresourceFilterTestHarness::SubresourceFilterTestHarness() = default; +SubresourceFilterTestHarness::~SubresourceFilterTestHarness() = default; + +// ChromeRenderViewHostTestHarness: +void SubresourceFilterTestHarness::SetUp() { + ChromeRenderViewHostTestHarness::SetUp(); + AfterStartupTaskUtils::SetBrowserStartupIsCompleteForTesting(); + + // Ensure correct features. + scoped_feature_toggle_.ResetSubresourceFilterState( + base::FeatureList::OVERRIDE_ENABLE_FEATURE, + "SafeBrowsingV4OnlyEnabled,SubresourceFilterExperimentalUI"); + scoped_configuration_.ResetConfiguration(subresource_filter::Configuration( + subresource_filter::ActivationLevel::ENABLED, + subresource_filter::ActivationScope::ACTIVATION_LIST, + subresource_filter::ActivationList::SUBRESOURCE_FILTER)); + + NavigateAndCommit(GURL("https://example.first")); + + // Set up safe browsing service with the fake database manager. + // + // TODO(csharrison): This is a bit ugly. See if the instructions in + // test_safe_browsing_service.h can be adapted to be used in unit tests. + safe_browsing::TestSafeBrowsingServiceFactory sb_service_factory; + fake_safe_browsing_database_ = new FakeSafeBrowsingDatabaseManager(); + sb_service_factory.SetTestDatabaseManager(fake_safe_browsing_database_.get()); + safe_browsing::SafeBrowsingService::RegisterFactory(&sb_service_factory); + auto* safe_browsing_service = sb_service_factory.CreateSafeBrowsingService(); + safe_browsing::SafeBrowsingService::RegisterFactory(nullptr); + TestingBrowserProcess::GetGlobal()->SetSafeBrowsingService( + safe_browsing_service); + g_browser_process->safe_browsing_service()->Initialize(); + + // Set up the ruleset service. + ASSERT_TRUE(ruleset_service_dir_.CreateUniqueTempDir()); + subresource_filter::IndexedRulesetVersion::RegisterPrefs( + pref_service_.registry()); + auto content_service = + base::MakeUnique<subresource_filter::ContentRulesetService>( + base::ThreadTaskRunnerHandle::Get()); + auto ruleset_service = base::MakeUnique<subresource_filter::RulesetService>( + &pref_service_, base::ThreadTaskRunnerHandle::Get(), + content_service.get(), ruleset_service_dir_.GetPath()); + content_service->set_ruleset_service(std::move(ruleset_service)); + TestingBrowserProcess::GetGlobal()->SetRulesetService( + std::move(content_service)); + + // Publish the test ruleset. + subresource_filter::testing::TestRulesetCreator ruleset_creator; + subresource_filter::testing::TestRulesetPair test_ruleset_pair; + ruleset_creator.CreateRulesetToDisallowURLsWithPathSuffix("disallowed.html", + &test_ruleset_pair); + subresource_filter::testing::TestRulesetPublisher test_ruleset_publisher; + ASSERT_NO_FATAL_FAILURE( + test_ruleset_publisher.SetRuleset(test_ruleset_pair.unindexed)); + + // Set up the tab helpers. + InfoBarService::CreateForWebContents(web_contents()); + TabSpecificContentSettings::CreateForWebContents(web_contents()); + ChromeSubresourceFilterClient::CreateForWebContents(web_contents()); + + base::RunLoop().RunUntilIdle(); +} + +void SubresourceFilterTestHarness::TearDown() { + fake_safe_browsing_database_ = nullptr; + TestingBrowserProcess::GetGlobal()->safe_browsing_service()->ShutDown(); + + // Must explicitly set these to null and pump the run loop to ensure that + // all cleanup related to these classes actually happens. + TestingBrowserProcess::GetGlobal()->SetRulesetService(nullptr); + TestingBrowserProcess::GetGlobal()->SetSafeBrowsingService(nullptr); + base::RunLoop().RunUntilIdle(); + + ChromeRenderViewHostTestHarness::TearDown(); +} + +// Will return nullptr if the navigation fails. +content::RenderFrameHost* +SubresourceFilterTestHarness::SimulateNavigateAndCommit( + const GURL& url, + content::RenderFrameHost* rfh) { + auto simulator = + content::NavigationSimulator::CreateRendererInitiated(url, rfh); + simulator->Commit(); + return simulator->GetLastThrottleCheckResult() == + content::NavigationThrottle::PROCEED + ? simulator->GetFinalRenderFrameHost() + : nullptr; +} + +// Returns the frame host the navigation commit in, or nullptr if it did not +// succeed. +content::RenderFrameHost* +SubresourceFilterTestHarness::CreateAndNavigateDisallowedSubframe( + content::RenderFrameHost* parent) { + auto* subframe = + content::RenderFrameHostTester::For(parent)->AppendChild("subframe"); + return SimulateNavigateAndCommit(GURL(kDefaultDisallowedUrl), subframe); +} + +void SubresourceFilterTestHarness::ConfigureAsSubresourceFilterOnlyURL( + const GURL& url) { + fake_safe_browsing_database_->AddBlacklistedUrl( + url, safe_browsing::SB_THREAT_TYPE_SUBRESOURCE_FILTER); +} + +ChromeSubresourceFilterClient* SubresourceFilterTestHarness::GetClient() { + return ChromeSubresourceFilterClient::FromWebContents(web_contents()); +} + +void SubresourceFilterTestHarness::RemoveURLFromBlacklist(const GURL& url) { + fake_safe_browsing_database_->RemoveBlacklistedUrl(url); +} + +SubresourceFilterContentSettingsManager* +SubresourceFilterTestHarness::GetSettingsManager() { + return SubresourceFilterProfileContextFactory::GetForProfile( + static_cast<Profile*>(profile())) + ->settings_manager(); +}
diff --git a/chrome/browser/subresource_filter/subresource_filter_test_harness.h b/chrome/browser/subresource_filter/subresource_filter_test_harness.h new file mode 100644 index 0000000..110d0db --- /dev/null +++ b/chrome/browser/subresource_filter/subresource_filter_test_harness.h
@@ -0,0 +1,75 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SUBRESOURCE_FILTER_SUBRESOURCE_FILTER_TEST_HARNESS_H_ +#define CHROME_BROWSER_SUBRESOURCE_FILTER_SUBRESOURCE_FILTER_TEST_HARNESS_H_ + +#include "base/files/scoped_temp_dir.h" +#include "base/macros.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "components/prefs/testing_pref_service.h" +#include "components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h" +#include "components/subresource_filter/core/browser/subresource_filter_features.h" +#include "components/subresource_filter/core/browser/subresource_filter_features_test_support.h" + +class ChromeSubresourceFilterClient; +class GURL; +class SubresourceFilterContentSettingsManager; + +namespace content { +class RenderFrameHost; +} // namespace content + +// End to end unit test harness of (most of) the browser process portions of the +// subresource filtering code. +class SubresourceFilterTestHarness : public ChromeRenderViewHostTestHarness { + public: + static constexpr char const kDefaultDisallowedUrl[] = + "https://example.test/disallowed.html"; + SubresourceFilterTestHarness(); + ~SubresourceFilterTestHarness() override; + + // ChromeRenderViewHostTestHarness: + void SetUp() override; + void TearDown() override; + + // Returns the frame host the navigation commit in, or nullptr if it did not + // succeed. + content::RenderFrameHost* SimulateNavigateAndCommit( + const GURL& url, + content::RenderFrameHost* rfh); + + // Creates a subframe as a child of |parent|, and navigates it to a URL + // disallowed by the default ruleset (kDefaultDisallowedUrl). Returns the + // frame host the navigation commit in, or nullptr if it did not succeed. + content::RenderFrameHost* CreateAndNavigateDisallowedSubframe( + content::RenderFrameHost* parent); + + void ConfigureAsSubresourceFilterOnlyURL(const GURL& url); + + ChromeSubresourceFilterClient* GetClient(); + + void RemoveURLFromBlacklist(const GURL& url); + + SubresourceFilterContentSettingsManager* GetSettingsManager(); + + subresource_filter::testing::ScopedSubresourceFilterConfigurator& + scoped_configuration() { + return scoped_configuration_; + } + + private: + base::ScopedTempDir ruleset_service_dir_; + TestingPrefServiceSimple pref_service_; + subresource_filter::testing::ScopedSubresourceFilterFeatureToggle + scoped_feature_toggle_; + subresource_filter::testing::ScopedSubresourceFilterConfigurator + scoped_configuration_; + + scoped_refptr<FakeSafeBrowsingDatabaseManager> fake_safe_browsing_database_; + + DISALLOW_COPY_AND_ASSIGN(SubresourceFilterTestHarness); +}; + +#endif // CHROME_BROWSER_SUBRESOURCE_FILTER_SUBRESOURCE_FILTER_TEST_HARNESS_H_
diff --git a/chrome/browser/subresource_filter/subresource_filter_unittest.cc b/chrome/browser/subresource_filter/subresource_filter_unittest.cc index 4886201..0bfee7c 100644 --- a/chrome/browser/subresource_filter/subresource_filter_unittest.cc +++ b/chrome/browser/subresource_filter/subresource_filter_unittest.cc
@@ -2,196 +2,28 @@ // 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/feature_list.h" -#include "base/files/scoped_temp_dir.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/run_loop.h" -#include "base/test/scoped_feature_list.h" -#include "base/threading/thread_task_runner_handle.h" -#include "chrome/browser/after_startup_task_utils.h" -#include "chrome/browser/content_settings/tab_specific_content_settings.h" -#include "chrome/browser/infobars/infobar_service.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/safe_browsing/test_safe_browsing_service.h" #include "chrome/browser/subresource_filter/chrome_subresource_filter_client.h" #include "chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h" -#include "chrome/browser/subresource_filter/subresource_filter_profile_context.h" -#include "chrome/browser/subresource_filter/subresource_filter_profile_context_factory.h" -#include "chrome/browser/subresource_filter/test_ruleset_publisher.h" -#include "chrome/test/base/chrome_render_view_host_test_harness.h" -#include "chrome/test/base/testing_browser_process.h" -#include "chrome/test/base/testing_profile.h" -#include "components/prefs/testing_pref_service.h" -#include "components/safe_browsing_db/v4_protocol_manager_util.h" -#include "components/subresource_filter/content/browser/content_ruleset_service.h" +#include "chrome/browser/subresource_filter/subresource_filter_test_harness.h" #include "components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h" -#include "components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h" #include "components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h" -#include "components/subresource_filter/core/browser/ruleset_service.h" #include "components/subresource_filter/core/browser/subresource_filter_features.h" #include "components/subresource_filter/core/browser/subresource_filter_features_test_support.h" #include "components/subresource_filter/core/common/activation_decision.h" -#include "components/subresource_filter/core/common/test_ruleset_creator.h" -#include "content/public/browser/navigation_throttle.h" -#include "content/public/test/navigation_simulator.h" -#include "content/public/test/test_renderer_host.h" +#include "components/subresource_filter/core/common/activation_level.h" +#include "components/subresource_filter/core/common/activation_list.h" +#include "components/subresource_filter/core/common/activation_scope.h" +#include "components/subresource_filter/core/common/load_policy.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" -namespace { -using subresource_filter::testing::ScopedSubresourceFilterConfigurator; -using subresource_filter::testing::ScopedSubresourceFilterFeatureToggle; -const char kDisallowedUrl[] = "https://example.test/disallowed.html"; -} // namespace - -// End to end unit test harness of (most of) the browser process portions of the -// subresource filtering code. -class SubresourceFilterTest : public ChromeRenderViewHostTestHarness { - public: - SubresourceFilterTest() {} - ~SubresourceFilterTest() override {} - - // ChromeRenderViewHostTestHarness: - void SetUp() override { - ChromeRenderViewHostTestHarness::SetUp(); - AfterStartupTaskUtils::SetBrowserStartupIsCompleteForTesting(); - - // Ensure correct features. - scoped_feature_toggle_.ResetSubresourceFilterState( - base::FeatureList::OVERRIDE_ENABLE_FEATURE, - "SafeBrowsingV4OnlyEnabled,SubresourceFilterExperimentalUI"); - scoped_configuration_.ResetConfiguration(subresource_filter::Configuration( - subresource_filter::ActivationLevel::ENABLED, - subresource_filter::ActivationScope::ACTIVATION_LIST, - subresource_filter::ActivationList::SUBRESOURCE_FILTER)); - - NavigateAndCommit(GURL("https://example.first")); - - // Set up safe browsing service with the fake database manager. - // - // TODO(csharrison): This is a bit ugly. See if the instructions in - // test_safe_browsing_service.h can be adapted to be used in unit tests. - safe_browsing::TestSafeBrowsingServiceFactory sb_service_factory; - fake_safe_browsing_database_ = new FakeSafeBrowsingDatabaseManager(); - sb_service_factory.SetTestDatabaseManager( - fake_safe_browsing_database_.get()); - safe_browsing::SafeBrowsingService::RegisterFactory(&sb_service_factory); - auto* safe_browsing_service = - sb_service_factory.CreateSafeBrowsingService(); - safe_browsing::SafeBrowsingService::RegisterFactory(nullptr); - TestingBrowserProcess::GetGlobal()->SetSafeBrowsingService( - safe_browsing_service); - g_browser_process->safe_browsing_service()->Initialize(); - - // Set up the ruleset service. - ASSERT_TRUE(ruleset_service_dir_.CreateUniqueTempDir()); - subresource_filter::IndexedRulesetVersion::RegisterPrefs( - pref_service_.registry()); - auto content_service = - base::MakeUnique<subresource_filter::ContentRulesetService>( - base::ThreadTaskRunnerHandle::Get()); - auto ruleset_service = base::MakeUnique<subresource_filter::RulesetService>( - &pref_service_, base::ThreadTaskRunnerHandle::Get(), - content_service.get(), ruleset_service_dir_.GetPath()); - content_service->set_ruleset_service(std::move(ruleset_service)); - TestingBrowserProcess::GetGlobal()->SetRulesetService( - std::move(content_service)); - - // Publish the test ruleset. - subresource_filter::testing::TestRulesetCreator ruleset_creator; - subresource_filter::testing::TestRulesetPair test_ruleset_pair; - ruleset_creator.CreateRulesetToDisallowURLsWithPathSuffix( - "disallowed.html", &test_ruleset_pair); - subresource_filter::testing::TestRulesetPublisher test_ruleset_publisher; - ASSERT_NO_FATAL_FAILURE( - test_ruleset_publisher.SetRuleset(test_ruleset_pair.unindexed)); - - // Set up the tab helpers. - InfoBarService::CreateForWebContents(web_contents()); - TabSpecificContentSettings::CreateForWebContents(web_contents()); - ChromeSubresourceFilterClient::CreateForWebContents(web_contents()); - - base::RunLoop().RunUntilIdle(); - } - - void TearDown() override { - fake_safe_browsing_database_ = nullptr; - TestingBrowserProcess::GetGlobal()->safe_browsing_service()->ShutDown(); - - // Must explicitly set these to null and pump the run loop to ensure that - // all cleanup related to these classes actually happens. - TestingBrowserProcess::GetGlobal()->SetRulesetService(nullptr); - TestingBrowserProcess::GetGlobal()->SetSafeBrowsingService(nullptr); - base::RunLoop().RunUntilIdle(); - - ChromeRenderViewHostTestHarness::TearDown(); - } - - // Will return nullptr if the navigation fails. - content::RenderFrameHost* SimulateNavigateAndCommit( - const GURL& url, - content::RenderFrameHost* rfh) { - auto simulator = - content::NavigationSimulator::CreateRendererInitiated(url, rfh); - simulator->Commit(); - return simulator->GetLastThrottleCheckResult() == - content::NavigationThrottle::PROCEED - ? simulator->GetFinalRenderFrameHost() - : nullptr; - } - - // Returns the frame host the navigation commit in, or nullptr if it did not - // succeed. - content::RenderFrameHost* CreateAndNavigateDisallowedSubframe( - content::RenderFrameHost* parent) { - auto* subframe = - content::RenderFrameHostTester::For(parent)->AppendChild("subframe"); - return SimulateNavigateAndCommit(GURL(kDisallowedUrl), subframe); - } - - void ConfigureAsSubresourceFilterOnlyURL(const GURL& url) { - fake_safe_browsing_database_->AddBlacklistedUrl( - url, safe_browsing::SB_THREAT_TYPE_SUBRESOURCE_FILTER); - } - - ChromeSubresourceFilterClient* client() { - return ChromeSubresourceFilterClient::FromWebContents(web_contents()); - } - - void RemoveURLFromBlacklist(const GURL& url) { - fake_safe_browsing_database_->RemoveBlacklistedUrl(url); - } - - SubresourceFilterContentSettingsManager* settings_manager() { - return SubresourceFilterProfileContextFactory::GetForProfile( - static_cast<Profile*>(profile())) - ->settings_manager(); - } - - ScopedSubresourceFilterConfigurator& scoped_configuration() { - return scoped_configuration_; - } - - private: - base::ScopedTempDir ruleset_service_dir_; - TestingPrefServiceSimple pref_service_; - ScopedSubresourceFilterFeatureToggle scoped_feature_toggle_; - ScopedSubresourceFilterConfigurator scoped_configuration_; - - scoped_refptr<FakeSafeBrowsingDatabaseManager> fake_safe_browsing_database_; - - DISALLOW_COPY_AND_ASSIGN(SubresourceFilterTest); -}; +class SubresourceFilterTest : public SubresourceFilterTestHarness {}; TEST_F(SubresourceFilterTest, SimpleAllowedLoad) { GURL url("https://example.test"); SimulateNavigateAndCommit(url, main_rfh()); EXPECT_TRUE(CreateAndNavigateDisallowedSubframe(main_rfh())); - EXPECT_FALSE(client()->did_show_ui_for_navigation()); + EXPECT_FALSE(GetClient()->did_show_ui_for_navigation()); } TEST_F(SubresourceFilterTest, SimpleDisallowedLoad) { @@ -199,7 +31,7 @@ ConfigureAsSubresourceFilterOnlyURL(url); SimulateNavigateAndCommit(url, main_rfh()); EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh())); - EXPECT_TRUE(client()->did_show_ui_for_navigation()); + EXPECT_TRUE(GetClient()->did_show_ui_for_navigation()); } TEST_F(SubresourceFilterTest, DeactivateUrl_ClearsSiteMetadata) { @@ -208,7 +40,7 @@ SimulateNavigateAndCommit(url, main_rfh()); EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh())); - EXPECT_NE(nullptr, settings_manager()->GetSiteMetadata(url)); + EXPECT_NE(nullptr, GetSettingsManager()->GetSiteMetadata(url)); RemoveURLFromBlacklist(url); @@ -216,7 +48,7 @@ SimulateNavigateAndCommit(url, main_rfh()); EXPECT_TRUE(CreateAndNavigateDisallowedSubframe(main_rfh())); - EXPECT_EQ(nullptr, settings_manager()->GetSiteMetadata(url)); + EXPECT_EQ(nullptr, GetSettingsManager()->GetSiteMetadata(url)); } // If the underlying configuration changes and a site only activates to DRYRUN, @@ -227,7 +59,7 @@ SimulateNavigateAndCommit(url, main_rfh()); EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh())); - EXPECT_NE(nullptr, settings_manager()->GetSiteMetadata(url)); + EXPECT_NE(nullptr, GetSettingsManager()->GetSiteMetadata(url)); // If the site later activates as DRYRUN due to e.g. a configuration change, // it should also be removed from the metadata. @@ -240,7 +72,7 @@ SimulateNavigateAndCommit(url, main_rfh()); EXPECT_TRUE(CreateAndNavigateDisallowedSubframe(main_rfh())); - EXPECT_EQ(nullptr, settings_manager()->GetSiteMetadata(url)); + EXPECT_EQ(nullptr, GetSettingsManager()->GetSiteMetadata(url)); } TEST_F(SubresourceFilterTest, ExplicitWhitelisting_ShouldNotClearMetadata) { @@ -250,13 +82,13 @@ EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh())); // Simulate explicit whitelisting and reload. - settings_manager()->WhitelistSite(url); + GetSettingsManager()->WhitelistSite(url); SimulateNavigateAndCommit(url, main_rfh()); EXPECT_TRUE(CreateAndNavigateDisallowedSubframe(main_rfh())); // Should not have cleared the metadata, since the site is still on the SB // blacklist. - EXPECT_NE(nullptr, settings_manager()->GetSiteMetadata(url)); + EXPECT_NE(nullptr, GetSettingsManager()->GetSiteMetadata(url)); } TEST_F(SubresourceFilterTest, @@ -308,10 +140,10 @@ EXPECT_EQ(subresource_filter::ActivationDecision::ACTIVATED, observer.GetPageActivation(url).value()); + GURL disallowed_url(SubresourceFilterTest::kDefaultDisallowedUrl); EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh())); - auto optional_load_policy = - observer.GetSubframeLoadPolicy(GURL(kDisallowedUrl)); + auto optional_load_policy = observer.GetSubframeLoadPolicy(disallowed_url); EXPECT_TRUE(optional_load_policy.has_value()); EXPECT_EQ(subresource_filter::LoadPolicy::DISALLOW, - observer.GetSubframeLoadPolicy(GURL(kDisallowedUrl)).value()); + observer.GetSubframeLoadPolicy(disallowed_url).value()); }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index f12717b..b0103f3 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -507,6 +507,7 @@ "//components/dom_distiller/content/browser", "//components/dom_distiller/webui", "//components/domain_reliability", + "//components/download/content/public", "//components/favicon/content", "//components/favicon/core", "//components/feedback",
diff --git a/chrome/browser/ui/cocoa/browser_window_layout.mm b/chrome/browser/ui/cocoa/browser_window_layout.mm index 041f0f8f..fcf2da13 100644 --- a/chrome/browser/ui/cocoa/browser_window_layout.mm +++ b/chrome/browser/ui/cocoa/browser_window_layout.mm
@@ -24,9 +24,10 @@ // stopped the window buttons from being covered by the content view. This // may break in a future macOS release. NSFullSizeContentViewWindowMask is a // new (10.10+), supported way to make the content view the full size of the - // window without covering the controls. + // window without covering the controls. It's only enabled in 10.12+ due to a + // performance regression seen in 10.11 (https://crbug.com/742472). return base::FeatureList::IsEnabled(features::kMacFullSizeContentView) && - base::mac::IsAtLeastOS10_11(); + base::mac::IsAtLeastOS10_12(); } } // namespace chrome
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index 8bd5b218..5ca4247 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -56,8 +56,7 @@ TabRendererData::NetworkState TabContentsNetworkState( WebContents* contents) { - if (!contents) - return TabRendererData::NETWORK_STATE_NONE; + DCHECK(contents); if (!contents->IsLoadingToDifferentDocument()) { content::NavigationEntry* entry = @@ -500,7 +499,6 @@ data->network_state = TabContentsNetworkState(contents); data->title = contents->GetTitle(); data->url = contents->GetURL(); - data->loading = contents->IsLoading(); data->crashed_status = contents->GetCrashedStatus(); data->incognito = contents->GetBrowserContext()->IsOffTheRecord(); data->pinned = model_->IsTabPinned(model_index);
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index 55766eac..f1b8614 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -540,9 +540,9 @@ base::string16 title = data_.title; if (title.empty()) { - title = data_.loading ? - l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) : - CoreTabHelper::GetDefaultTitle(); + title = ShouldShowThrobber(data_.network_state) + ? l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) + : CoreTabHelper::GetDefaultTitle(); } else { Browser::FormatTitleForDisplay(&title); }
diff --git a/chrome/browser/ui/views/tabs/tab_renderer_data.cc b/chrome/browser/ui/views/tabs/tab_renderer_data.cc index 4f10179..030695c 100644 --- a/chrome/browser/ui/views/tabs/tab_renderer_data.cc +++ b/chrome/browser/ui/views/tabs/tab_renderer_data.cc
@@ -9,7 +9,6 @@ TabRendererData::TabRendererData() : network_state(NETWORK_STATE_NONE), - loading(false), crashed_status(base::TERMINATION_STATUS_STILL_RUNNING), incognito(false), show_icon(true), @@ -39,7 +38,6 @@ network_state == data.network_state && title == data.title && url == data.url && - loading == data.loading && crashed_status == data.crashed_status && incognito == data.incognito && show_icon == data.show_icon &&
diff --git a/chrome/browser/ui/views/tabs/tab_renderer_data.h b/chrome/browser/ui/views/tabs/tab_renderer_data.h index 9b1d2ab..15ad5f6e 100644 --- a/chrome/browser/ui/views/tabs/tab_renderer_data.h +++ b/chrome/browser/ui/views/tabs/tab_renderer_data.h
@@ -39,7 +39,6 @@ NetworkState network_state; base::string16 title; GURL url; - bool loading; base::TerminationStatus crashed_status; bool incognito; bool show_icon;
diff --git a/chrome/browser/ui/webui/md_downloads/downloads_list_tracker.cc b/chrome/browser/ui/webui/md_downloads/downloads_list_tracker.cc index fe52433d..30cb212 100644 --- a/chrome/browser/ui/webui/md_downloads/downloads_list_tracker.cc +++ b/chrome/browser/ui/webui/md_downloads/downloads_list_tracker.cc
@@ -21,7 +21,6 @@ #include "chrome/browser/extensions/api/downloads/downloads_api.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile.h" -#include "content/public/browser/all_download_item_notifier.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/download_item.h" #include "content/public/browser/download_manager.h" @@ -354,7 +353,7 @@ GetMainNotifierManager()->GetBrowserContext()); if (profile->IsOffTheRecord()) { Profile* original_profile = profile->GetOriginalProfile(); - original_notifier_.reset(new content::AllDownloadItemNotifier( + original_notifier_.reset(new download::AllDownloadItemNotifier( BrowserContext::GetDownloadManager(original_profile), this)); }
diff --git a/chrome/browser/ui/webui/md_downloads/downloads_list_tracker.h b/chrome/browser/ui/webui/md_downloads/downloads_list_tracker.h index 8d99d185..b92245ac 100644 --- a/chrome/browser/ui/webui/md_downloads/downloads_list_tracker.h +++ b/chrome/browser/ui/webui/md_downloads/downloads_list_tracker.h
@@ -15,7 +15,7 @@ #include "base/strings/string16.h" #include "base/time/time.h" #include "base/values.h" -#include "content/public/browser/all_download_item_notifier.h" +#include "components/download/content/public/all_download_item_notifier.h" #include "content/public/browser/download_item.h" namespace base { @@ -30,7 +30,8 @@ // A class that tracks all downloads activity and keeps a sorted representation // of the downloads as chrome://downloads wants to display them. -class DownloadsListTracker : public content::AllDownloadItemNotifier::Observer { +class DownloadsListTracker + : public download::AllDownloadItemNotifier::Observer { public: DownloadsListTracker(content::DownloadManager* download_manager, content::WebUI* web_ui); @@ -109,8 +110,8 @@ // if sending updates. void RemoveItem(const SortedSet::iterator& remove); - content::AllDownloadItemNotifier main_notifier_; - std::unique_ptr<content::AllDownloadItemNotifier> original_notifier_; + download::AllDownloadItemNotifier main_notifier_; + std::unique_ptr<download::AllDownloadItemNotifier> original_notifier_; // The WebUI object corresponding to the page we care about. content::WebUI* const web_ui_;
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index e833c10a..1874ff1 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -493,19 +493,6 @@ // proxy connection, and the endpoint host in a SOCKS proxy connection). const char kHostRules[] = "host-rules"; -// A set of public key hashes for which to ignore certificate-related errors. -// -// If the certificate chain presented by the server does not validate, and one -// or more certificates have public key hashes that match a key from this list, -// the error is ignored. -// -// The switch value must a be a comma-separated list of Base64-encoded SHA-256 -// SPKI Fingerprints (RFC 7469, Section 2.4). -// -// This switch has no effect unless --user-data-dir is also present. -const char kIgnoreCertificateErrorsSPKIList[] = - "ignore-certificate-errors-spki-list"; - // Causes net::URLFetchers to ignore requests for SSL client certificates, // causing them to attempt an unauthenticated SSL/TLS session. This is intended // for use when testing various service URLs (eg: kPromoServerURL, kSbURLPrefix,
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 25d3512..007fe78 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -148,7 +148,6 @@ extern const char kForceLocalNtp[]; extern const char kHomePage[]; extern const char kHostRules[]; -extern const char kIgnoreCertificateErrorsSPKIList[]; extern const char kIgnoreUrlFetcherCertRequests[]; extern const char kIncognito[]; extern const char kInstallChromeApp[];
diff --git a/chrome/installer/zucchini/BUILD.gn b/chrome/installer/zucchini/BUILD.gn index 97ea2b42..b1fbd88 100644 --- a/chrome/installer/zucchini/BUILD.gn +++ b/chrome/installer/zucchini/BUILD.gn
@@ -7,6 +7,10 @@ static_library("zucchini_lib") { sources = [ + "buffer_sink.cc", + "buffer_sink.h", + "buffer_source.cc", + "buffer_source.h", "buffer_view.h", "crc32.cc", "crc32.h", @@ -51,6 +55,8 @@ test("zucchini_unittests") { sources = [ + "buffer_sink_unittest.cc", + "buffer_source_unittest.cc", "buffer_view_unittest.cc", "crc32_unittest.cc", "io_utils_unittest.cc",
diff --git a/chrome/installer/zucchini/buffer_sink.cc b/chrome/installer/zucchini/buffer_sink.cc new file mode 100644 index 0000000..9c09af85 --- /dev/null +++ b/chrome/installer/zucchini/buffer_sink.cc
@@ -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 "chrome/installer/zucchini/buffer_sink.h" + +namespace zucchini { + +BufferSink::BufferSink(MutableBufferView buffer) : MutableBufferView(buffer) {} + +} // namespace zucchini
diff --git a/chrome/installer/zucchini/buffer_sink.h b/chrome/installer/zucchini/buffer_sink.h new file mode 100644 index 0000000..3e3be8e --- /dev/null +++ b/chrome/installer/zucchini/buffer_sink.h
@@ -0,0 +1,69 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_INSTALLER_ZUCCHINI_BUFFER_SINK_H_ +#define CHROME_INSTALLER_ZUCCHINI_BUFFER_SINK_H_ + +#include <algorithm> +#include <cstddef> +#include <cstdint> +#include <iterator> + +#include "base/logging.h" +#include "chrome/installer/zucchini/buffer_view.h" + +namespace zucchini { + +// BufferSink acts like an output stream with convenience methods to serialize +// data into a contiguous sequence of raw data. The underlying MutableBufferView +// emulates a cursor to track current write position, and guards against buffer +// overrun. Where applicable, BufferSink should be passed by pointer to maintain +// cursor progress across writes. +class BufferSink : public MutableBufferView { + public: + using iterator = MutableBufferView::iterator; + + using MutableBufferView::MutableBufferView; + BufferSink() = default; + explicit BufferSink(MutableBufferView buffer); + BufferSink(const BufferSink&) = default; + + BufferSink& operator=(BufferSink&&) = default; + + // If sufficient space is available, writes the binary representation of + // |value| starting at cursor, while advancing the cursor beyond the written + // region, and returns true. Otherwise returns false. + template <class T> + bool PutValue(const T& value) { + DCHECK_NE(begin(), nullptr); + if (Remaining() < sizeof(T)) + return false; + *reinterpret_cast<T*>(begin()) = value; + remove_prefix(sizeof(T)); + return true; + } + + // If sufficient space is available, writes the raw bytes [|first|, |last|) + // starting at cursor, while advancing the cursor beyond the written region, + // and returns true. Otherwise returns false. + template <class It> + bool PutRange(It first, It last) { + static_assert(sizeof(typename std::iterator_traits<It>::value_type) == + sizeof(uint8_t), + "value_type should fit in uint8_t"); + DCHECK_NE(begin(), nullptr); + DCHECK(last >= first); + if (Remaining() < size_type(last - first)) + return false; + std::copy(first, last, begin()); + remove_prefix(last - first); + return true; + } + + size_type Remaining() const { return size(); } +}; + +} // namespace zucchini + +#endif // CHROME_INSTALLER_ZUCCHINI_BUFFER_SINK_H_
diff --git a/chrome/installer/zucchini/buffer_sink_unittest.cc b/chrome/installer/zucchini/buffer_sink_unittest.cc new file mode 100644 index 0000000..c371cd72 --- /dev/null +++ b/chrome/installer/zucchini/buffer_sink_unittest.cc
@@ -0,0 +1,71 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/installer/zucchini/buffer_sink.h" + +#include <vector> + +#include "base/test/gtest_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace zucchini { + +constexpr uint8_t kUninit = 0xFF; + +class BufferSinkTest : public testing::Test { + protected: + void SetUp() override { + buffer_ = std::vector<uint8_t>(10, kUninit); + sink_ = BufferSink(buffer_.data(), buffer_.size()); + } + + std::vector<uint8_t> buffer_; + BufferSink sink_; +}; + +TEST_F(BufferSinkTest, PutValue) { + EXPECT_EQ(size_t(10), sink_.Remaining()); + + EXPECT_TRUE(sink_.PutValue(uint32_t(0x76543210))); + EXPECT_EQ(size_t(6), sink_.Remaining()); + + EXPECT_TRUE(sink_.PutValue(uint32_t(0xFEDCBA98))); + EXPECT_EQ(size_t(2), sink_.Remaining()); + + EXPECT_FALSE(sink_.PutValue(uint32_t(0x00))); + EXPECT_EQ(size_t(2), sink_.Remaining()); + + EXPECT_TRUE(sink_.PutValue(uint16_t(0x0010))); + EXPECT_EQ(size_t(0), sink_.Remaining()); + + // Assuming little-endian architecture. + EXPECT_EQ(std::vector<uint8_t>( + {0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, 0x10, 0x00}), + buffer_); +} + +TEST_F(BufferSinkTest, PutRange) { + std::vector<uint8_t> range = {0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, + 0xDC, 0xFE, 0x10, 0x00, 0x42}; + + EXPECT_EQ(size_t(10), sink_.Remaining()); + EXPECT_FALSE(sink_.PutRange(range.begin(), range.end())); + EXPECT_EQ(size_t(10), sink_.Remaining()); + + EXPECT_TRUE(sink_.PutRange(range.begin(), range.begin() + 8)); + EXPECT_EQ(size_t(2), sink_.Remaining()); + EXPECT_EQ(std::vector<uint8_t>({0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, + 0xFE, kUninit, kUninit}), + buffer_); + + EXPECT_FALSE(sink_.PutRange(range.begin(), range.begin() + 4)); + EXPECT_EQ(size_t(2), sink_.Remaining()); + + // range is not written + EXPECT_EQ(std::vector<uint8_t>({0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, + 0xFE, kUninit, kUninit}), + buffer_); +} + +} // namespace zucchini
diff --git a/chrome/installer/zucchini/buffer_source.cc b/chrome/installer/zucchini/buffer_source.cc new file mode 100644 index 0000000..b688dc4c --- /dev/null +++ b/chrome/installer/zucchini/buffer_source.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 "chrome/installer/zucchini/buffer_source.h" + +#include <algorithm> + +namespace zucchini { + +BufferSource::BufferSource(ConstBufferView buffer) : ConstBufferView(buffer) {} + +BufferSource& BufferSource::Skip(size_type n) { + remove_prefix(std::min(n, Remaining())); + return *this; +} + +bool BufferSource::CheckNextBytes(std::initializer_list<uint8_t> bytes) const { + if (Remaining() < bytes.size()) + return false; + return std::mismatch(bytes.begin(), bytes.end(), begin()).first == + bytes.end(); +} + +bool BufferSource::ConsumeBytes(std::initializer_list<uint8_t> bytes) { + if (!CheckNextBytes(bytes)) + return false; + remove_prefix(bytes.size()); + return true; +} + +bool BufferSource::GetRegion(size_type count, ConstBufferView* buffer) { + DCHECK_NE(begin(), nullptr); + if (Remaining() < count) + return false; + *buffer = ConstBufferView(begin(), count); + remove_prefix(count); + return true; +} + +} // namespace zucchini
diff --git a/chrome/installer/zucchini/buffer_source.h b/chrome/installer/zucchini/buffer_source.h new file mode 100644 index 0000000..6dab416 --- /dev/null +++ b/chrome/installer/zucchini/buffer_source.h
@@ -0,0 +1,125 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_INSTALLER_ZUCCHINI_BUFFER_SOURCE_H_ +#define CHROME_INSTALLER_ZUCCHINI_BUFFER_SOURCE_H_ + +#include <algorithm> +#include <cstddef> +#include <cstdint> +#include <initializer_list> +#include <type_traits> + +#include "chrome/installer/zucchini/buffer_view.h" + +namespace zucchini { + +// BufferSource acts like an input stream with convenience methods to parse data +// from a contiguous sequence of raw data. The underlying ConstBufferView +// emulates a cursor to track current read position, and guards against buffer +// overrun. Where applicable, BufferSource should be passed by pointer to +// maintain cursor progress across reads. +class BufferSource : public ConstBufferView { + public: + static BufferSource FromRange(const_iterator first, const_iterator last) { + return BufferSource(ConstBufferView::FromRange(first, last)); + } + + using ConstBufferView::ConstBufferView; + BufferSource() = default; + explicit BufferSource(ConstBufferView buffer); + BufferSource(const BufferSource&) = default; + + BufferSource& operator=(BufferSource&&) = default; + + // Moves cursor forward by |n| bytes, or until end if data is exhausted. + // Returns a reference to *this, to allow chaining, e.g.: + // if (!buffer_source.Skip(1024).GetValue<uint32_t>(&value)) { + // ... // Handle error. + // } + // Notice that Skip() defers error handling to GetValue(). + BufferSource& Skip(size_type n); + + // Returns true if |value| matches data starting at cursor when reinterpreted + // as the integral type |T|. + template <class T> + bool CheckNextValue(const T& value) const { + static_assert(std::is_integral<T>::value, + "Value type must be an integral type"); + + DCHECK_NE(begin(), nullptr); + if (Remaining() < sizeof(T)) + return false; + return value == *reinterpret_cast<const T*>(begin()); + } + + // Returns true if the next bytes.size() bytes at the cursor match those in + // |bytes|. + bool CheckNextBytes(std::initializer_list<uint8_t> bytes) const; + + // Same as CheckNextBytes(), but moves the cursor by bytes.size() if read is + // successfull. + bool ConsumeBytes(std::initializer_list<uint8_t> bytes); + + // Tries to reinterpret data as type |T|, starting at cursor and to write the + // result into |value|, while moving the cursor forward by sizeof(T). Returns + // true if sufficient data is available, and false otherwise. + template <class T> + bool GetValue(T* value) { + static_assert(std::is_standard_layout<T>::value, + "Value type must be a standard layout type"); + + DCHECK_NE(begin(), nullptr); + if (Remaining() < sizeof(T)) + return false; + *value = *reinterpret_cast<const T*>(begin()); + remove_prefix(sizeof(T)); + return true; + } + + // Tries to reinterpret data as type |T| at cursor and to return a + // reinterpreted pointer of type |T| pointing into the underlying data, while + // moving the cursor forward by sizeof(T). Returns nullptr if insufficient + // data is available. + template <class T> + const T* GetPointer() { + static_assert(std::is_standard_layout<T>::value, + "Value type must be a standard layout type"); + + DCHECK_NE(begin(), nullptr); + if (Remaining() < sizeof(T)) + return nullptr; + const T* ptr = reinterpret_cast<const T*>(begin()); + remove_prefix(sizeof(T)); + return ptr; + } + + // Tries to reinterpret data as an array of type |T| with |count| elements, + // starting at cursor, and to return a reinterpreted pointer of type |T| + // pointing into the underlying data, while advancing the cursor beyond the + // array. Returns nullptr if insufficient data is available. + template <class T> + const T* GetArray(size_t count) { + static_assert(std::is_standard_layout<T>::value, + "Value type must be a standard layout type"); + + if (Remaining() / sizeof(T) < count) + return nullptr; + const T* array = reinterpret_cast<const T*>(begin()); + remove_prefix(count * sizeof(T)); + return array; + } + + // If sufficient data is available, assigns |buffer| to point to a region of + // |size| bytes starting at cursor, while advancing the cursor beyond the + // region, and returns true. Otherwise returns false. + bool GetRegion(size_type size, ConstBufferView* buffer); + + // Returns the number of bytes remaining from cursor until end. + size_type Remaining() const { return size(); } +}; + +} // namespace zucchini + +#endif // CHROME_INSTALLER_ZUCCHINI_BUFFER_SOURCE_H_
diff --git a/chrome/installer/zucchini/buffer_source_unittest.cc b/chrome/installer/zucchini/buffer_source_unittest.cc new file mode 100644 index 0000000..edc04de5 --- /dev/null +++ b/chrome/installer/zucchini/buffer_source_unittest.cc
@@ -0,0 +1,170 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/installer/zucchini/buffer_source.h" + +#include <cstdint> +#include <iterator> +#include <vector> + +#include "base/test/gtest_util.h" + +namespace zucchini { + +using vec = std::vector<uint8_t>; + +static constexpr size_t kLen = 10; +constexpr const uint8_t bytes[kLen] = {0x10, 0x32, 0x54, 0x76, 0x98, + 0xBA, 0xDC, 0xFE, 0x10, 0x00}; + +class BufferSourceTest : public testing::Test { + protected: + BufferSource source_ = {std::begin(bytes), kLen}; +}; + +TEST_F(BufferSourceTest, Skip) { + EXPECT_EQ(kLen, source_.Remaining()); + source_.Skip(2); + EXPECT_EQ(kLen - 2, source_.Remaining()); + source_.Skip(10); // Skipping past end just moves cursor to end. + EXPECT_EQ(size_t(0), source_.Remaining()); +} + +TEST_F(BufferSourceTest, CheckNextBytes) { + EXPECT_TRUE(source_.CheckNextBytes({0x10, 0x32, 0x54, 0x76})); + source_.Skip(4); + EXPECT_TRUE(source_.CheckNextBytes({0x98, 0xBA, 0xDC, 0xFE})); + + // Cursor has not advanced, so check fails. + EXPECT_FALSE(source_.CheckNextBytes({0x10, 0x00})); + + source_.Skip(4); + EXPECT_EQ(size_t(2), source_.Remaining()); + + // Goes beyond end by 2 bytes. + EXPECT_FALSE(source_.CheckNextBytes({0x10, 0x00, 0x00, 0x00})); + EXPECT_EQ(size_t(2), source_.Remaining()); +} + +TEST_F(BufferSourceTest, ConsumeBytes) { + EXPECT_FALSE(source_.ConsumeBytes({0x10, 0x00})); + EXPECT_EQ(kLen, source_.Remaining()); + EXPECT_TRUE(source_.ConsumeBytes({0x10, 0x32, 0x54, 0x76})); + EXPECT_EQ(size_t(6), source_.Remaining()); + EXPECT_TRUE(source_.ConsumeBytes({0x98, 0xBA, 0xDC, 0xFE})); + EXPECT_EQ(size_t(2), source_.Remaining()); + + // Goes beyond end by 2 bytes. + EXPECT_FALSE(source_.ConsumeBytes({0x10, 0x00, 0x00, 0x00})); + EXPECT_EQ(size_t(2), source_.Remaining()); +} + +TEST_F(BufferSourceTest, CheckNextValue) { + EXPECT_TRUE(source_.CheckNextValue(uint32_t(0x76543210))); + EXPECT_FALSE(source_.CheckNextValue(uint32_t(0x0))); + EXPECT_TRUE(source_.CheckNextValue(uint64_t(0xFEDCBA9876543210))); + EXPECT_FALSE(source_.CheckNextValue(uint64_t(0x0))); + + source_.Skip(8); + EXPECT_EQ(size_t(2), source_.Remaining()); + + // Goes beyond end by 2 bytes. + EXPECT_FALSE(source_.CheckNextValue(uint32_t(0x1000))); +} + +// Supported by MSVC, g++, and clang++. +// Ensures no gaps in packing. +#pragma pack(push, 1) +struct ValueType { + uint32_t a; + uint16_t b; +}; +#pragma pack(pop) + +TEST_F(BufferSourceTest, GetValueIntegral) { + uint32_t value = 0; + EXPECT_TRUE(source_.GetValue(&value)); + EXPECT_EQ(uint32_t(0x76543210), value); + EXPECT_EQ(size_t(6), source_.Remaining()); + + EXPECT_TRUE(source_.GetValue(&value)); + EXPECT_EQ(uint32_t(0xFEDCBA98), value); + EXPECT_EQ(size_t(2), source_.Remaining()); + + EXPECT_FALSE(source_.GetValue(&value)); + EXPECT_EQ(size_t(2), source_.Remaining()); +} + +TEST_F(BufferSourceTest, GetValueAggregate) { + ValueType value = {}; + EXPECT_TRUE(source_.GetValue(&value)); + EXPECT_EQ(uint32_t(0x76543210), value.a); + EXPECT_EQ(uint32_t(0xBA98), value.b); + EXPECT_EQ(size_t(4), source_.Remaining()); +} + +TEST_F(BufferSourceTest, GetRegion) { + ConstBufferView region; + EXPECT_TRUE(source_.GetRegion(0, ®ion)); + EXPECT_EQ(kLen, source_.Remaining()); + EXPECT_TRUE(region.empty()); + + EXPECT_TRUE(source_.GetRegion(2, ®ion)); + EXPECT_EQ(size_t(2), region.size()); + EXPECT_EQ(vec({0x10, 0x32}), vec(region.begin(), region.end())); + EXPECT_EQ(size_t(8), source_.Remaining()); + + EXPECT_FALSE(source_.GetRegion(kLen, ®ion)); + EXPECT_EQ(size_t(8), source_.Remaining()); + // |region| is left untouched. + EXPECT_EQ(vec({0x10, 0x32}), vec(region.begin(), region.end())); + EXPECT_EQ(size_t(2), region.size()); +} + +TEST_F(BufferSourceTest, GetPointerIntegral) { + const uint32_t* ptr = source_.GetPointer<uint32_t>(); + EXPECT_NE(nullptr, ptr); + EXPECT_EQ(uint32_t(0x76543210), *ptr); + EXPECT_EQ(size_t(6), source_.Remaining()); + + ptr = source_.GetPointer<uint32_t>(); + EXPECT_NE(nullptr, ptr); + EXPECT_EQ(uint32_t(0xFEDCBA98), *ptr); + EXPECT_EQ(size_t(2), source_.Remaining()); + + EXPECT_EQ(nullptr, source_.GetPointer<uint32_t>()); + EXPECT_EQ(size_t(2), source_.Remaining()); +} + +TEST_F(BufferSourceTest, GetPointerAggregate) { + const ValueType* ptr = source_.GetPointer<ValueType>(); + EXPECT_NE(nullptr, ptr); + EXPECT_EQ(uint32_t(0x76543210), ptr->a); + EXPECT_EQ(uint32_t(0xBA98), ptr->b); + EXPECT_EQ(size_t(4), source_.Remaining()); +} + +TEST_F(BufferSourceTest, GetArrayIntegral) { + EXPECT_EQ(nullptr, source_.GetArray<uint32_t>(3)); + + const uint32_t* ptr = source_.GetArray<uint32_t>(2); + EXPECT_NE(nullptr, ptr); + EXPECT_EQ(uint32_t(0x76543210), ptr[0]); + EXPECT_EQ(uint32_t(0xFEDCBA98), ptr[1]); + EXPECT_EQ(size_t(2), source_.Remaining()); +} + +TEST_F(BufferSourceTest, GetArrayAggregate) { + const ValueType* ptr = source_.GetArray<ValueType>(2); + EXPECT_EQ(nullptr, ptr); + + ptr = source_.GetArray<ValueType>(1); + + EXPECT_NE(nullptr, ptr); + EXPECT_EQ(uint32_t(0x76543210), ptr[0].a); + EXPECT_EQ(uint32_t(0xBA98), ptr[0].b); + EXPECT_EQ(size_t(4), source_.Remaining()); +} + +} // namespace zucchini
diff --git a/chrome/installer/zucchini/buffer_view.h b/chrome/installer/zucchini/buffer_view.h index cf13fc48..8ac43ed6 100644 --- a/chrome/installer/zucchini/buffer_view.h +++ b/chrome/installer/zucchini/buffer_view.h
@@ -28,7 +28,7 @@ using difference_type = std::ptrdiff_t; static BufferViewBase FromRange(iterator first, iterator last) { - DCHECK(last >= first); + DCHECK_GE(last, first); BufferViewBase ret; ret.first_ = first; ret.last_ = last; @@ -39,7 +39,7 @@ BufferViewBase(iterator first, size_type size) : first_(first), last_(first_ + size) { - DCHECK(last_ >= first_); + DCHECK_GE(last_, first_); } BufferViewBase(const BufferViewBase&) = default; @@ -57,7 +57,7 @@ // Returns the raw value at specified location |pos|. // If |pos| is not within the range of the buffer, the process is terminated. reference operator[](size_type pos) const { - CHECK(first_ + pos < last_); + CHECK_LT(first_ + pos, last_); return first_[pos]; } @@ -69,10 +69,16 @@ // Modifiers void shrink(size_type new_size) { - DCHECK(first_ + new_size <= last_); + DCHECK_LE(first_ + new_size, last_); last_ = first_ + new_size; } + // Moves the start of the view forward by n bytes. + void remove_prefix(size_type n) { + DCHECK_LE(n, size()); + first_ += n; + } + private: iterator first_ = nullptr; iterator last_ = nullptr;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index cf44149..fc3e011 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3309,7 +3309,6 @@ "../browser/signin/test_signin_client_builder.cc", "../browser/signin/test_signin_client_builder.h", "../browser/ssl/chrome_expect_ct_reporter_unittest.cc", - "../browser/ssl/ignore_errors_cert_verifier_unittest.cc", "../browser/ssl/security_state_tab_helper_unittest.cc", "../browser/ssl/ssl_error_handler_unittest.cc", "../browser/status_icons/status_icon_menu_model_unittest.cc", @@ -3317,6 +3316,8 @@ "../browser/status_icons/status_tray_unittest.cc", "../browser/storage/durable_storage_permission_context_unittest.cc", "../browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc", + "../browser/subresource_filter/subresource_filter_test_harness.cc", + "../browser/subresource_filter/subresource_filter_test_harness.h", "../browser/subresource_filter/subresource_filter_unittest.cc", "../browser/subresource_filter/test_ruleset_publisher.cc", "../browser/subresource_filter/test_ruleset_publisher.h",
diff --git a/chrome/test/data/extensions/api_test/cast_channel/api/test_open_timeout.js b/chrome/test/data/extensions/api_test/cast_channel/api/test_open_timeout.js index f8949ffd..2ec299d 100644 --- a/chrome/test/data/extensions/api_test/cast_channel/api/test_open_timeout.js +++ b/chrome/test/data/extensions/api_test/cast_channel/api/test_open_timeout.js
@@ -18,7 +18,9 @@ chrome.test.assertEq(channel.keepAlive, true); if (channel.readyState == 'closed' && error.errorState == 'ping_timeout') { - chrome.test.sendMessage('timeout_ssl'); + chrome.cast.channel.close(channel, () => { + chrome.test.sendMessage('timeout_ssl'); + }); } }); chrome.test.notifyPass();
diff --git a/chrome/test/data/extensions/api_test/cast_channel/api/test_open_timeout_verified.js b/chrome/test/data/extensions/api_test/cast_channel/api/test_open_timeout_verified.js index 52b6a4d..f667b61c 100644 --- a/chrome/test/data/extensions/api_test/cast_channel/api/test_open_timeout_verified.js +++ b/chrome/test/data/extensions/api_test/cast_channel/api/test_open_timeout_verified.js
@@ -17,7 +17,9 @@ chrome.test.assertEq(channel.keepAlive, true); if (channel.readyState == 'closed' && error.errorState == 'ping_timeout') { - chrome.test.sendMessage('timeout_ssl_verified'); + chrome.cast.channel.close(channel, () => { + chrome.test.sendMessage('timeout_ssl_verified'); + }); } }); chrome.test.notifyPass();
diff --git a/chrome/test/media_router/media_router_integration_ui_browsertest.cc b/chrome/test/media_router/media_router_integration_ui_browsertest.cc index 3cd9737..ecf58df 100644 --- a/chrome/test/media_router/media_router_integration_ui_browsertest.cc +++ b/chrome/test/media_router/media_router_integration_ui_browsertest.cc
@@ -46,9 +46,8 @@ // closing after the route has been created. Then, check that the dialog // remains open. std::string mouse_enter_script = base::StringPrintf( - "domAutomationController.send(" - "window.document.getElementById('media-router-container').dispatchEvent(" - "new Event('mouseenter')))"); + "window.document.getElementById('media-router-container')" + " .dispatchEvent(new Event('mouseenter'));"); ASSERT_TRUE(content::ExecuteScript(dialog_contents, mouse_enter_script)); #endif WaitUntilRouteCreated(); @@ -121,9 +120,8 @@ // the timer started when the route is initially closed times out before the // mouseleave event is dispatched. In that case, the dialog remains open. std::string mouse_leave_script = base::StringPrintf( - "domAutomationController.send(" - "window.document.getElementById('media-router-container').dispatchEvent(" - "new Event('mouseleave')))"); + "window.document.getElementById('media-router-container')" + " .dispatchEvent(new Event('mouseleave'));"); ASSERT_TRUE(content::ExecuteScript(dialog_contents, mouse_leave_script)); #endif LOG(INFO) << "Closing route on UI";
diff --git a/chrome/test/media_router/telemetry/benchmarks/media_router_benchmark.py b/chrome/test/media_router/telemetry/benchmarks/media_router_benchmark.py index 82ae9da..93e270e 100644 --- a/chrome/test/media_router/telemetry/benchmarks/media_router_benchmark.py +++ b/chrome/test/media_router/telemetry/benchmarks/media_router_benchmark.py
@@ -41,7 +41,7 @@ class TraceEventCastBenckmark(_BaseCastBenchmark): """Benchmark for dialog latency from trace event.""" - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): media_router_category = 'media_router' category_filter = chrome_trace_category_filter.ChromeTraceCategoryFilter( media_router_category)
diff --git a/chrome/utility/printing_handler.cc b/chrome/utility/printing_handler.cc index 83366b9a..42b343c4 100644 --- a/chrome/utility/printing_handler.cc +++ b/chrome/utility/printing_handler.cc
@@ -91,18 +91,22 @@ pdf_rendering_settings_ = settings; chrome_pdf::SetPDFUseGDIPrinting(pdf_rendering_settings_.mode == PdfRenderSettings::Mode::GDI_TEXT); - int postscript_level; + int printing_mode; switch (pdf_rendering_settings_.mode) { + case PdfRenderSettings::Mode::TEXTONLY: + printing_mode = chrome_pdf::PrintingMode::kTextOnly; + break; case PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2: - postscript_level = 2; + printing_mode = chrome_pdf::PrintingMode::kPostScript2; break; case PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3: - postscript_level = 3; + printing_mode = chrome_pdf::PrintingMode::kPostScript3; break; default: - postscript_level = 0; // Not using postscript. + // Not using postscript or text only. + printing_mode = chrome_pdf::PrintingMode::kEmf; } - chrome_pdf::SetPDFPostscriptPrintingLevel(postscript_level); + chrome_pdf::SetPDFUsePrintMode(printing_mode); base::File pdf_file = IPC::PlatformFileForTransitToFile(pdf_transit); int page_count = LoadPDF(std::move(pdf_file));
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn index 555611ca..f1a4b9b9 100644 --- a/chromecast/browser/BUILD.gn +++ b/chromecast/browser/BUILD.gn
@@ -174,6 +174,8 @@ "//media/mojo/services", ] } + + configs += [ "//media/audio:platform_config" ] } # This target generates an "overlay" interface spec, allowing the Cast build to
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc index 7846871..bade8515 100644 --- a/chromecast/browser/cast_content_browser_client.cc +++ b/chromecast/browser/cast_content_browser_client.cc
@@ -82,6 +82,10 @@ #include "chromecast/media/cdm/cast_cdm_factory.h" #endif // BUILDFLAG(IS_CAST_USING_CMA_BACKEND) +#if defined(USE_ALSA) +#include "chromecast/media/audio/cast_audio_manager_alsa.h" // nogncheck +#endif // defined(USE_ALSA) + namespace chromecast { namespace shell { @@ -202,11 +206,19 @@ // because we already have a mixer in the audio pipeline downstream of // CastAudioManager. bool use_mixer = true; +#if defined(USE_ALSA) + return base::MakeUnique<media::CastAudioManagerAlsa>( + base::MakeUnique<::media::AudioThreadImpl>(), audio_log_factory, + base::MakeUnique<media::MediaPipelineBackendFactoryImpl>( + media_pipeline_backend_manager()), + GetMediaTaskRunner(), use_mixer); +#else return base::MakeUnique<media::CastAudioManager>( base::MakeUnique<::media::AudioThreadImpl>(), audio_log_factory, base::MakeUnique<media::MediaPipelineBackendFactoryImpl>( media_pipeline_backend_manager()), GetMediaTaskRunner(), use_mixer); +#endif // defined(USE_ALSA) } std::unique_ptr<::media::CdmFactory>
diff --git a/chromecast/media/BUILD.gn b/chromecast/media/BUILD.gn index 896700bdd..6711bd1 100644 --- a/chromecast/media/BUILD.gn +++ b/chromecast/media/BUILD.gn
@@ -3,6 +3,7 @@ # found in the LICENSE file. import("//chromecast/chromecast.gni") +import("//media/media_options.gni") import("//testing/test.gni") group("media") { @@ -24,6 +25,10 @@ "test/run_all_unittests.cc", ] + if (use_alsa && !is_cast_desktop_build) { + sources += [ "audio/cast_audio_manager_alsa_unittest.cc" ] + } + deps = [ ":media", "//base",
diff --git a/chromecast/media/audio/BUILD.gn b/chromecast/media/audio/BUILD.gn index cfead8c..fb07a2b7 100644 --- a/chromecast/media/audio/BUILD.gn +++ b/chromecast/media/audio/BUILD.gn
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//media/media_options.gni") + source_set("audio") { sources = [ "cast_audio_manager.cc", @@ -12,6 +14,13 @@ "cast_audio_output_stream.h", ] + if (use_alsa) { + sources += [ + "cast_audio_manager_alsa.cc", + "cast_audio_manager_alsa.h", + ] + } + deps = [ "//base", "//chromecast/base", @@ -22,4 +31,6 @@ "//media", "//media:shared_memory_support", ] + + configs += [ "//media/audio:platform_config" ] }
diff --git a/chromecast/media/audio/cast_audio_manager.cc b/chromecast/media/audio/cast_audio_manager.cc index 3cd80d6f..7627bfb 100644 --- a/chromecast/media/audio/cast_audio_manager.cc +++ b/chromecast/media/audio/cast_audio_manager.cc
@@ -24,6 +24,10 @@ static const int kMinimumOutputBufferSize = 512; static const int kMaximumOutputBufferSize = 8192; static const int kDefaultOutputBufferSize = 2048; + +// TODO(jyw): Query the preferred value from media backend. +static const int kDefaultInputBufferSize = 1024; + } // namespace namespace chromecast { @@ -65,10 +69,11 @@ ::media::AudioParameters CastAudioManager::GetInputStreamParameters( const std::string& device_id) { LOG(WARNING) << "No support for input audio devices"; - // Need to send a valid AudioParameters object even when it will unused. + // Need to send a valid AudioParameters object even when it will be unused. return ::media::AudioParameters( ::media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - ::media::CHANNEL_LAYOUT_STEREO, 48000, 16, 1024); + ::media::CHANNEL_LAYOUT_STEREO, kDefaultSampleRate, 16, + kDefaultInputBufferSize); } const char* CastAudioManager::GetName() {
diff --git a/chromecast/media/audio/cast_audio_manager_alsa.cc b/chromecast/media/audio/cast_audio_manager_alsa.cc new file mode 100644 index 0000000..fa1bd58 --- /dev/null +++ b/chromecast/media/audio/cast_audio_manager_alsa.cc
@@ -0,0 +1,213 @@ +// 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 "chromecast/media/audio/cast_audio_manager_alsa.h" + +#include <string> + +#include "base/memory/free_deleter.h" +#include "chromecast/media/cma/backend/media_pipeline_backend_factory.h" +#include "media/audio/alsa/alsa_input.h" +#include "media/audio/alsa/alsa_wrapper.h" + +namespace chromecast { +namespace media { + +namespace { +// TODO(alokp): Query the preferred value from media backend. +const int kDefaultSampleRate = 48000; + +// TODO(jyw): Query the preferred value from media backend. +static const int kDefaultInputBufferSize = 1024; + +// Since "default" and "dmix" devices are virtual devices mapped to real +// devices, we remove them from the list to avoiding duplicate counting. +static const char* kInvalidAudioInputDevices[] = { + "default", "dmix", "null", +}; + +} // namespace + +CastAudioManagerAlsa::CastAudioManagerAlsa( + std::unique_ptr<::media::AudioThread> audio_thread, + ::media::AudioLogFactory* audio_log_factory, + std::unique_ptr<MediaPipelineBackendFactory> backend_factory, + scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner, + bool use_mixer) + : CastAudioManager(std::move(audio_thread), + audio_log_factory, + std::move(backend_factory), + backend_task_runner, + use_mixer), + wrapper_(new ::media::AlsaWrapper()) {} + +CastAudioManagerAlsa::~CastAudioManagerAlsa() {} + +bool CastAudioManagerAlsa::HasAudioInputDevices() { + return true; +} + +void CastAudioManagerAlsa::ShowAudioInputSettings() { + LOG(WARNING) << "No support for input audio devices"; +} + +void CastAudioManagerAlsa::GetAudioInputDeviceNames( + ::media::AudioDeviceNames* device_names) { + DCHECK(device_names->empty()); + GetAlsaAudioDevices(kStreamCapture, device_names); +} + +::media::AudioParameters CastAudioManagerAlsa::GetInputStreamParameters( + const std::string& device_id) { + // TODO(jyw): Be smarter about sample rate instead of hardcoding it. + // Need to send a valid AudioParameters object even when it will be unused. + return ::media::AudioParameters( + ::media::AudioParameters::AUDIO_PCM_LOW_LATENCY, + ::media::CHANNEL_LAYOUT_STEREO, kDefaultSampleRate, 16, + kDefaultInputBufferSize); +} + +::media::AudioInputStream* CastAudioManagerAlsa::MakeLinearInputStream( + const ::media::AudioParameters& params, + const std::string& device_id, + const ::media::AudioManager::LogCallback& log_callback) { + DCHECK_EQ(::media::AudioParameters::AUDIO_PCM_LINEAR, params.format()); + return MakeInputStream(params, device_id); +} + +::media::AudioInputStream* CastAudioManagerAlsa::MakeLowLatencyInputStream( + const ::media::AudioParameters& params, + const std::string& device_id, + const ::media::AudioManager::LogCallback& log_callback) { + DCHECK_EQ(::media::AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); + return MakeInputStream(params, device_id); +} + +::media::AudioInputStream* CastAudioManagerAlsa::MakeInputStream( + const ::media::AudioParameters& params, + const std::string& device_id) { + std::string device_name = + (device_id == ::media::AudioDeviceDescription::kDefaultDeviceId) + ? ::media::AlsaPcmInputStream::kAutoSelectDevice + : device_id; + return new ::media::AlsaPcmInputStream(this, device_name, params, + wrapper_.get()); +} + +void CastAudioManagerAlsa::GetAlsaAudioDevices( + StreamType type, + ::media::AudioDeviceNames* device_names) { + // Constants specified by the ALSA API for device hints. + static const char kPcmInterfaceName[] = "pcm"; + int card = -1; + + // Loop through the sound cards to get ALSA device hints. + while (!wrapper_->CardNext(&card) && card >= 0) { + void** hints = NULL; + int error = wrapper_->DeviceNameHint(card, kPcmInterfaceName, &hints); + if (!error) { + GetAlsaDevicesInfo(type, hints, device_names); + + // Destroy the hints now that we're done with it. + wrapper_->DeviceNameFreeHint(hints); + } else { + DLOG(WARNING) << "GetAlsaAudioDevices: unable to get device hints: " + << wrapper_->StrError(error); + } + } +} + +void CastAudioManagerAlsa::GetAlsaDevicesInfo( + StreamType type, + void** hints, + ::media::AudioDeviceNames* device_names) { + static const char kIoHintName[] = "IOID"; + static const char kNameHintName[] = "NAME"; + static const char kDescriptionHintName[] = "DESC"; + + const char* unwanted_device_type = UnwantedDeviceTypeWhenEnumerating(type); + + for (void** hint_iter = hints; *hint_iter != NULL; hint_iter++) { + // Only examine devices of the right type. Valid values are + // "Input", "Output", and NULL which means both input and output. + std::unique_ptr<char, base::FreeDeleter> io( + wrapper_->DeviceNameGetHint(*hint_iter, kIoHintName)); + if (io != NULL && strcmp(unwanted_device_type, io.get()) == 0) + continue; + + // Found a device, prepend the default device since we always want + // it to be on the top of the list for all platforms. And there is + // no duplicate counting here since it is only done if the list is + // still empty. Note, pulse has exclusively opened the default + // device, so we must open the device via the "default" moniker. + if (device_names->empty()) + device_names->push_front(::media::AudioDeviceName::CreateDefault()); + + // Get the unique device name for the device. + std::unique_ptr<char, base::FreeDeleter> unique_device_name( + wrapper_->DeviceNameGetHint(*hint_iter, kNameHintName)); + + // Find out if the device is available. + if (IsAlsaDeviceAvailable(type, unique_device_name.get())) { + // Get the description for the device. + std::unique_ptr<char, base::FreeDeleter> desc( + wrapper_->DeviceNameGetHint(*hint_iter, kDescriptionHintName)); + + ::media::AudioDeviceName name; + name.unique_id = unique_device_name.get(); + if (desc) { + // Use the more user friendly description as name. + // Replace '\n' with '-'. + char* pret = strchr(desc.get(), '\n'); + if (pret) + *pret = '-'; + name.device_name = desc.get(); + } else { + // Virtual devices don't necessarily have descriptions. + // Use their names instead. + name.device_name = unique_device_name.get(); + } + + // Store the device information. + device_names->push_back(name); + } + } +} + +// static +bool CastAudioManagerAlsa::IsAlsaDeviceAvailable(StreamType type, + const char* device_name) { + if (!device_name) + return false; + + // We do prefix matches on the device name to see whether to include + // it or not. + if (type == kStreamCapture) { + // Check if the device is in the list of invalid devices. + for (size_t i = 0; i < arraysize(kInvalidAudioInputDevices); ++i) { + if (strncmp(kInvalidAudioInputDevices[i], device_name, + strlen(kInvalidAudioInputDevices[i])) == 0) + return false; + } + return true; + } else { + DCHECK_EQ(kStreamPlayback, type); + // We prefer the device type that maps straight to hardware but + // goes through software conversion if needed (e.g. incompatible + // sample rate). + // TODO(joi): Should we prefer "hw" instead? + static const char kDeviceTypeDesired[] = "plughw"; + return strncmp(kDeviceTypeDesired, device_name, + arraysize(kDeviceTypeDesired) - 1) == 0; + } +} + +// static +const char* CastAudioManagerAlsa::UnwantedDeviceTypeWhenEnumerating( + StreamType wanted_type) { + return wanted_type == kStreamPlayback ? "Input" : "Output"; +} + +} // namespace media +} // namespace chromecast
diff --git a/chromecast/media/audio/cast_audio_manager_alsa.h b/chromecast/media/audio/cast_audio_manager_alsa.h new file mode 100644 index 0000000..e0d8522e --- /dev/null +++ b/chromecast/media/audio/cast_audio_manager_alsa.h
@@ -0,0 +1,82 @@ +// 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 CHROMECAST_MEDIA_AUDIO_CAST_AUDIO_MANAGER_ALSA_H_ +#define CHROMECAST_MEDIA_AUDIO_CAST_AUDIO_MANAGER_ALSA_H_ + +#include <string> + +#include "base/macros.h" +#include "chromecast/media/audio/cast_audio_manager.h" + +namespace media { +class AlsaWrapper; +} + +namespace chromecast { + +namespace media { + +class CastAudioManagerAlsa : public CastAudioManager { + public: + CastAudioManagerAlsa( + std::unique_ptr<::media::AudioThread> audio_thread, + ::media::AudioLogFactory* audio_log_factory, + std::unique_ptr<MediaPipelineBackendFactory> backend_factory, + scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner, + bool use_mixer); + ~CastAudioManagerAlsa() override; + + // CastAudioManager implementation. + bool HasAudioInputDevices() override; + void ShowAudioInputSettings() override; + void GetAudioInputDeviceNames( + ::media::AudioDeviceNames* device_names) override; + ::media::AudioParameters GetInputStreamParameters( + const std::string& device_id) override; + + private: + enum StreamType { + kStreamPlayback = 0, + kStreamCapture, + }; + + // CastAudioManager implementation. + ::media::AudioInputStream* MakeLinearInputStream( + const ::media::AudioParameters& params, + const std::string& device_id, + const ::media::AudioManager::LogCallback& log_callback) override; + ::media::AudioInputStream* MakeLowLatencyInputStream( + const ::media::AudioParameters& params, + const std::string& device_id, + const ::media::AudioManager::LogCallback& log_callback) override; + + ::media::AudioInputStream* MakeInputStream( + const ::media::AudioParameters& params, + const std::string& device_id); + + // Gets a list of available ALSA devices. + void GetAlsaAudioDevices(StreamType type, + ::media::AudioDeviceNames* device_names); + + // Gets the ALSA devices' names and ids that support streams of the + // given type. + void GetAlsaDevicesInfo(StreamType type, + void** hint, + ::media::AudioDeviceNames* device_names); + + // Checks if the specific ALSA device is available. + static bool IsAlsaDeviceAvailable(StreamType type, const char* device_name); + + static const char* UnwantedDeviceTypeWhenEnumerating(StreamType wanted_type); + + std::unique_ptr<::media::AlsaWrapper> wrapper_; + + DISALLOW_COPY_AND_ASSIGN(CastAudioManagerAlsa); +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_AUDIO_CAST_AUDIO_MANAGER_ALSA_H_
diff --git a/chromecast/media/audio/cast_audio_manager_alsa_unittest.cc b/chromecast/media/audio/cast_audio_manager_alsa_unittest.cc new file mode 100644 index 0000000..f2aca60 --- /dev/null +++ b/chromecast/media/audio/cast_audio_manager_alsa_unittest.cc
@@ -0,0 +1,68 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/media/audio/cast_audio_manager_alsa.h" + +#include "base/memory/ptr_util.h" +#include "base/test/test_message_loop.h" +#include "chromecast/media/cma/test/mock_media_pipeline_backend_factory.h" +#include "media/audio/fake_audio_log_factory.h" +#include "media/audio/test_audio_thread.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::Invoke; +using testing::Return; +using testing::StrictMock; +using testing::_; + +namespace chromecast { +namespace media { +namespace { + +const char kDefaultAlsaDevice[] = "plug:default"; + +const ::media::AudioParameters kDefaultAudioParams( + ::media::AudioParameters::AUDIO_PCM_LOW_LATENCY, + ::media::CHANNEL_LAYOUT_STEREO, + ::media::AudioParameters::kAudioCDSampleRate, + 16, + 256); + +void OnLogMessage(const std::string& message) {} + +class CastAudioManagerAlsaTest : public testing::Test { + public: + CastAudioManagerAlsaTest() : media_thread_("CastMediaThread") { + CHECK(media_thread_.Start()); + + backend_factory_ = new MockMediaPipelineBackendFactory(); + audio_manager_ = base::MakeUnique<CastAudioManagerAlsa>( + base::MakeUnique<::media::TestAudioThread>(), &audio_log_factory_, + base::WrapUnique(backend_factory_), media_thread_.task_runner(), false); + } + + ~CastAudioManagerAlsaTest() override { audio_manager_->Shutdown(); } + + protected: + base::TestMessageLoop message_loop_; + base::Thread media_thread_; + ::media::FakeAudioLogFactory audio_log_factory_; + std::unique_ptr<CastAudioManagerAlsa> audio_manager_; + + // Owned by |audio_manager_| + MockMediaPipelineBackendFactory* backend_factory_; +}; + +TEST_F(CastAudioManagerAlsaTest, MakeAudioInputStream) { + ::media::AudioInputStream* stream = audio_manager_->MakeAudioInputStream( + kDefaultAudioParams, kDefaultAlsaDevice, base::Bind(&OnLogMessage)); + ASSERT_TRUE(stream); + EXPECT_TRUE(stream->Open()); + stream->Close(); +} + +} // namespace +} // namespace media +} // namespace chromecast
diff --git a/components/cast_channel/BUILD.gn b/components/cast_channel/BUILD.gn index 71f791ed..a766875 100644 --- a/components/cast_channel/BUILD.gn +++ b/components/cast_channel/BUILD.gn
@@ -16,8 +16,6 @@ "cast_socket.h", "cast_socket_service.cc", "cast_socket_service.h", - "cast_socket_service_factory.cc", - "cast_socket_service_factory.h", "cast_transport.cc", "cast_transport.h", "keep_alive_delegate.cc",
diff --git a/components/cast_channel/cast_socket.cc b/components/cast_channel/cast_socket.cc index 86adf57..4039ade 100644 --- a/components/cast_channel/cast_socket.cc +++ b/components/cast_channel/cast_socket.cc
@@ -296,6 +296,11 @@ observers_.AddObserver(observer); } +void CastSocketImpl::RemoveObserver(Observer* observer) { + DCHECK(observer); + observers_.RemoveObserver(observer); +} + void CastSocketImpl::OnConnectTimeout() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); // Stop all pending connection setup tasks and report back to the client.
diff --git a/components/cast_channel/cast_socket.h b/components/cast_channel/cast_socket.h index 566993b..31d829ee 100644 --- a/components/cast_channel/cast_socket.h +++ b/components/cast_channel/cast_socket.h
@@ -129,6 +129,9 @@ // Registers |observer| with the socket to receive messages and error events. virtual void AddObserver(Observer* observer) = 0; + + // Unregisters |observer|. + virtual void RemoveObserver(Observer* observer) = 0; }; // This class implements a channel between Chrome and a Cast device using a TCP @@ -181,6 +184,7 @@ bool keep_alive() const override; bool audio_only() const override; void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; protected: // CastTransport::Delegate methods for receiving handshake messages.
diff --git a/components/cast_channel/cast_socket_service.cc b/components/cast_channel/cast_socket_service.cc index 6bdeae3..7932395 100644 --- a/components/cast_channel/cast_socket_service.cc +++ b/components/cast_channel/cast_socket_service.cc
@@ -28,15 +28,17 @@ int CastSocketService::last_channel_id_ = 0; -CastSocketService::CastSocketService() - : RefcountedKeyedService( - BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)), - logger_(new Logger()) { +CastSocketService::CastSocketService() : logger_(new Logger()) { DETACH_FROM_THREAD(thread_checker_); } -CastSocketService::~CastSocketService() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); +// This is a leaky singleton and the dtor won't be called. +CastSocketService::~CastSocketService() = default; + +// static +CastSocketService* CastSocketService::GetInstance() { + return base::Singleton<CastSocketService, + base::LeakySingletonTraits<CastSocketService>>::get(); } scoped_refptr<Logger> CastSocketService::GetLogger() { @@ -128,17 +130,9 @@ observer); } -CastSocket::Observer* CastSocketService::GetObserver(const std::string& id) { - auto it = socket_observer_map_.find(id); - return it == socket_observer_map_.end() ? nullptr : it->second.get(); -} - -CastSocket::Observer* CastSocketService::AddObserver( - const std::string& id, - std::unique_ptr<CastSocket::Observer> observer) { - CastSocket::Observer* observer_ptr = observer.get(); - socket_observer_map_.insert(std::make_pair(id, std::move(observer))); - return observer_ptr; +void CastSocketService::RemoveObserver(CastSocket::Observer* observer) { + for (auto& socket_it : sockets_) + socket_it.second->RemoveObserver(observer); } void CastSocketService::SetSocketForTest( @@ -146,6 +140,4 @@ socket_for_test_ = std::move(socket_for_test); } -void CastSocketService::ShutdownOnUIThread() {} - } // namespace cast_channel
diff --git a/components/cast_channel/cast_socket_service.h b/components/cast_channel/cast_socket_service.h index bb465e9..d7dc8c2 100644 --- a/components/cast_channel/cast_socket_service.h +++ b/components/cast_channel/cast_socket_service.h
@@ -9,9 +9,9 @@ #include <memory> #include "base/macros.h" +#include "base/memory/singleton.h" #include "base/threading/thread_checker.h" #include "components/cast_channel/cast_socket.h" -#include "components/keyed_service/core/refcounted_keyed_service.h" #include "content/public/browser/browser_thread.h" namespace cast_channel { @@ -20,9 +20,9 @@ // to underlying storage. // Instance of this class is created on the UI thread and destroyed on the IO // thread. All public API must be called from the IO thread. -class CastSocketService : public RefcountedKeyedService { +class CastSocketService { public: - CastSocketService(); + static CastSocketService* GetInstance(); // Returns a pointer to the Logger member variable. scoped_refptr<cast_channel::Logger> GetLogger(); @@ -77,24 +77,20 @@ const CastSocket::OnOpenCallback& open_cb, CastSocket::Observer* observer); - // Returns an observer corresponding to |id|. - CastSocket::Observer* GetObserver(const std::string& id); - - // Adds |observer| to |socket_observer_map_| keyed by |id|. Return raw pointer - // of the newly added observer. - CastSocket::Observer* AddObserver( - const std::string& id, - std::unique_ptr<CastSocket::Observer> observer); + // Remove |observer| from each socket in |sockets_| + void RemoveObserver(CastSocket::Observer* observer); // Allow test to inject a mock cast socket. void SetSocketForTest(std::unique_ptr<CastSocket> socket_for_test); - protected: - ~CastSocketService() override; - private: - // RefcountedKeyedService implementation. - void ShutdownOnUIThread() override; + friend class CastSocketServiceTest; + friend class MockCastSocketService; + friend struct base::DefaultSingletonTraits<CastSocketService>; + friend struct std::default_delete<CastSocketService>; + + CastSocketService(); + virtual ~CastSocketService(); // Used to generate CastSocket id. static int last_channel_id_; @@ -102,13 +98,7 @@ // The collection of CastSocket keyed by channel_id. std::map<int, std::unique_ptr<CastSocket>> sockets_; - // Map of CastSocket::Observer keyed by observer id. For extension side - // observers, id is extension_id; For browser side observers, id is a hard - // coded string. - std::map<std::string, std::unique_ptr<CastSocket::Observer>> - socket_observer_map_; - - scoped_refptr<cast_channel::Logger> logger_; + scoped_refptr<Logger> logger_; std::unique_ptr<CastSocket> socket_for_test_;
diff --git a/components/cast_channel/cast_socket_service_factory.cc b/components/cast_channel/cast_socket_service_factory.cc deleted file mode 100644 index bf0757d..0000000 --- a/components/cast_channel/cast_socket_service_factory.cc +++ /dev/null
@@ -1,53 +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 "components/cast_channel/cast_socket_service_factory.h" - -#include "components/cast_channel/cast_socket_service.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" - -namespace cast_channel { - -using content::BrowserContext; - -namespace { - -base::LazyInstance<CastSocketServiceFactory>::DestructorAtExit service_factory = - LAZY_INSTANCE_INITIALIZER; -} // namespace - -// static -scoped_refptr<CastSocketService> CastSocketServiceFactory::GetForBrowserContext( - BrowserContext* context) { - DCHECK(context); - // GetServiceForBrowserContext returns a KeyedService hence the static_cast<> - // to construct a temporary scoped_refptr on the stack for the return value. - return static_cast<CastSocketService*>( - service_factory.Get().GetServiceForBrowserContext(context, true).get()); -} - -// static -CastSocketServiceFactory* CastSocketServiceFactory::GetInstance() { - return &service_factory.Get(); -} - -CastSocketServiceFactory::CastSocketServiceFactory() - : RefcountedBrowserContextKeyedServiceFactory( - "CastSocketService", - BrowserContextDependencyManager::GetInstance()) {} - -CastSocketServiceFactory::~CastSocketServiceFactory() {} - -content::BrowserContext* CastSocketServiceFactory::GetBrowserContextToUse( - content::BrowserContext* context) const { - return context; -} - -scoped_refptr<RefcountedKeyedService> -CastSocketServiceFactory::BuildServiceInstanceFor( - BrowserContext* context) const { - return make_scoped_refptr(new CastSocketService()); -} - -} // namespace cast_channel
diff --git a/components/cast_channel/cast_socket_service_factory.h b/components/cast_channel/cast_socket_service_factory.h deleted file mode 100644 index f3824c7..0000000 --- a/components/cast_channel/cast_socket_service_factory.h +++ /dev/null
@@ -1,46 +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. - -#ifndef COMPONENTS_CAST_CHANNEL_CAST_SOCKET_SERVICE_FACTORY_H_ -#define COMPONENTS_CAST_CHANNEL_CAST_SOCKET_SERVICE_FACTORY_H_ - -#include "base/lazy_instance.h" -#include "base/macros.h" -#include "components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h" - -namespace cast_channel { - -class CastSocketService; - -// TODO(crbug.com/725717): CastSocket created by one profile (browser context) -// could be shared with other profiles. -class CastSocketServiceFactory - : public RefcountedBrowserContextKeyedServiceFactory { - public: - // Caller needs to make sure that it passes in the same |context| instance to - // this function for both normal profile and incognito profile. - static scoped_refptr<CastSocketService> GetForBrowserContext( - content::BrowserContext* context); - - static CastSocketServiceFactory* GetInstance(); - - private: - friend struct base::LazyInstanceTraitsBase<CastSocketServiceFactory>; - - CastSocketServiceFactory(); - ~CastSocketServiceFactory() override; - - // BrowserContextKeyedServiceFactory interface. - content::BrowserContext* GetBrowserContextToUse( - content::BrowserContext* context) const override; - - scoped_refptr<RefcountedKeyedService> BuildServiceInstanceFor( - content::BrowserContext* context) const override; - - DISALLOW_COPY_AND_ASSIGN(CastSocketServiceFactory); -}; - -} // namespace cast_channel - -#endif // COMPONENTS_CAST_CHANNEL_CAST_SOCKET_SERVICE_FACTORY_H_
diff --git a/components/cast_channel/cast_socket_service_unittest.cc b/components/cast_channel/cast_socket_service_unittest.cc index ca4f9307..1c2abbc 100644 --- a/components/cast_channel/cast_socket_service_unittest.cc +++ b/components/cast_channel/cast_socket_service_unittest.cc
@@ -34,7 +34,7 @@ protected: content::TestBrowserThreadBundle thread_bundle_; - scoped_refptr<CastSocketService> cast_socket_service_; + std::unique_ptr<CastSocketService> cast_socket_service_; base::MockCallback<CastSocket::OnOpenCallback> mock_on_open_callback_; MockCastSocketObserver mock_observer_; };
diff --git a/components/cast_channel/cast_test_util.cc b/components/cast_channel/cast_test_util.cc index 36efe11..ab6ce72 100644 --- a/components/cast_channel/cast_test_util.cc +++ b/components/cast_channel/cast_test_util.cc
@@ -29,6 +29,9 @@ MockCastSocketObserver::MockCastSocketObserver() {} MockCastSocketObserver::~MockCastSocketObserver() {} +MockCastSocketService::MockCastSocketService() {} +MockCastSocketService::~MockCastSocketService() {} + MockCastSocket::MockCastSocket() : channel_id_(0), error_state_(ChannelError::NONE),
diff --git a/components/cast_channel/cast_test_util.h b/components/cast_channel/cast_test_util.h index 66bac563..7e37ca4 100644 --- a/components/cast_channel/cast_test_util.h +++ b/components/cast_channel/cast_test_util.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/threading/thread_task_runner_handle.h" #include "components/cast_channel/cast_socket.h" +#include "components/cast_channel/cast_socket_service.h" #include "components/cast_channel/cast_transport.h" #include "components/cast_channel/proto/cast_channel.pb.h" #include "net/base/ip_endpoint.h" @@ -64,6 +65,19 @@ void(const CastSocket& socket, const CastMessage& message)); }; +class MockCastSocketService : public CastSocketService { + public: + MockCastSocketService(); + ~MockCastSocketService() override; + + MOCK_METHOD4(OpenSocket, + int(const net::IPEndPoint& ip_endpoint, + net::NetLog* net_log, + const CastSocket::OnOpenCallback& open_cb, + CastSocket::Observer* observer)); + MOCK_CONST_METHOD1(GetSocket, CastSocket*(int channel_id)); +}; + class MockCastSocket : public CastSocket { public: MockCastSocket(); @@ -73,6 +87,7 @@ MOCK_METHOD1(Close, void(const net::CompletionCallback& callback)); MOCK_CONST_METHOD0(ready_state, ReadyState()); MOCK_METHOD1(AddObserver, void(Observer* observer)); + MOCK_METHOD1(RemoveObserver, void(Observer* observer)); const net::IPEndPoint& ip_endpoint() const override { return ip_endpoint_; } void SetIPEndpoint(const net::IPEndPoint& ip_endpoint) {
diff --git a/components/download/components_unittests.filter b/components/download/components_unittests.filter index 023467a6..f694bb6 100644 --- a/components/download/components_unittests.filter +++ b/components/download/components_unittests.filter
@@ -1,3 +1,4 @@ +AllDownloadItemNotifierTest.* DeviceStatusListenerTest.* DownloadDriverImplTest.* DownloadSchedulerImplTest.*
diff --git a/components/download/content/BUILD.gn b/components/download/content/BUILD.gn index 416f317cf..049294f 100644 --- a/components/download/content/BUILD.gn +++ b/components/download/content/BUILD.gn
@@ -9,5 +9,6 @@ deps = [ "//components/download/content/internal:unit_tests", + "//components/download/content/public:unit_tests", ] }
diff --git a/components/download/content/internal/BUILD.gn b/components/download/content/internal/BUILD.gn index 09d11a2..77025b91 100644 --- a/components/download/content/internal/BUILD.gn +++ b/components/download/content/internal/BUILD.gn
@@ -14,6 +14,7 @@ ] public_deps = [ + "//components/download/content/public", "//components/download/internal", "//components/download/public", ] @@ -36,6 +37,7 @@ deps = [ ":internal", "//base/test:test_support", + "//components/download/content/public", "//content/test:test_support", "//testing/gmock", "//testing/gtest",
diff --git a/components/download/content/internal/download_driver_impl.cc b/components/download/content/internal/download_driver_impl.cc index 2b4641f..74b7c801 100644 --- a/components/download/content/internal/download_driver_impl.cc +++ b/components/download/content/internal/download_driver_impl.cc
@@ -7,6 +7,7 @@ #include <set> #include <vector> +#include "base/memory/ptr_util.h" #include "base/threading/thread_task_runner_handle.h" #include "components/download/internal/driver_entry.h" #include "content/public/browser/download_interrupt_reasons.h" @@ -84,13 +85,7 @@ DCHECK(download_manager_); } -DownloadDriverImpl::~DownloadDriverImpl() { - // TODO(xingliu): We should maintain a list of observing download items, and - // remove the observer here. This can be fixed if we use - // AllDownloadItemNotifier. - if (download_manager_) - download_manager_->RemoveObserver(this); -} +DownloadDriverImpl::~DownloadDriverImpl() = default; void DownloadDriverImpl::Initialize(DownloadDriver::Client* client) { DCHECK(!client_); @@ -103,9 +98,8 @@ return; } - download_manager_->AddObserver(this); - if (download_manager_->IsManagerInitialized()) - client_->OnDriverReady(true); + notifier_ = + base::MakeUnique<AllDownloadItemNotifier>(download_manager_, this); } void DownloadDriverImpl::HardRecover() { @@ -216,7 +210,8 @@ return guids; } -void DownloadDriverImpl::OnDownloadUpdated(content::DownloadItem* item) { +void DownloadDriverImpl::OnDownloadUpdated(content::DownloadManager* manager, + content::DownloadItem* item) { DCHECK(client_); // Blocks the observer call if we asked to remove the download. if (guid_to_remove_.find(item->GetGuid()) != guid_to_remove_.end()) @@ -237,7 +232,8 @@ } } -void DownloadDriverImpl::OnDownloadRemoved(content::DownloadItem* download) { +void DownloadDriverImpl::OnDownloadRemoved(content::DownloadManager* manager, + content::DownloadItem* download) { guid_to_remove_.erase(download->GetGuid()); // |download| is about to be deleted. } @@ -245,7 +241,6 @@ void DownloadDriverImpl::OnDownloadCreated(content::DownloadManager* manager, content::DownloadItem* item) { // Listens to all downloads. - item->AddObserver(this); DCHECK(client_); DriverEntry entry = CreateDriverEntry(item); @@ -255,14 +250,17 @@ client_->OnDownloadCreated(entry); } -void DownloadDriverImpl::OnManagerInitialized() { +void DownloadDriverImpl::OnManagerInitialized( + content::DownloadManager* manager) { + DCHECK_EQ(download_manager_, manager); DCHECK(client_); DCHECK(download_manager_); client_->OnDriverReady(true); } -void DownloadDriverImpl::ManagerGoingDown(content::DownloadManager* manager) { +void DownloadDriverImpl::OnManagerGoingDown(content::DownloadManager* manager) { DCHECK_EQ(download_manager_, manager); + notifier_.reset(); download_manager_ = nullptr; }
diff --git a/components/download/content/internal/download_driver_impl.h b/components/download/content/internal/download_driver_impl.h index 18b7d3e..e6348620 100644 --- a/components/download/content/internal/download_driver_impl.h +++ b/components/download/content/internal/download_driver_impl.h
@@ -5,11 +5,13 @@ #ifndef COMPONENTS_DOWNLOAD_CONTENT_INTERNAL_DOWNLOAD_DRIVER_IMPL_H_ #define COMPONENTS_DOWNLOAD_CONTENT_INTERNAL_DOWNLOAD_DRIVER_IMPL_H_ +#include <memory> #include <set> #include <string> #include "base/files/file_path.h" #include "base/memory/weak_ptr.h" +#include "components/download/content/public/all_download_item_notifier.h" #include "components/download/internal/download_driver.h" #include "components/download/public/download_params.h" #include "content/public/browser/browser_context.h" @@ -23,8 +25,7 @@ // Aggregates and handles all interaction between download service and content // download logic. class DownloadDriverImpl : public DownloadDriver, - public content::DownloadManager::Observer, - public content::DownloadItem::Observer { + public AllDownloadItemNotifier::Observer { public: // Creates a driver entry based on a download item. static DriverEntry CreateDriverEntry(const content::DownloadItem* item); @@ -49,15 +50,15 @@ std::set<std::string> GetActiveDownloads() override; private: - // content::DownloadItem::Observer implementation. - void OnDownloadUpdated(content::DownloadItem* item) override; - void OnDownloadRemoved(content::DownloadItem* download) override; - - // content::DownloadManager::Observer implementation. + // content::AllDownloadItemNotifier::Observer implementation. + void OnManagerInitialized(content::DownloadManager* manager) override; + void OnManagerGoingDown(content::DownloadManager* manager) override; void OnDownloadCreated(content::DownloadManager* manager, content::DownloadItem* item) override; - void OnManagerInitialized() override; - void ManagerGoingDown(content::DownloadManager* manager) override; + void OnDownloadUpdated(content::DownloadManager* manager, + content::DownloadItem* item) override; + void OnDownloadRemoved(content::DownloadManager* manager, + content::DownloadItem* item) override; void OnHardRecoverComplete(bool success); @@ -70,6 +71,9 @@ // The client that receives updates from low level download logic. DownloadDriver::Client* client_; + // Built lazily on initialize and destroyed when/if the manager is torn down. + std::unique_ptr<AllDownloadItemNotifier> notifier_; + // Pending guid set of downloads that will be removed soon. std::set<std::string> guid_to_remove_;
diff --git a/components/download/content/internal/download_driver_impl_unittest.cc b/components/download/content/internal/download_driver_impl_unittest.cc index 32c1a987..f4937e0 100644 --- a/components/download/content/internal/download_driver_impl_unittest.cc +++ b/components/download/content/internal/download_driver_impl_unittest.cc
@@ -11,6 +11,7 @@ #include "base/memory/ptr_util.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "components/download/content/public/all_download_item_notifier.h" #include "content/public/test/fake_download_item.h" #include "content/public/test/mock_download_manager.h" #include "net/http/http_response_headers.h" @@ -85,8 +86,8 @@ driver_->Initialize(&mock_client_); EXPECT_CALL(mock_client_, OnDriverReady(true)); - static_cast<content::DownloadManager::Observer*>(driver_.get()) - ->OnManagerInitialized(); + static_cast<AllDownloadItemNotifier::Observer*>(driver_.get()) + ->OnManagerInitialized(&mock_manager_); } TEST_F(DownloadDriverImplTest, TestHardRecover) { @@ -121,13 +122,13 @@ EXPECT_CALL(mock_client_, OnDownloadUpdated(DriverEntryEqual(entry))) .Times(1) .RetiresOnSaturation(); - static_cast<content::DownloadItem::Observer*>(driver_.get()) - ->OnDownloadUpdated(&fake_item); + static_cast<AllDownloadItemNotifier::Observer*>(driver_.get()) + ->OnDownloadUpdated(&mock_manager_, &fake_item); // Nothing happens for cancelled state. fake_item.SetState(DownloadState::CANCELLED); - static_cast<content::DownloadItem::Observer*>(driver_.get()) - ->OnDownloadUpdated(&fake_item); + static_cast<AllDownloadItemNotifier::Observer*>(driver_.get()) + ->OnDownloadUpdated(&mock_manager_, &fake_item); fake_item.SetReceivedBytes(1024); fake_item.SetState(DownloadState::COMPLETE); @@ -135,8 +136,8 @@ EXPECT_CALL(mock_client_, OnDownloadSucceeded(DriverEntryEqual(entry))) .Times(1) .RetiresOnSaturation(); - static_cast<content::DownloadItem::Observer*>(driver_.get()) - ->OnDownloadUpdated(&fake_item); + static_cast<AllDownloadItemNotifier::Observer*>(driver_.get()) + ->OnDownloadUpdated(&mock_manager_, &fake_item); fake_item.SetState(DownloadState::INTERRUPTED); fake_item.SetLastReason( @@ -146,8 +147,8 @@ FailureType::RECOVERABLE)) .Times(1) .RetiresOnSaturation(); - static_cast<content::DownloadItem::Observer*>(driver_.get()) - ->OnDownloadUpdated(&fake_item); + static_cast<AllDownloadItemNotifier::Observer*>(driver_.get()) + ->OnDownloadUpdated(&mock_manager_, &fake_item); } TEST_F(DownloadDriverImplTest, TestGetActiveDownloadsCall) {
diff --git a/components/download/content/public/BUILD.gn b/components/download/content/public/BUILD.gn new file mode 100644 index 0000000..4cb80da --- /dev/null +++ b/components/download/content/public/BUILD.gn
@@ -0,0 +1,38 @@ +# 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. + +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + +source_set("public") { + sources = [ + "all_download_item_notifier.cc", + "all_download_item_notifier.h", + ] + + public_deps = [ + "//base", + ] + + deps = [ + "//content/public/browser", + ] +} + +source_set("unit_tests") { + testonly = true + + sources = [ + "all_download_item_notifier_unittest.cc", + ] + + deps = [ + ":public", + "//content/test:test_support", + "//testing/gmock", + "//testing/gtest", + ] +}
diff --git a/components/download/content/public/all_download_item_notifier.cc b/components/download/content/public/all_download_item_notifier.cc new file mode 100644 index 0000000..81159f57 --- /dev/null +++ b/components/download/content/public/all_download_item_notifier.cc
@@ -0,0 +1,75 @@ +// 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 "components/download/content/public/all_download_item_notifier.h" + +namespace download { + +AllDownloadItemNotifier::AllDownloadItemNotifier( + content::DownloadManager* manager, + AllDownloadItemNotifier::Observer* observer) + : manager_(manager), observer_(observer) { + DCHECK(observer_); + manager_->AddObserver(this); + content::DownloadManager::DownloadVector items; + manager_->GetAllDownloads(&items); + for (content::DownloadManager::DownloadVector::const_iterator it = + items.begin(); + it != items.end(); ++it) { + (*it)->AddObserver(this); + observing_.insert(*it); + } + + if (manager_->IsManagerInitialized()) + observer_->OnManagerInitialized(manager_); +} + +AllDownloadItemNotifier::~AllDownloadItemNotifier() { + if (manager_) + manager_->RemoveObserver(this); + for (std::set<content::DownloadItem*>::const_iterator it = observing_.begin(); + it != observing_.end(); ++it) { + (*it)->RemoveObserver(this); + } + observing_.clear(); +} + +void AllDownloadItemNotifier::OnManagerInitialized() { + observer_->OnManagerInitialized(manager_); +} + +void AllDownloadItemNotifier::ManagerGoingDown( + content::DownloadManager* manager) { + DCHECK_EQ(manager_, manager); + observer_->OnManagerGoingDown(manager); + manager_->RemoveObserver(this); + manager_ = NULL; +} + +void AllDownloadItemNotifier::OnDownloadCreated( + content::DownloadManager* manager, + content::DownloadItem* item) { + item->AddObserver(this); + observing_.insert(item); + observer_->OnDownloadCreated(manager, item); +} + +void AllDownloadItemNotifier::OnDownloadUpdated(content::DownloadItem* item) { + observer_->OnDownloadUpdated(manager_, item); +} + +void AllDownloadItemNotifier::OnDownloadOpened(content::DownloadItem* item) { + observer_->OnDownloadOpened(manager_, item); +} + +void AllDownloadItemNotifier::OnDownloadRemoved(content::DownloadItem* item) { + observer_->OnDownloadRemoved(manager_, item); +} + +void AllDownloadItemNotifier::OnDownloadDestroyed(content::DownloadItem* item) { + item->RemoveObserver(this); + observing_.erase(item); +} + +} // namespace download
diff --git a/components/download/content/public/all_download_item_notifier.h b/components/download/content/public/all_download_item_notifier.h new file mode 100644 index 0000000..d52cc92 --- /dev/null +++ b/components/download/content/public/all_download_item_notifier.h
@@ -0,0 +1,94 @@ +// 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 COMPONENTS_DOWNLOAD_CONTENT_PUBLIC_ALL_DOWNLOAD_ITEM_NOTIFIER_H_ +#define COMPONENTS_DOWNLOAD_CONTENT_PUBLIC_ALL_DOWNLOAD_ITEM_NOTIFIER_H_ + +#include <set> + +#include "base/macros.h" +#include "content/public/browser/download_item.h" +#include "content/public/browser/download_manager.h" + +// AllDownloadItemNotifier observes ALL the DownloadItems on a given +// DownloadManager. +// Clients should use GetManager() instead of storing their own pointer to the +// manager so that they can be sensitive to managers that have gone down. + +// Example Usage: +// class DownloadSystemConsumer : public AllDownloadItemNotifier::Observer { +// public: +// DownloadSystemConsumer(DownloadManager* original_manager, +// DownloadManager* incognito_manager) +// : original_notifier_(original_manager, this), +// incognito_notifier_(incognito_manager, this) { +// } +// +// virtual void OnDownloadUpdated( +// DownloadManager* manager, DownloadItem* item) { ... } +// +// private: +// AllDownloadItemNotifier original_notifier_; +// AllDownloadItemNotifier incognito_notifier_; +// }; + +namespace download { + +class AllDownloadItemNotifier : public content::DownloadManager::Observer, + public content::DownloadItem::Observer { + public: + // All of the methods take the DownloadManager so that subclasses can observe + // multiple managers at once and easily distinguish which manager a given item + // belongs to. + class Observer { + public: + Observer() {} + virtual ~Observer() {} + + virtual void OnManagerInitialized(content::DownloadManager* manager) {} + virtual void OnManagerGoingDown(content::DownloadManager* manager) {} + virtual void OnDownloadCreated(content::DownloadManager* manager, + content::DownloadItem* item) {} + virtual void OnDownloadUpdated(content::DownloadManager* manager, + content::DownloadItem* item) {} + virtual void OnDownloadOpened(content::DownloadManager* manager, + content::DownloadItem* item) {} + virtual void OnDownloadRemoved(content::DownloadManager* manager, + content::DownloadItem* item) {} + + private: + DISALLOW_COPY_AND_ASSIGN(Observer); + }; + + AllDownloadItemNotifier(content::DownloadManager* manager, + Observer* observer); + + ~AllDownloadItemNotifier() override; + + // Returns NULL if the manager has gone down. + content::DownloadManager* GetManager() const { return manager_; } + + private: + // DownloadManager::Observer + void OnManagerInitialized() override; + void ManagerGoingDown(content::DownloadManager* manager) override; + void OnDownloadCreated(content::DownloadManager* manager, + content::DownloadItem* item) override; + + // DownloadItem::Observer + void OnDownloadUpdated(content::DownloadItem* item) override; + void OnDownloadOpened(content::DownloadItem* item) override; + void OnDownloadRemoved(content::DownloadItem* item) override; + void OnDownloadDestroyed(content::DownloadItem* item) override; + + content::DownloadManager* manager_; + AllDownloadItemNotifier::Observer* observer_; + std::set<content::DownloadItem*> observing_; + + DISALLOW_COPY_AND_ASSIGN(AllDownloadItemNotifier); +}; + +} // namespace download + +#endif // COMPONENTS_DOWNLOAD_CONTENT_PUBLIC_ALL_DOWNLOAD_ITEM_NOTIFIER_H_
diff --git a/content/browser/download/all_download_item_notifier_unittest.cc b/components/download/content/public/all_download_item_notifier_unittest.cc similarity index 96% rename from content/browser/download/all_download_item_notifier_unittest.cc rename to components/download/content/public/all_download_item_notifier_unittest.cc index 81f5f5a..271fed8 100644 --- a/content/browser/download/all_download_item_notifier_unittest.cc +++ b/components/download/content/public/all_download_item_notifier_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/public/browser/all_download_item_notifier.h" +#include "components/download/content/public/all_download_item_notifier.h" #include "base/macros.h" #include "content/public/test/mock_download_item.h" @@ -14,7 +14,7 @@ using testing::SetArgPointee; using testing::_; -namespace content { +namespace download { namespace { class MockNotifierObserver : public AllDownloadItemNotifier::Observer { @@ -111,4 +111,4 @@ ClearNotifier(); } -} // namespace content +} // namespace download
diff --git a/components/net_log/net_export_file_writer.cc b/components/net_log/net_export_file_writer.cc index e20448d..94d64e6 100644 --- a/components/net_log/net_export_file_writer.cc +++ b/components/net_log/net_export_file_writer.cc
@@ -38,11 +38,6 @@ const base::FilePath::CharType kLogRelativePath[] = FILE_PATH_LITERAL("net-export/chrome-net-export-log.json"); -// Old path used by net-export. Used to delete old files. -// TODO(mmenke): Should remove at some point. Added in M46. -const base::FilePath::CharType kOldLogRelativePath[] = - FILE_PATH_LITERAL("chrome-net-export-log.json"); - // Contains file-related initialization tasks for NetExportFileWriter. NetExportFileWriter::DefaultLogPathResults SetUpDefaultLogPath( const NetExportFileWriter::DirectoryGetter& default_log_base_dir_getter) { @@ -54,9 +49,6 @@ if (!default_log_base_dir_getter.Run(&default_base_dir)) return results; - // Delete log file at old location, if present. - base::DeleteFile(default_base_dir.Append(kOldLogRelativePath), false); - results.default_log_path = default_base_dir.Append(kLogRelativePath); if (!base::CreateDirectoryAndGetError(results.default_log_path.DirName(), nullptr))
diff --git a/components/safe_browsing/password_protection/password_protection_service.cc b/components/safe_browsing/password_protection/password_protection_service.cc index 5eaffb20..d4ddb38c 100644 --- a/components/safe_browsing/password_protection/password_protection_service.cc +++ b/components/safe_browsing/password_protection/password_protection_service.cc
@@ -180,11 +180,14 @@ continue; } base::DictionaryValue* verdict_entry = nullptr; - CHECK(verdict_dictionary->GetDictionaryWithoutPathExpansion( - it.key() /* cache_expression */, &verdict_entry)); + verdict_dictionary->GetDictionaryWithoutPathExpansion( + it.key() /* cache_expression */, &verdict_entry); int verdict_received_time; LoginReputationClientResponse verdict; - CHECK(ParseVerdictEntry(verdict_entry, &verdict_received_time, &verdict)); + // Ignore any entry that we cannot parse. These invalid entries will be + // cleaned up during shutdown. + if (!ParseVerdictEntry(verdict_entry, &verdict_received_time, &verdict)) + continue; // Since password protection content settings are keyed by origin, we only // need to compare the path part of the cache_expression and the given url. std::string cache_expression_path = @@ -609,13 +612,13 @@ continue; base::DictionaryValue* verdict_entry = nullptr; - CHECK(verdict_dictionary->GetDictionaryWithoutPathExpansion( - it.key(), &verdict_entry)); + verdict_dictionary->GetDictionaryWithoutPathExpansion(it.key(), + &verdict_entry); int verdict_received_time; LoginReputationClientResponse verdict; - CHECK(ParseVerdictEntry(verdict_entry, &verdict_received_time, &verdict)); - if (IsCacheExpired(verdict_received_time, verdict.cache_duration_sec())) { + if (!ParseVerdictEntry(verdict_entry, &verdict_received_time, &verdict) || + IsCacheExpired(verdict_received_time, verdict.cache_duration_sec())) { // Since DictionaryValue::Iterator cannot be used to modify the // dictionary, we record the keys of expired verdicts in |expired_keys| // and remove them in the next for-loop.
diff --git a/components/safe_browsing/password_protection/password_protection_service_unittest.cc b/components/safe_browsing/password_protection/password_protection_service_unittest.cc index 4ce4a41..dbf0ec6 100644 --- a/components/safe_browsing/password_protection/password_protection_service_unittest.cc +++ b/components/safe_browsing/password_protection/password_protection_service_unittest.cc
@@ -222,6 +222,27 @@ verdict_received_time); } + void CacheInvalidVerdict() { + GURL invalid_hostname("http://invalid.com"); + std::unique_ptr<base::DictionaryValue> verdict_dictionary = + base::DictionaryValue::From(content_setting_map_->GetWebsiteSetting( + invalid_hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, + std::string(), nullptr)); + + if (!verdict_dictionary.get()) + verdict_dictionary = base::MakeUnique<base::DictionaryValue>(); + + std::unique_ptr<base::DictionaryValue> invalid_verdict_entry = + base::MakeUnique<base::DictionaryValue>(); + invalid_verdict_entry->SetString("invalid", "invalid_string"); + + verdict_dictionary->SetWithoutPathExpansion( + "invalid_cache_expression", std::move(invalid_verdict_entry)); + content_setting_map_->SetWebsiteSettingDefaultScope( + invalid_hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, + std::string(), std::move(verdict_dictionary)); + } + size_t GetStoredVerdictCount(LoginReputationClientRequest::TriggerType type) { return password_protection_service_->GetStoredVerdictCount(type); } @@ -815,6 +836,23 @@ &actual_verdict)); } +TEST_F(PasswordProtectionServiceTest, + TestCleanUpExpiredVerdictWithInvalidEntry) { + CacheInvalidVerdict(); + ContentSettingsForOneType password_protection_settings; + content_setting_map_->GetSettingsForOneType( + CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(), + &password_protection_settings); + ASSERT_FALSE(password_protection_settings.empty()); + + password_protection_service_->CleanUpExpiredVerdicts(); + + content_setting_map_->GetSettingsForOneType( + CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(), + &password_protection_settings); + EXPECT_TRUE(password_protection_settings.empty()); +} + TEST_F(PasswordProtectionServiceTest, VerifyPasswordOnFocusRequestProto) { // Set up valid response. net::TestURLFetcher fetcher(0, GURL("http://bar.com"), nullptr);
diff --git a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc index a44ccfae..d8ae42f 100644 --- a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc +++ b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc
@@ -123,6 +123,17 @@ navigation_handle()->Resume(); } +AsyncDocumentSubresourceFilter* +ActivationStateComputingNavigationThrottle::filter() const { + // TODO(csharrison): This should not really be necessary, as we should be + // delaying the navigation until the filter has computed an activation state. + // See crbug.com/736249. In the mean time, have a check here to avoid + // returning a filter in an invalid state. + if (async_filter_ && async_filter_->has_activation_state()) + return async_filter_.get(); + return nullptr; +} + // Ensure the caller cannot take ownership of a subresource filter for cases // when activation IPCs are not sent to the render process. std::unique_ptr<AsyncDocumentSubresourceFilter>
diff --git a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h index 7850de3d..0cee864 100644 --- a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h +++ b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h
@@ -69,16 +69,12 @@ // frame. std::unique_ptr<AsyncDocumentSubresourceFilter> ReleaseFilter(); - AsyncDocumentSubresourceFilter* filter() { return async_filter_.get(); } + AsyncDocumentSubresourceFilter* filter() const; void WillSendActivationToRenderer(); private: void OnActivationStateComputed(ActivationState state); - void set_filter( - std::unique_ptr<AsyncDocumentSubresourceFilter> async_filter) { - async_filter_ = std::move(async_filter); - } ActivationStateComputingNavigationThrottle( content::NavigationHandle* navigation_handle,
diff --git a/components/subresource_filter/content/browser/async_document_subresource_filter.h b/components/subresource_filter/content/browser/async_document_subresource_filter.h index fa607e8..1c3b511 100644 --- a/components/subresource_filter/content/browser/async_document_subresource_filter.h +++ b/components/subresource_filter/content/browser/async_document_subresource_filter.h
@@ -116,6 +116,8 @@ // Must be called after activation state computation is finished. const ActivationState& activation_state() const; + bool has_activation_state() const { return activation_state_.has_value(); } + // The |first_disallowed_load_callback|, if it is non-null, is invoked on the // first ReportDisallowedLoad() call. void set_first_disallowed_load_callback(base::OnceClosure callback) {
diff --git a/components/sync/syncable/directory_backing_store.cc b/components/sync/syncable/directory_backing_store.cc index 677ffc5..17fa7b9 100644 --- a/components/sync/syncable/directory_backing_store.cc +++ b/components/sync/syncable/directory_backing_store.cc
@@ -39,6 +39,61 @@ namespace syncer { namespace syncable { +// Must be in exact same order as fields in entry_kernel.h. +const ColumnSpec g_metas_columns[] = { + ////////////////////////////////////// + // int64s + {"metahandle", "bigint primary key ON CONFLICT FAIL"}, + {"base_version", "bigint default " CHANGES_VERSION_STRING}, + {"server_version", "bigint default 0"}, + // This is the item ID that we store for the embedding application. + {"local_external_id", "bigint default 0"}, + {"transaction_version", "bigint default 0"}, + // These timestamps are kept in the same format as that of the + // protocol (ms since Unix epoch). + {"mtime", "bigint default 0"}, + {"server_mtime", "bigint default 0"}, + {"ctime", "bigint default 0"}, + {"server_ctime", "bigint default 0"}, + ////////////////////////////////////// + // Ids + {"id", "varchar(255) default \"r\""}, + {"parent_id", "varchar(255) default \"r\""}, + {"server_parent_id", "varchar(255) default \"r\""}, + ////////////////////////////////////// + // bits + {"is_unsynced", "bit default 0"}, + {"is_unapplied_update", "bit default 0"}, + {"is_del", "bit default 0"}, + {"is_dir", "bit default 0"}, + {"server_is_dir", "bit default 0"}, + {"server_is_del", "bit default 0"}, + ////////////////////////////////////// + // Strings + {"non_unique_name", "varchar"}, + {"server_non_unique_name", "varchar(255)"}, + {"unique_server_tag", "varchar"}, + {"unique_client_tag", "varchar"}, + {"unique_bookmark_tag", "varchar"}, + ////////////////////////////////////// + // Blobs (serialized protos). + {"specifics", "blob"}, + {"server_specifics", "blob"}, + {"base_server_specifics", "blob"}, + ////////////////////////////////////// + // Blobs (positions). + {"server_unique_position", "blob"}, + {"unique_position", "blob"}, + ////////////////////////////////////// + // AttachmentMetadata is a proto that contains all the metadata associated + // with an entry's attachments. Each entry has only one AttachmentMetadata + // proto. We store a single proto per entry (as opposed to one for each + // attachment) because it simplifies the database schema and implementation + // of + // DirectoryBackingStore. + {"attachment_metadata", "blob"}, + {"server_attachment_metadata", "blob"}}; + // Increment this version whenever updating DB tables. const int32_t kCurrentDBVersion = 91; @@ -205,6 +260,8 @@ string ComposeCreateTableColumnSpecs() { const ColumnSpec* begin = g_metas_columns; const ColumnSpec* end = g_metas_columns + arraysize(g_metas_columns); + // Verify that the array was fully initialized. + DCHECK(g_metas_columns[arraysize(g_metas_columns) - 1].name != nullptr); string query; query.reserve(kUpdateStatementBufferSize); char separator = '(';
diff --git a/components/sync/syncable/entry_kernel.h b/components/sync/syncable/entry_kernel.h index fa57de9..fbaac41 100644 --- a/components/sync/syncable/entry_kernel.h +++ b/components/sync/syncable/entry_kernel.h
@@ -174,6 +174,7 @@ enum { ATTACHMENT_METADATA_FIELDS_COUNT = ATTACHMENT_METADATA_FIELDS_END - ATTACHMENT_METADATA_FIELDS_BEGIN, + // If FIELD_COUNT is changed then g_metas_columns must be updated. FIELD_COUNT = ATTACHMENT_METADATA_FIELDS_END - BEGIN_FIELDS, // Past this point we have temporaries, stored in memory only. BEGIN_TEMPS = ATTACHMENT_METADATA_FIELDS_END,
diff --git a/components/sync/syncable/syncable_columns.h b/components/sync/syncable/syncable_columns.h index 23b1871..4f29f21 100644 --- a/components/sync/syncable/syncable_columns.h +++ b/components/sync/syncable/syncable_columns.h
@@ -17,67 +17,10 @@ const char* spec; }; -// Must be in exact same order as fields in entry_kernel.h. -static const ColumnSpec g_metas_columns[] = { - ////////////////////////////////////// - // int64s - {"metahandle", "bigint primary key ON CONFLICT FAIL"}, - {"base_version", "bigint default " CHANGES_VERSION_STRING}, - {"server_version", "bigint default 0"}, - // This is the item ID that we store for the embedding application. - {"local_external_id", "bigint default 0"}, - {"transaction_version", "bigint default 0"}, - // These timestamps are kept in the same format as that of the - // protocol (ms since Unix epoch). - {"mtime", "bigint default 0"}, - {"server_mtime", "bigint default 0"}, - {"ctime", "bigint default 0"}, - {"server_ctime", "bigint default 0"}, - ////////////////////////////////////// - // Ids - {"id", "varchar(255) default \"r\""}, - {"parent_id", "varchar(255) default \"r\""}, - {"server_parent_id", "varchar(255) default \"r\""}, - ////////////////////////////////////// - // bits - {"is_unsynced", "bit default 0"}, - {"is_unapplied_update", "bit default 0"}, - {"is_del", "bit default 0"}, - {"is_dir", "bit default 0"}, - {"server_is_dir", "bit default 0"}, - {"server_is_del", "bit default 0"}, - ////////////////////////////////////// - // Strings - {"non_unique_name", "varchar"}, - {"server_non_unique_name", "varchar(255)"}, - {"unique_server_tag", "varchar"}, - {"unique_client_tag", "varchar"}, - {"unique_bookmark_tag", "varchar"}, - ////////////////////////////////////// - // Blobs (serialized protos). - {"specifics", "blob"}, - {"server_specifics", "blob"}, - {"base_server_specifics", "blob"}, - ////////////////////////////////////// - // Blobs (positions). - {"server_unique_position", "blob"}, - {"unique_position", "blob"}, - ////////////////////////////////////// - // AttachmentMetadata is a proto that contains all the metadata associated - // with an entry's attachments. Each entry has only one AttachmentMetadata - // proto. We store a single proto per entry (as opposed to one for each - // attachment) because it simplifies the database schema and implementation - // of - // DirectoryBackingStore. - {"attachment_metadata", "blob"}, - {"server_attachment_metadata", "blob"}}; - -// At least enforce that there are equal number of column names and fields. -static_assert(arraysize(g_metas_columns) >= FIELD_COUNT, "missing column name"); -static_assert(arraysize(g_metas_columns) <= FIELD_COUNT, "extra column names"); +extern const ColumnSpec g_metas_columns[FIELD_COUNT]; static inline const char* ColumnName(int field) { - DCHECK(field < BEGIN_TEMPS); + DCHECK(field >= 0 && field < BEGIN_TEMPS); return g_metas_columns[field].name; }
diff --git a/components/viz/client/client_shared_bitmap_manager.cc b/components/viz/client/client_shared_bitmap_manager.cc index 2a35491..8c1d51a 100644 --- a/components/viz/client/client_shared_bitmap_manager.cc +++ b/components/viz/client/client_shared_bitmap_manager.cc
@@ -24,24 +24,27 @@ class ClientSharedBitmap : public SharedBitmap { public: ClientSharedBitmap( - scoped_refptr< - cc::mojom::ThreadSafeSharedBitmapAllocationNotifierAssociatedPtr> + scoped_refptr<cc::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> shared_bitmap_allocation_notifier, base::SharedMemory* shared_memory, - const SharedBitmapId& id) - : SharedBitmap(static_cast<uint8_t*>(shared_memory->memory()), id), + const SharedBitmapId& id, + uint32_t sequence_number) + : SharedBitmap(static_cast<uint8_t*>(shared_memory->memory()), + id, + sequence_number), shared_bitmap_allocation_notifier_( std::move(shared_bitmap_allocation_notifier)) {} ClientSharedBitmap( - scoped_refptr< - cc::mojom::ThreadSafeSharedBitmapAllocationNotifierAssociatedPtr> + scoped_refptr<cc::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> shared_bitmap_allocation_notifier, std::unique_ptr<base::SharedMemory> shared_memory_holder, - const SharedBitmapId& id) + const SharedBitmapId& id, + uint32_t sequence_number) : ClientSharedBitmap(std::move(shared_bitmap_allocation_notifier), shared_memory_holder.get(), - id) { + id, + sequence_number) { shared_memory_holder_ = std::move(shared_memory_holder); } @@ -57,8 +60,7 @@ } private: - scoped_refptr< - cc::mojom::ThreadSafeSharedBitmapAllocationNotifierAssociatedPtr> + scoped_refptr<cc::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> shared_bitmap_allocation_notifier_; std::unique_ptr<base::SharedMemory> shared_memory_holder_; }; @@ -110,8 +112,7 @@ } // namespace ClientSharedBitmapManager::ClientSharedBitmapManager( - scoped_refptr< - cc::mojom::ThreadSafeSharedBitmapAllocationNotifierAssociatedPtr> + scoped_refptr<cc::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> shared_bitmap_allocation_notifier) : shared_bitmap_allocation_notifier_( std::move(shared_bitmap_allocation_notifier)) {} @@ -131,14 +132,15 @@ if (!memory || !memory->Map(memory_size)) CollectMemoryUsageAndDie(size, memory_size); - NotifyAllocatedSharedBitmap(memory.get(), id); + uint32_t sequence_number = NotifyAllocatedSharedBitmap(memory.get(), id); // Close the associated FD to save resources, the previously mapped memory // remains available. memory->Close(); return base::MakeUnique<ClientSharedBitmap>( - shared_bitmap_allocation_notifier_, std::move(memory), id); + shared_bitmap_allocation_notifier_, std::move(memory), id, + sequence_number); } std::unique_ptr<SharedBitmap> ClientSharedBitmapManager::GetSharedBitmapFromId( @@ -151,28 +153,32 @@ std::unique_ptr<SharedBitmap> ClientSharedBitmapManager::GetBitmapForSharedMemory(base::SharedMemory* mem) { SharedBitmapId id = SharedBitmap::GenerateId(); - NotifyAllocatedSharedBitmap(mem, SharedBitmap::GenerateId()); + uint32_t sequence_number = NotifyAllocatedSharedBitmap(mem, id); return base::MakeUnique<ClientSharedBitmap>( - shared_bitmap_allocation_notifier_, mem, id); + shared_bitmap_allocation_notifier_, mem, id, sequence_number); } // Notifies the browser process that a shared bitmap with the given ID was // allocated. Caller keeps ownership of |memory|. -void ClientSharedBitmapManager::NotifyAllocatedSharedBitmap( +uint32_t ClientSharedBitmapManager::NotifyAllocatedSharedBitmap( base::SharedMemory* memory, const SharedBitmapId& id) { base::SharedMemoryHandle handle_to_send = base::SharedMemory::DuplicateHandle(memory->handle()); if (!base::SharedMemory::IsHandleValid(handle_to_send)) { LOG(ERROR) << "Failed to duplicate shared memory handle for bitmap."; - return; + return 0; } mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle( handle_to_send, memory->mapped_size(), true /* read_only */); - (*shared_bitmap_allocation_notifier_) - ->DidAllocateSharedBitmap(std::move(buffer_handle), id); + { + base::AutoLock lock(lock_); + (*shared_bitmap_allocation_notifier_) + ->DidAllocateSharedBitmap(std::move(buffer_handle), id); + return ++last_sequence_number_; + } } } // namespace viz
diff --git a/components/viz/client/client_shared_bitmap_manager.h b/components/viz/client/client_shared_bitmap_manager.h index 095c535..8bb479c 100644 --- a/components/viz/client/client_shared_bitmap_manager.h +++ b/components/viz/client/client_shared_bitmap_manager.h
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/shared_memory.h" +#include "base/synchronization/lock.h" #include "cc/ipc/shared_bitmap_allocation_notifier.mojom.h" #include "components/viz/common/resources/shared_bitmap_manager.h" #include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h" @@ -24,8 +25,7 @@ class ClientSharedBitmapManager : public SharedBitmapManager { public: explicit ClientSharedBitmapManager( - scoped_refptr< - cc::mojom::ThreadSafeSharedBitmapAllocationNotifierAssociatedPtr> + scoped_refptr<cc::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> shared_bitmap_allocation_notifier); ~ClientSharedBitmapManager() override; @@ -40,13 +40,18 @@ base::SharedMemory* mem); private: - void NotifyAllocatedSharedBitmap(base::SharedMemory* memory, - const SharedBitmapId& id); + uint32_t NotifyAllocatedSharedBitmap(base::SharedMemory* memory, + const SharedBitmapId& id); - scoped_refptr< - cc::mojom::ThreadSafeSharedBitmapAllocationNotifierAssociatedPtr> + scoped_refptr<cc::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> shared_bitmap_allocation_notifier_; + base::Lock lock_; + + // Each SharedBitmap allocated by this class is assigned a unique sequence + // number that is incremental. + uint32_t last_sequence_number_ = 0; + DISALLOW_COPY_AND_ASSIGN(ClientSharedBitmapManager); };
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn index a0f0dc8..b074c74 100644 --- a/components/viz/common/BUILD.gn +++ b/components/viz/common/BUILD.gn
@@ -13,6 +13,7 @@ "gl_helper_readback_support.h", "gl_helper_scaling.cc", "gl_helper_scaling.h", + "hit_test/aggregated_hit_test_region.h", "quads/resource_format.h", "quads/shared_bitmap.cc", "quads/shared_bitmap.h", @@ -51,6 +52,7 @@ "//mojo/public/cpp/bindings", "//skia", "//ui/gfx:color_space", + "//ui/gfx:geometry_skia", "//ui/gfx/geometry", ]
diff --git a/components/viz/common/hit_test/DEPS b/components/viz/common/hit_test/DEPS new file mode 100644 index 0000000..b49b863 --- /dev/null +++ b/components/viz/common/hit_test/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + "+ui/gfx/geometry", + "+ui/gfx/transform.h", +] \ No newline at end of file
diff --git a/components/viz/common/hit_test/aggregated_hit_test_region.h b/components/viz/common/hit_test/aggregated_hit_test_region.h new file mode 100644 index 0000000..b90bfb19 --- /dev/null +++ b/components/viz/common/hit_test/aggregated_hit_test_region.h
@@ -0,0 +1,49 @@ +// 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 COMPONENTS_VIZ_COMMON_HIT_TEST_AGGREGATED_HIT_TEST_REGION_H_ +#define COMPONENTS_VIZ_COMMON_HIT_TEST_AGGREGATED_HIT_TEST_REGION_H_ + +#include <stdint.h> + +#include "components/viz/common/surfaces/surface_id.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/transform.h" + +namespace viz { + +// A AggregatedHitTestRegion element with child_count of kEndOfList indicates +// the last element and end of the list. +constexpr int kEndOfList = -1; + +// An array of AggregatedHitTestRegion elements is used to define the +// aggregated hit-test data for the Display. +// +// It is designed to be in shared memory so that the viz service can +// write the hit_test data, and the viz host can read without +// process hops. +struct AggregatedHitTestRegion { + // The FrameSinkId corresponding to this region. Events that match + // are routed to this surface. + FrameSinkId frame_sink_id; + + // Flags to indicate the type of region as defined for + // mojom::HitTestRegion + uint32_t flags; + + // The rectangle that defines the region in parent region's coordinate space. + gfx::Rect rect; + + // The transform applied to the rect in parent region's coordinate space. + gfx::Transform transform; + + // The number of children including their children below this entry. + // If this element is not matched then child_count elements can be skipped + // to move to the next entry. + int child_count; +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_COMMON_HIT_TEST_AGGREGATED_HIT_TEST_REGION_H_
diff --git a/components/viz/common/quads/shared_bitmap.cc b/components/viz/common/quads/shared_bitmap.cc index 9f78ee18..c17074b 100644 --- a/components/viz/common/quads/shared_bitmap.cc +++ b/components/viz/common/quads/shared_bitmap.cc
@@ -16,8 +16,10 @@ namespace viz { -SharedBitmap::SharedBitmap(uint8_t* pixels, const SharedBitmapId& id) - : pixels_(pixels), id_(id) {} +SharedBitmap::SharedBitmap(uint8_t* pixels, + const SharedBitmapId& id, + uint32_t sequence_number) + : pixels_(pixels), id_(id), sequence_number_(sequence_number) {} SharedBitmap::~SharedBitmap() {}
diff --git a/components/viz/common/quads/shared_bitmap.h b/components/viz/common/quads/shared_bitmap.h index 9eb1d977..98e9cca 100644 --- a/components/viz/common/quads/shared_bitmap.h +++ b/components/viz/common/quads/shared_bitmap.h
@@ -32,7 +32,9 @@ class SharedBitmap { public: - SharedBitmap(uint8_t* pixels, const SharedBitmapId& id); + SharedBitmap(uint8_t* pixels, + const SharedBitmapId& id, + uint32_t sequence_number); virtual ~SharedBitmap(); @@ -40,6 +42,10 @@ const SharedBitmapId& id() { return id_; } + // The sequence number that ClientSharedBitmapManager assigned to this + // SharedBitmap. + uint32_t sequence_number() const { return sequence_number_; } + // Returns the shared memory's handle when the back end is base::SharedMemory. // Otherwise, this returns an invalid handle. virtual base::SharedMemoryHandle GetSharedMemoryHandle() const = 0; @@ -60,6 +66,7 @@ private: uint8_t* pixels_; SharedBitmapId id_; + const uint32_t sequence_number_; DISALLOW_COPY_AND_ASSIGN(SharedBitmap); };
diff --git a/components/viz/host/host_frame_sink_manager_unittests.cc b/components/viz/host/host_frame_sink_manager_unittests.cc index c4c6cbe6..6ee7cf7 100644 --- a/components/viz/host/host_frame_sink_manager_unittests.cc +++ b/components/viz/host/host_frame_sink_manager_unittests.cc
@@ -131,10 +131,10 @@ nullptr /* client */, kFrameSinkId1, true /* is_root */, true /* handles_frame_sink_id_invalidation */, false /* needs_sync_points */); - EXPECT_TRUE(FrameSinkIdExists(support->frame_sink_id())); + EXPECT_TRUE(FrameSinkIdExists(kFrameSinkId1)); support.reset(); - EXPECT_FALSE(FrameSinkIdExists(support->frame_sink_id())); + EXPECT_FALSE(FrameSinkIdExists(kFrameSinkId1)); } } // namespace test
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index 81c6075f..1edce15e 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -51,6 +51,8 @@ "frame_sinks/gpu_compositor_frame_sink_delegate.h", "frame_sinks/gpu_root_compositor_frame_sink.cc", "frame_sinks/gpu_root_compositor_frame_sink.h", + "hit_test/hit_test_aggregator.cc", + "hit_test/hit_test_aggregator.h", "viz_service_export.h", ] @@ -77,6 +79,7 @@ "//cc/surfaces", "//gpu/command_buffer/client:gles2_interface", "//gpu/ipc:command_buffer", + "//services/viz/hit_test/public/interfaces", "//ui/gfx", "//ui/gfx/geometry", "//ui/latency", @@ -127,6 +130,7 @@ "frame_sinks/compositor_frame_sink_support_unittest.cc", "frame_sinks/direct_layer_tree_frame_sink_unittest.cc", "frame_sinks/frame_sink_manager_unittest.cc", + "hit_test/hit_test_aggregator_unittest.cc", ] if (!use_aura && !is_mac) { @@ -144,6 +148,12 @@ "//base/test:test_support", "//cc:test_support", "//components/viz/common", + "//gpu/command_buffer/client", + "//gpu/command_buffer/client:gles2_implementation", + "//gpu/ipc:gl_in_process_context", + "//media", + "//services/viz/hit_test/public/interfaces", + "//skia", "//testing/gmock", "//testing/gtest", "//ui/display/types",
diff --git a/components/viz/service/display_embedder/server_shared_bitmap_manager.cc b/components/viz/service/display_embedder/server_shared_bitmap_manager.cc index adb493a..5f1f77b1 100644 --- a/components/viz/service/display_embedder/server_shared_bitmap_manager.cc +++ b/components/viz/service/display_embedder/server_shared_bitmap_manager.cc
@@ -40,7 +40,7 @@ scoped_refptr<BitmapData> bitmap_data, const SharedBitmapId& id, ServerSharedBitmapManager* manager) - : SharedBitmap(pixels, id), + : SharedBitmap(pixels, id, 0 /* sequence_number */), bitmap_data_(bitmap_data), manager_(manager) {}
diff --git a/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc b/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc index 0c667bd..d320a3d 100644 --- a/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc +++ b/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc
@@ -11,31 +11,44 @@ SharedBitmapAllocationNotifierImpl::SharedBitmapAllocationNotifierImpl( ServerSharedBitmapManager* manager) - : manager_(manager), binding_(this) {} + : manager_(manager), binding_(this) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); +} SharedBitmapAllocationNotifierImpl::~SharedBitmapAllocationNotifierImpl() { - for (const auto& id : owned_bitmaps_) - manager_->ChildDeletedSharedBitmap(id); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + ChildDied(); } void SharedBitmapAllocationNotifierImpl::Bind( - cc::mojom::SharedBitmapAllocationNotifierAssociatedRequest request) { + cc::mojom::SharedBitmapAllocationNotifierRequest request) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + if (binding_.is_bound()) { + DLOG(ERROR) << "Only one SharedBitmapAllocationNotifierRequest is " + << "expected from the renderer."; + return; + } binding_.Bind(std::move(request)); } void SharedBitmapAllocationNotifierImpl::DidAllocateSharedBitmap( mojo::ScopedSharedBufferHandle buffer, const SharedBitmapId& id) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); base::SharedMemoryHandle memory_handle; size_t size; MojoResult result = mojo::UnwrapSharedMemoryHandle( std::move(buffer), &memory_handle, &size, NULL); DCHECK_EQ(result, MOJO_RESULT_OK); this->ChildAllocatedSharedBitmap(size, memory_handle, id); + last_sequence_number_++; + for (SharedBitmapAllocationObserver& observer : observers_) + observer.DidAllocateSharedBitmap(last_sequence_number_); } void SharedBitmapAllocationNotifierImpl::DidDeleteSharedBitmap( const SharedBitmapId& id) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); manager_->ChildDeletedSharedBitmap(id); owned_bitmaps_.erase(id); } @@ -44,8 +57,29 @@ size_t buffer_size, const base::SharedMemoryHandle& handle, const SharedBitmapId& id) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (manager_->ChildAllocatedSharedBitmap(buffer_size, handle, id)) owned_bitmaps_.insert(id); } +void SharedBitmapAllocationNotifierImpl::ChildDied() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + for (const auto& id : owned_bitmaps_) + manager_->ChildDeletedSharedBitmap(id); + owned_bitmaps_.clear(); + binding_.Close(); +} + +void SharedBitmapAllocationNotifierImpl::AddObserver( + SharedBitmapAllocationObserver* observer) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + observers_.AddObserver(observer); +} + +void SharedBitmapAllocationNotifierImpl::RemoveObserver( + SharedBitmapAllocationObserver* observer) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + observers_.RemoveObserver(observer); +} + } // namespace viz
diff --git a/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h b/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h index c807b55f..4e9330a 100644 --- a/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h +++ b/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h
@@ -7,14 +7,21 @@ #include <unordered_set> +#include "base/observer_list.h" +#include "base/threading/thread_checker.h" #include "cc/ipc/shared_bitmap_allocation_notifier.mojom.h" #include "components/viz/common/quads/shared_bitmap.h" #include "components/viz/service/viz_service_export.h" -#include "mojo/public/cpp/bindings/associated_binding.h" +#include "mojo/public/cpp/bindings/binding.h" namespace viz { class ServerSharedBitmapManager; +class SharedBitmapAllocationObserver { + public: + virtual void DidAllocateSharedBitmap(uint32_t sequence_number) = 0; +}; + class VIZ_SERVICE_EXPORT SharedBitmapAllocationNotifierImpl : NON_EXPORTED_BASE(public cc::mojom::SharedBitmapAllocationNotifier) { public: @@ -23,7 +30,10 @@ ~SharedBitmapAllocationNotifierImpl() override; - void Bind(cc::mojom::SharedBitmapAllocationNotifierAssociatedRequest request); + void AddObserver(SharedBitmapAllocationObserver* observer); + void RemoveObserver(SharedBitmapAllocationObserver* observer); + + void Bind(cc::mojom::SharedBitmapAllocationNotifierRequest request); // cc::mojom::SharedBitmapAllocationNotifier overrides: void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, @@ -34,10 +44,17 @@ const base::SharedMemoryHandle& handle, const SharedBitmapId& id); + void ChildDied(); + + uint32_t last_sequence_number() const { return last_sequence_number_; } + private: + THREAD_CHECKER(thread_checker_); ServerSharedBitmapManager* const manager_; - mojo::AssociatedBinding<cc::mojom::SharedBitmapAllocationNotifier> binding_; + mojo::Binding<cc::mojom::SharedBitmapAllocationNotifier> binding_; std::unordered_set<SharedBitmapId, SharedBitmapIdHash> owned_bitmaps_; + base::ObserverList<SharedBitmapAllocationObserver> observers_; + uint32_t last_sequence_number_ = 0; DISALLOW_COPY_AND_ASSIGN(SharedBitmapAllocationNotifierImpl); };
diff --git a/components/viz/service/hit_test/DEPS b/components/viz/service/hit_test/DEPS new file mode 100644 index 0000000..e207341 --- /dev/null +++ b/components/viz/service/hit_test/DEPS
@@ -0,0 +1,5 @@ +include_rules = [ + "+components/viz/common", + "+cc/surfaces/surface_observer.h", + "+services/viz/hit_test/public/interfaces", +]
diff --git a/components/viz/service/hit_test/OWNERS b/components/viz/service/hit_test/OWNERS new file mode 100644 index 0000000..3940e4c --- /dev/null +++ b/components/viz/service/hit_test/OWNERS
@@ -0,0 +1 @@ +rjkroege@chromium.org \ No newline at end of file
diff --git a/components/viz/service/hit_test/hit_test_aggregator.cc b/components/viz/service/hit_test/hit_test_aggregator.cc new file mode 100644 index 0000000..fbd4751 --- /dev/null +++ b/components/viz/service/hit_test/hit_test_aggregator.cc
@@ -0,0 +1,212 @@ +// 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 "components/viz/service/hit_test/hit_test_aggregator.h" +#include "components/viz/common/hit_test/aggregated_hit_test_region.h" + +namespace viz { + +namespace { +// TODO(gklassen): Review and select appropriate sizes based on +// telemetry / UMA. +constexpr int kInitialSize = 1024; +constexpr int kIncrementalSize = 1024; +constexpr int kMaxRegionsPerSurface = 1024; +constexpr int kMaxSize = 100 * 1024; + +bool ValidateHitTestRegion(const mojom::HitTestRegionPtr& hit_test_region) { + if (hit_test_region->flags == mojom::kHitTestChildSurface) { + if (!hit_test_region->surface_id.is_valid()) + return false; + } + + return true; +} + +bool ValidateHitTestRegionList( + const mojom::HitTestRegionListPtr& hit_test_region_list) { + if (hit_test_region_list->regions.size() > kMaxRegionsPerSurface) + return false; + for (auto& region : hit_test_region_list->regions) { + if (!ValidateHitTestRegion(region)) + return false; + } + return true; +} + +} // namespace + +HitTestAggregator::HitTestAggregator() : weak_ptr_factory_(this) { + AllocateHitTestRegionArray(); +} + +HitTestAggregator::~HitTestAggregator() = default; + +void HitTestAggregator::SubmitHitTestRegionList( + mojom::HitTestRegionListPtr hit_test_region_list) { + DCHECK(ValidateHitTestRegionList(hit_test_region_list)); + // TODO(gklassen): Runtime validation that hit_test_region_list is valid. + // TODO(gklassen): Inform FrameSink that the hit_test_region_list is invalid. + // TODO(gklassen): FrameSink needs to inform the host of a difficult renderer. + pending_[hit_test_region_list->surface_id] = std::move(hit_test_region_list); +} + +bool HitTestAggregator::OnSurfaceDamaged(const SurfaceId& surface_id, + const cc::BeginFrameAck& ack) { + return false; +} + +void HitTestAggregator::OnSurfaceDiscarded(const SurfaceId& surface_id) { + // Update the region count. + auto active_search = active_.find(surface_id); + if (active_search != active_.end()) { + mojom::HitTestRegionList* old_hit_test_data = active_search->second.get(); + active_region_count_ -= old_hit_test_data->regions.size(); + } + DCHECK_GE(active_region_count_, 0); + + pending_.erase(surface_id); + active_.erase(surface_id); +} + +void HitTestAggregator::OnSurfaceWillDraw(const SurfaceId& surface_id) { + auto pending_search = pending_.find(surface_id); + if (pending_search == pending_.end()) { + // Have already activated pending hit_test_region_list objects for this + // surface. + return; + } + mojom::HitTestRegionList* hit_test_region_list = pending_search->second.get(); + + // Update the region count. + auto active_search = active_.find(surface_id); + if (active_search != active_.end()) { + mojom::HitTestRegionList* old_hit_test_data = active_search->second.get(); + active_region_count_ -= old_hit_test_data->regions.size(); + } + active_region_count_ += hit_test_region_list->regions.size(); + DCHECK_GE(active_region_count_, 0); + + active_[surface_id] = std::move(pending_[surface_id]); + pending_.erase(surface_id); +} + +void HitTestAggregator::AllocateHitTestRegionArray() { + AllocateHitTestRegionArray(kInitialSize); + Swap(); + AllocateHitTestRegionArray(kInitialSize); +} + +void HitTestAggregator::AllocateHitTestRegionArray(int size) { + size_t num_bytes = size * sizeof(AggregatedHitTestRegion); + write_handle_ = mojo::SharedBufferHandle::Create(num_bytes); + write_size_ = size; + write_buffer_ = write_handle_->Map(num_bytes); + + AggregatedHitTestRegion* region = + (AggregatedHitTestRegion*)write_buffer_.get(); + region[0].child_count = kEndOfList; +} + +void HitTestAggregator::PostTaskAggregate(SurfaceId display_surface_id) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&HitTestAggregator::Aggregate, + weak_ptr_factory_.GetWeakPtr(), display_surface_id)); +} + +void HitTestAggregator::Aggregate(SurfaceId display_surface_id) { + // Check to ensure that enough memory has been allocated. + int size = write_size_; + int max_size = active_region_count_ + active_.size() + 1; + if (max_size > kMaxSize) + max_size = kMaxSize; + + if (max_size > size) { + size = (1 + max_size / kIncrementalSize) * kIncrementalSize; + AllocateHitTestRegionArray(size); + } + + AppendRoot(display_surface_id); +} + +void HitTestAggregator::AppendRoot(SurfaceId surface_id) { + auto search = active_.find(surface_id); + DCHECK(search != active_.end()); + + mojom::HitTestRegionList* hit_test_region_list = search->second.get(); + + AggregatedHitTestRegion* regions = + static_cast<AggregatedHitTestRegion*>(write_buffer_.get()); + + regions[0].frame_sink_id = hit_test_region_list->surface_id.frame_sink_id(); + regions[0].flags = hit_test_region_list->flags; + regions[0].rect = hit_test_region_list->bounds; + regions[0].transform = hit_test_region_list->transform; + + int region_index = 1; + for (const auto& region : hit_test_region_list->regions) { + if (region_index >= write_size_ - 1) + break; + region_index = AppendRegion(regions, region_index, region); + } + + DCHECK_GE(region_index, 1); + regions[0].child_count = region_index - 1; + regions[region_index].child_count = kEndOfList; +} + +int HitTestAggregator::AppendRegion(AggregatedHitTestRegion* regions, + int region_index, + const mojom::HitTestRegionPtr& region) { + AggregatedHitTestRegion* element = ®ions[region_index]; + + element->frame_sink_id = region->surface_id.frame_sink_id(); + element->flags = region->flags; + element->rect = region->rect; + element->transform = region->transform; + + int parent_index = region_index++; + if (region_index >= write_size_ - 1) { + element->child_count = 0; + return region_index; + } + + if (region->flags == mojom::kHitTestChildSurface) { + auto search = active_.find(region->surface_id); + if (search == active_.end()) { + // Surface HitTestRegionList not found - it may be late. + // Don't include this region so that it doesn't receive events. + return parent_index; + } + + // Rather than add a node in the tree for this hit_test_region_list element + // we can simplify the tree by merging the flags and transform into + // the kHitTestChildSurface element. + mojom::HitTestRegionList* hit_test_region_list = search->second.get(); + if (!hit_test_region_list->transform.IsIdentity()) + element->transform.PreconcatTransform(hit_test_region_list->transform); + + element->flags |= hit_test_region_list->flags; + + for (const auto& child_region : hit_test_region_list->regions) { + region_index = AppendRegion(regions, region_index, child_region); + if (region_index >= write_size_ - 1) + break; + } + } + DCHECK_GE(region_index - parent_index - 1, 0); + element->child_count = region_index - parent_index - 1; + return region_index; +} + +void HitTestAggregator::Swap() { + using std::swap; + + swap(read_handle_, write_handle_); + swap(read_size_, write_size_); + swap(read_buffer_, write_buffer_); +} + +} // namespace viz
diff --git a/components/viz/service/hit_test/hit_test_aggregator.h b/components/viz/service/hit_test/hit_test_aggregator.h new file mode 100644 index 0000000..2977c37 --- /dev/null +++ b/components/viz/service/hit_test/hit_test_aggregator.h
@@ -0,0 +1,107 @@ +// 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 COMPONENTS_VIZ_SERVICE_HIT_TEST_HIT_TEST_AGGREGATOR_H_ +#define COMPONENTS_VIZ_SERVICE_HIT_TEST_HIT_TEST_AGGREGATOR_H_ + +#include "cc/surfaces/surface_observer.h" +#include "components/viz/common/hit_test/aggregated_hit_test_region.h" +#include "components/viz/common/surfaces/surface_id.h" +#include "components/viz/service/viz_service_export.h" +#include "services/viz/hit_test/public/interfaces/hit_test_region_list.mojom.h" + +namespace viz { + +// HitTestAggregator collects HitTestRegionList objects from surfaces and +// aggregates them into a DisplayHitTesData structue made available in +// shared memory to enable efficient hit testing across processes. +// +// This is intended to be created in the viz or GPU process. For mus+ash this +// will be true after the mus process split. +class VIZ_SERVICE_EXPORT HitTestAggregator : public cc::SurfaceObserver { + public: + HitTestAggregator(); + ~HitTestAggregator(); + + // Called when HitTestRegionList is submitted along with every call + // to SubmitCompositorFrame. This is collected in pending_ until + // surfaces are aggregated and put on the display. + void SubmitHitTestRegionList( + mojom::HitTestRegionListPtr hit_test_region_list); + + // Called after surfaces have been aggregated into the DisplayFrame. + // In this call HitTestRegionList structures received from active surfaces + // are aggregated into the HitTestRegionList structure in + // shared memory used for event targetting. + void Aggregate(SurfaceId display_surface_id); + + // Performs the work of Aggregate by creating a PostTask so that + // the work is not directly on the call. + void PostTaskAggregate(SurfaceId display_surface_id); + + // Called at BeginFrame. Swaps buffers in shared memory. + void Swap(); + + protected: + // cc::SurfaceObserver: + void OnSurfaceCreated(const SurfaceInfo& surface_info) override {} + void OnSurfaceDestroyed(const SurfaceId& surface_id) override {} + bool OnSurfaceDamaged(const SurfaceId& surface_id, + const cc::BeginFrameAck& ack) override; + void OnSurfaceDiscarded(const SurfaceId& surface_id) override; + void OnSurfaceDamageExpected(const SurfaceId& surface_id, + const cc::BeginFrameArgs& args) override {} + + // Called when a surface has been aggregated and added to the + // display frame. HitTestRegionList objects are held but ignored until + // this happens. HitTestRegionList for the surface is copied from |pending_| + // to |active_| in this method. + void OnSurfaceWillDraw(const SurfaceId& surface_id) override; + + // The collection of received HitTestRegionList objects that have not yet + // been added to the DisplayFrame (OnSurfaceWillDraw has not been called). + std::map<SurfaceId, mojom::HitTestRegionListPtr> pending_; + + // The collection of HitTestRegionList objects that have been added to the + // DisplayFrame (OnSurfaceWillDraw has been called). + std::map<SurfaceId, mojom::HitTestRegionListPtr> active_; + + // Keeps track of the number of regions in the active list + // so that we know when we exceed the available length. + int active_region_count_ = 0; + + mojo::ScopedSharedBufferHandle read_handle_; + mojo::ScopedSharedBufferHandle write_handle_; + + // The number of elements allocated. + int read_size_ = 0; + int write_size_ = 0; + + mojo::ScopedSharedBufferMapping read_buffer_; + mojo::ScopedSharedBufferMapping write_buffer_; + + private: + // Allocates memory for the AggregatedHitTestRegion array. + void AllocateHitTestRegionArray(); + void AllocateHitTestRegionArray(int length); + + // Appends the root element to the AggregatedHitTestRegion array. + void AppendRoot(SurfaceId surface_id); + + // Appends a region to the HitTestRegionList structure to recursively + // build the tree. + int AppendRegion(AggregatedHitTestRegion* regions, + int region_index, + const mojom::HitTestRegionPtr& region); + + // Handles the case when this object is deleted after + // the PostTaskAggregation call is scheduled but before invocation. + base::WeakPtrFactory<HitTestAggregator> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(HitTestAggregator); +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_SERVICE_HIT_TEST_HIT_TEST_AGGREGATOR_H_
diff --git a/components/viz/service/hit_test/hit_test_aggregator_unittest.cc b/components/viz/service/hit_test/hit_test_aggregator_unittest.cc new file mode 100644 index 0000000..4a23b4d --- /dev/null +++ b/components/viz/service/hit_test/hit_test_aggregator_unittest.cc
@@ -0,0 +1,1017 @@ +// 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 "components/viz/service/hit_test/hit_test_aggregator.h" + +#include "components/viz/common/surfaces/frame_sink_id.h" +#include "components/viz/common/surfaces/local_surface_id.h" +#include "components/viz/common/surfaces/surface_id.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace viz { + +namespace { + +constexpr FrameSinkId kDisplayFrameSink(2, 0); + +SurfaceId MakeSurfaceId(const FrameSinkId& frame_sink_id, uint32_t local_id) { + return SurfaceId( + frame_sink_id, + LocalSurfaceId(local_id, base::UnguessableToken::Deserialize(0, 1u))); +} + +} // namespace + +class TestHitTestAggregator : public HitTestAggregator { + public: + TestHitTestAggregator() = default; + ~TestHitTestAggregator() = default; + + void CallOnSurfaceWillDraw(SurfaceId surface_id) { + OnSurfaceWillDraw(surface_id); + } + void CallOnSurfaceDiscarded(SurfaceId surface_id) { + OnSurfaceDiscarded(surface_id); + } + + int Count() { + AggregatedHitTestRegion* start = + static_cast<AggregatedHitTestRegion*>(read_buffer_.get()); + AggregatedHitTestRegion* end = start; + while (end->child_count != kEndOfList) + end++; + + int count = end - start; + return count; + } + int GetPendingCount() { return pending_.size(); } + int GetActiveCount() { return active_.size(); } + int GetActiveRegionCount() { return active_region_count_; } + int GetHitTestRegionListSize() { return read_size_; } + AggregatedHitTestRegion* GetRegions() { + return static_cast<AggregatedHitTestRegion*>(read_buffer_.get()); + } + + void Reset() { + AggregatedHitTestRegion* regions = + static_cast<AggregatedHitTestRegion*>(write_buffer_.get()); + regions[0].child_count = kEndOfList; + + regions = static_cast<AggregatedHitTestRegion*>(read_buffer_.get()); + regions[0].child_count = kEndOfList; + + pending_.clear(); + active_.clear(); + } +}; + +class HitTestAggregatorTest : public testing::Test { + public: + HitTestAggregatorTest() = default; + ~HitTestAggregatorTest() override = default; + + // testing::Test: + void SetUp() override {} + void TearDown() override { aggregator_.Reset(); } + + TestHitTestAggregator aggregator_; + + // Creates a hit test data element with 8 children recursively to + // the specified depth. SurfaceIds are generated in sequential order and + // the method returns the next unused id. + int CreateAndSubmitHitTestRegionListWith8Children(int id, int depth) { + SurfaceId surface_id = MakeSurfaceId(kDisplayFrameSink, id); + id++; + + auto hit_test_region_list = mojom::HitTestRegionList::New(); + hit_test_region_list->surface_id = surface_id; + hit_test_region_list->flags = mojom::kHitTestMine; + hit_test_region_list->bounds.SetRect(0, 0, 1024, 768); + + for (int i = 0; i < 8; i++) { + auto hit_test_region = mojom::HitTestRegion::New(); + hit_test_region->rect.SetRect(100, 100, 100, 100); + + if (depth > 0) { + hit_test_region->flags = mojom::kHitTestChildSurface; + hit_test_region->surface_id = MakeSurfaceId(kDisplayFrameSink, id); + id = CreateAndSubmitHitTestRegionListWith8Children(id, depth - 1); + } else { + hit_test_region->flags = mojom::kHitTestMine; + } + hit_test_region_list->regions.push_back(std::move(hit_test_region)); + } + + aggregator_.SubmitHitTestRegionList(std::move(hit_test_region_list)); + return id; + } +}; + +// TODO(gklassen): Add tests for 3D use cases as suggested by and with +// input from rjkroege. + +// One surface. +// +// +----------+ +// | | +// | | +// | | +// +----------+ +// +TEST_F(HitTestAggregatorTest, OneSurface) { + EXPECT_EQ(0, aggregator_.Count()); + + SurfaceId display_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); + + auto hit_test_region_list = mojom::HitTestRegionList::New(); + hit_test_region_list->surface_id = display_surface_id; + hit_test_region_list->flags = mojom::kHitTestMine; + hit_test_region_list->bounds.SetRect(0, 0, 1024, 768); + + aggregator_.SubmitHitTestRegionList(std::move(hit_test_region_list)); + EXPECT_EQ(0, aggregator_.Count()); + + EXPECT_EQ(1, aggregator_.GetPendingCount()); + EXPECT_EQ(0, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(display_surface_id); + + EXPECT_EQ(0, aggregator_.GetPendingCount()); + EXPECT_EQ(1, aggregator_.GetActiveCount()); + + aggregator_.Aggregate(display_surface_id); + aggregator_.Swap(); + + // Expect 1 entry routing all events to the one surface (display root). + EXPECT_EQ(1, aggregator_.Count()); + + AggregatedHitTestRegion* regions = aggregator_.GetRegions(); + + AggregatedHitTestRegion* region = nullptr; + + region = ®ions[0]; + EXPECT_EQ(mojom::kHitTestMine, region->flags); + EXPECT_EQ(display_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(0, 0, 1024, 768), region->rect); + EXPECT_EQ(0, region->child_count); +} + +// One opaque embedder with two regions. +// +// +e-------------+ +// | +r1-+ +r2--+ | +// | | | | | | +// | | | | | | +// | +---+ +----+ | +// +--------------+ +// +TEST_F(HitTestAggregatorTest, OneEmbedderTwoRegions) { + EXPECT_EQ(0, aggregator_.Count()); + + SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); + + auto e_hit_test_data = mojom::HitTestRegionList::New(); + e_hit_test_data->surface_id = e_surface_id; + e_hit_test_data->flags = mojom::kHitTestMine; + e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + + auto e_hit_test_region_r1 = mojom::HitTestRegion::New(); + e_hit_test_region_r1->flags = mojom::kHitTestMine; + e_hit_test_region_r1->rect.SetRect(100, 100, 200, 400); + + auto e_hit_test_region_r2 = mojom::HitTestRegion::New(); + e_hit_test_region_r2->flags = mojom::kHitTestMine; + e_hit_test_region_r2->rect.SetRect(400, 100, 300, 400); + + e_hit_test_data->regions.push_back(std::move(e_hit_test_region_r1)); + e_hit_test_data->regions.push_back(std::move(e_hit_test_region_r2)); + + // Submit mojom::HitTestRegionList. + + EXPECT_EQ(0, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data)); + EXPECT_EQ(1, aggregator_.GetPendingCount()); + + // Add Surfaces to DisplayFrame in unexpected order. + + EXPECT_EQ(0, aggregator_.Count()); + EXPECT_EQ(0, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(e_surface_id); + EXPECT_EQ(1, aggregator_.GetActiveCount()); + + // Aggregate and swap. + + aggregator_.Aggregate(e_surface_id); + EXPECT_EQ(0, aggregator_.Count()); + + aggregator_.Swap(); + EXPECT_EQ(3, aggregator_.Count()); + + AggregatedHitTestRegion* regions = aggregator_.GetRegions(); + + AggregatedHitTestRegion* region = nullptr; + + region = ®ions[0]; + EXPECT_EQ(mojom::kHitTestMine, region->flags); + EXPECT_EQ(e_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(0, 0, 1024, 768), region->rect); + EXPECT_EQ(2, region->child_count); + + region = ®ions[1]; + EXPECT_EQ(mojom::kHitTestMine, region->flags); + EXPECT_EQ(gfx::Rect(100, 100, 200, 400), region->rect); + EXPECT_EQ(0, region->child_count); + + region = ®ions[2]; + EXPECT_EQ(mojom::kHitTestMine, region->flags); + EXPECT_EQ(gfx::Rect(400, 100, 300, 400), region->rect); + EXPECT_EQ(0, region->child_count); +} + +// One embedder with two children. +// +// +e-------------+ +// | +c1-+ +c2--+ | +// | | | | | | +// | | | | | | +// | +---+ +----+ | +// +--------------+ +// + +TEST_F(HitTestAggregatorTest, OneEmbedderTwoChildren) { + EXPECT_EQ(0, aggregator_.Count()); + + SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); + SurfaceId c1_surface_id = MakeSurfaceId(kDisplayFrameSink, 2); + SurfaceId c2_surface_id = MakeSurfaceId(kDisplayFrameSink, 3); + + auto e_hit_test_data = mojom::HitTestRegionList::New(); + e_hit_test_data->surface_id = e_surface_id; + e_hit_test_data->flags = mojom::kHitTestMine; + e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + + auto e_hit_test_region_c1 = mojom::HitTestRegion::New(); + e_hit_test_region_c1->flags = mojom::kHitTestChildSurface; + e_hit_test_region_c1->surface_id = c1_surface_id; + e_hit_test_region_c1->rect.SetRect(100, 100, 200, 300); + + auto e_hit_test_region_c2 = mojom::HitTestRegion::New(); + e_hit_test_region_c2->flags = mojom::kHitTestChildSurface; + e_hit_test_region_c2->surface_id = c2_surface_id; + e_hit_test_region_c2->rect.SetRect(400, 100, 400, 300); + + e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c1)); + e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c2)); + + auto c1_hit_test_data = mojom::HitTestRegionList::New(); + c1_hit_test_data->surface_id = c1_surface_id; + + auto c2_hit_test_data = mojom::HitTestRegionList::New(); + c2_hit_test_data->surface_id = c2_surface_id; + + // Submit in unexpected order. + + EXPECT_EQ(0, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(c1_hit_test_data)); + EXPECT_EQ(1, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data)); + EXPECT_EQ(2, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(c2_hit_test_data)); + EXPECT_EQ(3, aggregator_.GetPendingCount()); + + // Surfaces added to DisplayFrame in unexpected order. + + EXPECT_EQ(0, aggregator_.Count()); + + EXPECT_EQ(0, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(c2_surface_id); + EXPECT_EQ(1, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(c1_surface_id); + EXPECT_EQ(2, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(e_surface_id); + EXPECT_EQ(3, aggregator_.GetActiveCount()); + + // Aggregate and swap. + + aggregator_.Aggregate(e_surface_id); + EXPECT_EQ(0, aggregator_.Count()); + + aggregator_.Swap(); + + EXPECT_EQ(3, aggregator_.Count()); + + AggregatedHitTestRegion* regions = aggregator_.GetRegions(); + + AggregatedHitTestRegion* region = nullptr; + + region = ®ions[0]; + EXPECT_EQ(mojom::kHitTestMine, region->flags); + EXPECT_EQ(e_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(0, 0, 1024, 768), region->rect); + EXPECT_EQ(2, region->child_count); + + region = ®ions[1]; + EXPECT_EQ(mojom::kHitTestChildSurface, region->flags); + EXPECT_EQ(c1_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(100, 100, 200, 300), region->rect); + EXPECT_EQ(0, region->child_count); + + region = ®ions[2]; + EXPECT_EQ(mojom::kHitTestChildSurface, region->flags); + EXPECT_EQ(c2_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(400, 100, 400, 300), region->rect); + EXPECT_EQ(0, region->child_count); +} + +// Occluded child frame (OOPIF). +// +// +e-----------+ +// | +c--+ | +// | | +div-+ | +// | | | | | +// | | +----+ | +// | +---+ | +// +------------+ +// + +TEST_F(HitTestAggregatorTest, OccludedChildFrame) { + EXPECT_EQ(0, aggregator_.Count()); + + SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); + SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2); + + auto e_hit_test_data = mojom::HitTestRegionList::New(); + e_hit_test_data->surface_id = e_surface_id; + e_hit_test_data->flags = mojom::kHitTestMine; + e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + + auto e_hit_test_region_div = mojom::HitTestRegion::New(); + e_hit_test_region_div->flags = mojom::kHitTestMine; + e_hit_test_region_div->surface_id = e_surface_id; + e_hit_test_region_div->rect.SetRect(200, 200, 300, 200); + + auto e_hit_test_region_c = mojom::HitTestRegion::New(); + e_hit_test_region_c->flags = mojom::kHitTestChildSurface; + e_hit_test_region_c->surface_id = c_surface_id; + e_hit_test_region_c->rect.SetRect(100, 100, 200, 500); + + e_hit_test_data->regions.push_back(std::move(e_hit_test_region_div)); + e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c)); + + auto c_hit_test_data = mojom::HitTestRegionList::New(); + c_hit_test_data->surface_id = c_surface_id; + c_hit_test_data->flags = mojom::kHitTestMine; + c_hit_test_data->bounds.SetRect(0, 0, 200, 500); + + // Submit in unexpected order. + + EXPECT_EQ(0, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(c_hit_test_data)); + EXPECT_EQ(1, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data)); + EXPECT_EQ(2, aggregator_.GetPendingCount()); + + // Surfaces added to DisplayFrame in unexpected order. + + EXPECT_EQ(0, aggregator_.Count()); + + EXPECT_EQ(0, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(e_surface_id); + EXPECT_EQ(1, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(c_surface_id); + EXPECT_EQ(2, aggregator_.GetActiveCount()); + + // Aggregate and swap. + + aggregator_.Aggregate(e_surface_id); + EXPECT_EQ(0, aggregator_.Count()); + + aggregator_.Swap(); + + EXPECT_EQ(3, aggregator_.Count()); + + AggregatedHitTestRegion* regions = aggregator_.GetRegions(); + + AggregatedHitTestRegion* region = nullptr; + + region = ®ions[0]; + EXPECT_EQ(mojom::kHitTestMine, region->flags); + EXPECT_EQ(e_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(0, 0, 1024, 768), region->rect); + EXPECT_EQ(2, region->child_count); + + region = ®ions[1]; + EXPECT_EQ(mojom::kHitTestMine, region->flags); + EXPECT_EQ(e_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(200, 200, 300, 200), region->rect); + EXPECT_EQ(0, region->child_count); + + region = ®ions[2]; + EXPECT_EQ(region->flags, mojom::kHitTestChildSurface | mojom::kHitTestMine); + EXPECT_EQ(c_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(100, 100, 200, 500), region->rect); + EXPECT_EQ(0, region->child_count); +} + +// Foreground child frame (OOPIF). +// Same as the previous test except the child is foreground. +// +// +e-----------+ +// | +c--+ | +// | | |div-+ | +// | | | | | +// | | |----+ | +// | +---+ | +// +------------+ +// + +TEST_F(HitTestAggregatorTest, ForegroundChildFrame) { + EXPECT_EQ(0, aggregator_.Count()); + + SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); + SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2); + + auto e_hit_test_data = mojom::HitTestRegionList::New(); + e_hit_test_data->surface_id = e_surface_id; + e_hit_test_data->flags = mojom::kHitTestMine; + e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + + auto e_hit_test_region_div = mojom::HitTestRegion::New(); + e_hit_test_region_div->flags = mojom::kHitTestMine; + e_hit_test_region_div->surface_id = e_surface_id; + e_hit_test_region_div->rect.SetRect(200, 200, 300, 200); + + auto e_hit_test_region_c = mojom::HitTestRegion::New(); + e_hit_test_region_c->flags = mojom::kHitTestChildSurface; + e_hit_test_region_c->surface_id = c_surface_id; + e_hit_test_region_c->rect.SetRect(100, 100, 200, 500); + + e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c)); + e_hit_test_data->regions.push_back(std::move(e_hit_test_region_div)); + + auto c_hit_test_data = mojom::HitTestRegionList::New(); + c_hit_test_data->surface_id = c_surface_id; + c_hit_test_data->flags = mojom::kHitTestMine; + c_hit_test_data->bounds.SetRect(0, 0, 200, 500); + + // Submit in unexpected order. + + EXPECT_EQ(0, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(c_hit_test_data)); + EXPECT_EQ(1, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data)); + EXPECT_EQ(2, aggregator_.GetPendingCount()); + + // Surfaces added to DisplayFrame in unexpected order. + + EXPECT_EQ(0, aggregator_.Count()); + + EXPECT_EQ(0, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(e_surface_id); + EXPECT_EQ(1, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(c_surface_id); + EXPECT_EQ(2, aggregator_.GetActiveCount()); + + // Aggregate and swap. + + aggregator_.Aggregate(e_surface_id); + EXPECT_EQ(0, aggregator_.Count()); + + aggregator_.Swap(); + + EXPECT_EQ(3, aggregator_.Count()); + + AggregatedHitTestRegion* regions = aggregator_.GetRegions(); + + AggregatedHitTestRegion* region = nullptr; + + region = ®ions[0]; + EXPECT_EQ(mojom::kHitTestMine, region->flags); + EXPECT_EQ(e_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(0, 0, 1024, 768), region->rect); + EXPECT_EQ(2, region->child_count); + + region = ®ions[1]; + EXPECT_EQ(region->flags, mojom::kHitTestChildSurface | mojom::kHitTestMine); + EXPECT_EQ(c_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(100, 100, 200, 500), region->rect); + EXPECT_EQ(0, region->child_count); + + region = ®ions[2]; + EXPECT_EQ(mojom::kHitTestMine, region->flags); + EXPECT_EQ(e_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(200, 200, 300, 200), region->rect); + EXPECT_EQ(0, region->child_count); +} + +// One embedder with a clipped child with a tab and transparent background. +// +// +e-------------+ +// | +c---------| Point maps to +// | 1 |+a--+ | ----- ------- +// | || 2 | 3 | 1 e +// | |+b--------| 2 a +// | || | 3 e (transparent area in c) +// | || 4 | 4 b +// +--------------+ +// + +TEST_F(HitTestAggregatorTest, ClippedChildWithTabAndTransparentBackground) { + EXPECT_EQ(0, aggregator_.Count()); + + SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); + SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2); + SurfaceId a_surface_id = MakeSurfaceId(kDisplayFrameSink, 3); + SurfaceId b_surface_id = MakeSurfaceId(kDisplayFrameSink, 4); + + auto e_hit_test_data = mojom::HitTestRegionList::New(); + e_hit_test_data->surface_id = e_surface_id; + e_hit_test_data->flags = mojom::kHitTestMine; + e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + + auto e_hit_test_region_c = mojom::HitTestRegion::New(); + e_hit_test_region_c->flags = mojom::kHitTestChildSurface; + e_hit_test_region_c->surface_id = c_surface_id; + e_hit_test_region_c->rect.SetRect(200, 100, 1600, 800); + e_hit_test_region_c->transform.Translate(200, 100); + + e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c)); + + auto c_hit_test_data = mojom::HitTestRegionList::New(); + c_hit_test_data->surface_id = c_surface_id; + c_hit_test_data->flags = mojom::kHitTestIgnore; + c_hit_test_data->bounds.SetRect(0, 0, 1600, 800); + + auto c_hit_test_region_a = mojom::HitTestRegion::New(); + c_hit_test_region_a->flags = mojom::kHitTestChildSurface; + c_hit_test_region_a->surface_id = a_surface_id; + c_hit_test_region_a->rect.SetRect(0, 0, 200, 100); + + auto c_hit_test_region_b = mojom::HitTestRegion::New(); + c_hit_test_region_b->flags = mojom::kHitTestChildSurface; + c_hit_test_region_b->surface_id = b_surface_id; + c_hit_test_region_b->rect.SetRect(0, 100, 800, 600); + + c_hit_test_data->regions.push_back(std::move(c_hit_test_region_a)); + c_hit_test_data->regions.push_back(std::move(c_hit_test_region_b)); + + auto a_hit_test_data = mojom::HitTestRegionList::New(); + a_hit_test_data->surface_id = a_surface_id; + a_hit_test_data->flags = mojom::kHitTestMine; + a_hit_test_data->bounds.SetRect(0, 0, 200, 100); + + auto b_hit_test_data = mojom::HitTestRegionList::New(); + b_hit_test_data->surface_id = b_surface_id; + b_hit_test_data->flags = mojom::kHitTestMine; + b_hit_test_data->bounds.SetRect(0, 100, 800, 600); + + // Submit in unexpected order. + + EXPECT_EQ(0, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(c_hit_test_data)); + EXPECT_EQ(1, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(a_hit_test_data)); + EXPECT_EQ(2, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(b_hit_test_data)); + EXPECT_EQ(3, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data)); + EXPECT_EQ(4, aggregator_.GetPendingCount()); + + // Surfaces added to DisplayFrame in unexpected order. + + EXPECT_EQ(0, aggregator_.Count()); + + EXPECT_EQ(0, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(c_surface_id); + EXPECT_EQ(1, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(e_surface_id); + EXPECT_EQ(2, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(b_surface_id); + EXPECT_EQ(3, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(a_surface_id); + EXPECT_EQ(4, aggregator_.GetActiveCount()); + + // Aggregate and swap. + + aggregator_.Aggregate(e_surface_id); + EXPECT_EQ(0, aggregator_.Count()); + + aggregator_.Swap(); + + EXPECT_EQ(4, aggregator_.Count()); + + AggregatedHitTestRegion* regions = aggregator_.GetRegions(); + + AggregatedHitTestRegion* region = nullptr; + + region = ®ions[0]; + EXPECT_EQ(mojom::kHitTestMine, region->flags); + EXPECT_EQ(e_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(0, 0, 1024, 768), region->rect); + EXPECT_EQ(3, region->child_count); + + region = ®ions[1]; + EXPECT_EQ(region->flags, mojom::kHitTestChildSurface | mojom::kHitTestIgnore); + EXPECT_EQ(c_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(200, 100, 1600, 800), region->rect); + EXPECT_EQ(2, region->child_count); + + gfx::Point point(300, 300); + region->transform.TransformPointReverse(&point); + EXPECT_TRUE(point == gfx::Point(100, 200)); + + region = ®ions[2]; + EXPECT_EQ(region->flags, mojom::kHitTestChildSurface | mojom::kHitTestMine); + EXPECT_EQ(a_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(0, 0, 200, 100), region->rect); + EXPECT_EQ(0, region->child_count); + + region = ®ions[3]; + EXPECT_EQ(region->flags, mojom::kHitTestChildSurface | mojom::kHitTestMine); + EXPECT_EQ(b_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(0, 100, 800, 600), region->rect); + EXPECT_EQ(0, region->child_count); +} + +// Three children deep. +// +// +e------------+ +// | +c1-------+ | +// | | +c2---+ | | +// | | | +c3-| | | +// | | | | | | | +// | | | +---| | | +// | | +-----+ | | +// | +---------+ | +// +-------------+ +// + +TEST_F(HitTestAggregatorTest, ThreeChildrenDeep) { + EXPECT_EQ(0, aggregator_.Count()); + + SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); + SurfaceId c1_surface_id = MakeSurfaceId(kDisplayFrameSink, 2); + SurfaceId c2_surface_id = MakeSurfaceId(kDisplayFrameSink, 3); + SurfaceId c3_surface_id = MakeSurfaceId(kDisplayFrameSink, 4); + + auto e_hit_test_data = mojom::HitTestRegionList::New(); + e_hit_test_data->surface_id = e_surface_id; + e_hit_test_data->flags = mojom::kHitTestMine; + e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + + auto e_hit_test_region_c1 = mojom::HitTestRegion::New(); + e_hit_test_region_c1->flags = mojom::kHitTestChildSurface; + e_hit_test_region_c1->surface_id = c1_surface_id; + e_hit_test_region_c1->rect.SetRect(100, 100, 700, 700); + + e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c1)); + + auto c1_hit_test_data = mojom::HitTestRegionList::New(); + c1_hit_test_data->surface_id = c1_surface_id; + c1_hit_test_data->flags = mojom::kHitTestMine; + c1_hit_test_data->bounds.SetRect(0, 0, 600, 600); + + auto c1_hit_test_region_c2 = mojom::HitTestRegion::New(); + c1_hit_test_region_c2->flags = mojom::kHitTestChildSurface; + c1_hit_test_region_c2->surface_id = c2_surface_id; + c1_hit_test_region_c2->rect.SetRect(100, 100, 500, 500); + + c1_hit_test_data->regions.push_back(std::move(c1_hit_test_region_c2)); + + auto c2_hit_test_data = mojom::HitTestRegionList::New(); + c2_hit_test_data->surface_id = c2_surface_id; + c2_hit_test_data->flags = mojom::kHitTestMine; + c2_hit_test_data->bounds.SetRect(0, 0, 400, 400); + + auto c2_hit_test_region_c3 = mojom::HitTestRegion::New(); + c2_hit_test_region_c3->flags = mojom::kHitTestChildSurface; + c2_hit_test_region_c3->surface_id = c3_surface_id; + c2_hit_test_region_c3->rect.SetRect(100, 100, 300, 300); + + c2_hit_test_data->regions.push_back(std::move(c2_hit_test_region_c3)); + + auto c3_hit_test_data = mojom::HitTestRegionList::New(); + c3_hit_test_data->surface_id = c3_surface_id; + c3_hit_test_data->flags = mojom::kHitTestMine; + c3_hit_test_data->bounds.SetRect(0, 0, 200, 200); + + // Submit in unexpected order. + + EXPECT_EQ(0, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(c1_hit_test_data)); + EXPECT_EQ(1, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(c3_hit_test_data)); + EXPECT_EQ(2, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data)); + EXPECT_EQ(3, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(c2_hit_test_data)); + EXPECT_EQ(4, aggregator_.GetPendingCount()); + + // Surfaces added to DisplayFrame in unexpected order. + + EXPECT_EQ(0, aggregator_.Count()); + + EXPECT_EQ(0, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(c2_surface_id); + EXPECT_EQ(1, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(c1_surface_id); + EXPECT_EQ(2, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(e_surface_id); + EXPECT_EQ(3, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(c3_surface_id); + EXPECT_EQ(4, aggregator_.GetActiveCount()); + + // Aggregate and swap. + + aggregator_.Aggregate(e_surface_id); + EXPECT_EQ(0, aggregator_.Count()); + + aggregator_.Swap(); + + EXPECT_EQ(4, aggregator_.Count()); + + AggregatedHitTestRegion* regions = aggregator_.GetRegions(); + + AggregatedHitTestRegion* region = nullptr; + + region = ®ions[0]; + EXPECT_EQ(mojom::kHitTestMine, region->flags); + EXPECT_EQ(e_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(0, 0, 1024, 768), region->rect); + EXPECT_EQ(3, region->child_count); + + region = ®ions[1]; + EXPECT_EQ(region->flags, mojom::kHitTestChildSurface | mojom::kHitTestMine); + EXPECT_EQ(c1_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(100, 100, 700, 700), region->rect); + EXPECT_EQ(2, region->child_count); + + region = ®ions[2]; + EXPECT_EQ(region->flags, mojom::kHitTestChildSurface | mojom::kHitTestMine); + EXPECT_EQ(c2_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(100, 100, 500, 500), region->rect); + EXPECT_EQ(1, region->child_count); + + region = ®ions[3]; + EXPECT_EQ(region->flags, mojom::kHitTestChildSurface | mojom::kHitTestMine); + EXPECT_EQ(c3_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(100, 100, 300, 300), region->rect); + EXPECT_EQ(0, region->child_count); +} + +// Missing / late child. +// +// +e-----------+ +// | +c--+ | +// | | |div-+ | +// | | | | | +// | | |----+ | +// | +---+ | +// +------------+ +// + +TEST_F(HitTestAggregatorTest, MissingChildFrame) { + EXPECT_EQ(0, aggregator_.Count()); + + SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); + SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2); + + auto e_hit_test_data = mojom::HitTestRegionList::New(); + e_hit_test_data->surface_id = e_surface_id; + e_hit_test_data->flags = mojom::kHitTestMine; + e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + + auto e_hit_test_region_div = mojom::HitTestRegion::New(); + e_hit_test_region_div->flags = mojom::kHitTestMine; + e_hit_test_region_div->surface_id = e_surface_id; + e_hit_test_region_div->rect.SetRect(200, 200, 300, 200); + + auto e_hit_test_region_c = mojom::HitTestRegion::New(); + e_hit_test_region_c->flags = mojom::kHitTestChildSurface; + e_hit_test_region_c->surface_id = c_surface_id; + e_hit_test_region_c->rect.SetRect(100, 100, 200, 500); + + e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c)); + e_hit_test_data->regions.push_back(std::move(e_hit_test_region_div)); + + auto c_hit_test_data = mojom::HitTestRegionList::New(); + c_hit_test_data->surface_id = c_surface_id; + c_hit_test_data->flags = mojom::kHitTestMine; + c_hit_test_data->bounds.SetRect(0, 0, 200, 500); + + // Submit in unexpected order, but not the child. + + EXPECT_EQ(0, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data)); + EXPECT_EQ(1, aggregator_.GetPendingCount()); + + // Surfaces added to DisplayFrame in unexpected order. + + EXPECT_EQ(0, aggregator_.Count()); + + EXPECT_EQ(0, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(e_surface_id); + EXPECT_EQ(1, aggregator_.GetActiveCount()); + + // Aggregate and swap. + + aggregator_.Aggregate(e_surface_id); + EXPECT_EQ(0, aggregator_.Count()); + + aggregator_.Swap(); + + EXPECT_EQ(2, aggregator_.Count()); + + AggregatedHitTestRegion* regions = aggregator_.GetRegions(); + + AggregatedHitTestRegion* region = nullptr; + + region = ®ions[0]; + EXPECT_EQ(mojom::kHitTestMine, region->flags); + EXPECT_EQ(e_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(0, 0, 1024, 768), region->rect); + EXPECT_EQ(1, region->child_count); + + // Child would exist here but it was not included in the Display Frame. + + region = ®ions[1]; + EXPECT_EQ(mojom::kHitTestMine, region->flags); + EXPECT_EQ(e_surface_id.frame_sink_id(), region->frame_sink_id); + EXPECT_EQ(gfx::Rect(200, 200, 300, 200), region->rect); + EXPECT_EQ(0, region->child_count); +} + +// Exceed limits to ensure that bounds and resize work. +// +// A tree of embedders each with 8 children and 4 levels deep = 4096 regions. +// This will exceed initial allocation and force a resize. +// +// +e--------------------------------------------------------+ +// | +c1----------++c2----------++c3----------++c4----------+| +// | | +c1--------|| +c1--------|| +c1--------|| +c1--------|| +// | | | +c1-++c2-|| | +c1-++c2-|| | +c1-++c2-|| | +c1-++c2-|| +// | | | | || || | | || || | | || || | | || || +// | | | +---++---|| | +---++---|| | +---++---|| | +---++---|| +// | +------------++------------++------------++------------+| +// | +c5----------++c6----------++c7----------++c8----------+| +// | | +c1--------|| +c1--------|| +c1--------|| +c1--------|| +// | | | +c1-++c2-|| | +c1-++c2-|| | +c1-++c2-|| | +c1-++c2-|| +// | | | | || || | | || || | | || || | | || || +// | | | +---++---|| | +---++---|| | +---++---|| | +---++---|| +// | +------------++------------++------------++------------+| +// +---------------------------------------------------------+ +// + +TEST_F(HitTestAggregatorTest, ExceedLimits) { + EXPECT_EQ(0, aggregator_.Count()); + + EXPECT_LT(aggregator_.GetHitTestRegionListSize(), 4096); + + SurfaceId display_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); + + int next_surface_id = CreateAndSubmitHitTestRegionListWith8Children(1, 3); + int surface_count = next_surface_id - 1; + + EXPECT_EQ(surface_count, aggregator_.GetPendingCount()); + + // Mark Surfaces as added to DisplayFrame in unexpected order. + + EXPECT_EQ(0, aggregator_.Count()); + EXPECT_EQ(0, aggregator_.GetActiveCount()); + + for (int i = 1; i <= surface_count; i++) { + SurfaceId surface_id = MakeSurfaceId(kDisplayFrameSink, i); + aggregator_.CallOnSurfaceWillDraw(surface_id); + } + + EXPECT_EQ(surface_count, aggregator_.GetActiveCount()); + + // Aggregate and swap. + aggregator_.Aggregate(display_surface_id); + EXPECT_EQ(0, aggregator_.Count()); + + aggregator_.Swap(); + + // Expect 4680 regions: + // 8 children 4 levels deep 8*8*8*8 is 4096 + // 1 region for each embedder/surface + 584 + // 1 root + 1 + // ----- + // 4681. + EXPECT_EQ(4681, aggregator_.Count()); + + EXPECT_GE(aggregator_.GetHitTestRegionListSize(), 4681); +} + +TEST_F(HitTestAggregatorTest, ActiveRegionCount) { + EXPECT_EQ(0, aggregator_.GetActiveRegionCount()); + + SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); + SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2); + + auto e_hit_test_data = mojom::HitTestRegionList::New(); + e_hit_test_data->surface_id = e_surface_id; + e_hit_test_data->flags = mojom::kHitTestMine; + e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + + auto e_hit_test_region_div = mojom::HitTestRegion::New(); + e_hit_test_region_div->flags = mojom::kHitTestMine; + e_hit_test_region_div->surface_id = e_surface_id; + e_hit_test_region_div->rect.SetRect(200, 200, 300, 200); + + auto e_hit_test_region_c = mojom::HitTestRegion::New(); + e_hit_test_region_c->flags = mojom::kHitTestChildSurface; + e_hit_test_region_c->surface_id = c_surface_id; + e_hit_test_region_c->rect.SetRect(100, 100, 200, 500); + + e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c)); + e_hit_test_data->regions.push_back(std::move(e_hit_test_region_div)); + + auto c_hit_test_data = mojom::HitTestRegionList::New(); + c_hit_test_data->surface_id = c_surface_id; + c_hit_test_data->flags = mojom::kHitTestMine; + c_hit_test_data->bounds.SetRect(0, 0, 200, 500); + + EXPECT_EQ(0, aggregator_.GetActiveRegionCount()); + + // Submit in unexpected order. + + EXPECT_EQ(0, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(c_hit_test_data)); + EXPECT_EQ(1, aggregator_.GetPendingCount()); + + aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data)); + EXPECT_EQ(2, aggregator_.GetPendingCount()); + + EXPECT_EQ(0, aggregator_.GetActiveRegionCount()); + + // Surfaces added to DisplayFrame in unexpected order. + + EXPECT_EQ(0, aggregator_.Count()); + EXPECT_EQ(0, aggregator_.GetActiveCount()); + + aggregator_.CallOnSurfaceWillDraw(e_surface_id); + EXPECT_EQ(1, aggregator_.GetActiveCount()); + EXPECT_EQ(2, aggregator_.GetActiveRegionCount()); + + aggregator_.CallOnSurfaceWillDraw(c_surface_id); + EXPECT_EQ(2, aggregator_.GetActiveCount()); + EXPECT_EQ(2, aggregator_.GetActiveRegionCount()); + + // Aggregate and swap. + + aggregator_.Aggregate(e_surface_id); + EXPECT_EQ(0, aggregator_.Count()); + EXPECT_EQ(2, aggregator_.GetActiveRegionCount()); + + aggregator_.Swap(); + + EXPECT_EQ(3, aggregator_.Count()); + EXPECT_EQ(2, aggregator_.GetActiveRegionCount()); + + // Discard Surface and ensure active count goes down. + + aggregator_.CallOnSurfaceDiscarded(c_surface_id); + EXPECT_EQ(2, aggregator_.GetActiveRegionCount()); + + aggregator_.CallOnSurfaceDiscarded(e_surface_id); + EXPECT_EQ(0, aggregator_.GetActiveRegionCount()); +} + +} // namespace viz
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 152d6e4..ec3b745 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -113,7 +113,9 @@ "//services/data_decoder/public/cpp", "//services/data_decoder/public/interfaces", "//services/device:lib", + "//services/device/public/cpp:device_features", "//services/device/public/interfaces", + "//services/device/public/interfaces:generic_sensor", "//services/file:lib", "//services/file/public/interfaces", "//services/metrics/public/cpp:metrics_cpp", @@ -611,7 +613,6 @@ "dom_storage/session_storage_database_adapter.h", "dom_storage/session_storage_namespace_impl.cc", "dom_storage/session_storage_namespace_impl.h", - "download/all_download_item_notifier.cc", "download/base_file.cc", "download/base_file.h", "download/base_file_posix.cc", @@ -1465,6 +1466,7 @@ "speech/speech_recognizer.h", "speech/speech_recognizer_impl_android.cc", "speech/speech_recognizer_impl_android.h", + "ssl/ignore_errors_cert_verifier.cc", "ssl/ssl_client_auth_handler.cc", "ssl/ssl_client_auth_handler.h", "ssl/ssl_error_handler.cc",
diff --git a/content/browser/download/all_download_item_notifier.cc b/content/browser/download/all_download_item_notifier.cc deleted file mode 100644 index 9385e4f..0000000 --- a/content/browser/download/all_download_item_notifier.cc +++ /dev/null
@@ -1,64 +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 "content/public/browser/all_download_item_notifier.h" - -namespace content { - -AllDownloadItemNotifier::AllDownloadItemNotifier( - DownloadManager* manager, - AllDownloadItemNotifier::Observer* observer) - : manager_(manager), observer_(observer) { - DCHECK(observer_); - manager_->AddObserver(this); - DownloadManager::DownloadVector items; - manager_->GetAllDownloads(&items); - for (DownloadManager::DownloadVector::const_iterator it = items.begin(); - it != items.end(); ++it) { - (*it)->AddObserver(this); - observing_.insert(*it); - } -} - -AllDownloadItemNotifier::~AllDownloadItemNotifier() { - if (manager_) - manager_->RemoveObserver(this); - for (std::set<DownloadItem*>::const_iterator it = observing_.begin(); - it != observing_.end(); ++it) { - (*it)->RemoveObserver(this); - } - observing_.clear(); -} - -void AllDownloadItemNotifier::ManagerGoingDown(DownloadManager* manager) { - DCHECK_EQ(manager_, manager); - manager_->RemoveObserver(this); - manager_ = NULL; -} - -void AllDownloadItemNotifier::OnDownloadCreated(DownloadManager* manager, - DownloadItem* item) { - item->AddObserver(this); - observing_.insert(item); - observer_->OnDownloadCreated(manager, item); -} - -void AllDownloadItemNotifier::OnDownloadUpdated(DownloadItem* item) { - observer_->OnDownloadUpdated(manager_, item); -} - -void AllDownloadItemNotifier::OnDownloadOpened(DownloadItem* item) { - observer_->OnDownloadOpened(manager_, item); -} - -void AllDownloadItemNotifier::OnDownloadRemoved(DownloadItem* item) { - observer_->OnDownloadRemoved(manager_, item); -} - -void AllDownloadItemNotifier::OnDownloadDestroyed(DownloadItem* item) { - item->RemoveObserver(this); - observing_.erase(item); -} - -} // namespace content
diff --git a/content/browser/frame_host/frame_tree_browsertest.cc b/content/browser/frame_host/frame_tree_browsertest.cc index ac1b31f..459f3ca 100644 --- a/content/browser/frame_host/frame_tree_browsertest.cc +++ b/content/browser/frame_host/frame_tree_browsertest.cc
@@ -26,11 +26,6 @@ #include "third_party/WebKit/public/web/WebSandboxFlags.h" #include "url/url_constants.h" -// For fine-grained suppression on flaky tests. -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - namespace content { namespace { @@ -168,11 +163,6 @@ #define MAYBE_NavigateWithLeftoverFrames NavigateWithLeftoverFrames #endif IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, MAYBE_NavigateWithLeftoverFrames) { -#if defined(OS_WIN) - // Flaky on XP bot http://crbug.com/468713 - if (base::win::GetVersion() <= base::win::VERSION_XP) - return; -#endif GURL base_url = embedded_test_server()->GetURL("A.com", "/site_isolation/"); NavigateToURL(shell(),
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 32b79dc7..fba3353 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -116,6 +116,9 @@ #include "mojo/public/cpp/bindings/associated_interface_ptr.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/system/data_pipe.h" +#include "services/device/public/cpp/device_features.h" +#include "services/device/public/interfaces/constants.mojom.h" +#include "services/device/public/interfaces/sensor_provider.mojom.h" #include "services/device/public/interfaces/wake_lock.mojom.h" #include "services/device/public/interfaces/wake_lock_context.mojom.h" #include "services/resource_coordinator/public/cpp/resource_coordinator_interface.h" @@ -348,16 +351,15 @@ *rfph = RenderFrameProxyHost::FromID(process_id, routing_id); } -// Forwards service requests to Service Manager since the renderer cannot launch -// out-of-process services on its own. -template <typename R> -void ForwardShapeDetectionRequest(const service_manager::BindSourceInfo&, - R request) { +// Forwards service requests to Service Manager. +template <typename Interface> +void ForwardRequest(const char* service_name, + const service_manager::BindSourceInfo&, + mojo::InterfaceRequest<Interface> request) { // TODO(beng): This should really be using the per-profile connector. service_manager::Connector* connector = ServiceManagerConnection::GetForProcess()->GetConnector(); - connector->BindInterface(shape_detection::mojom::kServiceName, - std::move(request)); + connector->BindInterface(service_name, std::move(request)); } void CreatePaymentManager(RenderFrameHostImpl* rfh, @@ -2944,14 +2946,14 @@ GetInterfaceRegistry()->AddInterface(base::Bind(&ImageCaptureImpl::Create)); GetInterfaceRegistry()->AddInterface( - base::Bind(&ForwardShapeDetectionRequest< - shape_detection::mojom::BarcodeDetectionRequest>)); + base::Bind(&ForwardRequest<shape_detection::mojom::BarcodeDetection>, + shape_detection::mojom::kServiceName)); GetInterfaceRegistry()->AddInterface( - base::Bind(&ForwardShapeDetectionRequest< - shape_detection::mojom::FaceDetectionProviderRequest>)); + base::Bind(&ForwardRequest<shape_detection::mojom::FaceDetectionProvider>, + shape_detection::mojom::kServiceName)); GetInterfaceRegistry()->AddInterface( - base::Bind(&ForwardShapeDetectionRequest< - shape_detection::mojom::TextDetectionRequest>)); + base::Bind(&ForwardRequest<shape_detection::mojom::TextDetection>, + shape_detection::mojom::kServiceName)); GetInterfaceRegistry()->AddInterface( base::Bind(&CreatePaymentManager, base::Unretained(this))); @@ -2960,6 +2962,12 @@ GetInterfaceRegistry()->AddInterface( base::Bind(&AuthenticatorImpl::Create, base::Unretained(this))); } + + if (base::FeatureList::IsEnabled(features::kGenericSensor)) { + GetInterfaceRegistry()->AddInterface( + base::Bind(&ForwardRequest<device::mojom::SensorProvider>, + device::mojom::kServiceName)); + } } void RenderFrameHostImpl::ResetWaitingState() {
diff --git a/content/browser/gpu/gpu_client.cc b/content/browser/gpu/gpu_client.cc index ccb775f..8963ea3c 100644 --- a/content/browser/gpu/gpu_client.cc +++ b/content/browser/gpu/gpu_client.cc
@@ -43,6 +43,20 @@ const IPC::ChannelHandle& channel, const gpu::GPUInfo& gpu_info, GpuProcessHost::EstablishChannelStatus status) { + if (status == GpuProcessHost::EstablishChannelStatus::GPU_ACCESS_DENIED) { + // GPU access is not allowed. Notify the client immediately. + DCHECK(!channel.mojo_handle.is_valid()); + callback.Run(render_process_id_, mojo::ScopedMessagePipeHandle(), gpu_info); + return; + } + + if (status == GpuProcessHost::EstablishChannelStatus::GPU_HOST_INVALID) { + // GPU process may have crashed or been killed. Try again. + DCHECK(!channel.mojo_handle.is_valid()); + EstablishGpuChannel(callback); + return; + } + DCHECK(channel.mojo_handle.is_valid()); mojo::ScopedMessagePipeHandle channel_handle; channel_handle.reset(channel.mojo_handle); callback.Run(render_process_id_, std::move(channel_handle), gpu_info);
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index cfe6fab..8c1824b 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -78,7 +78,6 @@ #endif #if defined(OS_WIN) -#include "base/win/windows_version.h" #include "content/common/sandbox_win.h" #include "sandbox/win/src/sandbox_policy.h" #include "ui/gfx/switches.h" @@ -260,38 +259,31 @@ // backend. Note that the GPU process is connected to the interactive // desktop. bool PreSpawnTarget(sandbox::TargetPolicy* policy) override { - if (base::win::GetVersion() > base::win::VERSION_XP) { - if (cmd_line_.GetSwitchValueASCII(switches::kUseGL) == - gl::kGLImplementationDesktopName) { - // Open GL path. - policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, - sandbox::USER_LIMITED); - SetJobLevel(cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy); - policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); - } else { - policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, - sandbox::USER_LIMITED); - - // UI restrictions break when we access Windows from outside our job. - // However, we don't want a proxy window in this process because it can - // introduce deadlocks where the renderer blocks on the gpu, which in - // turn blocks on the browser UI thread. So, instead we forgo a window - // message pump entirely and just add job restrictions to prevent child - // processes. - SetJobLevel(cmd_line_, - sandbox::JOB_LIMITED_USER, - JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | - JOB_OBJECT_UILIMIT_DESKTOP | - JOB_OBJECT_UILIMIT_EXITWINDOWS | - JOB_OBJECT_UILIMIT_DISPLAYSETTINGS, - policy); - - policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); - } - } else { - SetJobLevel(cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy); - policy->SetTokenLevel(sandbox::USER_UNPROTECTED, + if (cmd_line_.GetSwitchValueASCII(switches::kUseGL) == + gl::kGLImplementationDesktopName) { + // Open GL path. + policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, sandbox::USER_LIMITED); + SetJobLevel(cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy); + policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); + } else { + policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, + sandbox::USER_LIMITED); + + // UI restrictions break when we access Windows from outside our job. + // However, we don't want a proxy window in this process because it can + // introduce deadlocks where the renderer blocks on the gpu, which in + // turn blocks on the browser UI thread. So, instead we forgo a window + // message pump entirely and just add job restrictions to prevent child + // processes. + SetJobLevel(cmd_line_, sandbox::JOB_LIMITED_USER, + JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | + JOB_OBJECT_UILIMIT_DESKTOP | + JOB_OBJECT_UILIMIT_EXITWINDOWS | + JOB_OBJECT_UILIMIT_DISPLAYSETTINGS, + policy); + + policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); } // Allow the server side of GPU sockets, which are pipes that have
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index 298e085e7..661136c6 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -503,7 +503,7 @@ int page_request_id, const StreamControls& controls, const url::Origin& security_origin, - const MediaRequestResponseCallback& callback) { + MediaRequestResponseCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); // TODO(perkj): The argument list with NULL parameters to DeviceRequest @@ -516,7 +516,7 @@ const std::string& label = AddRequest(request); - request->callback = callback; + request->callback = std::move(callback); // Post a task and handle the request asynchronously. The reason is that the // requester won't have a label for the request until this function returns // and thus can not handle a response. Using base::Unretained is safe since @@ -1219,7 +1219,8 @@ if (request->request_type == MEDIA_DEVICE_ACCESS && !request->callback.is_null()) { - request->callback.Run(MediaStreamDevices(), std::move(request->ui_proxy)); + std::move(request->callback) + .Run(MediaStreamDevices(), std::move(request->ui_proxy)); } DeleteRequest(label); @@ -1238,7 +1239,7 @@ DeviceRequest* request, const MediaStreamDevices& devices) { if (!request->callback.is_null()) - request->callback.Run(devices, std::move(request->ui_proxy)); + std::move(request->callback).Run(devices, std::move(request->ui_proxy)); // Delete the request since it is done. DeleteRequest(label);
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h index 3d4baa1..3594098 100644 --- a/content/browser/renderer_host/media/media_stream_manager.h +++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -73,8 +73,8 @@ public base::PowerObserver { public: // Callback to deliver the result of a media request. - typedef base::Callback<void(const MediaStreamDevices& devices, - std::unique_ptr<MediaStreamUIProxy> ui)> + typedef base::OnceCallback<void(const MediaStreamDevices& devices, + std::unique_ptr<MediaStreamUIProxy> ui)> MediaRequestResponseCallback; // Callback for testing. @@ -124,13 +124,12 @@ // used to determine where the infobar will appear to the user. |callback| is // used to send the selected device to the clients. An empty list of device // will be returned if the users deny the access. - std::string MakeMediaAccessRequest( - int render_process_id, - int render_frame_id, - int page_request_id, - const StreamControls& controls, - const url::Origin& security_origin, - const MediaRequestResponseCallback& callback); + std::string MakeMediaAccessRequest(int render_process_id, + int render_frame_id, + int page_request_id, + const StreamControls& controls, + const url::Origin& security_origin, + MediaRequestResponseCallback callback); // GenerateStream opens new media devices according to |components|. It // creates a new request which is identified by a unique string that's
diff --git a/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/content/browser/renderer_host/media/media_stream_manager_unittest.cc index 754c99d..f0e968a 100644 --- a/content/browser/renderer_host/media/media_stream_manager_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -191,12 +191,12 @@ const int page_request_id = 1; const url::Origin security_origin; MediaStreamManager::MediaRequestResponseCallback callback = - base::Bind(&MediaStreamManagerTest::ResponseCallback, - base::Unretained(this), index); + base::BindOnce(&MediaStreamManagerTest::ResponseCallback, + base::Unretained(this), index); StreamControls controls(true, true); return media_stream_manager_->MakeMediaAccessRequest( render_process_id, render_frame_id, page_request_id, controls, - security_origin, callback); + security_origin, std::move(callback)); } // media_stream_manager_ needs to outlive thread_bundle_ because it is a @@ -237,12 +237,11 @@ int page_request_id = 2; url::Origin security_origin; StreamControls controls(true, true); - MediaStreamManager::MediaRequestResponseCallback callback = - base::Bind(&MediaStreamManagerTest::ResponseCallback, - base::Unretained(this), 1); + MediaStreamManager::MediaRequestResponseCallback callback = base::BindOnce( + &MediaStreamManagerTest::ResponseCallback, base::Unretained(this), 1); std::string label2 = media_stream_manager_->MakeMediaAccessRequest( render_process_id, render_frame_id, page_request_id, controls, - security_origin, callback); + security_origin, std::move(callback)); // Expecting the callbackS from requests will be triggered and quit the test. // Note, the callbacks might come in a different order depending on the
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index e0fc0f46..2a31b249 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc
@@ -21,7 +21,6 @@ #include "base/task_scheduler/post_task.h" #include "base/threading/thread.h" #include "build/build_config.h" -#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/browser/browser_main_loop.h" #include "content/browser/cache_storage/cache_storage_cache.h" @@ -129,8 +128,6 @@ arraysize(kFilteredMessageClasses)), BrowserAssociatedInterface<mojom::RenderMessageFilter>(this, this), resource_dispatcher_host_(ResourceDispatcherHostImpl::Get()), - shared_bitmap_allocation_notifier_impl_( - viz::ServerSharedBitmapManager::current()), request_context_(request_context), resource_context_(browser_context->GetResourceContext()), render_widget_helper_(render_widget_helper), @@ -217,11 +214,6 @@ std::move(callback).Run(route_id); } -void RenderMessageFilter::GetSharedBitmapAllocationNotifier( - cc::mojom::SharedBitmapAllocationNotifierAssociatedRequest request) { - shared_bitmap_allocation_notifier_impl_.Bind(std::move(request)); -} - #if defined(OS_MACOSX) void RenderMessageFilter::OnLoadFont(const FontDescriptor& font,
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h index b6202cb3..d0e7c36 100644 --- a/content/browser/renderer_host/render_message_filter.h +++ b/content/browser/renderer_host/render_message_filter.h
@@ -20,7 +20,6 @@ #include "base/strings/string16.h" #include "build/build_config.h" #include "components/viz/common/resources/shared_bitmap_manager.h" -#include "components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h" #include "content/common/cache_storage/cache_storage_types.h" #include "content/common/render_message_filter.mojom.h" #include "content/public/browser/browser_associated_interface.h" @@ -114,9 +113,6 @@ void CreateFullscreenWidget(int opener_id, mojom::WidgetPtr widget, CreateFullscreenWidgetCallback callback) override; - void GetSharedBitmapAllocationNotifier( - cc::mojom::SharedBitmapAllocationNotifierAssociatedRequest request) - override; // Message handlers called on the browser IO thread: void OnHasGpuProcess(IPC::Message* reply); @@ -158,9 +154,6 @@ // than we do. ResourceDispatcherHostImpl* resource_dispatcher_host_; - viz::SharedBitmapAllocationNotifierImpl - shared_bitmap_allocation_notifier_impl_; - // Contextual information to be used for requests created here. scoped_refptr<net::URLRequestContextGetter> request_context_;
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 5f842b1..ff3ca79 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -56,6 +56,7 @@ #include "components/metrics/single_sample_metrics.h" #include "components/tracing/common/tracing_switches.h" #include "components/viz/common/resources/buffer_to_texture_target_map.h" +#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" #include "content/browser/appcache/appcache_dispatcher_host.h" #include "content/browser/appcache/chrome_appcache_service.h" #include "content/browser/background_fetch/background_fetch_service_impl.h" @@ -1084,6 +1085,8 @@ instance_weak_factory_( new base::WeakPtrFactory<RenderProcessHostImpl>(this)), frame_sink_provider_(id_), + shared_bitmap_allocation_notifier_impl_( + viz::ServerSharedBitmapManager::current()), weak_factory_(this) { widget_helper_ = new RenderWidgetHelper(); @@ -1617,6 +1620,11 @@ AddUIThreadInterface( registry.get(), + base::Bind(&RenderProcessHostImpl::BindSharedBitmapAllocationNotifier, + base::Unretained(this))); + + AddUIThreadInterface( + registry.get(), base::Bind(&BackgroundSyncContext::CreateService, base::Unretained( storage_partition_impl_->GetBackgroundSyncContext()))); @@ -1793,6 +1801,12 @@ frame_sink_provider_.Bind(std::move(request)); } +void RenderProcessHostImpl::BindSharedBitmapAllocationNotifier( + const service_manager::BindSourceInfo& source_info, + cc::mojom::SharedBitmapAllocationNotifierRequest request) { + shared_bitmap_allocation_notifier_impl_.Bind(std::move(request)); +} + void RenderProcessHostImpl::CreateStoragePartitionService( const service_manager::BindSourceInfo& source_info, mojom::StoragePartitionServiceRequest request) { @@ -3410,6 +3424,8 @@ // for that. frame_sink_provider_.Unbind(); + shared_bitmap_allocation_notifier_impl_.ChildDied(); + // This object is not deleted at this point and might be reused later. // TODO(darin): clean this up } @@ -3811,4 +3827,9 @@ bad_message::RPH_MOJO_PROCESS_ERROR); } +viz::SharedBitmapAllocationNotifierImpl* +RenderProcessHostImpl::GetSharedBitmapAllocationNotifier() { + return &shared_bitmap_allocation_notifier_impl_; +} + } // namespace content
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index 52320c0..078fe06 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -21,6 +21,7 @@ #include "base/single_thread_task_runner.h" #include "base/synchronization/waitable_event.h" #include "build/build_config.h" +#include "components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h" #include "content/browser/child_process_launcher.h" #include "content/browser/dom_storage/session_storage_namespace_impl.h" #include "content/browser/renderer_host/frame_sink_provider_impl.h" @@ -337,6 +338,9 @@ RenderProcessHost* render_process_host, const GURL& site_url); + viz::SharedBitmapAllocationNotifierImpl* GetSharedBitmapAllocationNotifier() + override; + protected: // A proxy for our IPC::Channel that lives on the IO thread. std::unique_ptr<IPC::ChannelProxy> channel_; @@ -399,6 +403,9 @@ blink::mojom::OffscreenCanvasProviderRequest request); void BindFrameSinkProvider(const service_manager::BindSourceInfo& source_info, mojom::FrameSinkProviderRequest request); + void BindSharedBitmapAllocationNotifier( + const service_manager::BindSourceInfo& source_info, + cc::mojom::SharedBitmapAllocationNotifierRequest request); void CreateStoragePartitionService( const service_manager::BindSourceInfo& source_info, mojom::StoragePartitionServiceRequest request); @@ -717,6 +724,9 @@ FrameSinkProviderImpl frame_sink_provider_; + viz::SharedBitmapAllocationNotifierImpl + shared_bitmap_allocation_notifier_impl_; + base::WeakPtrFactory<RenderProcessHostImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(RenderProcessHostImpl);
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index a445f9c..5308d98c 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -327,6 +327,7 @@ CHECK(result.second) << "Inserting a duplicate item!"; process_->AddRoute(routing_id_, this); process_->AddWidget(this); + process_->GetSharedBitmapAllocationNotifier()->AddObserver(this); // If we're initially visible, tell the process host that we're alive. // Otherwise we'll notify the process host when we are first shown. @@ -1790,6 +1791,7 @@ view_.reset(); } + process_->GetSharedBitmapAllocationNotifier()->RemoveObserver(this); process_->RemoveWidget(this); process_->RemoveRoute(routing_id_); g_routing_id_widget_map.Get().erase( @@ -2588,6 +2590,28 @@ return; } + uint32_t max_sequence_number = 0; + for (const auto& resource : frame.resource_list) { + max_sequence_number = + std::max(max_sequence_number, resource.shared_bitmap_sequence_number); + } + + // If the CompositorFrame references SharedBitmaps that we are not aware of, + // defer the submission until they are registered. + uint32_t last_registered_sequence_number = + GetProcess()->GetSharedBitmapAllocationNotifier()->last_sequence_number(); + if (max_sequence_number > last_registered_sequence_number) { + saved_frame_.frame = std::move(frame); + saved_frame_.local_surface_id = local_surface_id; + saved_frame_.max_shared_bitmap_sequence_number = max_sequence_number; + TRACE_EVENT_ASYNC_BEGIN2("renderer_host", "PauseCompositorFrameSink", this, + "LastRegisteredSequenceNumber", + last_registered_sequence_number, + "RequiredSequenceNumber", max_sequence_number); + compositor_frame_sink_binding_.PauseIncomingMethodCallProcessing(); + return; + } + last_local_surface_id_ = local_surface_id; last_surface_properties_ = new_surface_properties; @@ -2687,4 +2711,15 @@ } #endif +void RenderWidgetHostImpl::DidAllocateSharedBitmap(uint32_t sequence_number) { + if (saved_frame_.local_surface_id.is_valid() && + sequence_number >= saved_frame_.max_shared_bitmap_sequence_number) { + SubmitCompositorFrame(saved_frame_.local_surface_id, + std::move(saved_frame_.frame)); + saved_frame_.local_surface_id = viz::LocalSurfaceId(); + compositor_frame_sink_binding_.ResumeIncomingMethodCallProcessing(); + TRACE_EVENT_ASYNC_END0("renderer_host", "PauseCompositorFrameSink", this); + } +} + } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 035b6b7..bdee193 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -28,6 +28,7 @@ #include "cc/ipc/compositor_frame_sink.mojom.h" #include "components/viz/common/quads/shared_bitmap.h" #include "components/viz/common/surfaces/frame_sink_id.h" +#include "components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h" #include "content/browser/renderer_host/event_with_latency_info.h" #include "content/browser/renderer_host/input/input_ack_handler.h" #include "content/browser/renderer_host/input/input_router_client.h" @@ -105,6 +106,7 @@ public TouchEmulatorClient, public NON_EXPORTED_BASE(SyntheticGestureController::Delegate), public NON_EXPORTED_BASE(cc::mojom::CompositorFrameSink), + public NON_EXPORTED_BASE(viz::SharedBitmapAllocationObserver), public IPC::Listener { public: // |routing_id| must not be MSG_ROUTING_NONE. @@ -755,6 +757,10 @@ // process the messages. Virtual for tests. virtual void ProcessSwapMessages(std::vector<IPC::Message> messages); + // viz::SharedBitmapAllocationObserver implementation. + void DidAllocateSharedBitmap( + uint32_t last_shared_bitmap_sequence_number) override; + #if defined(OS_MACOSX) device::mojom::WakeLock* GetWakeLock(); #endif @@ -983,6 +989,14 @@ // Sorted by frame token. std::queue<std::pair<uint32_t, std::vector<IPC::Message>>> queued_messages_; + // If a CompositorFrame is submitted that references SharedBitmaps that don't + // exist yet, we keep it here until they are available. + struct { + viz::LocalSurfaceId local_surface_id; + cc::CompositorFrame frame; + uint32_t max_shared_bitmap_sequence_number = 0; + } saved_frame_; + std::unique_ptr<LegacyIPCWidgetInputHandler> legacy_widget_input_handler_; base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_;
diff --git a/content/browser/speech/speech_recognition_manager_impl.cc b/content/browser/speech/speech_recognition_manager_impl.cc index 740885a..135d5f6e 100644 --- a/content/browser/speech/speech_recognition_manager_impl.cc +++ b/content/browser/speech/speech_recognition_manager_impl.cc
@@ -181,7 +181,7 @@ context.label = media_stream_manager_->MakeMediaAccessRequest( context.render_process_id, context.render_frame_id, context.request_id, StreamControls(true, false), url::Origin(GURL(context.context_name)), - base::Bind( + base::BindOnce( &SpeechRecognitionManagerImpl::MediaRequestPermissionCallback, weak_factory_.GetWeakPtr(), session_id)); return;
diff --git a/chrome/browser/ssl/ignore_errors_cert_verifier.cc b/content/browser/ssl/ignore_errors_cert_verifier.cc similarity index 94% rename from chrome/browser/ssl/ignore_errors_cert_verifier.cc rename to content/browser/ssl/ignore_errors_cert_verifier.cc index af0e370..7fe840b 100644 --- a/chrome/browser/ssl/ignore_errors_cert_verifier.cc +++ b/content/browser/ssl/ignore_errors_cert_verifier.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ssl/ignore_errors_cert_verifier.h" +#include "content/public/browser/ignore_errors_cert_verifier.h" #include <iterator> #include <utility> @@ -12,7 +12,7 @@ #include "base/memory/ref_counted.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" -#include "chrome/common/chrome_switches.h" +#include "content/public/common/content_switches.h" #include "crypto/sha2.h" #include "net/base/completion_callback.h" #include "net/base/hash_value.h" @@ -29,11 +29,14 @@ using ::net::SHA256HashValueLessThan; using ::net::X509Certificate; +namespace content { + // static std::unique_ptr<CertVerifier> IgnoreErrorsCertVerifier::MaybeWrapCertVerifier( const base::CommandLine& command_line, + const char* user_data_dir_switch, std::unique_ptr<CertVerifier> verifier) { - if (!command_line.HasSwitch(switches::kUserDataDir) || + if (!command_line.HasSwitch(user_data_dir_switch) || !command_line.HasSwitch(switches::kIgnoreCertificateErrorsSPKIList)) { return verifier; } @@ -130,3 +133,5 @@ void IgnoreErrorsCertVerifier::set_whitelist(const SPKIHashSet& whitelist) { whitelist_ = whitelist; } + +} // namespace content
diff --git a/chrome/browser/ssl/ignore_errors_cert_verifier_unittest.cc b/content/browser/ssl/ignore_errors_cert_verifier_unittest.cc similarity index 94% rename from chrome/browser/ssl/ignore_errors_cert_verifier_unittest.cc rename to content/browser/ssl/ignore_errors_cert_verifier_unittest.cc index 1863367..29ea418e 100644 --- a/chrome/browser/ssl/ignore_errors_cert_verifier_unittest.cc +++ b/content/browser/ssl/ignore_errors_cert_verifier_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ssl/ignore_errors_cert_verifier.h" +#include "content/public/browser/ignore_errors_cert_verifier.h" #include "base/base64.h" #include "base/files/file_path.h" @@ -10,8 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" -#include "chrome/browser/io_thread.h" -#include "chrome/common/chrome_switches.h" +#include "content/public/common/content_switches.h" #include "crypto/sha2.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" @@ -43,6 +42,10 @@ using net::test::IsError; using net::test::IsOk; +namespace content { + +static const char kTestUserDataDirSwitch[] = "test-user-data-dir"; + static std::vector<std::string> MakeWhitelist() { base::FilePath certs_dir = net::GetTestCertsDirectory(); net::CertificateList certs = net::CreateCertificateListFromFile( @@ -157,7 +160,7 @@ IgnoreCertificateErrorsSPKIListFlagTest() { base::CommandLine command_line(base::CommandLine::NO_PROGRAM); if (GetParam()) { - command_line.AppendSwitchASCII(switches::kUserDataDir, "/foo/bar/baz"); + command_line.AppendSwitchASCII(kTestUserDataDirSwitch, "/foo/bar/baz"); } command_line.AppendSwitchASCII(switches::kIgnoreCertificateErrorsSPKIList, base::JoinString(MakeWhitelist(), ",")); @@ -165,7 +168,7 @@ auto mock_verifier = base::MakeUnique<MockCertVerifier>(); mock_verifier->set_default_result(ERR_CERT_INVALID); verifier_ = IgnoreErrorsCertVerifier::MaybeWrapCertVerifier( - command_line, std::move(mock_verifier)); + command_line, kTestUserDataDirSwitch, std::move(mock_verifier)); } ~IgnoreCertificateErrorsSPKIListFlagTest() override {} @@ -198,3 +201,5 @@ INSTANTIATE_TEST_CASE_P(WithUserDataDirSwitchPresent, IgnoreCertificateErrorsSPKIListFlagTest, ::testing::Bool()); + +} // namespace content
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index b85d291..e967a2f 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -4812,7 +4812,8 @@ void WebContentsImpl::DidStartLoading(FrameTreeNode* frame_tree_node, bool to_different_document) { - LoadingStateChanged(to_different_document, false, nullptr); + LoadingStateChanged(frame_tree_node->IsMainFrame() && to_different_document, + false, nullptr); // Notify accessibility that the user is navigating away from the // current document.
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 9c837588..569ae3d 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -1361,7 +1361,7 @@ // Data for loading state ---------------------------------------------------- // Indicates whether the current load is to a different document. Only valid - // if is_loading_ is true. + // if |is_loading_| is true and only tracks loads in the main frame. bool is_load_to_different_document_; // Indicates if the tab is considered crashed.
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc index 378075df..31e4ebf 100644 --- a/content/browser/web_contents/web_contents_impl_unittest.cc +++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -3245,6 +3245,58 @@ EXPECT_FALSE(observer.is_loading()); } +// Tests that WebContentsImpl::IsLoadingToDifferentDocument only reports main +// frame loads. Browser-initiated navigation of subframes is only possible in +// --site-per-process mode within unit tests. +TEST_F(WebContentsImplTestWithSiteIsolation, IsLoadingToDifferentDocument) { + const GURL main_url("http://www.chromium.org"); + TestRenderFrameHost* orig_rfh = main_test_rfh(); + + // Navigate the main RenderFrame, simulate the DidStartLoading, and commit. + // The frame should still be loading. + controller().LoadURL(main_url, Referrer(), ui::PAGE_TRANSITION_TYPED, + std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); + + // PlzNavigate: the RenderFrameHost does not expect to receive + // DidStartLoading IPCs for navigations to different documents. + if (!IsBrowserSideNavigationEnabled()) { + orig_rfh->OnMessageReceived( + FrameHostMsg_DidStartLoading(orig_rfh->GetRoutingID(), false)); + } + main_test_rfh()->PrepareForCommit(); + contents()->TestDidNavigate(orig_rfh, entry_id, true, main_url, + ui::PAGE_TRANSITION_TYPED); + EXPECT_FALSE(contents()->CrossProcessNavigationPending()); + EXPECT_EQ(orig_rfh, main_test_rfh()); + EXPECT_TRUE(contents()->IsLoading()); + EXPECT_TRUE(contents()->IsLoadingToDifferentDocument()); + + // Send the DidStopLoading for the main frame and ensure it isn't loading + // anymore. + orig_rfh->OnMessageReceived( + FrameHostMsg_DidStopLoading(orig_rfh->GetRoutingID())); + EXPECT_FALSE(contents()->IsLoading()); + EXPECT_FALSE(contents()->IsLoadingToDifferentDocument()); + + // Create a child frame to navigate. + TestRenderFrameHost* subframe = orig_rfh->AppendChild("subframe"); + + // Navigate the child frame to about:blank, make sure the web contents is + // marked as "loading" but not "loading to different document". + if (!IsBrowserSideNavigationEnabled()) { + subframe->OnMessageReceived( + FrameHostMsg_DidStartLoading(subframe->GetRoutingID(), true)); + } + subframe->SendNavigateWithTransition(0, false, GURL("about:blank"), + ui::PAGE_TRANSITION_AUTO_SUBFRAME); + EXPECT_TRUE(contents()->IsLoading()); + EXPECT_FALSE(contents()->IsLoadingToDifferentDocument()); + subframe->OnMessageReceived( + FrameHostMsg_DidStopLoading(subframe->GetRoutingID())); + EXPECT_FALSE(contents()->IsLoading()); +} + // Ensure that WebContentsImpl does not stop loading too early when there still // is a pending renderer. This can happen if a same-process non user-initiated // navigation completes while there is an ongoing cross-process navigation.
diff --git a/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/content/browser/web_contents/web_contents_view_aura_browsertest.cc index 3167829..99c5e17 100644 --- a/content/browser/web_contents/web_contents_view_aura_browsertest.cc +++ b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -49,10 +49,6 @@ #include "ui/events/event_utils.h" #include "ui/events/test/event_generator.h" -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - namespace { // TODO(tdresser): Find a way to avoid sleeping like this. See crbug.com/405282 @@ -639,14 +635,6 @@ #define MAYBE_OverscrollScreenshot OverscrollScreenshot #endif IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollScreenshot) { - // Disable the test for WinXP. See http://crbug/294116. -#if defined(OS_WIN) - if (base::win::GetVersion() < base::win::VERSION_VISTA) { - LOG(WARNING) << "Test disabled due to unknown bug on WinXP."; - return; - } -#endif - ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html")); WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents());
diff --git a/content/common/render_message_filter.mojom b/content/common/render_message_filter.mojom index 720032d..e51d3dc 100644 --- a/content/common/render_message_filter.mojom +++ b/content/common/render_message_filter.mojom
@@ -21,7 +21,4 @@ // Similar to CreateWidget except the widget is a full screen window. [Sync] CreateFullscreenWidget(int32 opener_id, Widget widget) => (int32 route_id); - - GetSharedBitmapAllocationNotifier( - associated cc.mojom.SharedBitmapAllocationNotifier& notifier); };
diff --git a/content/common/sandbox_win.cc b/content/common/sandbox_win.cc index 323e57e..54e31d3 100644 --- a/content/common/sandbox_win.cc +++ b/content/common/sandbox_win.cc
@@ -409,22 +409,10 @@ if (result != sandbox::SBOX_ALL_OK) return result; - // Close the proxy settings on XP. - if (base::win::GetVersion() <= base::win::VERSION_SERVER_2003) - result = policy->AddKernelObjectToClose(L"Key", - L"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\" \ - L"CurrentVersion\\Internet Settings"); - if (result != sandbox::SBOX_ALL_OK) - return result; - - sandbox::TokenLevel initial_token = sandbox::USER_UNPROTECTED; - if (base::win::GetVersion() > base::win::VERSION_XP) { - // On 2003/Vista the initial token has to be restricted if the main - // token is restricted. - initial_token = sandbox::USER_RESTRICTED_SAME_ACCESS; - } - - result = policy->SetTokenLevel(initial_token, sandbox::USER_LOCKDOWN); + // On 2003/Vista+ the initial token has to be restricted if the main + // token is restricted. + result = policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, + sandbox::USER_LOCKDOWN); if (result != sandbox::SBOX_ALL_OK) return result; // Prevents the renderers from manipulating low-integrity processes.
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java index d4af7a5..8b32c13 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -1126,6 +1126,9 @@ private void onTouchDown(MotionEvent event) { if (mShouldRequestUnbufferedDispatch) requestUnbufferedDispatch(event); cancelRequestToScrollFocusedEditableNodeIntoView(); + for (mGestureStateListenersIterator.rewind(); mGestureStateListenersIterator.hasNext();) { + mGestureStateListenersIterator.next().onTouchDown(); + } } private void updateAfterSizeChanged() {
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/GestureStateListener.java b/content/public/android/java/src/org/chromium/content_public/browser/GestureStateListener.java index 2854b35..4b7f89c 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/GestureStateListener.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/GestureStateListener.java
@@ -37,33 +37,39 @@ */ public void onScrollUpdateGestureConsumed() {} - /* + /** * Called when a scroll gesture has started. */ public void onScrollStarted(int scrollOffsetY, int scrollExtentY) {} - /* + /** * Called when a scroll gesture has stopped. */ public void onScrollEnded(int scrollOffsetY, int scrollExtentY) {} - /* + /** * Called when the min or max scale factor may have been changed. */ public void onScaleLimitsChanged(float minPageScaleFactor, float maxPageScaleFactor) {} - /* + /** * Called when the scroll offsets or extents may have changed. */ public void onScrollOffsetOrExtentChanged(int scrollOffsetY, int scrollExtentY) {} - /* + /** + * Called at the beginning of any kind of touch event when the user's finger first touches down + * onto the screen. The resulting gesture may be a single tap, long-press, or scroll. + */ + public void onTouchDown() {} + + /** * Called after a single-tap gesture event was dispatched to the renderer, * indicating whether or not the gesture was consumed. */ public void onSingleTap(boolean consumed) {} - /* + /** * Called after a single-tap gesture event was processed by the renderer, * but was not handled. */
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json index 124d48e..77bf554 100644 --- a/content/public/app/mojo/content_browser_manifest.json +++ b/content/public/app/mojo/content_browser_manifest.json
@@ -25,6 +25,7 @@ "blink::mojom::OffscreenCanvasProvider", "blink::mojom::PermissionService", "blink::mojom::WebSocket", + "cc::mojom::SharedBitmapAllocationNotifier", "content::mojom::FieldTrialRecorder", "content::mojom::FrameSinkProvider", "content::mojom::MemoryCoordinatorHandle", @@ -72,7 +73,7 @@ "content_renderer": [ "browser" ], "content_utility": [ "browser" ], "data_decoder": [ "image_decoder" ], - "device": [ "device:nfc", "device:wake_lock" ], + "device": [ "device:generic_sensor", "device:nfc", "device:wake_lock" ], "file": [ "file:filesystem", "file:leveldb" ], "media": [ "media:media" ], "network": [ @@ -92,7 +93,7 @@ "face_detection", "text_detection" ], - "resource_coordinator": [ "coordination_unit", "service_callbacks" ], + "resource_coordinator": [ "coordination_unit", "service_callbacks", "tab_signal" ], "video_capture": [ "capture", "tests" ] } }, @@ -111,12 +112,15 @@ "blink::mojom::SensitiveInputVisibilityService", "blink::mojom::WebBluetoothService", "blink::mojom::WebSocket", + // TODO(beng): figure out how to overlay test interfaces like this. "content::mojom::BrowserTarget", + "content::mojom::RendererAudioOutputStreamFactory", "device::mojom::VRService", "device::mojom::Geolocation", "device::mojom::NFC", + "device::mojom::SensorProvider", "device::mojom::WakeLock", "device::usb::DeviceManager", "discardable_memory::mojom::DiscardableSharedMemoryManager",
diff --git a/content/public/app/mojo/content_renderer_manifest.json b/content/public/app/mojo/content_renderer_manifest.json index 52a453ba..a850e12 100644 --- a/content/public/app/mojo/content_renderer_manifest.json +++ b/content/public/app/mojo/content_renderer_manifest.json
@@ -22,7 +22,6 @@ "content_browser": [ "memory_instrumentation", "renderer" ], "device": [ "device:battery_monitor", - "device:generic_sensor", "device:power_monitor", "device:screen_orientation", "device:sensors",
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index 2cf71897..c5467c7 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -22,7 +22,6 @@ visibility = [ "//content/*" ] sources = [ - "all_download_item_notifier.h", "android/android_overlay_provider.h", "android/browser_media_player_manager_register.cc", "android/browser_media_player_manager_register.h", @@ -131,6 +130,7 @@ "guest_mode.cc", "guest_mode.h", "histogram_fetcher.h", + "ignore_errors_cert_verifier.h", "indexed_db_context.h", "indexed_db_info.h", "interstitial_page.h",
diff --git a/content/public/browser/all_download_item_notifier.h b/content/public/browser/all_download_item_notifier.h deleted file mode 100644 index 4f07a28..0000000 --- a/content/public/browser/all_download_item_notifier.h +++ /dev/null
@@ -1,90 +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. - -#ifndef CONTENT_PUBLIC_BROWSER_ALL_DOWNLOAD_ITEM_NOTIFIER_H_ -#define CONTENT_PUBLIC_BROWSER_ALL_DOWNLOAD_ITEM_NOTIFIER_H_ - -#include <set> - -#include "base/macros.h" -#include "content/common/content_export.h" -#include "content/public/browser/download_item.h" -#include "content/public/browser/download_manager.h" - -// AllDownloadItemNotifier observes ALL the DownloadItems on a given -// DownloadManager. -// Clients should use GetManager() instead of storing their own pointer to the -// manager so that they can be sensitive to managers that have gone down. - -// Example Usage: -// class DownloadSystemConsumer : public AllDownloadItemNotifier::Observer { -// public: -// DownloadSystemConsumer(DownloadManager* original_manager, -// DownloadManager* incognito_manager) -// : original_notifier_(original_manager, this), -// incognito_notifier_(incognito_manager, this) { -// } -// -// virtual void OnDownloadUpdated( -// DownloadManager* manager, DownloadItem* item) { ... } -// -// private: -// AllDownloadItemNotifier original_notifier_; -// AllDownloadItemNotifier incognito_notifier_; -// }; - -namespace content { - -class CONTENT_EXPORT AllDownloadItemNotifier : public DownloadManager::Observer, - public DownloadItem::Observer { - public: - // All of the methods take the DownloadManager so that subclasses can observe - // multiple managers at once and easily distinguish which manager a given item - // belongs to. - class Observer { - public: - Observer() {} - virtual ~Observer() {} - - virtual void OnDownloadCreated(DownloadManager* manager, - DownloadItem* item) {} - virtual void OnDownloadUpdated(DownloadManager* manager, - DownloadItem* item) {} - virtual void OnDownloadOpened(DownloadManager* manager, - DownloadItem* item) {} - virtual void OnDownloadRemoved(DownloadManager* manager, - DownloadItem* item) {} - - private: - DISALLOW_COPY_AND_ASSIGN(Observer); - }; - - AllDownloadItemNotifier(DownloadManager* manager, Observer* observer); - - ~AllDownloadItemNotifier() override; - - // Returns NULL if the manager has gone down. - DownloadManager* GetManager() const { return manager_; } - - private: - // DownloadManager::Observer - void ManagerGoingDown(DownloadManager* manager) override; - void OnDownloadCreated(DownloadManager* manager, DownloadItem* item) override; - - // DownloadItem::Observer - void OnDownloadUpdated(DownloadItem* item) override; - void OnDownloadOpened(DownloadItem* item) override; - void OnDownloadRemoved(DownloadItem* item) override; - void OnDownloadDestroyed(DownloadItem* item) override; - - DownloadManager* manager_; - AllDownloadItemNotifier::Observer* observer_; - std::set<DownloadItem*> observing_; - - DISALLOW_COPY_AND_ASSIGN(AllDownloadItemNotifier); -}; - -} // namespace content - -#endif // CONTENT_PUBLIC_BROWSER_ALL_DOWNLOAD_ITEM_NOTIFIER_H_
diff --git a/chrome/browser/ssl/ignore_errors_cert_verifier.h b/content/public/browser/ignore_errors_cert_verifier.h similarity index 81% rename from chrome/browser/ssl/ignore_errors_cert_verifier.h rename to content/public/browser/ignore_errors_cert_verifier.h index 2b163904..28625b4e 100644 --- a/chrome/browser/ssl/ignore_errors_cert_verifier.h +++ b/content/public/browser/ignore_errors_cert_verifier.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_SSL_IGNORE_ERRORS_CERT_VERIFIER_H_ -#define CHROME_BROWSER_SSL_IGNORE_ERRORS_CERT_VERIFIER_H_ +#ifndef CONTENT_PUBLIC_BROWSER_IGNORE_ERRORS_CERT_VERIFIER_H_ +#define CONTENT_PUBLIC_BROWSER_IGNORE_ERRORS_CERT_VERIFIER_H_ #include <memory> #include <string> @@ -11,6 +11,7 @@ #include "base/command_line.h" #include "base/containers/flat_set.h" +#include "content/common/content_export.h" #include "net/cert/cert_verifier.h" namespace net { @@ -18,10 +19,12 @@ class SHA256HashValueLessThan; } // namespace net +namespace content { + // IgnoreErrorsCertVerifier wraps another CertVerifier in order to ignore // verification errors from certificate chains that match a whitelist of SPKI // fingerprints. -class IgnoreErrorsCertVerifier : public net::CertVerifier { +class CONTENT_EXPORT IgnoreErrorsCertVerifier : public net::CertVerifier { public: // SPKIHashSet is a set of SHA-256 SPKI fingerprints (RFC 7469, Section 2.4). using SPKIHashSet = @@ -32,8 +35,11 @@ // --ignore-certificate-errors-spki-list flag of the command line if the // --user-data-dir flag is also present. If either of these flags are missing, // it returns the supplied verifier. + // As the --user-data-dir flag is embedder defined, the flag to check for + // needs to be passed in. static std::unique_ptr<net::CertVerifier> MaybeWrapCertVerifier( const base::CommandLine& command_line, + const char* user_data_dir_switch, std::unique_ptr<net::CertVerifier> verifier); // MakeWhitelist converts a vector of Base64-encoded SHA-256 SPKI fingerprints @@ -63,6 +69,10 @@ std::unique_ptr<net::CertVerifier> verifier_; SPKIHashSet whitelist_; + + DISALLOW_COPY_AND_ASSIGN(IgnoreErrorsCertVerifier); }; -#endif // CHROME_BROWSER_SSL_IGNORE_ERRORS_CERT_VERIFIER_H_ +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_IGNORE_ERRORS_CERT_VERIFIER_H_
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h index e42a39f9..d047a98 100644 --- a/content/public/browser/render_process_host.h +++ b/content/public/browser/render_process_host.h
@@ -37,6 +37,10 @@ class ResourceCoordinatorInterface; } +namespace viz { +class SharedBitmapAllocationNotifierImpl; +} + namespace content { class BrowserContext; class BrowserMessageFilter; @@ -389,6 +393,12 @@ // be posted back on the UI thread). void PostTaskWhenProcessIsReady(base::OnceClosure task); + // Returns the SharedBitmapAllocationNotifier associated with this process. + // SharedBitmapAllocationNotifier manages viz::SharedBitmaps created by this + // process and can notify observers when a new SharedBitmap is allocated. + virtual viz::SharedBitmapAllocationNotifierImpl* + GetSharedBitmapAllocationNotifier() = 0; + // Static management functions ----------------------------------------------- // Flag to run the renderer in process. This is primarily
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h index 993bf7a..0a3d303 100644 --- a/content/public/browser/web_contents.h +++ b/content/public/browser/web_contents.h
@@ -373,7 +373,8 @@ // Returns whether this WebContents is loading and and the load is to a // different top-level document (rather than being a navigation within the - // same document). This being true implies that IsLoading() is also true. + // same document) in the main frame. This being true implies that IsLoading() + // is also true. virtual bool IsLoadingToDifferentDocument() const = 0; // Returns whether this WebContents is waiting for a first-response for the
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 1e56d09..32b513f7 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc
@@ -575,6 +575,20 @@ // These mappings only apply to the host resolver. const char kHostResolverRules[] = "host-resolver-rules"; +// A set of public key hashes for which to ignore certificate-related errors. +// +// If the certificate chain presented by the server does not validate, and one +// or more certificates have public key hashes that match a key from this list, +// the error is ignored. +// +// The switch value must a be a comma-separated list of Base64-encoded SHA-256 +// SPKI Fingerprints (RFC 7469, Section 2.4). +// +// This switch has no effect unless --user-data-dir (as defined by the content +// embedder) is also present. +const char kIgnoreCertificateErrorsSPKIList[] = + "ignore-certificate-errors-spki-list"; + // Makes all APIs reflect the layout viewport. const char kInertVisualViewport[] = "inert-visual-viewport";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index cf2af3a..987e5db3 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h
@@ -175,6 +175,7 @@ CONTENT_EXPORT extern const char kGpuStartupDialog[]; CONTENT_EXPORT extern const char kHistoryEntryRequiresUserGesture[]; CONTENT_EXPORT extern const char kHostResolverRules[]; +CONTENT_EXPORT extern const char kIgnoreCertificateErrorsSPKIList[]; CONTENT_EXPORT extern const char kInertVisualViewport[]; CONTENT_EXPORT extern const char kInProcessGPU[]; CONTENT_EXPORT extern const char kIPCConnectionTimeout[];
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc index efabfce4..37715d1 100644 --- a/content/public/test/mock_render_process_host.cc +++ b/content/public/test/mock_render_process_host.cc
@@ -15,6 +15,7 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" +#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" #include "content/browser/child_process_security_policy_impl.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_view_host_impl.h" @@ -48,6 +49,8 @@ is_process_backgrounded_(false), is_unused_(true), worker_ref_count_(0), + shared_bitmap_allocation_notifier_impl_( + viz::ServerSharedBitmapManager::current()), weak_ptr_factory_(this) { // Child process security operations can't be unit tested unless we add // ourselves as an existing child process. @@ -449,4 +452,9 @@ } } +viz::SharedBitmapAllocationNotifierImpl* +MockRenderProcessHost::GetSharedBitmapAllocationNotifier() { + return &shared_bitmap_allocation_notifier_impl_; +} + } // namespace content
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h index f2802c9..d93ccc69 100644 --- a/content/public/test/mock_render_process_host.h +++ b/content/public/test/mock_render_process_host.h
@@ -15,6 +15,7 @@ #include "base/memory/weak_ptr.h" #include "base/metrics/persistent_memory_allocator.h" #include "base/observer_list.h" +#include "components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host_factory.h" #include "ipc/ipc_test_sink.h" @@ -130,6 +131,8 @@ bool MayReuseHost() override; bool IsUnused() override; void SetIsUsed() override; + viz::SharedBitmapAllocationNotifierImpl* GetSharedBitmapAllocationNotifier() + override; // IPC::Sender via RenderProcessHost. bool Send(IPC::Message* msg) override; @@ -182,6 +185,8 @@ renderer_interface_; std::map<std::string, InterfaceBinder> binder_overrides_; service_manager::Identity child_identity_; + viz::SharedBitmapAllocationNotifierImpl + shared_bitmap_allocation_notifier_impl_; base::WeakPtrFactory<MockRenderProcessHost> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(MockRenderProcessHost);
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc index 8d49131..2bc7194 100644 --- a/content/public/test/mock_render_thread.cc +++ b/content/public/test/mock_render_thread.cc
@@ -61,12 +61,6 @@ NOTREACHED(); } - void GetSharedBitmapAllocationNotifier( - cc::mojom::SharedBitmapAllocationNotifierAssociatedRequest request) - override { - NOTREACHED(); - } - private: MockRenderThread* const thread_; };
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index e5522c4..fd27299 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -259,8 +259,7 @@ RenderWidgetCompositor::RenderWidgetCompositor( RenderWidgetCompositorDelegate* delegate, CompositorDependencies* compositor_deps) - : num_failed_recreate_attempts_(0), - delegate_(delegate), + : delegate_(delegate), compositor_deps_(compositor_deps), threaded_(!!compositor_deps_->GetCompositorImplThreadTaskRunner()), never_visible_(false), @@ -572,10 +571,18 @@ size_t dalvik_mb = base::SysInfo::DalvikHeapSizeMB(); size_t physical_mb = base::SysInfo::AmountOfPhysicalMemoryMB(); size_t physical_memory_mb = 0; - if (dalvik_mb >= 256) + if (base::SysInfo::IsLowEndDevice()) { + // TODO(crbug.com/742534): The code below appears to no longer work. + // |dalvik_mb| no longer follows the expected heuristic pattern, causing us + // to over-estimate memory on low-end devices. This entire section probably + // needs to be re-written, but for now we can address the low-end Android + // issues by ignoring |dalvik_mb|. + physical_memory_mb = physical_mb; + } else if (dalvik_mb >= 256) { physical_memory_mb = dalvik_mb * 4; - else + } else { physical_memory_mb = std::max(dalvik_mb * 4, (physical_mb * 4) / 3); + } // Now we take a default of 1/8th of memory on high-memory devices, // and gradually scale that back for low-memory devices (to be nicer @@ -1154,30 +1161,26 @@ if (delegate_->IsClosing()) return; - bool fallback = num_failed_recreate_attempts_ >= - LAYER_TREE_FRAME_SINK_RETRIES_BEFORE_FALLBACK; - #ifdef OS_ANDROID - LOG_IF(FATAL, fallback) << "Android does not support fallback frame sinks."; + LOG_IF(FATAL, attempt_software_fallback_) + << "Android does not support fallback frame sinks."; #endif delegate_->RequestNewLayerTreeFrameSink( - fallback, base::Bind(&RenderWidgetCompositor::SetLayerTreeFrameSink, - weak_factory_.GetWeakPtr())); + attempt_software_fallback_, + base::Bind(&RenderWidgetCompositor::SetLayerTreeFrameSink, + weak_factory_.GetWeakPtr())); } void RenderWidgetCompositor::DidInitializeLayerTreeFrameSink() { - num_failed_recreate_attempts_ = 0; + attempt_software_fallback_ = false; } void RenderWidgetCompositor::DidFailToInitializeLayerTreeFrameSink() { - ++num_failed_recreate_attempts_; - // Tolerate a certain number of recreation failures to work around races - // in the output-surface-lost machinery. - LOG_IF(FATAL, - (num_failed_recreate_attempts_ >= MAX_LAYER_TREE_FRAME_SINK_RETRIES)) + LOG_IF(FATAL, attempt_software_fallback_) << "Failed to create a fallback LayerTreeFrameSink."; + attempt_software_fallback_ = true; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(&RenderWidgetCompositor::RequestNewLayerTreeFrameSink,
diff --git a/content/renderer/gpu/render_widget_compositor.h b/content/renderer/gpu/render_widget_compositor.h index 1743a5a40..bf36242d 100644 --- a/content/renderer/gpu/render_widget_compositor.h +++ b/content/renderer/gpu/render_widget_compositor.h
@@ -210,11 +210,6 @@ void DidLoseLayerTreeFrameSink() override; void RequestBeginMainFrameNotExpected(bool new_state) override; - enum { - LAYER_TREE_FRAME_SINK_RETRIES_BEFORE_FALLBACK = 4, - MAX_LAYER_TREE_FRAME_SINK_RETRIES = 5, - }; - protected: friend class RenderViewImplScaleFactorTest; @@ -231,7 +226,7 @@ bool CompositeIsSynchronous() const; void SynchronouslyComposite(); - int num_failed_recreate_attempts_; + bool attempt_software_fallback_ = false; RenderWidgetCompositorDelegate* const delegate_; CompositorDependencies* const compositor_deps_; const bool threaded_;
diff --git a/content/renderer/gpu/render_widget_compositor_unittest.cc b/content/renderer/gpu/render_widget_compositor_unittest.cc index 007194b..05192682 100644 --- a/content/renderer/gpu/render_widget_compositor_unittest.cc +++ b/content/renderer/gpu/render_widget_compositor_unittest.cc
@@ -13,6 +13,7 @@ #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "build/build_config.h" #include "cc/animation/animation_host.h" #include "cc/output/begin_frame_args.h" #include "cc/output/copy_output_request.h" @@ -34,6 +35,11 @@ namespace content { namespace { +enum FailureMode { + NO_FAILURE, + GPU_CHANNEL_FAILURE, +}; + class StubRenderWidgetCompositorDelegate : public RenderWidgetCompositorDelegate { public: @@ -73,10 +79,6 @@ void RequestNewLayerTreeFrameSink( bool fallback, const LayerTreeFrameSinkCallback& callback) override { - EXPECT_EQ(num_requests_since_last_success_ > - RenderWidgetCompositor:: - LAYER_TREE_FRAME_SINK_RETRIES_BEFORE_FALLBACK, - fallback); last_create_was_fallback_ = fallback; bool success = num_failures_ >= num_failures_before_success_; @@ -94,6 +96,15 @@ cc::FakeLayerTreeFrameSink::Create3d(std::move(context_provider))); } + void Reset() { + num_requests_ = 0; + num_requests_since_last_success_ = 0; + num_failures_ = 0; + num_failures_before_success_ = 0; + num_fallback_successes_ = 0; + num_successes_ = 0; + } + void add_success() { if (last_create_was_fallback_) ++num_fallback_successes_; @@ -123,9 +134,6 @@ void set_use_null_layer_tree_frame_sink(bool u) { use_null_layer_tree_frame_sink_ = u; } - bool use_null_layer_tree_frame_sink() const { - return use_null_layer_tree_frame_sink_; - } private: int num_requests_ = 0; @@ -171,11 +179,11 @@ } void DidInitializeLayerTreeFrameSink() override { + RenderWidgetCompositor::DidInitializeLayerTreeFrameSink(); delegate_->add_success(); if (delegate_->num_requests() == expected_requests_) { EndTest(); } else { - RenderWidgetCompositor::DidInitializeLayerTreeFrameSink(); // Post the synchronous composite task so that it is not called // reentrantly as a part of RequestNewLayerTreeFrameSink. base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -186,38 +194,48 @@ } void DidFailToInitializeLayerTreeFrameSink() override { + RenderWidgetCompositor::DidFailToInitializeLayerTreeFrameSink(); delegate_->add_failure(); if (delegate_->num_requests() == expected_requests_) { EndTest(); return; } - - RenderWidgetCompositor::DidFailToInitializeLayerTreeFrameSink(); } - void SetUp(int expected_successes, int expected_fallback_succeses) { + void SetUp(int expected_successes, FailureMode failure_mode) { + failure_mode_ = failure_mode; + switch (failure_mode_) { + case NO_FAILURE: + expected_requests_ = 1; + break; + case GPU_CHANNEL_FAILURE: + expected_requests_ = 2; + break; + } expected_successes_ = expected_successes; - expected_fallback_successes_ = expected_fallback_succeses; - expected_requests_ = delegate_->num_failures_before_success() + - expected_successes_ + expected_fallback_successes_; + expected_requests_ += (expected_successes - 1); } void EndTest() { base::MessageLoop::current()->QuitWhenIdle(); } void AfterTest() { - EXPECT_EQ(delegate_->num_failures_before_success(), - delegate_->num_failures()); - EXPECT_EQ(expected_successes_, delegate_->num_successes()); - EXPECT_EQ(expected_fallback_successes_, - delegate_->num_fallback_successes()); + if (failure_mode_ == NO_FAILURE) { + EXPECT_EQ(expected_successes_, delegate_->num_successes()); + EXPECT_EQ(0, delegate_->num_fallback_successes()); + } else if (failure_mode_ == GPU_CHANNEL_FAILURE) { + EXPECT_EQ(0, delegate_->num_successes()); + EXPECT_EQ(1, delegate_->num_fallback_successes()); + } else { + NOTREACHED(); + } EXPECT_EQ(expected_requests_, delegate_->num_requests()); } private: FakeRenderWidgetCompositorDelegate* delegate_; int expected_successes_ = 0; - int expected_fallback_successes_ = 0; int expected_requests_ = 0; + FailureMode failure_mode_ = NO_FAILURE; DISALLOW_COPY_AND_ASSIGN(RenderWidgetLayerTreeFrameSink); }; @@ -240,15 +258,14 @@ } void RunTest(bool use_null_layer_tree_frame_sink, - int num_failures_before_success, int expected_successes, - int expected_fallback_succeses) { + FailureMode failure_mode) { + compositor_delegate_.Reset(); compositor_delegate_.set_use_null_layer_tree_frame_sink( use_null_layer_tree_frame_sink); compositor_delegate_.set_num_failures_before_success( - num_failures_before_success); - render_widget_compositor_.SetUp(expected_successes, - expected_fallback_succeses); + failure_mode == NO_FAILURE ? 0 : 1); + render_widget_compositor_.SetUp(expected_successes, failure_mode); render_widget_compositor_.SetVisible(true); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, @@ -270,48 +287,31 @@ }; TEST_F(RenderWidgetLayerTreeFrameSinkTest, SucceedOnce) { - RunTest(false, 0, 1, 0); + RunTest(false, 1, NO_FAILURE); } TEST_F(RenderWidgetLayerTreeFrameSinkTest, SucceedTwice) { - RunTest(false, 0, 2, 0); + RunTest(false, 2, NO_FAILURE); } TEST_F(RenderWidgetLayerTreeFrameSinkTest, FailOnceNull) { - static_assert( - RenderWidgetCompositor::LAYER_TREE_FRAME_SINK_RETRIES_BEFORE_FALLBACK >= - 2, - "Adjust the values of this test if this fails"); - RunTest(true, 1, 1, 0); -} - -TEST_F(RenderWidgetLayerTreeFrameSinkTest, FailOnceBind) { - static_assert( - RenderWidgetCompositor::LAYER_TREE_FRAME_SINK_RETRIES_BEFORE_FALLBACK >= - 2, - "Adjust the values of this test if this fails"); - RunTest(false, 1, 1, 0); + RunTest(true, 1, NO_FAILURE); } // Android doesn't support fallback frame sinks. (crbug.com/721102) -#ifndef OS_ANDROID -TEST_F(RenderWidgetLayerTreeFrameSinkTest, FallbackSuccessNull) { - RunTest(true, - RenderWidgetCompositor::LAYER_TREE_FRAME_SINK_RETRIES_BEFORE_FALLBACK, - 0, 1); +#if !defined(OS_ANDROID) +TEST_F(RenderWidgetLayerTreeFrameSinkTest, SoftwareFallbackSucceed) { + RunTest(false, 1, GPU_CHANNEL_FAILURE); } -TEST_F(RenderWidgetLayerTreeFrameSinkTest, FallbackSuccessBind) { - RunTest(false, - RenderWidgetCompositor::LAYER_TREE_FRAME_SINK_RETRIES_BEFORE_FALLBACK, - 0, 1); +TEST_F(RenderWidgetLayerTreeFrameSinkTest, FallbackSuccessNull) { + RunTest(true, 1, GPU_CHANNEL_FAILURE); } TEST_F(RenderWidgetLayerTreeFrameSinkTest, FallbackSuccessNormalSuccess) { // The first success is a fallback, but the next should not be a fallback. - RunTest(false, - RenderWidgetCompositor::LAYER_TREE_FRAME_SINK_RETRIES_BEFORE_FALLBACK, - 1, 1); + RunTest(false, 1, GPU_CHANNEL_FAILURE); + RunTest(false, 1, NO_FAILURE); } #endif
diff --git a/content/renderer/pepper/pepper_plugin_instance_metrics.cc b/content/renderer/pepper/pepper_plugin_instance_metrics.cc index b0736e7c..2df79b7 100644 --- a/content/renderer/pepper/pepper_plugin_instance_metrics.cc +++ b/content/renderer/pepper/pepper_plugin_instance_metrics.cc
@@ -11,10 +11,6 @@ #include "build/build_config.h" #include "ppapi/shared_impl/ppapi_preferences.h" -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - #define UMA_HISTOGRAM_ASPECT_RATIO(name, width, height) \ UMA_HISTOGRAM_SPARSE_SLOWLY( \ name, (height) ? ((width)*100) / (height) : kInfiniteRatio); @@ -84,7 +80,6 @@ // run Stage3D content on machines that have it blacklisted. #if defined(OS_WIN) bool needs_gpu = false; - bool is_xp = base::win::GetVersion() <= base::win::VERSION_XP; for (size_t i = 0; i < arg_names.size(); i++) { if (arg_names[i] == "wmode") { @@ -99,12 +94,8 @@ // 1 : No 3D content and GPU is not blacklisted // 2 : 3D content but GPU is blacklisted // 3 : 3D content and GPU is not blacklisted - // 4 : No 3D content and GPU is blacklisted on XP - // 5 : No 3D content and GPU is not blacklisted on XP - // 6 : 3D content but GPU is blacklisted on XP - // 7 : 3D content and GPU is not blacklisted on XP - UMA_HISTOGRAM_ENUMERATION( - "Flash.UsesGPU", is_xp * 4 + needs_gpu * 2 + prefs.is_webgl_supported, 8); + UMA_HISTOGRAM_ENUMERATION("Flash.UsesGPU", + needs_gpu * 2 + prefs.is_webgl_supported, 8); #endif }
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 388367820..e22d4f20 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -670,12 +670,13 @@ IsRunningInMash() ? ui::mojom::kServiceName : mojom::kBrowserServiceName, GetIOTaskRunner()); - cc::mojom::SharedBitmapAllocationNotifierAssociatedPtr + cc::mojom::SharedBitmapAllocationNotifierPtr shared_bitmap_allocation_notifier_ptr; - render_message_filter()->GetSharedBitmapAllocationNotifier( + GetConnector()->BindInterface( + mojom::kBrowserServiceName, mojo::MakeRequest(&shared_bitmap_allocation_notifier_ptr)); shared_bitmap_manager_ = base::MakeUnique<viz::ClientSharedBitmapManager>( - cc::mojom::ThreadSafeSharedBitmapAllocationNotifierAssociatedPtr::Create( + cc::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr::Create( shared_bitmap_allocation_notifier_ptr.PassInterface(), GetChannel()->ipc_task_runner_refptr()));
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 934b624..0a7da2c 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -1178,7 +1178,7 @@ const wchar_t* result; }; static const ImeMessage kImeMessages[] = { - // Scenario 1: input a Chinese word with Microsoft IME (on Vista). + // Scenario 1: input a Chinese word with Microsoft IME. {IME_INITIALIZE, true, 0, 0, NULL, NULL}, {IME_SETINPUTMODE, true, 0, 0, NULL, NULL}, {IME_SETFOCUS, true, 0, 0, NULL, NULL}, @@ -1188,7 +1188,7 @@ {IME_SETCOMPOSITION, false, 4, 4, L"niha", L"niha"}, {IME_SETCOMPOSITION, false, 5, 5, L"nihao", L"nihao"}, {IME_COMMITTEXT, false, -1, -1, L"\x4F60\x597D", L"\x4F60\x597D"}, - // Scenario 2: input a Japanese word with Microsoft IME (on Vista). + // Scenario 2: input a Japanese word with Microsoft IME. {IME_INITIALIZE, true, 0, 0, NULL, NULL}, {IME_SETINPUTMODE, true, 0, 0, NULL, NULL}, {IME_SETFOCUS, true, 0, 0, NULL, NULL}, @@ -1203,7 +1203,7 @@ {IME_SETCOMPOSITION, false, 0, 2, L"\x6F22\x5B57", L"\x6F22\x5B57"}, {IME_FINISHCOMPOSINGTEXT, false, -1, -1, L"", L"\x6F22\x5B57"}, {IME_CANCELCOMPOSITION, false, -1, -1, L"", L"\x6F22\x5B57"}, - // Scenario 3: input a Korean word with Microsot IME (on Vista). + // Scenario 3: input a Korean word with Microsot IME. {IME_INITIALIZE, true, 0, 0, NULL, NULL}, {IME_SETINPUTMODE, true, 0, 0, NULL, NULL}, {IME_SETFOCUS, true, 0, 0, NULL, NULL}, @@ -1498,12 +1498,6 @@ #if defined(OS_MACOSX) || defined(USE_AURA) TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) { -#if defined(OS_WIN) - // http://crbug.com/304193 - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return; -#endif - LoadHTML("<textarea id=\"test\" cols=\"100\"></textarea>"); ExecuteJavaScriptForTests("document.getElementById('test').focus();");
diff --git a/content/shell/browser/layout_test/layout_test_url_request_context_getter.cc b/content/shell/browser/layout_test/layout_test_url_request_context_getter.cc index 0421518..b739b6f0 100644 --- a/content/shell/browser/layout_test/layout_test_url_request_context_getter.cc +++ b/content/shell/browser/layout_test/layout_test_url_request_context_getter.cc
@@ -10,7 +10,10 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/ignore_errors_cert_verifier.h" #include "content/shell/browser/shell_network_delegate.h" +#include "content/shell/common/layout_test/layout_test_switches.h" +#include "net/cert/cert_verifier.h" #include "net/proxy/proxy_service.h" namespace content { @@ -41,6 +44,13 @@ return base::WrapUnique(new ShellNetworkDelegate); } +std::unique_ptr<net::CertVerifier> +LayoutTestURLRequestContextGetter::GetCertVerifier() { + return IgnoreErrorsCertVerifier::MaybeWrapCertVerifier( + *base::CommandLine::ForCurrentProcess(), switches::kRunLayoutTest, + net::CertVerifier::CreateDefault()); +} + std::unique_ptr<net::ProxyConfigService> LayoutTestURLRequestContextGetter::GetProxyConfigService() { return nullptr;
diff --git a/content/shell/browser/layout_test/layout_test_url_request_context_getter.h b/content/shell/browser/layout_test/layout_test_url_request_context_getter.h index 1fc56da..342eb0f 100644 --- a/content/shell/browser/layout_test/layout_test_url_request_context_getter.h +++ b/content/shell/browser/layout_test/layout_test_url_request_context_getter.h
@@ -39,6 +39,7 @@ // ShellURLRequestContextGetter implementation. std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate() override; + std::unique_ptr<net::CertVerifier> GetCertVerifier() override; std::unique_ptr<net::ProxyConfigService> GetProxyConfigService() override; std::unique_ptr<net::ProxyService> GetProxyService() override;
diff --git a/content/shell/browser/shell_url_request_context_getter.cc b/content/shell/browser/shell_url_request_context_getter.cc index d161f06..a425e2b 100644 --- a/content/shell/browser/shell_url_request_context_getter.cc +++ b/content/shell/browser/shell_url_request_context_getter.cc
@@ -115,6 +115,11 @@ return base::WrapUnique(new ShellNetworkDelegate); } +std::unique_ptr<net::CertVerifier> +ShellURLRequestContextGetter::GetCertVerifier() { + return net::CertVerifier::CreateDefault(); +} + std::unique_ptr<net::ProxyConfigService> ShellURLRequestContextGetter::GetProxyConfigService() { return net::ProxyService::CreateSystemProxyConfigService(io_task_runner_); @@ -153,7 +158,7 @@ net::HostResolver::CreateDefaultResolver( url_request_context_->net_log())); - storage_->set_cert_verifier(net::CertVerifier::CreateDefault()); + storage_->set_cert_verifier(GetCertVerifier()); storage_->set_transport_security_state( base::WrapUnique(new net::TransportSecurityState)); storage_->set_cert_transparency_verifier(
diff --git a/content/shell/browser/shell_url_request_context_getter.h b/content/shell/browser/shell_url_request_context_getter.h index fdfdac2..fbeb854 100644 --- a/content/shell/browser/shell_url_request_context_getter.h +++ b/content/shell/browser/shell_url_request_context_getter.h
@@ -18,6 +18,7 @@ #include "net/url_request/url_request_job_factory.h" namespace net { +class CertVerifier; class HostResolver; class NetworkDelegate; class NetLog; @@ -51,6 +52,7 @@ // Used by subclasses to create their own implementation of NetworkDelegate // and net::ProxyService. virtual std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate(); + virtual std::unique_ptr<net::CertVerifier> GetCertVerifier(); virtual std::unique_ptr<net::ProxyConfigService> GetProxyConfigService(); virtual std::unique_ptr<net::ProxyService> GetProxyService();
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index ac1e5a06..21739d7 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1127,7 +1127,6 @@ "../browser/dom_storage/dom_storage_database_unittest.cc", "../browser/dom_storage/local_storage_context_mojo_unittest.cc", "../browser/dom_storage/session_storage_database_unittest.cc", - "../browser/download/all_download_item_notifier_unittest.cc", "../browser/download/base_file_unittest.cc", "../browser/download/base_file_win_unittest.cc", "../browser/download/download_file_unittest.cc", @@ -1329,6 +1328,7 @@ "../browser/shared_worker/shared_worker_instance_unittest.cc", "../browser/shared_worker/shared_worker_service_impl_unittest.cc", "../browser/site_instance_impl_unittest.cc", + "../browser/ssl/ignore_errors_cert_verifier_unittest.cc", "../browser/ssl/ssl_manager_unittest.cc", "../browser/startup_task_runner_unittest.cc", "../browser/storage_partition_impl_map_unittest.cc",
diff --git a/content/test/content_browser_test_test.cc b/content/test/content_browser_test_test.cc index 446349da..f9799b6d 100644 --- a/content/test/content_browser_test_test.cc +++ b/content/test/content_browser_test_test.cc
@@ -25,10 +25,6 @@ #include "content/shell/common/shell_switches.h" #include "testing/gtest/include/gtest/gtest.h" -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - namespace content { // Disabled on official builds because symbolization in sandboxes processes @@ -73,13 +69,6 @@ // Tests that browser tests print the callstack when a child process crashes. IN_PROC_BROWSER_TEST_F(ContentBrowserTest, RendererCrashCallStack) { -#if defined(OS_WIN) - // Matches the same condition in RouteStdioToConsole, which makes this test - // fail on XP. - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return; -#endif - base::ThreadRestrictions::ScopedAllowIO allow_io_for_temp_dir; base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 935ae4d..9d982ee 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -63,6 +63,8 @@ bug=1966) # angle bug ID # Windows only. + self.Fail('conformance/glsl/bugs/sampler-struct-function-arg.html', + ['win'], bug=2103) # angle bug ID self.Fail('conformance2/rendering/blitframebuffer-outside-readbuffer.html', ['win', 'd3d11'], bug=644740) self.Fail('conformance2/textures/misc/tex-base-level-bug.html', @@ -70,6 +72,8 @@ self.Flaky('conformance2/textures/svg_image/' + 'tex-2d-rgb565-rgb-unsigned_short_5_6_5.html', ['win'], bug=736926) + self.Fail('conformance2/uniforms/uniform-blocks-with-arrays.html', + ['win'], bug=2103) # angle bug ID # Win / NVidia self.Flaky('deqp/functional/gles3/fbomultisample*', @@ -382,6 +386,10 @@ ['mac', ('nvidia', 0xfe9)], bug=654187) # Mac AMD + self.Fail('conformance/rendering/texture-switch-performance.html', + ['mac', 'amd'], bug=735483) + self.Fail('conformance2/rendering/texture-switch-performance.html', + ['mac', 'amd'], bug=735483) self.Fail('deqp/functional/gles3/transformfeedback/' + 'array_interleaved_lines.html', ['mac', 'amd'], bug=483282) @@ -587,6 +595,8 @@ ['linux', 'nvidia'], bug=679677) self.Fail('conformance2/rendering/framebuffer-texture-level1.html', ['linux', 'nvidia', 'opengl'], bug=680278) + self.Fail('conformance2/rendering/multisampling-fragment-evaluation.html', + ['linux', 'nvidia', 'no_passthrough'], bug=682815) self.Fail('conformance2/textures/image/' + 'tex-3d-rg8ui-rg_integer-unsigned_byte.html', ['linux', ('nvidia', 0xf02)], bug=680282)
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index bdde5f75..ecfb0f4 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -195,6 +195,9 @@ ['win', 'nvidia', 'passthrough', 'd3d11'], bug=737016) # Win failures + # TODO(kbr): re-enable suppression for same test below once fixed. + self.Fail('conformance/glsl/bugs/sampler-struct-function-arg.html', + ['win'], bug=2103) # angle bug ID # Note that the following test seems to pass, but it may still be flaky. self.Fail('conformance/glsl/constructors/' + 'glsl-construct-vec-mat-index.html', @@ -314,8 +317,8 @@ ['win', 'intel', 'opengl'], bug=1007) # angle bug ID self.Fail('conformance/uniforms/uniform-default-values.html', ['win', 'intel', 'opengl'], bug=1007) # angle bug ID - self.Fail('conformance/glsl/bugs/sampler-struct-function-arg.html', - ['win10', 'intel', 'opengl'], bug=1007) # angle bug ID + # self.Fail('conformance/glsl/bugs/sampler-struct-function-arg.html', + # ['win10', 'intel', 'opengl'], bug=1007) # angle bug ID self.Fail('conformance/glsl/variables/gl-pointcoord.html', ['win10', 'intel', 'opengl'], bug=1007) # angle bug ID @@ -376,6 +379,8 @@ ['mac', 'amd', 'no_passthrough'], bug=625365) self.Fail('conformance/rendering/clipping-wide-points.html', ['mac', 'amd'], bug=642822) + self.Fail('conformance/rendering/texture-switch-performance.html', + ['mac', 'amd'], bug=735483) # Mac Retina NVidia failures self.Fail('conformance/attribs/gl-disabled-vertex-attrib.html', @@ -468,6 +473,16 @@ self.Skip('conformance/textures/misc/texture-npot-video.html', ['android', 'android-webview-instrumentation', 'no_passthrough'], bug=352645) + # New video-to-luminance-alpha tests are failing on Android right now. + self.Fail('conformance/textures/video/' + + 'tex-2d-alpha-alpha-unsigned_byte.html', + ['android'], bug=733599) + self.Fail('conformance/textures/video/' + + 'tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html', + ['android'], bug=733599) + self.Fail('conformance/textures/video/' + + 'tex-2d-luminance-luminance-unsigned_byte.html', + ['android'], bug=733599) # This crashes in Android WebView on the Nexus 6, preventing the # suite from running further. Rather than add multiple # suppressions, skip it until it's passing at least in content
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_revision.txt b/content/test/gpu/gpu_tests/webgl_conformance_revision.txt index ef76714..223e1a0 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_revision.txt +++ b/content/test/gpu/gpu_tests/webgl_conformance_revision.txt
@@ -1,3 +1,3 @@ # AUTOGENERATED FILE - DO NOT EDIT # SEE roll_webgl_conformance.py -Current webgl revision 5e57726d6fe2833c957b5a33cd0aed19d67a4fa9 +Current webgl revision 72eda82d069da578af04e5c4e8e411ae006b6a18
diff --git a/docs/callback.md b/docs/callback.md index 5f93ad6a..3c5fec5d 100644 --- a/docs/callback.md +++ b/docs/callback.md
@@ -76,7 +76,9 @@ When you pass a `Callback` object to a function parameter, use `std::move()` if you don't need to keep a reference to it, otherwise, pass the object directly. You may see a compile error when the function requires the exclusive ownership, -and you didn't pass the callback by move. +and you didn't pass the callback by move. Note that the moved-from `Callback` +becomes null, as if its `Reset()` method had been called, and its `is_null()` +method will return true. ## Quick reference for basic stuff
diff --git a/docs/speed/README.md b/docs/speed/README.md index 7421f550..967349e 100644 --- a/docs/speed/README.md +++ b/docs/speed/README.md
@@ -17,7 +17,6 @@ * [I want Chrome to have better performance](help_improve_performance.md) * [Perf sheriffing documentation](perf_regression_sheriffing.md) * [I want to add tests or platforms to the perf waterfall](adding_tests_bots.md) - * [I'm looking for more information on the Speed Progam](speed_program.md) ## Core Teams and Work
diff --git a/docs/testing/web_platform_tests.md b/docs/testing/web_platform_tests.md index acdf2cc..36f2dae 100644 --- a/docs/testing/web_platform_tests.md +++ b/docs/testing/web_platform_tests.md
@@ -63,20 +63,38 @@ ### Automatic export process -If a commit to Chromium master changes any files in the -[third_party/WebKit/LayoutTests/external/wpt](../../third_party/WebKit/LayoutTests/external/wpt) -directory, the WPT Exporter will create a Pull Request on GitHub for it. -All PRs use the `chromium-export` label: see -[all of them here](https://github.com/w3c/web-platform-tests/pulls?utf8=%E2%9C%93&q=is%3Apr%20label%3Achromium-export). -The exporter runs continuously under the chromium.infra.cron master: -see [all recent builds](https://build.chromium.org/p/chromium.infra.cron/builders/wpt-exporter). -The source for the exporter lives in -[third_party/WebKit/Tools/Scripts/wpt-exporter](../../third_party/WebKit/Tools/Scripts/wpt-exporter). +If you upload a CL with any changes in +[third_party/WebKit/LayoutTests/external/wpt](../../third_party/WebKit/LayoutTests/external/wpt), +once you add reviewers the exporter will create a provisional pull request with +those changes in the [upstream WPT GitHub repository](https://github.com/w3c/web-platform-tests/). -In the unlikely event that the exporter starts misbehaving -- for example, -creating the same PR over and over again -- **all you need to do to disable the -exporter is [land this CL](https://chromium-review.googlesource.com/c/462381/)**, -which will put it in "dry run" mode. +Once you're ready to land your CL, please check the Travis CI status on the +upstream PR (link at the bottom of the page). If it's green, go ahead and land your CL +and the exporter will automatically remove the "do not merge yet" label and merge the PR. + +If Travis CI is red on the upstream PR, please try to resolve the failures before +merging. If you run into Travis CI issues, or if you have a CL with WPT changes that +the exporter did not pick up, please reach out to ecosystem-infra@chromium.org. + +Additional things to note: + +- CLs that change over 1000 files will not be exported. +- All PRs use the + [`chromium-export`](https://github.com/w3c/web-platform-tests/pulls?utf8=%E2%9C%93&q=is%3Apr%20label%3Achromium-export) label. +- All PRs for CLs that haven't yet been landed in Chromium also use the + [`do not merge yet`](https://github.com/w3c/web-platform-tests/pulls?q=is%3Apr+is%3Aopen+label%3A%22do+not+merge+yet%22) label. +- The exporter cannot create upstream PRs for in-flight CLs with binary files (e.g. webm files). + An export PR will still be made after the CL lands. + +For maintainers: + +- The exporter runs continuously under the + [chromium.infra.cron master](https://build.chromium.org/p/chromium.infra.cron/builders/wpt-exporter). +- The source lives in + [third_party/WebKit/Tools/Scripts/wpt-exporter](../../third_party/WebKit/Tools/Scripts/wpt-exporter). +- If the exporter starts misbehaving + (for example, creating the same PR over and over again) + put it in "dry run" mode by landing [this CL](https://crrev.com/c/462381/). ### Skipped tests
diff --git a/extensions/browser/api/cast_channel/cast_channel_api.cc b/extensions/browser/api/cast_channel/cast_channel_api.cc index 811b681d..94f90eb 100644 --- a/extensions/browser/api/cast_channel/cast_channel_api.cc +++ b/extensions/browser/api/cast_channel/cast_channel_api.cc
@@ -22,7 +22,6 @@ #include "components/cast_channel/cast_message_util.h" #include "components/cast_channel/cast_socket.h" #include "components/cast_channel/cast_socket_service.h" -#include "components/cast_channel/cast_socket_service_factory.h" #include "components/cast_channel/keep_alive_delegate.h" #include "components/cast_channel/logger.h" #include "components/cast_channel/proto/cast_channel.pb.h" @@ -137,6 +136,18 @@ } } +cast_channel::CastSocket::Observer* CastChannelAPI::GetObserver( + const std::string& extension_id, + scoped_refptr<cast_channel::Logger> logger) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + if (!observer_) { + observer_.reset(new CastMessageHandler( + base::Bind(&CastChannelAPI::SendEvent, this->AsWeakPtr(), extension_id), + logger)); + } + return observer_.get(); +} + static base::LazyInstance< BrowserContextKeyedAPIFactory<CastChannelAPI>>::DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER; @@ -168,9 +179,7 @@ CastChannelAsyncApiFunction::~CastChannelAsyncApiFunction() { } bool CastChannelAsyncApiFunction::PrePrepare() { - cast_socket_service_ = - cast_channel::CastSocketServiceFactory::GetForBrowserContext( - browser_context()); + cast_socket_service_ = cast_channel::CastSocketService::GetInstance(); DCHECK(cast_socket_service_); return true; } @@ -277,14 +286,8 @@ if (test_socket.get()) cast_socket_service_->SetSocketForTest(std::move(test_socket)); - auto* observer = cast_socket_service_->GetObserver(extension_->id()); - if (!observer) { - observer = cast_socket_service_->AddObserver( - extension_->id(), base::MakeUnique<CastMessageHandler>( - base::Bind(&CastChannelAPI::SendEvent, - api_->AsWeakPtr(), extension_->id()), - cast_socket_service_->GetLogger())); - } + auto* observer = + api_->GetObserver(extension_->id(), cast_socket_service_->GetLogger()); cast_socket_service_->OpenSocket( *ip_endpoint_, ExtensionsBrowserClient::Get()->GetNetLog(), @@ -422,20 +425,23 @@ AsyncWorkCompleted(); } -CastChannelOpenFunction::CastMessageHandler::CastMessageHandler( +CastChannelAPI::CastMessageHandler::CastMessageHandler( const EventDispatchCallback& ui_dispatch_cb, scoped_refptr<Logger> logger) : ui_dispatch_cb_(ui_dispatch_cb), logger_(logger) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(logger_); } -CastChannelOpenFunction::CastMessageHandler::~CastMessageHandler() { +CastChannelAPI::CastMessageHandler::~CastMessageHandler() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + cast_channel::CastSocketService::GetInstance()->RemoveObserver(this); } -void CastChannelOpenFunction::CastMessageHandler::OnError( +void CastChannelAPI::CastMessageHandler::OnError( const cast_channel::CastSocket& socket, ChannelError error_state) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); ChannelInfo channel_info; FillChannelInfo(socket, &channel_info); @@ -453,10 +459,10 @@ base::Bind(ui_dispatch_cb_, base::Passed(std::move(event)))); } -void CastChannelOpenFunction::CastMessageHandler::OnMessage( +void CastChannelAPI::CastMessageHandler::OnMessage( const cast_channel::CastSocket& socket, const CastMessage& message) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); MessageInfo message_info; CastMessageToMessageInfo(message, &message_info);
diff --git a/extensions/browser/api/cast_channel/cast_channel_api.h b/extensions/browser/api/cast_channel/cast_channel_api.h index c65af793..69c2a74 100644 --- a/extensions/browser/api/cast_channel/cast_channel_api.h +++ b/extensions/browser/api/cast_channel/cast_channel_api.h
@@ -60,11 +60,49 @@ // Sends an event to the extension's EventRouter, if it exists. void SendEvent(const std::string& extension_id, std::unique_ptr<Event> event); + // Registers |extension_id| with |observer_| and returns |observer_|. + cast_channel::CastSocket::Observer* GetObserver( + const std::string& extension_id, + scoped_refptr<cast_channel::Logger> logger); + private: friend class BrowserContextKeyedAPIFactory<CastChannelAPI>; friend class ::CastChannelAPITest; friend class CastTransportDelegate; + // Defines a callback used to send events to the extension's + // EventRouter. + // Parameter #0 is a unique pointer to the event payload. + using EventDispatchCallback = base::Callback<void(std::unique_ptr<Event>)>; + + // Receives incoming messages and errors and provides additional API context. + class CastMessageHandler : public cast_channel::CastSocket::Observer { + public: + CastMessageHandler(const EventDispatchCallback& ui_dispatch_cb, + scoped_refptr<cast_channel::Logger> logger); + ~CastMessageHandler() override; + + // CastSocket::Observer implementation. + void OnError(const cast_channel::CastSocket& socket, + cast_channel::ChannelError error_state) override; + void OnMessage(const cast_channel::CastSocket& socket, + const cast_channel::CastMessage& message) override; + + void RegisterExtensionId(const std::string& extension_id); + + private: + // Callback for sending events to the extension. + // Should be bound to a weak pointer, to prevent any use-after-free + // conditions. + EventDispatchCallback const ui_dispatch_cb_; + // Logger object for reporting error details. + scoped_refptr<cast_channel::Logger> logger_; + + THREAD_CHECKER(thread_checker_); + + DISALLOW_COPY_AND_ASSIGN(CastMessageHandler); + }; + ~CastChannelAPI() override; // BrowserContextKeyedAPI implementation. @@ -72,6 +110,9 @@ content::BrowserContext* const browser_context_; std::unique_ptr<cast_channel::CastSocket> socket_for_test_; + // Created and destroyed on the IO thread. + std::unique_ptr<CastMessageHandler, content::BrowserThread::DeleteOnIOThread> + observer_; DISALLOW_COPY_AND_ASSIGN(CastChannelAPI); }; @@ -96,8 +137,9 @@ void SetResultFromError(int channel_id, api::cast_channel::ChannelError error); - // Manages creating and removing Cast sockets. - scoped_refptr<cast_channel::CastSocketService> cast_socket_service_; + // Raw pointer of leaky singleton CastSocketService, which manages creating + // and removing Cast sockets. + cast_channel::CastSocketService* cast_socket_service_; private: // Sets the function result from |channel_info|. @@ -120,35 +162,6 @@ private: DECLARE_EXTENSION_FUNCTION("cast.channel.open", CAST_CHANNEL_OPEN) - // Defines a callback used to send events to the extension's - // EventRouter. - // Parameter #0 is a scoped pointer to the event payload. - using EventDispatchCallback = base::Callback<void(std::unique_ptr<Event>)>; - - // Receives incoming messages and errors and provides additional API context. - class CastMessageHandler : public cast_channel::CastSocket::Observer { - public: - CastMessageHandler(const EventDispatchCallback& ui_dispatch_cb, - scoped_refptr<cast_channel::Logger> logger); - ~CastMessageHandler() override; - - // CastSocket::Observer implementation. - void OnError(const cast_channel::CastSocket& socket, - cast_channel::ChannelError error_state) override; - void OnMessage(const cast_channel::CastSocket& socket, - const cast_channel::CastMessage& message) override; - - private: - // Callback for sending events to the extension. - // Should be bound to a weak pointer, to prevent any use-after-free - // conditions. - EventDispatchCallback const ui_dispatch_cb_; - // Logger object for reporting error details. - scoped_refptr<cast_channel::Logger> logger_; - - DISALLOW_COPY_AND_ASSIGN(CastMessageHandler); - }; - // Validates that |connect_info| represents a valid IP end point and returns a // new IPEndPoint if so. Otherwise returns nullptr. static net::IPEndPoint* ParseConnectInfo(
diff --git a/extensions/browser/api/cast_channel/cast_channel_apitest.cc b/extensions/browser/api/cast_channel/cast_channel_apitest.cc index b3d76cb..a93e7b54 100644 --- a/extensions/browser/api/cast_channel/cast_channel_apitest.cc +++ b/extensions/browser/api/cast_channel/cast_channel_apitest.cc
@@ -14,7 +14,6 @@ #include "chrome/browser/ui/browser.h" #include "components/cast_channel/cast_socket.h" #include "components/cast_channel/cast_socket_service.h" -#include "components/cast_channel/cast_socket_service_factory.h" #include "components/cast_channel/cast_test_util.h" #include "components/cast_channel/logger.h" #include "components/cast_channel/proto/cast_channel.pb.h" @@ -145,8 +144,11 @@ .WillOnce(Return(ReadyState::OPEN)) .RetiresOnSaturation(); EXPECT_CALL(*mock_cast_socket_, ready_state()) - .WillOnce(Return(ReadyState::CLOSED)); + .Times(2) + .WillRepeatedly(Return(ReadyState::CLOSED)); } + EXPECT_CALL(*mock_cast_socket_, Close(_)) + .WillOnce(InvokeCompletionCallback<0>(net::OK)); } extensions::CastChannelAPI* GetApi() { @@ -154,9 +156,7 @@ } cast_channel::CastSocketService* GetCastSocketService() { - return cast_channel::CastSocketServiceFactory::GetForBrowserContext( - profile()) - .get(); + return cast_channel::CastSocketService::GetInstance(); } // Logs some bogus error details and calls the OnError handler. @@ -224,7 +224,7 @@ content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, base::Bind(&CastChannelAPITest::DoCallOnError, base::Unretained(api_test), - base::RetainedRef(cast_socket_service))); + base::Unretained(cast_socket_service))); } // TODO(kmarshall): Win Dbg has a workaround that makes RunExtensionSubtest
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc index 5ce0945..e40ca95 100644 --- a/extensions/browser/extension_prefs.cc +++ b/extensions/browser/extension_prefs.cc
@@ -14,6 +14,7 @@ #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" @@ -214,8 +215,8 @@ DISALLOW_COPY_AND_ASSIGN(ScopedExtensionPrefUpdate); }; -std::string JoinPrefs(const std::string& parent, const char* child) { - return parent + "." + child; +std::string JoinPrefs(base::StringPiece parent, base::StringPiece child) { + return base::JoinString({parent, child}, "."); } // Checks if kPrefBlacklist is set to true in the base::DictionaryValue. @@ -435,7 +436,7 @@ void ExtensionPrefs::UpdateExtensionPref( const std::string& extension_id, - const std::string& key, + base::StringPiece key, std::unique_ptr<base::Value> data_value) { if (!crx_file::id_util::IdIsValid(extension_id)) { NOTREACHED() << "Invalid extension_id " << extension_id; @@ -457,7 +458,7 @@ } bool ExtensionPrefs::ReadPrefAsBoolean(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, bool* out_value) const { const base::DictionaryValue* ext = GetExtensionPref(extension_id); if (!ext || !ext->GetBoolean(pref_key, out_value)) @@ -467,7 +468,7 @@ } bool ExtensionPrefs::ReadPrefAsInteger(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, int* out_value) const { const base::DictionaryValue* ext = GetExtensionPref(extension_id); if (!ext || !ext->GetInteger(pref_key, out_value)) @@ -477,7 +478,7 @@ } bool ExtensionPrefs::ReadPrefAsString(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, std::string* out_value) const { const base::DictionaryValue* ext = GetExtensionPref(extension_id); if (!ext || !ext->GetString(pref_key, out_value)) @@ -487,7 +488,7 @@ } bool ExtensionPrefs::ReadPrefAsList(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, const base::ListValue** out_value) const { const base::DictionaryValue* ext = GetExtensionPref(extension_id); const base::ListValue* out = NULL; @@ -501,7 +502,7 @@ bool ExtensionPrefs::ReadPrefAsDictionary( const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, const base::DictionaryValue** out_value) const { const base::DictionaryValue* ext = GetExtensionPref(extension_id); const base::DictionaryValue* out = NULL; @@ -519,7 +520,7 @@ } bool ExtensionPrefs::ReadPrefAsURLPatternSet(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, URLPatternSet* result, int valid_schemes) const { const base::ListValue* value = NULL; @@ -540,21 +541,21 @@ void ExtensionPrefs::SetExtensionPrefURLPatternSet( const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, const URLPatternSet& new_value) { UpdateExtensionPref(extension_id, pref_key, new_value.ToValue()); } bool ExtensionPrefs::ReadPrefAsBooleanAndReturn( const std::string& extension_id, - const std::string& pref_key) const { + base::StringPiece pref_key) const { bool out_value = false; return ReadPrefAsBoolean(extension_id, pref_key, &out_value) && out_value; } std::unique_ptr<const PermissionSet> ExtensionPrefs::ReadPrefAsPermissionSet( const std::string& extension_id, - const std::string& pref_key) const { + base::StringPiece pref_key) const { if (!GetExtensionPref(extension_id)) return nullptr; @@ -625,7 +626,7 @@ void ExtensionPrefs::SetExtensionPrefPermissionSet( const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, const PermissionSet& new_value) { std::string api_pref = JoinPrefs(pref_key, kPrefAPIs); UpdateExtensionPref(extension_id, api_pref,
diff --git a/extensions/browser/extension_prefs.h b/extensions/browser/extension_prefs.h index b4395f93..9e2f4f10 100644 --- a/extensions/browser/extension_prefs.h +++ b/extensions/browser/extension_prefs.h
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/observer_list.h" +#include "base/strings/string_piece_forward.h" #include "base/time/time.h" #include "base/values.h" #include "components/keyed_service/core/keyed_service.h" @@ -247,30 +248,30 @@ // ExtensionScopedPrefs methods: void UpdateExtensionPref(const std::string& id, - const std::string& key, + base::StringPiece key, std::unique_ptr<base::Value> value) override; void DeleteExtensionPrefs(const std::string& id) override; bool ReadPrefAsBoolean(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, bool* out_value) const override; bool ReadPrefAsInteger(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, int* out_value) const override; bool ReadPrefAsString(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, std::string* out_value) const override; bool ReadPrefAsList(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, const base::ListValue** out_value) const override; bool ReadPrefAsDictionary( const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, const base::DictionaryValue** out_value) const override; bool HasPrefForExtension(const std::string& extension_id) const override; @@ -601,7 +602,7 @@ // Interprets the list pref, |pref_key| in |extension_id|'s preferences, as a // URLPatternSet. The |valid_schemes| specify how to parse the URLPatterns. bool ReadPrefAsURLPatternSet(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, URLPatternSet* result, int valid_schemes) const; @@ -614,24 +615,24 @@ // Converts |new_value| to a list of strings and sets the |pref_key| pref // belonging to |extension_id|. void SetExtensionPrefURLPatternSet(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, const URLPatternSet& new_value); // Read the boolean preference entry and return true if the preference exists // and the preference's value is true; false otherwise. bool ReadPrefAsBooleanAndReturn(const std::string& extension_id, - const std::string& key) const; + base::StringPiece pref_key) const; // Interprets |pref_key| in |extension_id|'s preferences as an // PermissionSet, and passes ownership of the set to the caller. std::unique_ptr<const PermissionSet> ReadPrefAsPermissionSet( const std::string& extension_id, - const std::string& pref_key) const; + base::StringPiece pref_key) const; // Converts the |new_value| to its value and sets the |pref_key| pref // belonging to |extension_id|. void SetExtensionPrefPermissionSet(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, const PermissionSet& new_value); // Returns an immutable dictionary for extension |id|'s prefs, or NULL if it
diff --git a/extensions/browser/extension_scoped_prefs.h b/extensions/browser/extension_scoped_prefs.h index f814db7..2e988d8 100644 --- a/extensions/browser/extension_scoped_prefs.h +++ b/extensions/browser/extension_scoped_prefs.h
@@ -8,6 +8,8 @@ #include <memory> #include <string> +#include "base/strings/string_piece_forward.h" + namespace base { class DictionaryValue; class ListValue; @@ -23,7 +25,7 @@ // Sets the pref |key| for extension |id| to |value|. virtual void UpdateExtensionPref(const std::string& id, - const std::string& key, + base::StringPiece key, std::unique_ptr<base::Value> value) = 0; // Deletes the pref dictionary for extension |id|. @@ -31,28 +33,28 @@ // Reads a boolean pref |pref_key| from extension with id |extension_id|. virtual bool ReadPrefAsBoolean(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, bool* out_value) const = 0; // Reads an integer pref |pref_key| from extension with id |extension_id|. virtual bool ReadPrefAsInteger(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, int* out_value) const = 0; // Reads a string pref |pref_key| from extension with id |extension_id|. virtual bool ReadPrefAsString(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, std::string* out_value) const = 0; // Reads a list pref |pref_key| from extension with id |extension_id|. virtual bool ReadPrefAsList(const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, const base::ListValue** out_value) const = 0; // Reads a dictionary pref |pref_key| from extension with id |extension_id|. virtual bool ReadPrefAsDictionary( const std::string& extension_id, - const std::string& pref_key, + base::StringPiece pref_key, const base::DictionaryValue** out_value) const = 0; // Returns true if the prefs contain an entry for an extension with id
diff --git a/extensions/renderer/user_script_set.cc b/extensions/renderer/user_script_set.cc index b4ed9cc..6288a37 100644 --- a/extensions/renderer/user_script_set.cc +++ b/extensions/renderer/user_script_set.cc
@@ -8,6 +8,7 @@ #include <utility> +#include "base/debug/alias.h" #include "base/memory/ref_counted.h" #include "content/public/common/url_constants.h" #include "content/public/renderer/render_frame.h" @@ -35,6 +36,11 @@ // user script to wrap it in an anonymous scope. const char kUserScriptHead[] = "(function (unsafeWindow) {\n"; const char kUserScriptTail[] = "\n})(window);"; +// Maximum number of total content scripts we allow (across all extensions). +// The limit exists to diagnose https://crbug.com/723381. The number is +// arbitrarily chosen. +// TODO(lazyboy): Remove when the bug is fixed. +const uint32_t kNumScriptsArbitraryMax = 100000u; GURL GetDocumentUrlForFrame(blink::WebLocalFrame* frame) { GURL data_source_url = ScriptContext::GetDataSourceURLForFrame(frame); @@ -115,8 +121,14 @@ base::Pickle pickle(reinterpret_cast<char*>(shared_memory_->memory()), pickle_size); base::PickleIterator iter(pickle); + base::debug::Alias(&pickle_size); CHECK(iter.ReadUInt32(&num_scripts)); + // Sometimes the shared memory contents seem to be corrupted + // (https://crbug.com/723381). Set an arbitrary max limit to the number of + // scripts so that we don't add OOM noise to crash reports. + CHECK_LT(num_scripts, kNumScriptsArbitraryMax); + scripts_.clear(); script_sources_.clear(); scripts_.reserve(num_scripts);
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.h b/ios/public/provider/chrome/browser/chrome_browser_provider.h index 5a0c81a4..5792a70 100644 --- a/ios/public/provider/chrome/browser/chrome_browser_provider.h +++ b/ios/public/provider/chrome/browser/chrome_browser_provider.h
@@ -157,6 +157,9 @@ // Returns an instance of the spotlight provider. virtual SpotlightProvider* GetSpotlightProvider() const; + // Checks for native iOS apps that are installed. + virtual void CheckForFirstPartyApps() const; + // Adds and removes observers. void AddObserver(Observer* observer); void RemoveObserver(Observer* observer);
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.mm b/ios/public/provider/chrome/browser/chrome_browser_provider.mm index 8f9a57c..a6628c9 100644 --- a/ios/public/provider/chrome/browser/chrome_browser_provider.mm +++ b/ios/public/provider/chrome/browser/chrome_browser_provider.mm
@@ -108,6 +108,8 @@ return nullptr; } +void ChromeBrowserProvider::CheckForFirstPartyApps() const {} + BrandedImageProvider* ChromeBrowserProvider::GetBrandedImageProvider() const { return nullptr; }
diff --git a/ios/public/provider/chrome/browser/test_chrome_browser_provider.h b/ios/public/provider/chrome/browser/test_chrome_browser_provider.h index 7fdc76b..d7f95ea 100644 --- a/ios/public/provider/chrome/browser/test_chrome_browser_provider.h +++ b/ios/public/provider/chrome/browser/test_chrome_browser_provider.h
@@ -33,6 +33,7 @@ OmahaServiceProvider* GetOmahaServiceProvider() const override; UserFeedbackProvider* GetUserFeedbackProvider() const override; SpotlightProvider* GetSpotlightProvider() const override; + void CheckForFirstPartyApps() const override; BrandedImageProvider* GetBrandedImageProvider() const override; id<NativeAppWhitelistManager> GetNativeAppWhitelistManager() const override;
diff --git a/ios/public/provider/chrome/browser/test_chrome_browser_provider.mm b/ios/public/provider/chrome/browser/test_chrome_browser_provider.mm index b61186e..c4c9b6a 100644 --- a/ios/public/provider/chrome/browser/test_chrome_browser_provider.mm +++ b/ios/public/provider/chrome/browser/test_chrome_browser_provider.mm
@@ -90,6 +90,8 @@ return spotlight_provider_.get(); } +void TestChromeBrowserProvider::CheckForFirstPartyApps() const {} + BrandedImageProvider* TestChromeBrowserProvider::GetBrandedImageProvider() const { return branded_image_provider_.get();
diff --git a/ios/testing/perf/startupLoggers.mm b/ios/testing/perf/startupLoggers.mm index 389e919..38bd2ec 100644 --- a/ios/testing/perf/startupLoggers.mm +++ b/ios/testing/perf/startupLoggers.mm
@@ -28,7 +28,6 @@ void RegisterAppDidBecomeActiveTime() { DCHECK(g_start_time); - DCHECK(!g_become_active_time); g_become_active_time = new base::Time(base::Time::Now()); }
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn index cd97490..ae7e467 100644 --- a/ios/web_view/BUILD.gn +++ b/ios/web_view/BUILD.gn
@@ -27,6 +27,7 @@ "public/cwv_html_element.h", "public/cwv_navigation_action.h", "public/cwv_navigation_delegate.h", + "public/cwv_preferences.h", "public/cwv_scroll_view.h", "public/cwv_scroll_view_delegate.h", "public/cwv_translation_controller.h", @@ -49,6 +50,8 @@ "internal/cwv_html_element_internal.h", "internal/cwv_navigation_action.mm", "internal/cwv_navigation_action_internal.h", + "internal/cwv_preferences.mm", + "internal/cwv_preferences_internal.h", "internal/cwv_scroll_view.mm", "internal/cwv_scroll_view_internal.h", "internal/cwv_user_content_controller.mm",
diff --git a/ios/web_view/internal/cwv_preferences.mm b/ios/web_view/internal/cwv_preferences.mm new file mode 100644 index 0000000..7ebd2ed --- /dev/null +++ b/ios/web_view/internal/cwv_preferences.mm
@@ -0,0 +1,45 @@ +// 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. + +#import "ios/web_view/internal/cwv_preferences_internal.h" + +#include "components/prefs/pref_service.h" +#include "components/translate/core/browser/translate_pref_names.h" +#include "components/translate/core/browser/translate_prefs.h" +#include "ios/web_view/internal/pref_names.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@implementation CWVPreferences { + PrefService* _prefService; +} + +- (instancetype)initWithPrefService:(PrefService*)prefService { + self = [super init]; + if (self) { + _prefService = prefService; + } + return self; +} + +#pragma mark - Public Methods + +- (void)setTranslationEnabled:(BOOL)enabled { + _prefService->SetBoolean(prefs::kEnableTranslate, enabled); +} + +- (BOOL)isTranslationEnabled { + return _prefService->GetBoolean(prefs::kEnableTranslate); +} + +- (void)resetTranslationSettings { + translate::TranslatePrefs translatePrefs( + _prefService, prefs::kAcceptLanguages, + /*preferred_languages_pref=*/nullptr); + translatePrefs.ResetToDefaults(); +} + +@end
diff --git a/ios/web_view/internal/cwv_preferences_internal.h b/ios/web_view/internal/cwv_preferences_internal.h new file mode 100644 index 0000000..fa6681a --- /dev/null +++ b/ios/web_view/internal/cwv_preferences_internal.h
@@ -0,0 +1,21 @@ +// 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 IOS_WEB_VIEW_INTERNAL_CWV_PREFERENCES_INTERNAL_H_ +#define IOS_WEB_VIEW_INTERNAL_CWV_PREFERENCES_INTERNAL_H_ + +#import "ios/web_view/public/cwv_preferences.h" + +class PrefService; + +@interface CWVPreferences () + +// Takes a PrefService object used to modify settings. +// Caller must ensure |prefService| outlives this instance. +- (instancetype)initWithPrefService:(PrefService*)prefService + NS_DESIGNATED_INITIALIZER; + +@end + +#endif // IOS_WEB_VIEW_INTERNAL_CWV_PREFERENCES_INTERNAL_H_
diff --git a/ios/web_view/internal/cwv_web_view_configuration.mm b/ios/web_view/internal/cwv_web_view_configuration.mm index 736dfbb..3669671 100644 --- a/ios/web_view/internal/cwv_web_view_configuration.mm +++ b/ios/web_view/internal/cwv_web_view_configuration.mm
@@ -8,6 +8,7 @@ #include "base/memory/ptr_util.h" #include "base/threading/thread_restrictions.h" #include "ios/web_view/internal/app/application_context.h" +#import "ios/web_view/internal/cwv_preferences_internal.h" #import "ios/web_view/internal/cwv_user_content_controller_internal.h" #include "ios/web_view/internal/web_view_browser_state.h" #include "ios/web_view/internal/web_view_global_state_util.h" @@ -28,6 +29,7 @@ @implementation CWVWebViewConfiguration +@synthesize preferences = _preferences; @synthesize userContentController = _userContentController; + (instancetype)defaultConfiguration { @@ -68,6 +70,9 @@ if (self) { _browserState = std::move(browserState); + _preferences = + [[CWVPreferences alloc] initWithPrefService:_browserState->GetPrefs()]; + _userContentController = [[CWVUserContentController alloc] initWithConfiguration:self]; }
diff --git a/ios/web_view/internal/translate/cwv_translation_controller.mm b/ios/web_view/internal/translate/cwv_translation_controller.mm index 17ed9e9..a5c03fd 100644 --- a/ios/web_view/internal/translate/cwv_translation_controller.mm +++ b/ios/web_view/internal/translate/cwv_translation_controller.mm
@@ -12,10 +12,8 @@ #include "components/translate/core/browser/translate_download_manager.h" #include "components/translate/core/browser/translate_manager.h" #import "ios/web_view/internal/cwv_web_view_configuration_internal.h" -#include "ios/web_view/internal/pref_names.h" #import "ios/web_view/internal/translate/cwv_translation_language_internal.h" #import "ios/web_view/internal/translate/web_view_translate_client.h" -#include "ios/web_view/internal/web_view_browser_state.h" #import "ios/web_view/public/cwv_translation_controller_delegate.h" #import "ios/web_view/public/cwv_translation_policy.h" #include "ui/base/l10n/l10n_util.h" @@ -68,17 +66,6 @@ @synthesize supportedLanguagesByCode = _supportedLanguagesByCode; @synthesize webState = _webState; -#pragma mark - Class Methods - -+ (void)resetTranslationPolicies { - CWVWebViewConfiguration* configuration = - [CWVWebViewConfiguration defaultConfiguration]; - PrefService* prefService = configuration.browserState->GetPrefs(); - translate::TranslatePrefs translatePrefs(prefService, prefs::kAcceptLanguages, - nullptr); - translatePrefs.ResetToDefaults(); -} - #pragma mark - Internal Methods - (void)setWebState:(web::WebState*)webState { @@ -169,7 +156,6 @@ - (void)setTranslationPolicy:(CWVTranslationPolicy*)policy forPageLanguage:(CWVTranslationLanguage*)pageLanguage { - DCHECK(!_webState->GetBrowserState()->IsOffTheRecord()); std::string languageCode = base::SysNSStringToUTF8(pageLanguage.languageCode); switch (policy.type) { case CWVTranslationPolicyAsk: { @@ -213,7 +199,6 @@ - (void)setTranslationPolicy:(CWVTranslationPolicy*)policy forPageHost:(NSString*)pageHost { - DCHECK(!_webState->GetBrowserState()->IsOffTheRecord()); DCHECK(pageHost.length); switch (policy.type) { case CWVTranslationPolicyAsk: {
diff --git a/ios/web_view/internal/web_view_web_main_delegate.mm b/ios/web_view/internal/web_view_web_main_delegate.mm index 40b0be9..4e2454e 100644 --- a/ios/web_view/internal/web_view_web_main_delegate.mm +++ b/ios/web_view/internal/web_view_web_main_delegate.mm
@@ -5,12 +5,18 @@ #import "ios/web_view/internal/web_view_web_main_delegate.h" #import "base/mac/bundle_locations.h" -#import "ios/web_view/public/cwv_html_element.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif +// Dummy class used to locate the containing NSBundle. +@interface CWVBundleLocator : NSObject +@end + +@implementation CWVBundleLocator +@end + namespace ios_web_view { WebViewWebMainDelegate::WebViewWebMainDelegate() {} @@ -18,11 +24,8 @@ WebViewWebMainDelegate::~WebViewWebMainDelegate() = default; void WebViewWebMainDelegate::BasicStartupComplete() { - // Use CWVHTMLElement instead of CWVWebView and CWVWebViewConfiguration - // because the latter two classes' +intialize calls in to this method and may - // cause a deadlock. base::mac::SetOverrideFrameworkBundle( - [NSBundle bundleForClass:[CWVHTMLElement class]]); + [NSBundle bundleForClass:[CWVBundleLocator class]]); } } // namespace ios_web_view
diff --git a/ios/web_view/public/ChromeWebView.h b/ios/web_view/public/ChromeWebView.h index 19de1a4..ca3e8d2 100644 --- a/ios/web_view/public/ChromeWebView.h +++ b/ios/web_view/public/ChromeWebView.h
@@ -13,6 +13,7 @@ #import "cwv_html_element.h" #import "cwv_navigation_action.h" #import "cwv_navigation_delegate.h" +#import "cwv_preferences.h" #import "cwv_scroll_view.h" #import "cwv_scroll_view_delegate.h" #import "cwv_translation_controller.h"
diff --git a/ios/web_view/public/cwv_preferences.h b/ios/web_view/public/cwv_preferences.h new file mode 100644 index 0000000..194df0d --- /dev/null +++ b/ios/web_view/public/cwv_preferences.h
@@ -0,0 +1,28 @@ +// 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 IOS_WEB_VIEW_PUBLIC_CWV_PREFERENCES_H_ +#define IOS_WEB_VIEW_PUBLIC_CWV_PREFERENCES_H_ + +#import <Foundation/Foundation.h> + +#import "cwv_export.h" + +// Preferences for user settings. +CWV_EXPORT +@interface CWVPreferences : NSObject + +// Whether or not translation as a feature is turned on. +@property(nonatomic, assign, getter=isTranslationEnabled) + BOOL translationEnabled; + +- (instancetype)init NS_UNAVAILABLE; + +// Resets all translation settings back to default. In particular, this will +// change all translation policies back to CWVTranslationPolicyAsk. +- (void)resetTranslationSettings; + +@end + +#endif // IOS_WEB_VIEW_PUBLIC_CWV_PREFERENCES_H_
diff --git a/ios/web_view/public/cwv_translation_controller.h b/ios/web_view/public/cwv_translation_controller.h index 6e9476d..ee31066 100644 --- a/ios/web_view/public/cwv_translation_controller.h +++ b/ios/web_view/public/cwv_translation_controller.h
@@ -52,10 +52,6 @@ @property(nonatomic, readonly) NSSet<CWVTranslationLanguage*>* supportedLanguages; -// Resets all translation policies to default (CWVTranslationPolicyAsk). -// Only resets non-incognito settings. -+ (void)resetTranslationPolicies; - // Begins translation on the current page from |sourceLanguage| to // |targetLanguage|. These language parameters must be chosen from // |supportedLanguages|. Set |userInitiated| to YES if translation @@ -74,7 +70,6 @@ // Sets or retrieves translation policies associated with a specified language. // |pageLanguage| should be the language code of the language. -// Not supported in incognito mode. - (void)setTranslationPolicy:(CWVTranslationPolicy*)policy forPageLanguage:(CWVTranslationLanguage*)pageLanguage; - (CWVTranslationPolicy*)translationPolicyForPageLanguage: @@ -82,7 +77,6 @@ // Sets or retrieves translation policies associated with a specified page. // |pageHost| should be the hostname of the website. Must not be empty. -// Not supported in incognito mode. - (void)setTranslationPolicy:(CWVTranslationPolicy*)policy forPageHost:(NSString*)pageHost; - (CWVTranslationPolicy*)translationPolicyForPageHost:(NSString*)pageHost;
diff --git a/ios/web_view/public/cwv_web_view_configuration.h b/ios/web_view/public/cwv_web_view_configuration.h index e1de098..881e051 100644 --- a/ios/web_view/public/cwv_web_view_configuration.h +++ b/ios/web_view/public/cwv_web_view_configuration.h
@@ -9,6 +9,7 @@ #import "cwv_export.h" +@class CWVPreferences; @class CWVUserContentController; @class CWVWebsiteDataStore; @@ -24,6 +25,9 @@ - (instancetype)init NS_UNAVAILABLE; +// The preferences object associated with this web view configuration. +@property(nonatomic, readonly) CWVPreferences* preferences; + // The user content controller to associate with web views created using this // configuration. @property(nonatomic, readonly) CWVUserContentController* userContentController;
diff --git a/media/blink/cdm_session_adapter.cc b/media/blink/cdm_session_adapter.cc index 66483948..3837820 100644 --- a/media/blink/cdm_session_adapter.cc +++ b/media/blink/cdm_session_adapter.cc
@@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/metrics/histogram.h" #include "base/metrics/histogram_functions.h" #include "base/stl_util.h" @@ -75,8 +76,9 @@ cdm_->GetStatusForPolicy(min_hdcp_version, std::move(promise)); } -WebContentDecryptionModuleSessionImpl* CdmSessionAdapter::CreateSession() { - return new WebContentDecryptionModuleSessionImpl(this); +std::unique_ptr<WebContentDecryptionModuleSessionImpl> +CdmSessionAdapter::CreateSession() { + return base::MakeUnique<WebContentDecryptionModuleSessionImpl>(this); } bool CdmSessionAdapter::RegisterSession(
diff --git a/media/blink/cdm_session_adapter.h b/media/blink/cdm_session_adapter.h index 4fdecc9b..1c7aefa 100644 --- a/media/blink/cdm_session_adapter.h +++ b/media/blink/cdm_session_adapter.h
@@ -54,10 +54,9 @@ void GetStatusForPolicy(HdcpVersion min_hdcp_version, std::unique_ptr<KeyStatusCdmPromise> promise); - // Creates a new session and adds it to the internal map. The caller owns the - // created session. RemoveSession() must be called when destroying it, if - // RegisterSession() was called. - WebContentDecryptionModuleSessionImpl* CreateSession(); + // Creates a new session and adds it to the internal map. RemoveSession() + // must be called when destroying it, if RegisterSession() was called. + std::unique_ptr<WebContentDecryptionModuleSessionImpl> CreateSession(); // Adds a session to the internal map. Called once the session is successfully // initialized. Returns true if the session was registered, false if there is
diff --git a/media/blink/webcontentdecryptionmodule_impl.cc b/media/blink/webcontentdecryptionmodule_impl.cc index 8a0aa48..d2c56c3a 100644 --- a/media/blink/webcontentdecryptionmodule_impl.cc +++ b/media/blink/webcontentdecryptionmodule_impl.cc
@@ -120,8 +120,7 @@ WebContentDecryptionModuleImpl::~WebContentDecryptionModuleImpl() { } -// The caller owns the created session. -blink::WebContentDecryptionModuleSession* +std::unique_ptr<blink::WebContentDecryptionModuleSession> WebContentDecryptionModuleImpl::CreateSession() { return adapter_->CreateSession(); }
diff --git a/media/blink/webcontentdecryptionmodule_impl.h b/media/blink/webcontentdecryptionmodule_impl.h index 28c62ea9..ec436ba 100644 --- a/media/blink/webcontentdecryptionmodule_impl.h +++ b/media/blink/webcontentdecryptionmodule_impl.h
@@ -41,7 +41,8 @@ ~WebContentDecryptionModuleImpl() override; // blink::WebContentDecryptionModule implementation. - blink::WebContentDecryptionModuleSession* CreateSession() override; + std::unique_ptr<blink::WebContentDecryptionModuleSession> CreateSession() + override; void SetServerCertificate( const uint8_t* server_certificate,
diff --git a/media/gpu/vaapi_drm_picture.cc b/media/gpu/vaapi_drm_picture.cc index b6e1f13..5fc1cc5 100644 --- a/media/gpu/vaapi_drm_picture.cc +++ b/media/gpu/vaapi_drm_picture.cc
@@ -65,9 +65,6 @@ return false; } - pixmap_->SetProcessingCallback( - base::Bind(&VaapiWrapper::ProcessPixmap, vaapi_wrapper_)); - if (texture_id_ != 0 && !make_context_current_cb_.is_null()) { if (!make_context_current_cb_.Run()) return false;
diff --git a/media/gpu/vaapi_wrapper.cc b/media/gpu/vaapi_wrapper.cc index 5146f43..0df3cbb 100644 --- a/media/gpu/vaapi_wrapper.cc +++ b/media/gpu/vaapi_wrapper.cc
@@ -666,31 +666,6 @@ return va_surface; } - -bool VaapiWrapper::ProcessPixmap( - const scoped_refptr<gfx::NativePixmap>& source_pixmap, - scoped_refptr<gfx::NativePixmap> target_pixmap) { - scoped_refptr<VASurface> va_surface = CreateVASurfaceForPixmap(source_pixmap); - if (!va_surface) { - LOG(ERROR) << "Failed creating VA Surface for source_pixmap"; - return false; - } - - scoped_refptr<VASurface> processed_va_surface = - CreateVASurfaceForPixmap(target_pixmap); - if (!processed_va_surface) { - LOG(ERROR) << "Failed creating processed VA Surface for pixmap"; - return false; - } - - if (!BlitSurface(va_surface, processed_va_surface)) { - LOG(ERROR) << "Failed scaling NativePixmap"; - return false; - } - - return true; -} - #endif void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) {
diff --git a/media/gpu/vaapi_wrapper.h b/media/gpu/vaapi_wrapper.h index e3f9006..948f4fb 100644 --- a/media/gpu/vaapi_wrapper.h +++ b/media/gpu/vaapi_wrapper.h
@@ -119,12 +119,6 @@ // CreateSurfaces(), where VaapiWrapper is the owner of the surfaces. scoped_refptr<VASurface> CreateVASurfaceForPixmap( const scoped_refptr<gfx::NativePixmap>& pixmap); - - // Use VPP to process |source_pixmap| to |target_pixmap| with scaling and - // color space conversion. - bool ProcessPixmap(const scoped_refptr<gfx::NativePixmap>& source_pixmap, - scoped_refptr<gfx::NativePixmap> target_pixmap); - #endif // Submit parameters or slice data of |va_buffer_type|, copying them from
diff --git a/mojo/edk/system/ports/message_queue.h b/mojo/edk/system/ports/message_queue.h index 724f0bb..3dc6226 100644 --- a/mojo/edk/system/ports/message_queue.h +++ b/mojo/edk/system/ports/message_queue.h
@@ -18,8 +18,8 @@ namespace edk { namespace ports { -const uint64_t kInitialSequenceNum = 1; -const uint64_t kInvalidSequenceNum = std::numeric_limits<uint64_t>::max(); +constexpr uint64_t kInitialSequenceNum = 1; +constexpr uint64_t kInvalidSequenceNum = std::numeric_limits<uint64_t>::max(); class MessageFilter;
diff --git a/net/http/http_cache.h b/net/http/http_cache.h index c2221cc..12e072a 100644 --- a/net/http/http_cache.h +++ b/net/http/http_cache.h
@@ -341,7 +341,9 @@ // Dooms the entry selected by |key|. |trans| will be notified via its IO // callback if this method returns ERR_IO_PENDING. The entry can be - // currently in use or not. + // currently in use or not. If entry is in use and the invoking transaction + // is associated with this entry and this entry is already doomed, this API + // should not be invoked. int DoomEntry(const std::string& key, Transaction* trans); // Dooms the entry selected by |key|. |trans| will be notified via its IO
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc index 10b6d91..68640aab 100644 --- a/net/http/http_cache_transaction.cc +++ b/net/http/http_cache_transaction.cc
@@ -1609,7 +1609,8 @@ // Invalidate any cached GET with a successful PUT or DELETE. if (mode_ == WRITE && (method_ == "PUT" || method_ == "DELETE")) { - if (NonErrorResponse(new_response->headers->response_code())) { + if (NonErrorResponse(new_response->headers->response_code()) && + (entry_ && !entry_->doomed)) { int ret = cache_->DoomEntry(cache_key_, NULL); DCHECK_EQ(OK, ret); } @@ -2902,8 +2903,10 @@ void HttpCache::Transaction::DoomPartialEntry(bool delete_object) { DVLOG(2) << "DoomPartialEntry"; - int rv = cache_->DoomEntry(cache_key_, NULL); - DCHECK_EQ(OK, rv); + if (entry_ && !entry_->doomed) { + int rv = cache_->DoomEntry(cache_key_, NULL); + DCHECK_EQ(OK, rv); + } cache_->DoneWithEntry(entry_, this, false /* process_cancel */, partial_ != nullptr); entry_ = NULL;
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index 1c05602a..db03ce6 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc
@@ -147,7 +147,7 @@ EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); } -void DeferNetworkStart(bool* defer) { +void DeferCallback(bool* defer) { *defer = true; } @@ -1478,6 +1478,184 @@ EXPECT_EQ(5, cache.disk_cache()->create_count()); } +// Tests that if a transaction is dooming the entry and the entry was doomed by +// another transaction that was not part of the entry and created a new entry, +// the new entry should not be incorrectly doomed. (crbug.com/736993) +TEST(HttpCache, RangeGET_ParallelValidationNoMatchDoomEntry) { + MockHttpCache cache; + + ScopedMockTransaction transaction(kRangeGET_TransactionOK); + MockHttpRequest request(transaction); + + MockTransaction dooming_transaction(kRangeGET_TransactionOK); + dooming_transaction.load_flags |= LOAD_BYPASS_CACHE; + MockHttpRequest dooming_request(dooming_transaction); + + std::vector<std::unique_ptr<Context>> context_list; + const int kNumTransactions = 3; + + scoped_refptr<MockDiskEntry> first_entry; + scoped_refptr<MockDiskEntry> second_entry; + for (int i = 0; i < kNumTransactions; ++i) { + context_list.push_back(base::MakeUnique<Context>()); + auto& c = context_list[i]; + + c->result = cache.CreateTransaction(&c->trans); + ASSERT_THAT(c->result, IsOk()); + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState()); + + MockHttpRequest* this_request = &request; + + if (i == 2) + this_request = &dooming_request; + + if (i == 1) { + ASSERT_TRUE(first_entry); + first_entry->SetDefer(MockDiskEntry::DEFER_READ); + } + + c->result = c->trans->Start(this_request, c->callback.callback(), + NetLogWithSource()); + + // Continue the transactions. 2nd will pause at the cache reading state and + // 3rd transaction will doom the entry. + base::RunLoop().RunUntilIdle(); + + // Check status of the first and second entries after every transaction. + switch (i) { + case 0: + first_entry = + cache.disk_cache()->GetDiskEntryRef(kRangeGET_TransactionOK.url); + break; + case 1: + EXPECT_FALSE(first_entry->is_doomed()); + break; + case 2: + EXPECT_TRUE(first_entry->is_doomed()); + second_entry = + cache.disk_cache()->GetDiskEntryRef(kRangeGET_TransactionOK.url); + EXPECT_FALSE(second_entry->is_doomed()); + break; + } + } + // Resume cache read by 1st transaction which will lead to dooming the entry + // as well since the entry cannot be validated. This double dooming should not + // lead to an assertion. + first_entry->ResumeDiskEntryOperation(); + base::RunLoop().RunUntilIdle(); + + // Since second_entry is already created, when 1st transaction goes on to + // create an entry, it will get ERR_CACHE_RACE leading to dooming of + // second_entry and creation of a third entry. + EXPECT_TRUE(second_entry->is_doomed()); + + EXPECT_EQ(3, cache.network_layer()->transaction_count()); + EXPECT_EQ(0, cache.disk_cache()->open_count()); + EXPECT_EQ(3, cache.disk_cache()->create_count()); + + for (auto& context : context_list) { + EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState()); + } + + for (auto& c : context_list) { + ReadAndVerifyTransaction(c->trans.get(), kRangeGET_TransactionOK); + } + + EXPECT_EQ(3, cache.network_layer()->transaction_count()); + EXPECT_EQ(0, cache.disk_cache()->open_count()); + EXPECT_EQ(3, cache.disk_cache()->create_count()); +} + +// Same as above but tests that the 2nd transaction does not do anything if +// there is nothing to doom. (crbug.com/736993) +TEST(HttpCache, RangeGET_ParallelValidationNoMatchDoomEntry1) { + MockHttpCache cache; + + ScopedMockTransaction transaction(kRangeGET_TransactionOK); + MockHttpRequest request(transaction); + + MockTransaction dooming_transaction(kRangeGET_TransactionOK); + dooming_transaction.load_flags |= LOAD_BYPASS_CACHE; + MockHttpRequest dooming_request(dooming_transaction); + + std::vector<std::unique_ptr<Context>> context_list; + const int kNumTransactions = 3; + + scoped_refptr<MockDiskEntry> first_entry; + for (int i = 0; i < kNumTransactions; ++i) { + context_list.push_back(base::MakeUnique<Context>()); + auto& c = context_list[i]; + + c->result = cache.CreateTransaction(&c->trans); + ASSERT_THAT(c->result, IsOk()); + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState()); + + MockHttpRequest* this_request = &request; + + if (i == 2) { + this_request = &dooming_request; + cache.disk_cache()->SetDefer(MockDiskEntry::DEFER_CREATE); + } + + if (i == 1) { + ASSERT_TRUE(first_entry); + first_entry->SetDefer(MockDiskEntry::DEFER_READ); + } + + c->result = c->trans->Start(this_request, c->callback.callback(), + NetLogWithSource()); + + // Continue the transactions. 2nd will pause at the cache reading state and + // 3rd transaction will doom the entry and pause before creating a new + // entry. + base::RunLoop().RunUntilIdle(); + + // Check status of the entry after every transaction. + switch (i) { + case 0: + first_entry = + cache.disk_cache()->GetDiskEntryRef(kRangeGET_TransactionOK.url); + break; + case 1: + EXPECT_FALSE(first_entry->is_doomed()); + break; + case 2: + EXPECT_TRUE(first_entry->is_doomed()); + break; + } + } + // Resume cache read by 2nd transaction which will lead to dooming the entry + // as well since the entry cannot be validated. This double dooming should not + // lead to an assertion. + first_entry->ResumeDiskEntryOperation(); + base::RunLoop().RunUntilIdle(); + + // Resume creation of entry by 3rd transaction. + cache.disk_cache()->ResumeCacheOperation(); + base::RunLoop().RunUntilIdle(); + + // Note that since 3rd transaction's entry is already created but its + // callback is deferred, MockDiskCache's implementation returns + // ERR_CACHE_CREATE_FAILURE when 2nd transaction tries to create an entry + // during that time, leading to it switching over to pass-through mode. + // Thus the number of entries is 2 below. + EXPECT_EQ(3, cache.network_layer()->transaction_count()); + EXPECT_EQ(0, cache.disk_cache()->open_count()); + EXPECT_EQ(2, cache.disk_cache()->create_count()); + + for (auto& context : context_list) { + EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState()); + } + + for (auto& c : context_list) { + ReadAndVerifyTransaction(c->trans.get(), kRangeGET_TransactionOK); + } + + EXPECT_EQ(3, cache.network_layer()->transaction_count()); + EXPECT_EQ(0, cache.disk_cache()->open_count()); + EXPECT_EQ(2, cache.disk_cache()->create_count()); +} + // Tests parallel validation on range requests with non-overlapping ranges. TEST(HttpCache, RangeGET_ParallelValidationDifferentRanges) { MockHttpCache cache; @@ -2159,7 +2337,7 @@ MockHttpRequest* this_request = &request; if (i == 3) { this_request = &validate_request; - c->trans->SetBeforeNetworkStartCallback(base::Bind(&DeferNetworkStart)); + c->trans->SetBeforeNetworkStartCallback(base::Bind(&DeferCallback)); } c->result = c->trans->Start(this_request, c->callback.callback(), @@ -2257,7 +2435,7 @@ MockHttpRequest* this_request = &request; if (i == 2) { this_request = &validate_request; - c->trans->SetBeforeNetworkStartCallback(base::Bind(&DeferNetworkStart)); + c->trans->SetBeforeNetworkStartCallback(base::Bind(&DeferCallback)); } c->result = c->trans->Start(this_request, c->callback.callback(), @@ -2395,7 +2573,7 @@ MockHttpRequest* this_request = &request; if (i == 2) { this_request = &validate_request; - c->trans->SetBeforeNetworkStartCallback(base::Bind(&DeferNetworkStart)); + c->trans->SetBeforeNetworkStartCallback(base::Bind(&DeferCallback)); } c->result = c->trans->Start(this_request, c->callback.callback(), @@ -2461,7 +2639,7 @@ ASSERT_THAT(c->result, IsOk()); if (i == 0) - c->trans->SetBeforeNetworkStartCallback(base::Bind(&DeferNetworkStart)); + c->trans->SetBeforeNetworkStartCallback(base::Bind(&DeferCallback)); c->result = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
diff --git a/net/http/mock_http_cache.cc b/net/http/mock_http_cache.cc index 514cc42..bf81c4ee 100644 --- a/net/http/mock_http_cache.cc +++ b/net/http/mock_http_cache.cc
@@ -74,7 +74,9 @@ fail_sparse_requests_(false), busy_(false), delayed_(false), - cancel_(false) { + cancel_(false), + defer_op_(DEFER_NONE), + resume_return_code_(0) { test_mode_ = GetTestModeForEntry(key); } @@ -125,10 +127,25 @@ if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ) return num; + // Pause and resume. + if (defer_op_ == DEFER_READ) { + defer_op_ = DEFER_NONE; + resume_callback_ = callback; + resume_return_code_ = num; + return ERR_IO_PENDING; + } + CallbackLater(callback, num); return ERR_IO_PENDING; } +void MockDiskEntry::ResumeDiskEntryOperation() { + DCHECK(!resume_callback_.is_null()); + CallbackLater(resume_callback_, resume_return_code_); + resume_callback_.Reset(); + resume_return_code_ = 0; +} + int MockDiskEntry::WriteData(int index, int offset, IOBuffer* buf, @@ -376,7 +393,9 @@ fail_requests_(false), soft_failures_(false), double_create_check_(true), - fail_sparse_requests_(false) {} + fail_sparse_requests_(false), + defer_op_(MockDiskEntry::DEFER_NONE), + resume_return_code_(0) {} MockDiskCache::~MockDiskCache() { ReleaseAll(); @@ -460,6 +479,14 @@ if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) return OK; + // Pause and resume. + if (defer_op_ == MockDiskEntry::DEFER_CREATE) { + defer_op_ = MockDiskEntry::DEFER_NONE; + resume_callback_ = callback; + resume_return_code_ = OK; + return ERR_IO_PENDING; + } + CallbackLater(callback, OK); return ERR_IO_PENDING; } @@ -526,9 +553,8 @@ } void MockDiskCache::ReleaseAll() { - EntryMap::iterator it = entries_.begin(); - for (; it != entries_.end(); ++it) - it->second->Release(); + for (auto entry : entries_) + entry.second->Release(); entries_.clear(); } @@ -540,9 +566,25 @@ bool MockDiskCache::IsDiskEntryDoomed(const std::string& key) { auto it = entries_.find(key); + if (it != entries_.end()) + return it->second->is_doomed(); + + return false; +} + +void MockDiskCache::ResumeCacheOperation() { + DCHECK(!resume_callback_.is_null()); + CallbackLater(resume_callback_, resume_return_code_); + resume_callback_.Reset(); + resume_return_code_ = 0; +} + +scoped_refptr<MockDiskEntry> MockDiskCache::GetDiskEntryRef( + const std::string& key) { + auto it = entries_.find(key); if (it == entries_.end()) - return false; - return it->second->is_doomed(); + return nullptr; + return it->second; } //-----------------------------------------------------------------------------
diff --git a/net/http/mock_http_cache.h b/net/http/mock_http_cache.h index d568c64..bc7847b 100644 --- a/net/http/mock_http_cache.h +++ b/net/http/mock_http_cache.h
@@ -27,6 +27,12 @@ class MockDiskEntry : public disk_cache::Entry, public base::RefCounted<MockDiskEntry> { public: + enum DeferOp { + DEFER_NONE, + DEFER_CREATE, + DEFER_READ, + }; + explicit MockDiskEntry(const std::string& key); bool is_doomed() const { return doomed_; } @@ -74,6 +80,14 @@ // again or all subsequent tests will fail. static void IgnoreCallbacks(bool value); + // Defers invoking the callback for the given operation. Calling code should + // invoke ResumeDiskEntryOperation to resume. + void SetDefer(DeferOp defer_op) { defer_op_ = defer_op; } + + // Resumes deferred cache operation by posting |resume_callback_| with + // |resume_return_code_|. + void ResumeDiskEntryOperation(); + private: friend class base::RefCounted<MockDiskEntry>; struct CallbackInfo; @@ -106,6 +120,12 @@ bool busy_; bool delayed_; bool cancel_; + + // Used for pause and restart. + DeferOp defer_op_; + CompletionCallback resume_callback_; + int resume_return_code_; + static bool ignore_callbacks_; }; @@ -161,8 +181,20 @@ void ReleaseAll(); + // Returns true if a doomed entry exists with this key. bool IsDiskEntryDoomed(const std::string& key); + // Defers invoking the callback for the given operation. Calling code should + // invoke ResumeCacheOperation to resume. + void SetDefer(MockDiskEntry::DeferOp defer_op) { defer_op_ = defer_op; } + + // Resume deferred cache operation by posting |resume_callback_| with + // |resume_return_code_|. + void ResumeCacheOperation(); + + // Returns a reference to the disk entry with the given |key|. + scoped_refptr<MockDiskEntry> GetDiskEntryRef(const std::string& key); + private: using EntryMap = std::unordered_map<std::string, MockDiskEntry*>; class NotImplementedIterator; @@ -177,6 +209,11 @@ bool soft_failures_; bool double_create_check_; bool fail_sparse_requests_; + + // Used for pause and restart. + MockDiskEntry::DeferOp defer_op_; + CompletionCallback resume_callback_; + int resume_return_code_; }; class MockBackendFactory : public HttpCache::BackendFactory { @@ -244,7 +281,6 @@ static void SetTestMode(int test_mode); // Functions to test the state of ActiveEntry. - bool IsWriterPresent(const std::string& key); bool IsHeadersTransactionPresent(const std::string& key); int GetCountReaders(const std::string& key);
diff --git a/pdf/pdf.cc b/pdf/pdf.cc index 03f6d72..8d3a2d5 100644 --- a/pdf/pdf.cc +++ b/pdf/pdf.cc
@@ -122,8 +122,8 @@ PDFEngineExports::Get()->SetPDFUseGDIPrinting(enable); } -void SetPDFPostscriptPrintingLevel(int postscript_level) { - PDFEngineExports::Get()->SetPDFPostscriptPrintingLevel(postscript_level); +void SetPDFUsePrintMode(int mode) { + PDFEngineExports::Get()->SetPDFUsePrintMode(mode); } #endif // defined(OS_WIN)
diff --git a/pdf/pdf.h b/pdf/pdf.h index d18489d..6f69bdb3d 100644 --- a/pdf/pdf.h +++ b/pdf/pdf.h
@@ -36,6 +36,14 @@ const void* PPP_GetInterface(const char* interface_name); #if defined(OS_WIN) +// Printing modes - type to convert PDF to for printing +enum PrintingMode { + kEmf = 0, + kTextOnly = 1, + kPostScript2 = 2, + kPostScript3 = 3, +}; + // |pdf_buffer| is the buffer that contains the entire PDF document to be // rendered. // |buffer_size| is the size of |pdf_buffer| in bytes. @@ -83,7 +91,7 @@ void SetPDFUseGDIPrinting(bool enable); -void SetPDFPostscriptPrintingLevel(int postscript_level); +void SetPDFUsePrintMode(int mode); #endif // defined(OS_WIN) // |page_count| and |max_page_width| are optional and can be NULL.
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h index ac18b5e..1556e51 100644 --- a/pdf/pdf_engine.h +++ b/pdf/pdf_engine.h
@@ -347,8 +347,7 @@ PDFEnsureTypefaceCharactersAccessible func) = 0; virtual void SetPDFUseGDIPrinting(bool enable) = 0; - - virtual void SetPDFPostscriptPrintingLevel(int postscript_level) = 0; + virtual void SetPDFUsePrintMode(int mode) = 0; #endif // defined(OS_WIN) // See the definition of RenderPDFPageToBitmap in pdf.cc for details.
diff --git a/pdf/pdfium/pdfium_assert_matching_enums.cc b/pdf/pdfium/pdfium_assert_matching_enums.cc index b173a32..e89225af 100644 --- a/pdf/pdfium/pdfium_assert_matching_enums.cc +++ b/pdf/pdfium/pdfium_assert_matching_enums.cc
@@ -2,9 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "build/build_config.h" +#include "pdf/pdf.h" #include "ppapi/c/pp_input_event.h" #include "ppapi/c/private/ppb_pdf.h" #include "ppapi/c/private/ppp_pdf.h" +#include "third_party/pdfium/public/fpdf_edit.h" #include "third_party/pdfium/public/fpdf_fwlevent.h" #include "third_party/pdfium/public/fpdf_sysfontinfo.h" #include "ui/events/keycodes/keyboard_codes.h" @@ -210,3 +213,10 @@ STATIC_ASSERT_ENUM(PP_PRIVATEDUPLEXMODE_SIMPLEX, Simplex); STATIC_ASSERT_ENUM(PP_PRIVATEDUPLEXMODE_SHORT_EDGE, DuplexFlipShortEdge); STATIC_ASSERT_ENUM(PP_PRIVATEDUPLEXMODE_LONG_EDGE, DuplexFlipLongEdge); + +#if defined(OS_WIN) +STATIC_ASSERT_ENUM(chrome_pdf::kEmf, FPDF_PRINTMODE_EMF); +STATIC_ASSERT_ENUM(chrome_pdf::kTextOnly, FPDF_PRINTMODE_TEXTONLY); +STATIC_ASSERT_ENUM(chrome_pdf::kPostScript2, FPDF_PRINTMODE_POSTSCRIPT2); +STATIC_ASSERT_ENUM(chrome_pdf::kPostScript3, FPDF_PRINTMODE_POSTSCRIPT3); +#endif
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index 37fef306..22cff050 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc
@@ -4154,10 +4154,9 @@ FPDF_SetPrintTextWithGDI(enable); } -void PDFiumEngineExports::SetPDFPostscriptPrintingLevel(int postscript_level) { - FPDF_SetPrintPostscriptLevel(postscript_level); +void PDFiumEngineExports::SetPDFUsePrintMode(int mode) { + FPDF_SetPrintMode(mode); } - #endif // defined(OS_WIN) bool PDFiumEngineExports::RenderPDFPageToBitmap(
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h index e19570d..3953c745 100644 --- a/pdf/pdfium/pdfium_engine.h +++ b/pdf/pdfium/pdfium_engine.h
@@ -808,8 +808,7 @@ PDFEnsureTypefaceCharactersAccessible func) override; void SetPDFUseGDIPrinting(bool enable) override; - - void SetPDFPostscriptPrintingLevel(int postscript_level) override; + void SetPDFUsePrintMode(int mode) override; #endif // defined(OS_WIN) bool RenderPDFPageToBitmap(const void* pdf_buffer, int pdf_buffer_size,
diff --git a/printing/pdf_render_settings.h b/printing/pdf_render_settings.h index 059f73d..1bb205d 100644 --- a/printing/pdf_render_settings.h +++ b/printing/pdf_render_settings.h
@@ -16,6 +16,7 @@ enum Mode { NORMAL = 0, #if defined(OS_WIN) + TEXTONLY, GDI_TEXT, POSTSCRIPT_LEVEL2, POSTSCRIPT_LEVEL3,
diff --git a/printing/print_settings.h b/printing/print_settings.h index 2158737..f55efc4 100644 --- a/printing/print_settings.h +++ b/printing/print_settings.h
@@ -37,6 +37,7 @@ #if defined(OS_WIN) enum PrinterType { TYPE_NONE = 0, + TYPE_TEXTONLY, TYPE_XPS, TYPE_POSTSCRIPT_LEVEL2, TYPE_POSTSCRIPT_LEVEL3 @@ -171,6 +172,9 @@ bool print_text_with_gdi() const { return print_text_with_gdi_; } void set_printer_type(PrinterType type) { printer_type_ = type; } + bool printer_is_textonly() const { + return printer_type_ == PrinterType::TYPE_TEXTONLY; + } bool printer_is_xps() const { return printer_type_ == PrinterType::TYPE_XPS;} bool printer_is_ps2() const { return printer_type_ == PrinterType::TYPE_POSTSCRIPT_LEVEL2;
diff --git a/printing/print_settings_initializer_win.cc b/printing/print_settings_initializer_win.cc index e611e84..fd243fe 100644 --- a/printing/print_settings_initializer_win.cc +++ b/printing/print_settings_initializer_win.cc
@@ -92,6 +92,9 @@ return IsTechnology(hdc, kXPSDriver); } +bool IsPrinterTextOnly(HDC hdc) { + return ::GetDeviceCaps(hdc, TECHNOLOGY) == DT_CHARSTREAM; +} } // namespace // static @@ -153,6 +156,11 @@ PrintSettings::PrinterType::TYPE_POSTSCRIPT_LEVEL3); return; } + // Detects the generic / text only driver. + if (IsPrinterTextOnly(hdc)) { + print_settings->set_printer_type(PrintSettings::PrinterType::TYPE_TEXTONLY); + return; + } if (IsPrinterXPS(hdc)) { print_settings->set_printer_type(PrintSettings::PrinterType::TYPE_XPS); return;
diff --git a/remoting/ios/app/client_connection_view_controller.mm b/remoting/ios/app/client_connection_view_controller.mm index a9cdc9f1..3892b2c 100644 --- a/remoting/ios/app/client_connection_view_controller.mm +++ b/remoting/ios/app/client_connection_view_controller.mm
@@ -58,6 +58,7 @@ RemotingClient* _client; SessionErrorCode _lastError; HostInfo* _hostInfo; + BOOL _hasViewAppeared; } @property(nonatomic, assign) SessionErrorCode lastError; @@ -74,6 +75,7 @@ if (self) { _hostInfo = hostInfo; _remoteHostName = hostInfo.hostName; + _hasViewAppeared = NO; // TODO(yuweih): This logic may be reused by other views. UIButton* cancelButton = [UIButton buttonWithType:UIButtonTypeSystem]; @@ -107,8 +109,6 @@ constraintEqualToAnchor:[self.view trailingAnchor]], [[_navBar heightAnchor] constraintEqualToConstant:kBarHeight], ]]; - - [self attemptConnectionToHost]; } return self; } @@ -174,6 +174,22 @@ selector:@selector(hostSessionStatusChanged:) name:kHostSessionStatusChanged object:nil]; + + [self attemptConnectionToHost]; + + // Although keyboard listeners are registered here, they won't work properly + // if the keyboard shows/hides before the view appears. + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(keyboardWillShow:) + name:UIKeyboardWillShowNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(keyboardWillHide:) + name:UIKeyboardWillHideNotification + object:nil]; } - (void)initializeLayoutConstraintsWithViews:(NSDictionary*)views { @@ -280,19 +296,11 @@ - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(keyboardWillShow:) - name:UIKeyboardWillShowNotification - object:nil]; - - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(keyboardWillHide:) - name:UIKeyboardWillHideNotification - object:nil]; - [_activityIndicator startAnimating]; + + _hasViewAppeared = YES; + + self.state = _state; } - (void)viewWillDisappear:(BOOL)animated { @@ -306,9 +314,6 @@ #pragma mark - Keyboard -// TODO(nicholss): We need to listen to screen rotation and re-adjust the -// topAnchor. - - (void)keyboardWillShow:(NSNotification*)notification { CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] @@ -324,7 +329,7 @@ _activityIndicatorTopConstraintKeyboard.active = NO; _activityIndicatorTopConstraintKeyboard = [_activityIndicator.topAnchor constraintEqualToAnchor:self.view.topAnchor - constant:kTopPadding + overlap]; + constant:_activityIndicator.frame.origin.y + overlap]; _activityIndicatorTopConstraintFull.active = NO; _activityIndicatorTopConstraintKeyboard.active = YES; [UIView animateWithDuration:kKeyboardAnimationTime @@ -346,6 +351,11 @@ - (void)setState:(ClientConnectionViewState)state { _state = state; + if (!_hasViewAppeared) { + // Showing different state will re-layout the view, which will be broken if + // the view is not shown yet. + return; + } switch (_state) { case ClientViewConnecting: [self showConnectingState];
diff --git a/services/device/public/cpp/generic_sensor/BUILD.gn b/services/device/public/cpp/generic_sensor/BUILD.gn index 351ea5c..bee8552 100644 --- a/services/device/public/cpp/generic_sensor/BUILD.gn +++ b/services/device/public/cpp/generic_sensor/BUILD.gn
@@ -8,6 +8,8 @@ "platform_sensor_configuration.h", "sensor_reading.cc", "sensor_reading.h", + "sensor_reading_shared_buffer_reader.cc", + "sensor_reading_shared_buffer_reader.h", ] public_deps = [
diff --git a/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.cc b/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.cc new file mode 100644 index 0000000..836234c --- /dev/null +++ b/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.cc
@@ -0,0 +1,48 @@ +// 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 "services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h" + +#include "device/base/synchronization/shared_memory_seqlock_buffer.h" + +namespace { + +constexpr int kMaxReadAttemptsCount = 10; + +} // namespace + +namespace device { + +SensorReadingSharedBufferReader::SensorReadingSharedBufferReader( + const SensorReadingSharedBuffer* buffer) + : buffer_(buffer) {} + +SensorReadingSharedBufferReader::~SensorReadingSharedBufferReader() = default; + +bool SensorReadingSharedBufferReader::GetReading(SensorReading* result) { + int read_attempts = 0; + while (!TryReadFromBuffer(result)) { + // Only try to read this many times before failing to avoid waiting here + // very long in case of contention with the writer. + if (++read_attempts == kMaxReadAttemptsCount) { + // Failed to successfully read, presumably because the hardware + // thread was taking unusually long. Data in |result| was not updated + // and was simply left what was there before. + return false; + } + } + + return true; +} + +bool SensorReadingSharedBufferReader::TryReadFromBuffer(SensorReading* result) { + auto version = buffer_->seqlock.value().ReadBegin(); + temp_reading_data_ = buffer_->reading; + if (buffer_->seqlock.value().ReadRetry(version)) + return false; + *result = temp_reading_data_; + return true; +} + +} // namespace device
diff --git a/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h b/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h new file mode 100644 index 0000000..354f8a3 --- /dev/null +++ b/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h
@@ -0,0 +1,36 @@ +// 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 SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_SENSOR_READING_SHARED_BUFFER_READER_H_ +#define SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_SENSOR_READING_SHARED_BUFFER_READER_H_ + +#include "base/macros.h" +#include "services/device/public/cpp/generic_sensor/sensor_reading.h" + +namespace device { + +class SensorReadingSharedBufferReader { + public: + // TODO(juncai): Maybe pass a mojo::ScopedSharedBufferHandle to the + // constructor. + // https://crbug.com/742408 + explicit SensorReadingSharedBufferReader( + const SensorReadingSharedBuffer* buffer); + ~SensorReadingSharedBufferReader(); + + // Get sensor reading from shared buffer. + bool GetReading(SensorReading* result); + + private: + bool TryReadFromBuffer(SensorReading* result); + + const SensorReadingSharedBuffer* buffer_; + SensorReading temp_reading_data_; + + DISALLOW_COPY_AND_ASSIGN(SensorReadingSharedBufferReader); +}; + +} // namespace device + +#endif // SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_SENSOR_READING_SHARED_BUFFER_READER_H_
diff --git a/services/device/public/interfaces/BUILD.gn b/services/device/public/interfaces/BUILD.gn index bd47483..db32b96 100644 --- a/services/device/public/interfaces/BUILD.gn +++ b/services/device/public/interfaces/BUILD.gn
@@ -36,9 +36,6 @@ public_deps = [ ":constants", ] - - # TODO(crbug.com/699569): Convert to use the new JS bindings. - use_new_js_bindings = false } mojom("constants") { @@ -47,5 +44,5 @@ ] # TODO(crbug.com/699569): Convert to use the new JS bindings. - use_new_js_bindings = false + js_bindings_mode = "both" }
diff --git a/services/resource_coordinator/BUILD.gn b/services/resource_coordinator/BUILD.gn index 179b6d5..4a59a5b 100644 --- a/services/resource_coordinator/BUILD.gn +++ b/services/resource_coordinator/BUILD.gn
@@ -26,8 +26,8 @@ "coordination_unit/frame_coordination_unit_impl.h", "coordination_unit/process_coordination_unit_impl.cc", "coordination_unit/process_coordination_unit_impl.h", - "coordination_unit/tab_signal_generator.cc", - "coordination_unit/tab_signal_generator.h", + "coordination_unit/tab_signal_generator_impl.cc", + "coordination_unit/tab_signal_generator_impl.h", "coordination_unit/web_contents_coordination_unit_impl.cc", "coordination_unit/web_contents_coordination_unit_impl.h", "memory_instrumentation/coordinator_impl.cc",
diff --git a/services/resource_coordinator/coordination_unit/coordination_unit_impl.cc b/services/resource_coordinator/coordination_unit/coordination_unit_impl.cc index f5f79a7..b6f7587 100644 --- a/services/resource_coordinator/coordination_unit/coordination_unit_impl.cc +++ b/services/resource_coordinator/coordination_unit/coordination_unit_impl.cc
@@ -9,6 +9,7 @@ #include "base/strings/string_number_conversions.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/resource_coordinator/coordination_unit/coordination_unit_graph_observer.h" +#include "services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h" #include "services/resource_coordinator/public/cpp/coordination_unit_id.h" namespace resource_coordinator { @@ -29,6 +30,13 @@ } // namespace +// static +const FrameCoordinationUnitImpl* CoordinationUnitImpl::ToFrameCoordinationUnit( + const CoordinationUnitImpl* coordination_unit) { + DCHECK(coordination_unit->id().type == CoordinationUnitType::kFrame); + return static_cast<const FrameCoordinationUnitImpl*>(coordination_unit); +} + CoordinationUnitImpl::CoordinationUnitImpl( const CoordinationUnitID& id, std::unique_ptr<service_manager::ServiceContextRef> service_ref) @@ -99,6 +107,7 @@ } void CoordinationUnitImpl::SendEvent(mojom::EventPtr event) { + // TODO(crbug.com/691886) Consider removing the following code. switch (event->type) { case mojom::EventType::kOnWebContentsShown: state_flags_[kTabVisible] = true; @@ -112,9 +121,6 @@ case mojom::EventType::kOnProcessAudioStopped: state_flags_[kAudioPlaying] = false; break; - case mojom::EventType::kOnLocalFrameNetworkIdle: - state_flags_[kNetworkIdle] = true; - break; case mojom::EventType::kTestEvent: state_flags_[kTestState] = true; break;
diff --git a/services/resource_coordinator/coordination_unit/coordination_unit_impl.h b/services/resource_coordinator/coordination_unit/coordination_unit_impl.h index 4dd1894d..c740f930 100644 --- a/services/resource_coordinator/coordination_unit/coordination_unit_impl.h +++ b/services/resource_coordinator/coordination_unit/coordination_unit_impl.h
@@ -23,6 +23,7 @@ namespace resource_coordinator { class CoordinationUnitGraphObserver; +class FrameCoordinationUnitImpl; class CoordinationUnitImpl : public mojom::CoordinationUnit { public: @@ -31,6 +32,9 @@ std::unique_ptr<service_manager::ServiceContextRef> service_ref); ~CoordinationUnitImpl() override; + static const FrameCoordinationUnitImpl* ToFrameCoordinationUnit( + const CoordinationUnitImpl* coordination_unit); + // Overridden from mojom::CoordinationUnit: void SendEvent(mojom::EventPtr event) override; void GetID(const GetIDCallback& callback) override;
diff --git a/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.cc b/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.cc index a788ba8..110f506bf 100644 --- a/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.cc +++ b/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.cc
@@ -37,4 +37,12 @@ } } +bool FrameCoordinationUnitImpl::IsMainFrame() const { + for (auto* parent : parents_) { + if (parent->id().type == CoordinationUnitType::kFrame) + return false; + } + return true; +} + } // namespace resource_coordinator
diff --git a/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h b/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h index 39d3fae..c66501c 100644 --- a/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h +++ b/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h
@@ -12,8 +12,6 @@ namespace resource_coordinator { -struct CoordinationUnitID; - class FrameCoordinationUnitImpl : public CoordinationUnitImpl { public: FrameCoordinationUnitImpl( @@ -25,6 +23,8 @@ std::set<CoordinationUnitImpl*> GetAssociatedCoordinationUnitsOfType( CoordinationUnitType type) override; + bool IsMainFrame() const; + private: DISALLOW_COPY_AND_ASSIGN(FrameCoordinationUnitImpl); };
diff --git a/services/resource_coordinator/coordination_unit/tab_signal_generator.cc b/services/resource_coordinator/coordination_unit/tab_signal_generator.cc deleted file mode 100644 index 7cc179e6..0000000 --- a/services/resource_coordinator/coordination_unit/tab_signal_generator.cc +++ /dev/null
@@ -1,20 +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 "services/resource_coordinator/coordination_unit/tab_signal_generator.h" - -#include "services/resource_coordinator/coordination_unit/coordination_unit_impl.h" - -namespace resource_coordinator { - -TabSignalGenerator::TabSignalGenerator() = default; - -TabSignalGenerator::~TabSignalGenerator() = default; - -bool TabSignalGenerator::ShouldObserve( - const CoordinationUnitImpl* coordination_unit) { - return coordination_unit->id().type == CoordinationUnitType::kWebContents; -} - -} // namespace resource_coordinator
diff --git a/services/resource_coordinator/coordination_unit/tab_signal_generator.h b/services/resource_coordinator/coordination_unit/tab_signal_generator.h deleted file mode 100644 index 5c5980d7..0000000 --- a/services/resource_coordinator/coordination_unit/tab_signal_generator.h +++ /dev/null
@@ -1,32 +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. - -#ifndef SERVICES_RESOURCE_COORDINATOR_COORDINATION_UNIT_TAB_SIGNAL_GENERATOR_H_ -#define SERVICES_RESOURCE_COORDINATOR_COORDINATION_UNIT_TAB_SIGNAL_GENERATOR_H_ - -#include "base/macros.h" -#include "services/resource_coordinator/coordination_unit/coordination_unit_graph_observer.h" - -namespace resource_coordinator { - -class CoordinationUnitImpl; - -// The TabSignalGenerator is a unified |CoordinationUnitGraphObserver| for -// calculating and emitting tab-scoped signals. Nonetheless, the observer -// has access to the whole coordination unit graph and thus can utilize -// the information contained within the entire graph to generate the signals. -class TabSignalGenerator : public CoordinationUnitGraphObserver { - public: - TabSignalGenerator(); - ~TabSignalGenerator() override; - - bool ShouldObserve(const CoordinationUnitImpl* coordination_unit) override; - - private: - DISALLOW_COPY_AND_ASSIGN(TabSignalGenerator); -}; - -} // namespace resource_coordinator - -#endif // SERVICES_RESOURCE_COORDINATOR_COORDINATION_UNIT_TAB_SIGNAL_GENERATOR_H_
diff --git a/services/resource_coordinator/coordination_unit/tab_signal_generator_impl.cc b/services/resource_coordinator/coordination_unit/tab_signal_generator_impl.cc new file mode 100644 index 0000000..a7d8eddf --- /dev/null +++ b/services/resource_coordinator/coordination_unit/tab_signal_generator_impl.cc
@@ -0,0 +1,69 @@ +// 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 "services/resource_coordinator/coordination_unit/tab_signal_generator_impl.h" + +#include "services/resource_coordinator/coordination_unit/coordination_unit_impl.h" +#include "services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h" +#include "services/resource_coordinator/coordination_unit/web_contents_coordination_unit_impl.h" + +namespace resource_coordinator { + +#define DISPATCH_TAB_SIGNAL(observers, METHOD, cu, ...) \ + observers.ForAllPtrs([cu](mojom::TabSignalObserver* observer) { \ + observer->METHOD(cu->id(), __VA_ARGS__); \ + }); + +TabSignalGeneratorImpl::TabSignalGeneratorImpl() = default; + +TabSignalGeneratorImpl::~TabSignalGeneratorImpl() = default; + +void TabSignalGeneratorImpl::AddObserver(mojom::TabSignalObserverPtr observer) { + observers_.AddPtr(std::move(observer)); +} + +bool TabSignalGeneratorImpl::ShouldObserve( + const CoordinationUnitImpl* coordination_unit) { + auto coordination_unit_type = coordination_unit->id().type; + return coordination_unit_type == CoordinationUnitType::kWebContents || + coordination_unit_type == CoordinationUnitType::kFrame; +} + +void TabSignalGeneratorImpl::OnPropertyChanged( + const CoordinationUnitImpl* coordination_unit, + const mojom::PropertyType property_type, + const base::Value& value) { + if (coordination_unit->id().type == CoordinationUnitType::kFrame) { + OnFramePropertyChanged( + CoordinationUnitImpl::ToFrameCoordinationUnit(coordination_unit), + property_type, value); + } +} + +void TabSignalGeneratorImpl::BindToInterface( + const service_manager::BindSourceInfo& source_info, + resource_coordinator::mojom::TabSignalGeneratorRequest request) { + bindings_.AddBinding(this, std::move(request)); +} + +void TabSignalGeneratorImpl::OnFramePropertyChanged( + const FrameCoordinationUnitImpl* coordination_unit, + const mojom::PropertyType property_type, + const base::Value& value) { + if (property_type == mojom::PropertyType::kNetworkIdle) { + // Ignore when the signal doesn't come from main frame. + if (!coordination_unit->IsMainFrame()) + return; + // TODO(lpy) Combine CPU usage or long task idleness signal. + for (auto* parent : coordination_unit->parents()) { + if (parent->id().type != CoordinationUnitType::kWebContents) + continue; + DISPATCH_TAB_SIGNAL(observers_, OnEventReceived, parent, + mojom::TabEvent::kDoneLoading); + break; + } + } +} + +} // namespace resource_coordinator
diff --git a/services/resource_coordinator/coordination_unit/tab_signal_generator_impl.h b/services/resource_coordinator/coordination_unit/tab_signal_generator_impl.h new file mode 100644 index 0000000..495e25d --- /dev/null +++ b/services/resource_coordinator/coordination_unit/tab_signal_generator_impl.h
@@ -0,0 +1,56 @@ +// 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 SERVICES_RESOURCE_COORDINATOR_COORDINATION_UNIT_TAB_SIGNAL_GENERATOR_IMPL_H_ +#define SERVICES_RESOURCE_COORDINATOR_COORDINATION_UNIT_TAB_SIGNAL_GENERATOR_IMPL_H_ + +#include "base/macros.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/interface_ptr_set.h" +#include "services/resource_coordinator/coordination_unit/coordination_unit_graph_observer.h" +#include "services/resource_coordinator/public/interfaces/tab_signal.mojom.h" +#include "services/service_manager/public/cpp/bind_source_info.h" + +namespace resource_coordinator { + +class CoordinationUnitImpl; +class FrameCoordinationUnitImpl; + +// The TabSignalGenerator is a dedicated |CoordinationUnitGraphObserver| for +// calculating and emitting tab-scoped signals. This observer observes Tab +// CoordinationUnits and Frame CoordinationUnits, utilize information from the +// graph and generate tab level signals. +class TabSignalGeneratorImpl : public CoordinationUnitGraphObserver, + public mojom::TabSignalGenerator { + public: + TabSignalGeneratorImpl(); + ~TabSignalGeneratorImpl() override; + + // mojom::SignalGenerator implementation. + void AddObserver(mojom::TabSignalObserverPtr observer) override; + + // CoordinationUnitGraphObserver implementation. + bool ShouldObserve(const CoordinationUnitImpl* coordination_unit) override; + void OnPropertyChanged(const CoordinationUnitImpl* coordination_unit, + const mojom::PropertyType property_type, + const base::Value& value) override; + + void BindToInterface( + const service_manager::BindSourceInfo& source_info, + resource_coordinator::mojom::TabSignalGeneratorRequest request); + + private: + void OnFramePropertyChanged( + const FrameCoordinationUnitImpl* coordination_unit, + const mojom::PropertyType property_type, + const base::Value& value); + + mojo::BindingSet<mojom::TabSignalGenerator> bindings_; + mojo::InterfacePtrSet<mojom::TabSignalObserver> observers_; + DISALLOW_COPY_AND_ASSIGN(TabSignalGeneratorImpl); +}; + +} // namespace resource_coordinator + +#endif // SERVICES_RESOURCE_COORDINATOR_COORDINATION_UNIT_TAB_SIGNAL_GENERATOR_IMPL_H_
diff --git a/services/resource_coordinator/manifest.json b/services/resource_coordinator/manifest.json index 78624785..57f8e979 100644 --- a/services/resource_coordinator/manifest.json +++ b/services/resource_coordinator/manifest.json
@@ -6,6 +6,7 @@ "provides": { "coordination_unit": [ "resource_coordinator::mojom::CoordinationUnitProvider" ], "service_callbacks": [ "resource_coordinator::mojom::ServiceCallbacks" ], + "tab_signal": [ "resource_coordinator::mojom::TabSignalGenerator" ], "tests": [ "*" ] }, "requires": {
diff --git a/services/resource_coordinator/public/cpp/coordination_unit_id.h b/services/resource_coordinator/public/cpp/coordination_unit_id.h index a145799..44d815b 100644 --- a/services/resource_coordinator/public/cpp/coordination_unit_id.h +++ b/services/resource_coordinator/public/cpp/coordination_unit_id.h
@@ -5,6 +5,7 @@ #define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_ID_H_ #include <string> +#include <tuple> #include "services/resource_coordinator/public/cpp/coordination_unit_types.h" #include "services/resource_coordinator/public/cpp/resource_coordinator_export.h" @@ -29,6 +30,10 @@ return id == b.id && type == b.type; } + bool operator<(const CoordinationUnitID& b) const { + return std::tie(id, type) < std::tie(b.id, b.type); + } + CoordinationUnitTypeId id; CoordinationUnitType type; };
diff --git a/services/resource_coordinator/public/cpp/resource_coordinator_features.cc b/services/resource_coordinator/public/cpp/resource_coordinator_features.cc index 0763762..1f514e0 100644 --- a/services/resource_coordinator/public/cpp/resource_coordinator_features.cc +++ b/services/resource_coordinator/public/cpp/resource_coordinator_features.cc
@@ -11,3 +11,11 @@ "GlobalResourceCoordinator", base::FEATURE_DISABLED_BY_DEFAULT}; } // namespace features + +namespace resource_coordinator { + +bool IsResourceCoordinatorEnabled() { + return base::FeatureList::IsEnabled(features::kGlobalResourceCoordinator); +} + +} // namespace resource_coordinator
diff --git a/services/resource_coordinator/public/cpp/resource_coordinator_features.h b/services/resource_coordinator/public/cpp/resource_coordinator_features.h index 83fe5ba6..2444a78 100644 --- a/services/resource_coordinator/public/cpp/resource_coordinator_features.h +++ b/services/resource_coordinator/public/cpp/resource_coordinator_features.h
@@ -20,4 +20,11 @@ } // namespace features +namespace resource_coordinator { + +bool SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_EXPORT +IsResourceCoordinatorEnabled(); + +} // namespace resource_coordinator + #endif // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_RESOURCE_COORDINATOR_FEATURES_H_
diff --git a/services/resource_coordinator/public/cpp/resource_coordinator_interface.cc b/services/resource_coordinator/public/cpp/resource_coordinator_interface.cc index 21b2928..b01d8ad 100644 --- a/services/resource_coordinator/public/cpp/resource_coordinator_interface.cc +++ b/services/resource_coordinator/public/cpp/resource_coordinator_interface.cc
@@ -51,6 +51,7 @@ const CoordinationUnitID& cu_id) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(connector); + cu_id_ = cu_id; mojom::CoordinationUnitProviderPtr provider; connector->BindInterface(mojom::kServiceName, mojo::MakeRequest(&provider));
diff --git a/services/resource_coordinator/public/cpp/resource_coordinator_interface.h b/services/resource_coordinator/public/cpp/resource_coordinator_interface.h index b1475105..8dd4028 100644 --- a/services/resource_coordinator/public/cpp/resource_coordinator_interface.h +++ b/services/resource_coordinator/public/cpp/resource_coordinator_interface.h
@@ -43,6 +43,7 @@ std::unique_ptr<base::Value> value); void AddChild(const ResourceCoordinatorInterface& child); void RemoveChild(const ResourceCoordinatorInterface& child); + CoordinationUnitID id() const { return cu_id_; } private: void ConnectToService(service_manager::Connector* connector, @@ -51,6 +52,7 @@ void RemoveChildByID(const CoordinationUnitID& child_id); mojom::CoordinationUnitPtr service_; + CoordinationUnitID cu_id_; base::ThreadChecker thread_checker_;
diff --git a/services/resource_coordinator/public/interfaces/BUILD.gn b/services/resource_coordinator/public/interfaces/BUILD.gn index 33587e1..9772afc 100644 --- a/services/resource_coordinator/public/interfaces/BUILD.gn +++ b/services/resource_coordinator/public/interfaces/BUILD.gn
@@ -15,6 +15,7 @@ "memory_instrumentation/memory_instrumentation.mojom", "service_callbacks.mojom", "service_constants.mojom", + "tab_signal.mojom", "tracing/tracing.mojom", "tracing/tracing_constants.mojom", ]
diff --git a/services/resource_coordinator/public/interfaces/coordination_unit.mojom b/services/resource_coordinator/public/interfaces/coordination_unit.mojom index 2b8ae10..be02883 100644 --- a/services/resource_coordinator/public/interfaces/coordination_unit.mojom +++ b/services/resource_coordinator/public/interfaces/coordination_unit.mojom
@@ -35,6 +35,7 @@ enum PropertyType { kTest, kCPUUsage, + kNetworkIdle, kVisible, };
diff --git a/services/resource_coordinator/public/interfaces/events.mojom b/services/resource_coordinator/public/interfaces/events.mojom index ee46713..57c942e3 100644 --- a/services/resource_coordinator/public/interfaces/events.mojom +++ b/services/resource_coordinator/public/interfaces/events.mojom
@@ -7,12 +7,14 @@ enum EventType { kTestEvent, kOnNavigationCommit, + + // WebContents event types. kOnWebContentsShown, kOnWebContentsHidden, - kOnRendererFrameCreated, + + // Process event types. kOnProcessAudioStarted, kOnProcessAudioStopped, - kOnLocalFrameNetworkIdle, }; struct Event {
diff --git a/services/resource_coordinator/public/interfaces/tab_signal.mojom b/services/resource_coordinator/public/interfaces/tab_signal.mojom new file mode 100644 index 0000000..7976f8b --- /dev/null +++ b/services/resource_coordinator/public/interfaces/tab_signal.mojom
@@ -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. + +module resource_coordinator.mojom; + +import "coordination_unit.mojom"; +import "mojo/common/values.mojom"; + +// Event signal scoped to a tab. +enum TabEvent { + kDoneLoading, +}; + +// A TabSignalObserver implementation receives tab-scoped signal from +// TabSignalGenerator. +// Any interested party that needs to observe tab-scoped signal from GRC must +// implement this interface, construct mojo channel to the implementation, and +// pass the interface pointer of mojo channel to TabSignalGenerator through +// TabSignalGenerator::AddObserver. +interface TabSignalObserver { + OnEventReceived(CoordinationUnitID cu_id, TabEvent event); +}; + +// A TabSignalGenerator implementation will be implemented inside GRC to observe +// signals from Coordination Units, generate tab-scoped signals, sends signals +// to TabSignalObserver implementations. +// There will be only one TabSignalGenerator implementation. +interface TabSignalGenerator { + AddObserver(TabSignalObserver observer); +}; \ No newline at end of file
diff --git a/services/resource_coordinator/resource_coordinator_service.cc b/services/resource_coordinator/resource_coordinator_service.cc index 1de5dfb..b733a052 100644 --- a/services/resource_coordinator/resource_coordinator_service.cc +++ b/services/resource_coordinator/resource_coordinator_service.cc
@@ -7,7 +7,7 @@ #include <utility> #include "base/memory/ptr_util.h" -#include "services/resource_coordinator/coordination_unit/tab_signal_generator.h" +#include "services/resource_coordinator/coordination_unit/tab_signal_generator_impl.h" #include "services/resource_coordinator/service_callbacks_impl.h" #include "services/service_manager/public/cpp/service_context.h" @@ -17,12 +17,7 @@ auto resource_coordinator_service = base::MakeUnique<ResourceCoordinatorService>(); - // Register new |CoordinationUnitGraphObserver| implementations here. - resource_coordinator_service->coordination_unit_manager()->RegisterObserver( - base::MakeUnique<TabSignalGenerator>()); - - return std::unique_ptr<service_manager::Service>( - resource_coordinator_service.release()); + return resource_coordinator_service; } ResourceCoordinatorService::ResourceCoordinatorService() @@ -39,6 +34,14 @@ base::Unretained(ref_factory_.get()), base::Unretained(this))); + // Register new |CoordinationUnitGraphObserver| implementations here. + auto tab_signal_generator_impl = base::MakeUnique<TabSignalGeneratorImpl>(); + registry_.AddInterface( + base::Bind(&TabSignalGeneratorImpl::BindToInterface, + base::Unretained(tab_signal_generator_impl.get()))); + coordination_unit_manager_.RegisterObserver( + std::move(tab_signal_generator_impl)); + coordination_unit_manager_.OnStart(®istry_, ref_factory_.get()); }
diff --git a/services/ui/public/interfaces/window_manager.mojom b/services/ui/public/interfaces/window_manager.mojom index 97f2b78a..269aba2b 100644 --- a/services/ui/public/interfaces/window_manager.mojom +++ b/services/ui/public/interfaces/window_manager.mojom
@@ -284,6 +284,8 @@ // WindowManagerWindowTreeFactory::CreateWindowTree() for details). // |local_surface_id| identifies the ID to use to submit CompositorFrames. // base::nullopt indicates failure. + // This function may also be used to move an existing display root to a new + // display. SetDisplayRoot(display.mojom.Display display, WmViewportMetrics viewport_metrics, bool is_primary_display,
diff --git a/services/ui/ws/window_tree.cc b/services/ui/ws/window_tree.cc index 92bbfdf..82fcc26b5 100644 --- a/services/ui/ws/window_tree.cc +++ b/services/ui/ws/window_tree.cc
@@ -291,8 +291,7 @@ DCHECK(window_manager_state_); // Only called for window manager. DVLOG(3) << "SetDisplayRoot client=" << id_ << " global window_id=" << client_window_id.id; - Display* display = display_manager()->GetDisplayById(display_to_create.id()); - if (display) { + if (display_manager()->GetDisplayById(display_to_create.id())) { DVLOG(1) << "SetDisplayRoot called with existing display " << display_to_create.id(); return nullptr; @@ -305,14 +304,15 @@ } ServerWindow* window = GetWindowByClientId(client_window_id); - // The window must not have a parent. - if (!window || window->parent()) { + const bool is_moving_to_new_display = + window && window->parent() && base::ContainsKey(roots_, window); + if (!window || (window->parent() && !is_moving_to_new_display)) { DVLOG(1) << "SetDisplayRoot called with invalid window id " << client_window_id.id; return nullptr; } - if (base::ContainsKey(roots_, window)) { + if (base::ContainsKey(roots_, window) && !is_moving_to_new_display) { DVLOG(1) << "SetDisplayRoot called with existing root"; return nullptr; } @@ -323,7 +323,7 @@ viewport_metrics.device_scale_factor = transport_viewport_metrics.device_scale_factor; viewport_metrics.ui_scale_factor = transport_viewport_metrics.ui_scale_factor; - display = display_manager()->AddDisplayForWindowManager( + Display* display = display_manager()->AddDisplayForWindowManager( is_primary_display, display_to_create, viewport_metrics); DCHECK(display); WindowManagerDisplayRoot* display_root = @@ -336,7 +336,13 @@ // care of any modifications it needs to do. roots_.insert(window); Operation op(this, window_server_, OperationType::ADD_WINDOW); + ServerWindow* old_parent = + is_moving_to_new_display ? window->parent() : nullptr; display_root->root()->Add(window); + if (is_moving_to_new_display) { + DCHECK(old_parent); + window_manager_state_->DeleteWindowManagerDisplayRoot(old_parent); + } return window; }
diff --git a/services/ui/ws/window_tree_unittest.cc b/services/ui/ws/window_tree_unittest.cc index 8350e1f..bc99456 100644 --- a/services/ui/ws/window_tree_unittest.cc +++ b/services/ui/ws/window_tree_unittest.cc
@@ -1644,6 +1644,81 @@ .empty()); } +TEST_F(WindowTreeManualDisplayTest, MoveDisplayRootToNewDisplay) { + const bool automatically_create_display_roots = false; + AddWindowManager(window_server(), kTestUserId1, + automatically_create_display_roots); + + WindowManagerState* window_manager_state = + window_server()->GetWindowManagerStateForUser(kTestUserId1); + ASSERT_TRUE(window_manager_state); + WindowTree* window_manager_tree = window_manager_state->window_tree(); + EXPECT_TRUE(window_manager_tree->roots().empty()); + TestWindowManager* test_window_manager = + window_server_delegate()->last_binding()->window_manager(); + EXPECT_EQ(1, test_window_manager->connect_count()); + EXPECT_EQ(0, test_window_manager->display_added_count()); + + // Create a window for the windowmanager and set it as the root. + ClientWindowId display_root_id = BuildClientWindowId(window_manager_tree, 10); + ASSERT_TRUE(window_manager_tree->NewWindow(display_root_id, + ServerWindow::Properties())); + ServerWindow* display_root = + window_manager_tree->GetWindowByClientId(display_root_id); + ASSERT_TRUE(display_root); + display::Display display1 = MakeDisplay(0, 0, 1024, 768, 1.0f); + constexpr int64_t display1_id = 101; + display1.set_id(display1_id); + + mojom::WmViewportMetrics metrics; + metrics.bounds_in_pixels = display1.bounds(); + metrics.device_scale_factor = 1.5; + metrics.ui_scale_factor = 2.5; + const bool is_primary_display = true; + ASSERT_TRUE(WindowTreeTestApi(window_manager_tree) + .ProcessSetDisplayRoot(display1, metrics, is_primary_display, + display_root_id)); + ASSERT_TRUE(display_root->parent()); + const WindowId display1_parent_id = display_root->parent()->id(); + EXPECT_TRUE(window_server_delegate() + ->last_binding() + ->client() + ->tracker() + ->changes() + ->empty()); + EXPECT_EQ(1u, window_manager_tree->roots().size()); + + // Call ProcessSetDisplayRoot() again, with a different display. + display::Display display2 = MakeDisplay(0, 0, 1024, 768, 1.0f); + constexpr int64_t display2_id = 102; + display2.set_id(display2_id); + ASSERT_TRUE(WindowTreeTestApi(window_manager_tree) + .ProcessSetDisplayRoot(display2, metrics, is_primary_display, + display_root_id)); + ASSERT_TRUE(display_root->parent()); + EXPECT_NE(display1_parent_id, display_root->parent()->id()); + EXPECT_TRUE(window_server_delegate() + ->last_binding() + ->client() + ->tracker() + ->changes() + ->empty()); + EXPECT_EQ(1u, window_manager_tree->roots().size()); + // The WindowManagerDisplayRoot for |display1| should have been deleted. + EXPECT_EQ(1u, WindowManagerStateTestApi(window_manager_state) + .window_manager_display_roots() + .size()); + EXPECT_FALSE(window_server()->display_manager()->GetDisplayById(display1_id)); + EXPECT_TRUE(window_server()->display_manager()->GetDisplayById(display2_id)); + + // Delete the root, which should delete the WindowManagerDisplayRoot. + EXPECT_TRUE(window_manager_tree->DeleteWindow(display_root_id)); + EXPECT_TRUE(window_manager_tree->roots().empty()); + EXPECT_TRUE(WindowManagerStateTestApi(window_manager_state) + .window_manager_display_roots() + .empty()); +} + TEST_F(WindowTreeManualDisplayTest, DisplayManagerObserverNotifiedWithManualRoots) { const bool automatically_create_display_roots = false;
diff --git a/services/viz/README.md b/services/viz/README.md new file mode 100644 index 0000000..2c81055 --- /dev/null +++ b/services/viz/README.md
@@ -0,0 +1,143 @@ +Viz Directory Structure +-------------------------------------------------------------------------------- + +The Viz (Visuals) service is a collection of subservices: compositing, gl, hit +testing, and media. + +Viz has two types of clients: a single privileged client and one or more +unprivileged clients. + +The privileged client is responsible for starting and restarting Viz after a +crash and for facilitating connections to Viz from unprivileged clients. The +privileged client is trusted by all other clients, and is expected to be +long-lived and not prone to crashes. + +Unprivileged clients request connections to Viz through the privileged client +such as the browser process or the window server. Furthermore, unprivileged +clients may be malicious or may crash at any time. Unprivileged clients are +expected to be mutually distrusting of one another. Thus, an unprivileged client +cannot be provided interfaces by which it can impact the operation of another +client. + +For example, a channel to the GL service can only be dispensed by the privileged +client, but can be used by unprivileged clients. GL commands are exposed as a +stable public API to the command buffer by the client library whereas the +underlying IPC messages and their semantics are constantly changing and +meaningless without deep knowledge of implementation details. + +We propose the following directory structure to accommodate Viz's needs. + +//services/viz/public/interfaces/{compositing, gl, hit_test, media} +//services/viz/public/<language>/{compositing, gl, hit_test, media} +-------------------------------------------------------------------------------- + +The interfaces directories contain mojoms that define the public, unprivileged +interface for the Viz subservices. Clients may directly use the mojo interfaces +in these directories or choose to use the client library in a public/<language> +directory if one exists for a given mojom. private and privileged interfaces +described below may depend on public interfaces. + +//services/viz/public/<language>/{compositing, gl, hit_test, media}:data_types +-------------------------------------------------------------------------------- + +Common data types such as CompositorFrame, and GpuMemoryBufferHandle can live in +//services/viz/public/<language>/{compositing, gl, hit_test, media} under the +data_types target. + +Their associated mojoms can live in: + +//services/viz/public/interfaces/{compositing, gl, hit_test, media}. + +Note: + +//services/viz/public/<language>/{compositing, gl, hit_test, media}:data_types +holds C++ types only and does not depend on +//services/viz/public/interfaces/{compositing, gl, hit_test, media}. Instead, +there are StructTraits with the interfaces that produce/consume data_types for +mojo transport. + +//services/viz/{compositing, gl, hit_test, media}/private/interfaces +-------------------------------------------------------------------------------- + +These interfaces directories contain mojoms that may only be used by going +through a language-specific client library. They are meant for unprivileged use, +without direct access to the mojoms. As such, only the +//services/viz/public/<language> and //services/viz/privileged/<language> +directories may depend on private, while other directories including interface +directories must not. There is no private client library, as these are meant for +consumption by the public client library. + +//services/viz/{compositing, gl, hit_test, media}/privileged/interfaces +//services/viz/{compositing, gl, hit_test, media}/privileged/<language> +-------------------------------------------------------------------------------- + +The interfaces directories contains mojoms that may only be used by the +privileged client. Privileged interfaces are kept in separate directories to +facilitate security reviews. These interfaces may be used directly or through +the a privileged/<language> client library. The public and private interfaces +must not depend on privileged interfaces. Typically, the browser process or the +window server serves as the privileged client to Viz. + +//services/viz/main +-------------------------------------------------------------------------------- + +This is the glue code that implements the primordial VizMain interface (in +//services/viz/main/privileged/interfaces) that starts up the Viz process +through the service manager. VizMain is a factory interface that enables the +privileged client to instantiate the Viz subservices: compositing, gl, hit_test, +and media. + +//services/viz/{compositing, gl, hit_test, media}/service +-------------------------------------------------------------------------------- + +Service-side implementation code live in the various sub-service "service" +directories. Service code may depend on the public/<language>/…:data_types +target and interfaces subdirectories, but cannot depend on any of the +//service/viz/public/<language>/... client library. + +Short term: //components/viz and //gpu and //media +-------------------------------------------------------------------------------- + +At this time, the Viz public client library for the compositing and hit_test +subservices live in //components/viz/client, and the privileged client library +lives in //components/viz/host. + +Command buffer code will continue to live in //gpu and media code will continue +to live in //media. + +Once the content module has been removed (or no longer depends on +components/viz/service), the code in //components/viz/client will move to +appropriate destinations in //services/viz/public/<language>/.... +//components/viz/service will move to the appropriate service directories in +//services/viz/.... //components/viz/host will move to +//services/viz/{compositing, gl, hit_test, media}/privileged. + +Once the content module is gone, and //services/ui is the only privileged +client, then perhaps the privileged client library may move to //services/ui. + +Acceptable Dependencies +-------------------------------------------------------------------------------- + +Note: => means can depend on + +Unprivileged client, can depend on + services/viz/public/<language>/{compositing, gl, hit_test, media} => + services/viz/public/interfaces/{compositing, gl, hit_test, media} => + services/viz/public/<language>/{compositing, gl, hit_test, media}:data_types + services/viz/private/interfaces/{compositing, gl, hit_test, media} => + services/viz/public/<language>/{compositing, gl, hit_test, media}:data_types + services/viz/public/interfaces/{compositing, gl, hit_test, media} + +The privileged client can depend on + services/viz/privileged/<language>/{compositing, gl, hit_test, media} => + services/viz/privileged/interfaces/{compositing, gl, hit_test, media} + services/viz/public/interfaces/{compositing, gl, hit_test, media} + services/viz/public/<language>/{compositing, gl, hit_test, media} + +Services can depend on: + services/viz/public/interfaces/{compositing, gl, hit_test, media} + services/viz/public/<language>/{compositing, gl, hit_test, media}:data_types + services/viz/privileged/interfaces/{compositing, gl, hit_test, media} + services/viz/private/interfaces/{compositing, gl, hit test, media} + +
diff --git a/services/viz/hit_test/public/interfaces/BUILD.gn b/services/viz/hit_test/public/interfaces/BUILD.gn new file mode 100644 index 0000000..b9d25a15 --- /dev/null +++ b/services/viz/hit_test/public/interfaces/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. + +import("//mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "hit_test_region_list.mojom", + ] + + public_deps = [ + "//cc/ipc:interfaces", + "//ui/gfx/geometry/mojo", + "//ui/gfx/mojo", + ] +}
diff --git a/services/viz/hit_test/public/interfaces/OWNERS b/services/viz/hit_test/public/interfaces/OWNERS new file mode 100644 index 0000000..e1fa1e06 --- /dev/null +++ b/services/viz/hit_test/public/interfaces/OWNERS
@@ -0,0 +1,3 @@ +rjkroege@chromium.org +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/services/viz/hit_test/public/interfaces/hit_test_region_list.mojom b/services/viz/hit_test/public/interfaces/hit_test_region_list.mojom new file mode 100644 index 0000000..3c36743 --- /dev/null +++ b/services/viz/hit_test/public/interfaces/hit_test_region_list.mojom
@@ -0,0 +1,59 @@ +// 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. + +module viz.mojom; + +import "cc/ipc/surface_id.mojom"; +import "ui/gfx/geometry/mojo/geometry.mojom"; +import "ui/gfx/mojo/transform.mojom"; + +// Region maps to this surface (me). +const uint32 kHitTestMine = 0x01; + +// Region ignored for hit testing (transparent backgrounds & hover:none). +const uint32 kHitTestIgnore = 0x02; + +// Region maps to child surface (OOPIF). +const uint32 kHitTestChildSurface = 0x04; + +// Irregular boundary - send HitTestRequest to resolve. +const uint32 kHitTestAsk = 0x08; + +// Touch event handler exists. +const uint32 kHitTestTouchEventHandler = 0x10; + +struct HitTestRegion { + // Flags to indicate the type of HitTestRegion. + uint32 flags; + + // SurfaceId is required when flags = kHitTestChildSurface. + cc.mojom.SurfaceId surface_id; + + // The rect of the region in the coordinate space of the embedder. + gfx.mojom.Rect rect; + + // The transform of the region. The transform applied to the rect + // defines the space occupied by this region in the coordinate space of + // the embedder. + gfx.mojom.Transform transform; +}; + +struct HitTestRegionList { + // SurfaceId corresponding to this HitTestData. + cc.mojom.SurfaceId surface_id; + + // Flags indicate how to handle events that match no sub-regions. + // kHitTestMine routes un-matched events to this surface (opaque). + // kHitTestIgnore keeps previous match in the parent (transparent). + uint32 flags; + + // The bounds of the surface. + gfx.mojom.Rect bounds; + + // The transform applied to all regions in this surface. + gfx.mojom.Transform transform; + + // The list of sub-regions in front to back order. + array<HitTestRegion> regions; +};
diff --git a/testing/buildbot/tryserver.chromium.perf.json b/testing/buildbot/tryserver.chromium.perf.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/testing/buildbot/tryserver.chromium.perf.json
@@ -0,0 +1 @@ +{}
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService index 4dc74b6..c73d3c1 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -547,6 +547,9 @@ Bug(none) fast/loader/stateobjects/pushstate-in-data-url-denied.html [ Failure ] Bug(none) fast/loader/url-strip-cr-lf-tab.html [ Failure ] Bug(none) fast/media/mq-color-gamut-picture.html [ Failure ] +Bug(none) fast/mediacapturefromelement/HTMLMediaElementCapture-capture.html [ Timeout ] +Bug(none) fast/mediacapturefromelement/HTMLMediaElementCapture-creation.html [ Timeout ] +Bug(none) fast/mediacapturefromelement/HTMLMediaElementCapture-ended.html [ Timeout ] Bug(none) fast/mediarecorder/BlobEvent-basic.html [ Failure ] Bug(none) fast/mediastream/MediaStreamTrack-clone.html [ Timeout ] Bug(none) fast/mediastream/MediaStreamTrack-contentHint.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 6a8af3f..86de759 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1804,6 +1804,19 @@ crbug.com/626703 external/wpt/css/css-writing-modes-3/sizing-orthog-vrl-in-htb-020.xht [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes-3/wm-propagation-body-008.xht [ Failure ] +crbug.com/743085 inspector-protocol/debugger/debugger-setBlackboxPatterns.js [ NeedsManualRebaseline ] +crbug.com/743085 inspector-protocol/debugger/stepping-with-blackboxed-ranges.js [ NeedsManualRebaseline ] +crbug.com/743085 inspector/sources/debugger-breakpoints/possible-breakpoints.html [ NeedsManualRebaseline ] +crbug.com/743085 inspector/sources/debugger-frameworks/frameworks-sourcemap.html [ NeedsManualRebaseline ] +crbug.com/743085 inspector/sources/debugger-frameworks/frameworks-step-into-skips-setTimeout.html [ NeedsManualRebaseline ] +crbug.com/743085 inspector/sources/debugger-step/debugger-step-into-inlined-scripts.html [ NeedsManualRebaseline ] +crbug.com/743085 inspector/sources/debugger-step/debugger-step-over-inlined-scripts.html [ NeedsManualRebaseline ] +crbug.com/743085 inspector/sources/debugger-step/debugger-step-through-promises.html [ NeedsManualRebaseline ] +crbug.com/743085 inspector/sources/debugger/debugger-return-value.html [ NeedsManualRebaseline ] +crbug.com/743085 inspector/sources/debugger/live-edit.html [ NeedsManualRebaseline ] +crbug.com/743085 inspector/sources/debugger/source-frame-breakpoint-decorations.html [ NeedsManualRebaseline ] +crbug.com/743085 inspector/sources/debugger/source-frame-inline-breakpoint-decorations.html [ NeedsManualRebaseline ] + crbug.com/655458 crbug.com/721814 external/wpt/mediacapture-image/idlharness.html [ Skip ] crbug.com/655458 crbug.com/721814 external/wpt/WebCryptoAPI/idlharness.html [ Skip ] crbug.com/655458 crbug.com/721814 external/wpt/WebCryptoAPI/idlharness.https.html [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 02dbe699..71fac13 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -104544,16 +104544,6 @@ {} ] ], - "service-workers/service-worker/fetch-canvas-tainting-cache.https-expected.txt": [ - [ - {} - ] - ], - "service-workers/service-worker/fetch-canvas-tainting.https-expected.txt": [ - [ - {} - ] - ], "service-workers/service-worker/fetch-event-redirect.https-expected.txt": [ [ {} @@ -125513,6 +125503,16 @@ {} ] ], + "dom/abort/event.any.js": [ + [ + "/dom/abort/event.any.html", + {} + ], + [ + "/dom/abort/event.any.worker.html", + {} + ] + ], "dom/collections/HTMLCollection-as-proto-length-get-throws.html": [ [ "/dom/collections/HTMLCollection-as-proto-length-get-throws.html", @@ -183681,11 +183681,11 @@ "reftest" ], "css-paint-api/background-image-tiled-ref.html": [ - "a879be73470aae683bd7596132225770bc8be27b", + "bcee5040691f057a672e58eec3beed75122be3b8", "support" ], "css-paint-api/background-image-tiled.html": [ - "03aff62fc21832b44d9de15805232d87d0089ed3", + "83f9e2566f9e6957fdf3b67e9e62374984861e78", "reftest" ], "css-paint-api/geometry-background-image-001-ref.html": [ @@ -183713,11 +183713,11 @@ "reftest" ], "css-paint-api/geometry-background-image-tiled-001-ref.html": [ - "df994fa58244f5e8d4b4aac7f0ad335fe8570dcc", + "475fd7979cd173f378c03a7d9d27503e12c2dc7c", "support" ], "css-paint-api/geometry-background-image-tiled-001.html": [ - "f89e6c4f164c10a64037a3feefd915d760a99765", + "a892266cab4d74a3f4df2bbe1cda8823a38f3153", "reftest" ], "css-paint-api/geometry-background-image-tiled-002-ref.html": [ @@ -220356,6 +220356,10 @@ "e3e7f3973cf8f9b466d4f22d1ec3b9b9241fb906", "support" ], + "dom/abort/event.any.js": [ + "25e9c1104acb9b0092d1303190588a3953cf635d", + "testharness" + ], "dom/collections/HTMLCollection-as-proto-length-get-throws.html": [ "487f3991b116ceb503352ed025961282a8761e95", "testharness" @@ -220601,7 +220605,7 @@ "testharness" ], "dom/interface-objects.html": [ - "144554e0a9d53cdbb2c1f01d3dc169010db693b3", + "05963c8b0a839f3e07b5478d99fc034e4654b515", "testharness" ], "dom/interfaces-expected.txt": [ @@ -220609,7 +220613,7 @@ "support" ], "dom/interfaces.html": [ - "aae8f328bc52cbb17f47f78ace6d20c25a9c3acc", + "7d00e3a778083a91156f4e042c7abd270060a7fc", "testharness" ], "dom/lists/DOMTokenList-Iterable.html": [ @@ -225193,7 +225197,7 @@ "support" ], "fetch/api/response/response-consume-stream.html": [ - "7dd429b389a997a879362629985089bad495a227", + "dad05becbd8f3944aa3709ae1a3e578c05d4d935", "testharness" ], "fetch/api/response/response-consume.html": [ @@ -241761,7 +241765,7 @@ "support" ], "interfaces/dom.idl": [ - "2b94c6332d8535bbcfd605bc3ed46ba6f705de62", + "f39e0bad95534e2cc59012436ea430fe2a414c05", "support" ], "interfaces/fullscreen.idl": [ @@ -251217,7 +251221,7 @@ "support" ], "payment-request/payment-request-canmakepayment-method.https.html": [ - "3b145e1e2164d5201ded51ce138aeeb4163e0261", + "988988ff3ff697b9e4ce615c709fb49df69235ab", "testharness" ], "payment-request/payment-request-constructor-crash.https-expected.txt": [ @@ -260648,18 +260652,10 @@ "401235c18e1594c7248b22eb6881d54801de9809", "testharness" ], - "service-workers/service-worker/fetch-canvas-tainting-cache.https-expected.txt": [ - "0d8e7b013322279c687fe6a602746db6c3a4bca2", - "support" - ], "service-workers/service-worker/fetch-canvas-tainting-cache.https.html": [ "b3f8375bc412c99099ac886673fd80f6cb0a312b", "testharness" ], - "service-workers/service-worker/fetch-canvas-tainting.https-expected.txt": [ - "76743fb558f5f25a03603e2795bfbdf90deca639", - "support" - ], "service-workers/service-worker/fetch-canvas-tainting.https.html": [ "9c2e160f95d2915a961bd7da840ac53779c9387d", "testharness" @@ -264417,7 +264413,7 @@ "support" ], "url/urlsearchparams-constructor.html": [ - "854e06efa9598f66705605bdef20c4a500ab2e9b", + "e7d341e38acba7c7608da8567c20a3468ca522e2", "testharness" ], "url/urlsearchparams-delete-expected.txt": [ @@ -264425,7 +264421,7 @@ "support" ], "url/urlsearchparams-delete.html": [ - "b1fcda755e2a9e3308a222fe213abf0a255f0777", + "4713dfec8b4277cc29520dbd25958bd74e440c19", "testharness" ], "url/urlsearchparams-foreach-expected.txt": [ @@ -264453,7 +264449,7 @@ "testharness" ], "url/urlsearchparams-sort.html": [ - "6a3904b5dada6b1e071b16529e75c6ce18ce45d6", + "dfc8f32339d084299318e9eb94fc47171247f2e1", "testharness" ], "url/urlsearchparams-stringifier.html": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-strict_dynamic_worker-importScripts.https.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-strict_dynamic_worker-importScripts.https.html new file mode 100644 index 0000000..681e195 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-strict_dynamic_worker-importScripts.https.html
@@ -0,0 +1,18 @@ +<!DOCTYPE html> +<script src='/resources/testharness.js'></script> +<script src='/resources/testharnessreport.js'></script> +<script src='../support/testharness-helper.js'></script> + +<meta http-equiv="content-security-policy" content="script-src 'nonce-abc' 'strict-dynamic'"> + +<script nonce="abc"> + async_test(t => { + assert_no_csp_event_for_url(t, "../support/import-scripts.js"); + var w = new Worker("../support/import-scripts.js"); + assert_no_event(t, w, "error"); + waitUntilEvent(w, "message") + .then(t.step_func_done(e => { + assert_true(e.data.executed); + })); + }, "`importScripts(...)` is allowed by 'strict-dynamic'"); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/support/import-scripts.js b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/support/import-scripts.js new file mode 100644 index 0000000..8325ebb3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/support/import-scripts.js
@@ -0,0 +1,3 @@ +self.a = false; +importScripts('/content-security-policy/support/var-a.js'); +postMessage({ 'executed': self.a });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/abort/event.any.js b/third_party/WebKit/LayoutTests/external/wpt/dom/abort/event.any.js new file mode 100644 index 0000000..3b25702 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/abort/event.any.js
@@ -0,0 +1,22 @@ +test(t => { + const c = new AbortController(), + s = c.signal; + let state = "begin"; + + assert_false(s.aborted); + + s.addEventListener("abort", + t.step_func(e => { + assert_equals(state, "begin"); + state = "aborted"; + }) + ); + c.abort(); + + assert_equals(state, "aborted"); + assert_true(s.aborted); + + c.abort(); +}, "AbortController() basics"); + +done();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/interface-objects-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/interface-objects-expected.txt new file mode 100644 index 0000000..cfa04f8d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/interface-objects-expected.txt
@@ -0,0 +1,26 @@ +This is a testharness.js-based test. +PASS Interface objects properties should not be Enumerable +PASS Should be able to delete Event. +PASS Should be able to delete CustomEvent. +PASS Should be able to delete EventTarget. +FAIL Should be able to delete AbortController. assert_true: Interface should exist. expected true got false +FAIL Should be able to delete AbortSignal. assert_true: Interface should exist. expected true got false +PASS Should be able to delete Node. +PASS Should be able to delete Document. +PASS Should be able to delete DOMImplementation. +PASS Should be able to delete DocumentFragment. +PASS Should be able to delete ProcessingInstruction. +PASS Should be able to delete DocumentType. +PASS Should be able to delete Element. +PASS Should be able to delete Attr. +PASS Should be able to delete CharacterData. +PASS Should be able to delete Text. +PASS Should be able to delete Comment. +PASS Should be able to delete NodeIterator. +PASS Should be able to delete TreeWalker. +PASS Should be able to delete NodeFilter. +PASS Should be able to delete NodeList. +PASS Should be able to delete HTMLCollection. +PASS Should be able to delete DOMTokenList. +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/interface-objects.html b/third_party/WebKit/LayoutTests/external/wpt/dom/interface-objects.html index df4ca51..936d635 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/interface-objects.html +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/interface-objects.html
@@ -15,6 +15,8 @@ "Event", "CustomEvent", "EventTarget", + "AbortController", + "AbortSignal", "Node", "Document", "DOMImplementation",
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 a5f71f6..d102b79 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 1618 tests; 1610 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 1646 tests; 1610 PASS, 36 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Test driver PASS Event interface: existence and properties of interface object PASS Event interface object length @@ -116,6 +116,34 @@ PASS EventListener interface: existence and properties of interface prototype object PASS EventListener interface: existence and properties of interface prototype object's "constructor" property PASS EventListener interface: operation handleEvent(Event) +FAIL AbortController interface: existence and properties of interface object assert_own_property: self does not have own property "AbortController" expected property "AbortController" missing +FAIL AbortController interface object length assert_own_property: self does not have own property "AbortController" expected property "AbortController" missing +FAIL AbortController interface object name assert_own_property: self does not have own property "AbortController" expected property "AbortController" missing +FAIL AbortController interface: existence and properties of interface prototype object assert_own_property: self does not have own property "AbortController" expected property "AbortController" missing +FAIL AbortController interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "AbortController" expected property "AbortController" missing +FAIL AbortController interface: attribute signal assert_own_property: self does not have own property "AbortController" expected property "AbortController" missing +FAIL AbortController interface: operation abort() assert_own_property: self does not have own property "AbortController" expected property "AbortController" missing +FAIL AbortController must be primary interface of new AbortController() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: AbortController is not defined" +FAIL Stringification of new AbortController() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: AbortController is not defined" +FAIL AbortController interface: new AbortController() must inherit property "signal" with the proper type (0) assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: AbortController is not defined" +FAIL AbortController interface: new AbortController() must inherit property "abort" with the proper type (1) assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: AbortController is not defined" +FAIL AbortSignal interface: existence and properties of interface object assert_own_property: self does not have own property "AbortSignal" expected property "AbortSignal" missing +FAIL AbortSignal interface object length assert_own_property: self does not have own property "AbortSignal" expected property "AbortSignal" missing +FAIL AbortSignal interface object name assert_own_property: self does not have own property "AbortSignal" expected property "AbortSignal" missing +FAIL AbortSignal interface: existence and properties of interface prototype object assert_own_property: self does not have own property "AbortSignal" expected property "AbortSignal" missing +FAIL AbortSignal interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "AbortSignal" expected property "AbortSignal" missing +FAIL AbortSignal interface: attribute aborted assert_own_property: self does not have own property "AbortSignal" expected property "AbortSignal" missing +FAIL AbortSignal interface: attribute onabort assert_own_property: self does not have own property "AbortSignal" expected property "AbortSignal" missing +FAIL AbortSignal must be primary interface of new AbortController().signal assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: AbortController is not defined" +FAIL Stringification of new AbortController().signal assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: AbortController is not defined" +FAIL AbortSignal interface: new AbortController().signal must inherit property "aborted" with the proper type (0) assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: AbortController is not defined" +FAIL AbortSignal interface: new AbortController().signal must inherit property "onabort" with the proper type (1) assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: AbortController is not defined" +FAIL EventTarget interface: new AbortController().signal must inherit property "addEventListener" with the proper type (0) assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: AbortController is not defined" +FAIL EventTarget interface: calling addEventListener(DOMString,EventListener,[object Object],[object Object]) on new AbortController().signal with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: AbortController is not defined" +FAIL EventTarget interface: new AbortController().signal must inherit property "removeEventListener" with the proper type (1) assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: AbortController is not defined" +FAIL EventTarget interface: calling removeEventListener(DOMString,EventListener,[object Object],[object Object]) on new AbortController().signal with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: AbortController is not defined" +FAIL EventTarget interface: new AbortController().signal must inherit property "dispatchEvent" with the proper type (2) assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: AbortController is not defined" +FAIL EventTarget interface: calling dispatchEvent(Event) on new AbortController().signal with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: AbortController is not defined" PASS NodeList interface: existence and properties of interface object PASS NodeList interface object length PASS NodeList interface object name
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces.html b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces.html index 8b4140d..8e9572d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces.html +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces.html
@@ -24,6 +24,8 @@ EventTarget: ['new EventTarget()'], Event: ['document.createEvent("Event")', 'new Event("foo")'], CustomEvent: ['new CustomEvent("foo")'], + AbortController: ['new AbortController()'], + AbortSignal: ['new AbortController().signal'], Document: ['new Document()'], XMLDocument: ['xmlDoc'], DOMImplementation: ['document.implementation'],
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/response/response-consume-stream.html b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/response/response-consume-stream.html index 54d55fcb..21424f2a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/response/response-consume-stream.html +++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/response/response-consume-stream.html
@@ -65,7 +65,7 @@ }, "Getting an error Response stream"); promise_test(function(test) { - assert_equals(Response.redirect(301).body, null); + assert_equals(Response.redirect("/").body, null); }, "Getting a redirect Response stream"); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/dom.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/dom.idl index 9ca270ea..b1a959ec 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/dom.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/dom.idl
@@ -1,5 +1,5 @@ -[Constructor(DOMString type, optional EventInit eventInitDict)/*, - Exposed=(Window,Worker)*/] +[Constructor(DOMString type, optional EventInit eventInitDict), + Exposed=(Window,Worker)] interface Event { readonly attribute DOMString type; readonly attribute EventTarget? target; @@ -31,8 +31,8 @@ }; -[Constructor(DOMString type, optional CustomEventInit eventInitDict)/*, - Exposed=(Window,Worker)*/] +[Constructor(DOMString type, optional CustomEventInit eventInitDict), + Exposed=(Window,Worker)] interface CustomEvent : Event { readonly attribute any detail; @@ -44,7 +44,8 @@ }; -[Constructor/*, Exposed=(Window,Worker)*/] +[Constructor, + Exposed=(Window,Worker)] interface EventTarget { void addEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options); void removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options); @@ -61,6 +62,23 @@ }; +[Constructor, + Exposed=(Window,Worker)] +interface AbortController { + [SameObject] readonly attribute AbortSignal signal; + + void abort(); +}; + + +[Exposed=(Window,Worker)] +interface AbortSignal : EventTarget { + readonly attribute boolean aborted; + + attribute EventHandler onabort; +}; + + [NoInterfaceObject, Exposed=Window] interface NonElementParentNode {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/webm/test-a-128k-44100Hz-1ch.webm b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/webm/test-a-128k-44100Hz-1ch.webm deleted file mode 100644 index c5b064de..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/webm/test-a-128k-44100Hz-1ch.webm +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/webm/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.webm b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/webm/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.webm deleted file mode 100644 index 8b705db..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/webm/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.webm +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/webm/test-v-128k-320x240-24fps-8kfr.webm b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/webm/test-v-128k-320x240-24fps-8kfr.webm deleted file mode 100644 index 189c472..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/webm/test-v-128k-320x240-24fps-8kfr.webm +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https.html index 891a62d..981ddb8 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https.html
@@ -30,7 +30,7 @@ `canMakePaymentPromise should be true` ); } catch (err) { - assert_equal( + assert_equals( err.name, "NotAllowedError", "if it throws, then it must be a NotAllowedError." @@ -71,7 +71,7 @@ `should have thrown InvalidStateError, but instead returned "${result}"` ); } catch (err) { - assert_equal( + assert_equals( err.name, "InvalidStateError", "must be an InvalidStateError." @@ -124,7 +124,7 @@ try { await request.canMakePayment(); } catch (err) { - assert_equal( + assert_equals( err.name, "NotAllowedError", "if it throws, then it must be a NotAllowedError." @@ -136,7 +136,7 @@ try { await new PaymentRequest(defaultMethods, defaultDetails).canMakePayment(); } catch (err) { - assert_equal( + assert_equals( err.name, "NotAllowedError", "if it throws, then it must be a NotAllowedError."
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-constructor-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-constructor-expected.txt deleted file mode 100644 index 31edfdf6..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-constructor-expected.txt +++ /dev/null
@@ -1,26 +0,0 @@ -This is a testharness.js-based test. -PASS Basic URLSearchParams construction -PASS URLSearchParams constructor, no arguments -FAIL URLSearchParams constructor, DOMException.prototype as argument Illegal invocation -PASS URLSearchParams constructor, empty string as argument -PASS URLSearchParams constructor, {} as argument -PASS URLSearchParams constructor, string. -PASS URLSearchParams constructor, object. -PASS Parse + -PASS Parse encoded + -PASS Parse space -PASS Parse %20 -PASS Parse \0 -PASS Parse %00 -PASS Parse ⎄ -PASS Parse %e2%8e%84 -PASS Parse 💩 -PASS Parse %f0%9f%92%a9 -PASS Constructor with sequence of sequences of strings -PASS Construct with object with + -PASS Construct with object with two keys -PASS Construct with array with two keys -PASS Construct with object with NULL, non-ASCII, and surrogate keys -PASS Custom [Symbol.iterator] -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-constructor.html b/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-constructor.html index 1e214e0..0637a38 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-constructor.html +++ b/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-constructor.html
@@ -23,9 +23,11 @@ }, "URLSearchParams constructor, no arguments") test(() => { - params = new URLSearchParams(DOMException.prototype); + params = new URLSearchParams(DOMException); assert_equals(params.toString(), "INDEX_SIZE_ERR=1&DOMSTRING_SIZE_ERR=2&HIERARCHY_REQUEST_ERR=3&WRONG_DOCUMENT_ERR=4&INVALID_CHARACTER_ERR=5&NO_DATA_ALLOWED_ERR=6&NO_MODIFICATION_ALLOWED_ERR=7&NOT_FOUND_ERR=8&NOT_SUPPORTED_ERR=9&INUSE_ATTRIBUTE_ERR=10&INVALID_STATE_ERR=11&SYNTAX_ERR=12&INVALID_MODIFICATION_ERR=13&NAMESPACE_ERR=14&INVALID_ACCESS_ERR=15&VALIDATION_ERR=16&TYPE_MISMATCH_ERR=17&SECURITY_ERR=18&NETWORK_ERR=19&ABORT_ERR=20&URL_MISMATCH_ERR=21"A_EXCEEDED_ERR=22&TIMEOUT_ERR=23&INVALID_NODE_TYPE_ERR=24&DATA_CLONE_ERR=25") -}, "URLSearchParams constructor, DOMException.prototype as argument") + assert_throws(new TypeError(), () => new URLSearchParams(DOMException.prototype), + "Constructing a URLSearchParams from DOMException.prototype should throw due to branding checks"); +}, "URLSearchParams constructor, DOMException as argument") test(() => { params = new URLSearchParams('');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-delete-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-delete-expected.txt deleted file mode 100644 index f3a9421..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-delete-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -PASS Delete basics -PASS Deleting appended multiple -FAIL Deleting all params keeps ? in URL assert_equals: url.href has ? expected "http://example.com/?" but got "http://example.com/" -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-delete.html b/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-delete.html index afc9c60..d4bc0a6 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-delete.html +++ b/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-delete.html
@@ -41,9 +41,16 @@ var url = new URL('http://example.com/?param1¶m2'); url.searchParams.delete('param1'); url.searchParams.delete('param2'); - assert_equals(url.href, 'http://example.com/?', 'url.href has ?'); + assert_equals(url.href, 'http://example.com/', 'url.href does not have ?'); assert_equals(url.search, '', 'url.search does not have ?'); -}, 'Deleting all params keeps ? in URL'); +}, 'Deleting all params removes ? from URL'); + +test(function() { + var url = new URL('http://example.com/?'); + url.searchParams.delete('param1'); + assert_equals(url.href, 'http://example.com/', 'url.href does not have ?'); + assert_equals(url.search, '', 'url.search does not have ?'); +}, 'Removing non-existent param removes ? from URL'); </script> </head> </html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-sort.html b/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-sort.html index e643ed3..34199894 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-sort.html +++ b/third_party/WebKit/LayoutTests/external/wpt/url/urlsearchparams-sort.html
@@ -47,4 +47,11 @@ } }, "URL parse and sort: " + val.input) }) + +test(function() { + const url = new URL("http://example.com/?") + url.searchParams.sort() + assert_equals(url.href, "http://example.com/") + assert_equals(url.search, "") +}, "Sorting non-existent params removes ? from URL") </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/capture.html b/third_party/WebKit/LayoutTests/fast/mediacapturefromelement/HTMLMediaElementCapture-capture.html similarity index 83% rename from third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/capture.html rename to third_party/WebKit/LayoutTests/fast/mediacapturefromelement/HTMLMediaElementCapture-capture.html index 3a99e5c..65d9d5c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/capture.html +++ b/third_party/WebKit/LayoutTests/fast/mediacapturefromelement/HTMLMediaElementCapture-capture.html
@@ -1,10 +1,6 @@ <!DOCTYPE html> -<html> -<head> -<script src=/resources/testharness.js></script> -<script src=/resources/testharnessreport.js></script> -</head> -<body> +<script src=../../resources/testharness.js></script> +<script src=../../resources/testharnessreport.js></script> <script> // Run captureStream() on different videos, and assert data is flowing. @@ -12,7 +8,7 @@ var makeAsyncTest = function(filename) { async_test(function(test) { var video = document.createElement('video'); - video.src = "webm/" + filename; + video.src = "../../http/tests/media/resources/media-source/webm/" + filename; video.onerror = this.unreached_func("<video> error"); video.play(); @@ -36,5 +32,3 @@ ]); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/creation.html b/third_party/WebKit/LayoutTests/fast/mediacapturefromelement/HTMLMediaElementCapture-creation.html similarity index 78% rename from third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/creation.html rename to third_party/WebKit/LayoutTests/fast/mediacapturefromelement/HTMLMediaElementCapture-creation.html index bf4c2f6c6..57a29e6 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/creation.html +++ b/third_party/WebKit/LayoutTests/fast/mediacapturefromelement/HTMLMediaElementCapture-creation.html
@@ -1,10 +1,6 @@ <!DOCTYPE html> -<html> -<head> -<script src=/resources/testharness.js></script> -<script src=/resources/testharnessreport.js></script> -</head> -<body> +<script src=../../resources/testharness.js></script> +<script src=../../resources/testharnessreport.js></script> <script> // Run captureStream() on <video>/<audio>s and inspect the generated Stream. @@ -12,7 +8,7 @@ var makeAsyncTest = function(filename, numTracks) { async_test(function() { var video = document.createElement('video'); - video.src = "webm/" + filename; + video.src = "../../http/tests/media/resources/media-source/webm/" + filename; video.onerror = this.unreached_func("<video> error"); video.play(); @@ -31,9 +27,7 @@ generate_tests(makeAsyncTest, [ [ "video-only", "test-v-128k-320x240-24fps-8kfr.webm", {vid : 1, aud : 0} ], [ "audio-only", "test-a-128k-44100Hz-1ch.webm", {vid : 0, aud : 1} ], - [ "video+audio", "test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.webm", {vid : 1, aud : 1} ] + [ "video+audio", "test.webm", {vid : 1, aud : 1} ] ]); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/ended.html b/third_party/WebKit/LayoutTests/fast/mediacapturefromelement/HTMLMediaElementCapture-ended.html similarity index 77% rename from third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/ended.html rename to third_party/WebKit/LayoutTests/fast/mediacapturefromelement/HTMLMediaElementCapture-ended.html index 91bdbbf8..bf49be23 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/ended.html +++ b/third_party/WebKit/LayoutTests/fast/mediacapturefromelement/HTMLMediaElementCapture-ended.html
@@ -1,10 +1,6 @@ <!DOCTYPE html> -<html> -<head> -<script src=/resources/testharness.js></script> -<script src=/resources/testharnessreport.js></script> -</head> -<body> +<script src=../../resources/testharness.js></script> +<script src=../../resources/testharnessreport.js></script> <script> // Run captureStream() on different videos, and assert the mediastream is @@ -13,7 +9,7 @@ var makeAsyncTest = function(filename) { async_test(function(test) { var video = document.createElement('video'); - video.src = "webm/" + filename; + video.src = "../../http/tests/media/resources/media-source/webm/" + filename; video.onerror = this.unreached_func("<video> error"); video.play(); @@ -25,7 +21,7 @@ assert_false(stream.active, 'stream must be inactive'); }); - }), "<video>.captureStream() and assert ended event."; + }), "<video>.captureStream() and assert data flows."; }; generate_tests(makeAsyncTest, [ @@ -35,5 +31,3 @@ ]); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/fast/text/recalc-position-of-linebox-after-deleting-ellipsis-expected.html b/third_party/WebKit/LayoutTests/fast/text/recalc-position-of-linebox-after-deleting-ellipsis-expected.html new file mode 100644 index 0000000..d912be9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/text/recalc-position-of-linebox-after-deleting-ellipsis-expected.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<style> +a.trigger { + width: 337px; + height: 16px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + display: inline-block; + border: 1px solid; +} + +div{ + height: 16px; + width: 32px; + float: left; +} + +</style> +<p>crbug.com/275883: Restore position of line box correctly after deleting ellipsis.</p> +<a class="trigger"> + <div></div> + <span id="span">This is shorter text</span> +</a> +<input type="button" id="input" value="Change Text" />
diff --git a/third_party/WebKit/LayoutTests/fast/text/recalc-position-of-linebox-after-deleting-ellipsis.html b/third_party/WebKit/LayoutTests/fast/text/recalc-position-of-linebox-after-deleting-ellipsis.html new file mode 100644 index 0000000..886aa295 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/text/recalc-position-of-linebox-after-deleting-ellipsis.html
@@ -0,0 +1,44 @@ +<!DOCTYPE html> +<style> +a.trigger { + width: 337px; + height: 16px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + display: inline-block; + border: 1px solid; +} + +div{ + height: 16px; + width: 32px; + float: left; +} + +</style> +<p>crbug.com/275883: Restore position of line box correctly after deleting ellipsis.</p> +<a class="trigger"> + <div></div> + <span id="span">Some text</span> +</a> +<input type="button" id="input" value="Change Text" /> +<script> +var toggle = 0; +input.onclick = function (e) { + var text = (toggle) ? 'Really really really long text that is so long long really long' : 'This is shorter text'; + span.textContent = text; + toggle = (toggle) ? 0 : 1; +}; +document.body.offsetTop; +eventSender.mouseMoveTo(355, 55); +eventSender.mouseDown(); +eventSender.mouseUp(); +eventSender.mouseDown(); +eventSender.mouseUp(); +eventSender.mouseDown(); +eventSender.mouseUp(); +eventSender.mouseMoveTo(155, 55); +eventSender.mouseDown(); +eventSender.mouseUp(); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/xssAuditor/script-tag-with-partial-close-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/xssAuditor/script-tag-with-partial-close-expected.txt new file mode 100644 index 0000000..ba4d5497 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/xssAuditor/script-tag-with-partial-close-expected.txt
@@ -0,0 +1,2 @@ +CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?q=%3Cscript%3Ealert(1)%3C/script&clutter=%20' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. +
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/xssAuditor/script-tag-with-partial-close.html b/third_party/WebKit/LayoutTests/http/tests/security/xssAuditor/script-tag-with-partial-close.html new file mode 100644 index 0000000..ee0468d --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/xssAuditor/script-tag-with-partial-close.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> +<script> +if (window.testRunner) { + testRunner.dumpAsText(); + testRunner.setXSSAuditorEnabled(true); +} +</script> +</head> +<body> +<iframe src="http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?q=<script>alert(1)</script&clutter=%20"> +</iframe> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setBlackboxPatterns-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setBlackboxPatterns-expected.txt index 287712b..3e19260 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setBlackboxPatterns-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setBlackboxPatterns-expected.txt
@@ -19,7 +19,7 @@ baz:4 (...):1 Paused in -qwe:6 +qwe:5 baz:4 (...):1 Paused in
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/stepping-with-blackboxed-ranges-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/stepping-with-blackboxed-ranges-expected.txt index 10cc9e4..e4a3e75 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/stepping-with-blackboxed-ranges-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/stepping-with-blackboxed-ranges-expected.txt
@@ -47,7 +47,7 @@ action: stepOver action: stepInto -foo: 16:0 +foo: 15:15 blackboxedBoo: 3:12 notBlackboxedFoo: 3:12 blackboxedFoo: 10:12
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/possible-breakpoints-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/possible-breakpoints-expected.txt index 16d03a1..cbb3951 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/possible-breakpoints-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/possible-breakpoints-expected.txt
@@ -13,7 +13,7 @@ location(3, 2) location(3, 10) location(4, 2) -location(5, 0) +location(4, 9) Existing location by position location(2, 31) Not existing location by position
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-sourcemap-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-sourcemap-expected.txt index 32425602c..8ab04c2 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-sourcemap-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-sourcemap-expected.txt
@@ -19,7 +19,7 @@ Executing StepOut... Call stack: - 0) testFunction (frameworks-sourcemap.html:12) + 0) testFunction (frameworks-sourcemap.html:11) [setTimeout] 0) scheduleTestFunction (debugger-test.js:3) <... skipped remaining frames ...>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-step-into-skips-setTimeout-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-step-into-skips-setTimeout-expected.txt index a3fe614..0bfaed1 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-step-into-skips-setTimeout-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-step-into-skips-setTimeout-expected.txt
@@ -28,7 +28,7 @@ Executing StepInto... Call stack: - 0) callback (frameworks-step-into-skips-setTimeout.html:21) + 0) callback (frameworks-step-into-skips-setTimeout.html:20) * 1) Framework_scheduleUntilDone (framework.js:142) [setTimeout] * 0) Framework.schedule (framework.js:45)
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-inlined-scripts-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-inlined-scripts-expected.txt index 8dc8ec8..fbc82ef 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-inlined-scripts-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-inlined-scripts-expected.txt
@@ -7,7 +7,7 @@ Executing StepInto... Call stack: - 0) f1 (debugger-step-into-inlined-scripts.html:8) + 0) f1 (debugger-step-into-inlined-scripts.html:7) 1) (debugger-step-into-inlined-scripts.html:9) Executing StepInto... @@ -25,7 +25,7 @@ Executing StepInto... Call stack: - 0) f2 (debugger-step-into-inlined-scripts.html:16) + 0) f2 (debugger-step-into-inlined-scripts.html:15) 1) (debugger-step-into-inlined-scripts.html:17) Executing StepInto...
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-inlined-scripts-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-inlined-scripts-expected.txt index 2a44a8c..3688b4dd 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-inlined-scripts-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-inlined-scripts-expected.txt
@@ -7,7 +7,7 @@ Executing StepOver... Call stack: - 0) f1 (debugger-step-over-inlined-scripts.html:8) + 0) f1 (debugger-step-over-inlined-scripts.html:7) 1) (debugger-step-over-inlined-scripts.html:9) Executing StepOver...
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-through-promises-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-through-promises-expected.txt index c43938c..5fa68e0 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-through-promises-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-through-promises-expected.txt
@@ -30,7 +30,7 @@ Executing StepOver... Call stack: - 0) p2 (debugger-step-through-promises.html:18) + 0) p2 (debugger-step-through-promises.html:17) [Promise.resolve] 0) testFunction (debugger-step-through-promises.html:14) [setTimeout] @@ -48,7 +48,7 @@ Executing StepOver... Call stack: - 0) p3 (debugger-step-through-promises.html:23) + 0) p3 (debugger-step-through-promises.html:22) [Promise.resolve] 0) testFunction (debugger-step-through-promises.html:19) [setTimeout]
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-return-value-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-return-value-expected.txt index 05c46e9e..73f47c6 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-return-value-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-return-value-expected.txt
@@ -2,6 +2,6 @@ Set timer for test function. Call stack: - 0) testFunction (debugger-return-value.html:17) + 0) testFunction (debugger-return-value.html:16) <return>: 10
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/live-edit-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger/live-edit-expected.txt index 0eb7a01..5c7fc3f3 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/live-edit-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/live-edit-expected.txt
@@ -35,6 +35,8 @@ Running: testBreakpointsUpdated breakpoint at 3 + inline breakpoint at (3, 4) + inline breakpoint at (3, 32) disabled Running: testNoCrashWhenLiveEditOnBreakpoint Script execution paused.
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-breakpoint-decorations-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-breakpoint-decorations-expected.txt index 9ed2e778..794f449 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-breakpoint-decorations-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-breakpoint-decorations-expected.txt
@@ -4,25 +4,41 @@ Running: testAddRemoveBreakpoint Setting breakpoint breakpoint at 2 + inline breakpoint at (2, 4) + inline breakpoint at (2, 13) disabled Toggle breakpoint Running: testTwoBreakpointsResolvedInOneLine Setting breakpoint breakpoint at 2 conditional + inline breakpoint at (2, 4) + inline breakpoint at (2, 13) disabled Toggle breakpoint Running: testDecorationInGutter Adding regular disabled breakpoint breakpoint at 2 disabled + inline breakpoint at (2, 4) disabled + inline breakpoint at (2, 13) disabled Adding conditional disabled breakpoint breakpoint at 2 disabled conditional + inline breakpoint at (2, 4) disabled + inline breakpoint at (2, 13) disabled Adding regular enabled breakpoint breakpoint at 2 + inline breakpoint at (2, 4) + inline breakpoint at (2, 13) disabled Adding conditional enabled breakpoint breakpoint at 2 conditional + inline breakpoint at (2, 4) + inline breakpoint at (2, 13) disabled Disable breakpoints breakpoint at 2 disabled conditional + inline breakpoint at (2, 4) disabled + inline breakpoint at (2, 13) disabled Enable breakpoints breakpoint at 2 conditional + inline breakpoint at (2, 4) + inline breakpoint at (2, 13) disabled Remove breakpoints
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-inline-breakpoint-decorations-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-inline-breakpoint-decorations-expected.txt index 41e13b8..3a35852 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-inline-breakpoint-decorations-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/source-frame-inline-breakpoint-decorations-expected.txt
@@ -14,6 +14,8 @@ Running: testAddRemoveBreakpointInLineWithOneLocation Setting breakpoint breakpoint at 5 + inline breakpoint at (5, 4) + inline breakpoint at (5, 13) disabled Toggle breakpoint Running: clickByInlineBreakpoint
diff --git a/third_party/WebKit/LayoutTests/platform/android/external/wpt/dom/interface-objects-expected.txt b/third_party/WebKit/LayoutTests/platform/android/external/wpt/dom/interface-objects-expected.txt deleted file mode 100644 index 231fddb2..0000000 --- a/third_party/WebKit/LayoutTests/platform/android/external/wpt/dom/interface-objects-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584
diff --git a/third_party/WebKit/LayoutTests/platform/linux/bluetooth/idl/idl-BluetoothDevice-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/bluetooth/idl/idl-BluetoothDevice-expected.txt new file mode 100644 index 0000000..73c8638c --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/bluetooth/idl/idl-BluetoothDevice-expected.txt
@@ -0,0 +1,6 @@ +CONSOLE MESSAGE: line 169: Web Bluetooth is experimental on this platform. See https://github.com/WebBluetoothCG/web-bluetooth/blob/gh-pages/implementation-status.md +This is a testharness.js-based test. +FAIL BluetoothDevice IDL test Test bug: need to pass exception to assert_throws() +PASS BluetoothDevice attributes. +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/platform/win/bluetooth/idl/idl-BluetoothDevice-expected.txt b/third_party/WebKit/LayoutTests/platform/win/bluetooth/idl/idl-BluetoothDevice-expected.txt new file mode 100644 index 0000000..73c8638c --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/bluetooth/idl/idl-BluetoothDevice-expected.txt
@@ -0,0 +1,6 @@ +CONSOLE MESSAGE: line 169: Web Bluetooth is experimental on this platform. See https://github.com/WebBluetoothCG/web-bluetooth/blob/gh-pages/implementation-status.md +This is a testharness.js-based test. +FAIL BluetoothDevice IDL test Test bug: need to pass exception to assert_throws() +PASS BluetoothDevice attributes. +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/sensor/accelerometer.html b/third_party/WebKit/LayoutTests/sensor/accelerometer.html index 0c89932..1acd08d 100644 --- a/third_party/WebKit/LayoutTests/sensor/accelerometer.html +++ b/third_party/WebKit/LayoutTests/sensor/accelerometer.html
@@ -2,6 +2,8 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="../resources/mojo-helpers.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/services/device/public/interfaces/sensor_provider.mojom.js"></script> <script src="resources/sensor-helpers.js"></script> <script src="resources/generic-sensor-tests.js"></script> <script>
diff --git a/third_party/WebKit/LayoutTests/sensor/ambient-light-sensor.html b/third_party/WebKit/LayoutTests/sensor/ambient-light-sensor.html index caa3503..da3ddf5 100644 --- a/third_party/WebKit/LayoutTests/sensor/ambient-light-sensor.html +++ b/third_party/WebKit/LayoutTests/sensor/ambient-light-sensor.html
@@ -2,6 +2,8 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="../resources/mojo-helpers.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/services/device/public/interfaces/sensor_provider.mojom.js"></script> <script src="resources/sensor-helpers.js"></script> <script src="resources/generic-sensor-tests.js"></script> <script>
diff --git a/third_party/WebKit/LayoutTests/sensor/gyroscope.html b/third_party/WebKit/LayoutTests/sensor/gyroscope.html index d0e1c72..15fdd03 100644 --- a/third_party/WebKit/LayoutTests/sensor/gyroscope.html +++ b/third_party/WebKit/LayoutTests/sensor/gyroscope.html
@@ -2,6 +2,8 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="../resources/mojo-helpers.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/services/device/public/interfaces/sensor_provider.mojom.js"></script> <script src="resources/sensor-helpers.js"></script> <script src="resources/generic-sensor-tests.js"></script> <script>
diff --git a/third_party/WebKit/LayoutTests/sensor/magnetometer.html b/third_party/WebKit/LayoutTests/sensor/magnetometer.html index 61e6bfbb..2c05dbe 100644 --- a/third_party/WebKit/LayoutTests/sensor/magnetometer.html +++ b/third_party/WebKit/LayoutTests/sensor/magnetometer.html
@@ -2,6 +2,8 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="../resources/mojo-helpers.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/services/device/public/interfaces/sensor_provider.mojom.js"></script> <script src="resources/sensor-helpers.js"></script> <script src="resources/generic-sensor-tests.js"></script> <script>
diff --git a/third_party/WebKit/LayoutTests/sensor/mock-sensor.html b/third_party/WebKit/LayoutTests/sensor/mock-sensor.html index 79683101..0383cfbc 100644 --- a/third_party/WebKit/LayoutTests/sensor/mock-sensor.html +++ b/third_party/WebKit/LayoutTests/sensor/mock-sensor.html
@@ -2,6 +2,8 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="../resources/mojo-helpers.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/services/device/public/interfaces/sensor_provider.mojom.js"></script> <script src="resources/sensor-helpers.js"></script> <script> @@ -11,4 +13,4 @@ assert_true(sensor instanceof Object); assert_true(sensor.mockSensorProvider instanceof Object); }, 'Sensor Mojo bindings and mock interfaces are available to tests.') -</script> \ No newline at end of file +</script>
diff --git a/third_party/WebKit/LayoutTests/sensor/orientation-sensor.html b/third_party/WebKit/LayoutTests/sensor/orientation-sensor.html index 75c8e4a..0244ed7e 100644 --- a/third_party/WebKit/LayoutTests/sensor/orientation-sensor.html +++ b/third_party/WebKit/LayoutTests/sensor/orientation-sensor.html
@@ -2,6 +2,8 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="../resources/mojo-helpers.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/services/device/public/interfaces/sensor_provider.mojom.js"></script> <script src="resources/sensor-helpers.js"></script> <script src="resources/generic-sensor-tests.js"></script> <script>
diff --git a/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js b/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js index 502316d..18853ee3 100644 --- a/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js +++ b/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js
@@ -54,7 +54,7 @@ .then(mockSensor => { return new Promise((resolve, reject) => { let wrapper = new CallbackWrapper(() => { - let configuration = mockSensor.active_sensor_configurations_[0]; + let configuration = mockSensor.activeSensorConfigurations_[0]; assert_equals(configuration.frequency, 60); sensorObject.stop(); assert_false(sensorObject.activated); @@ -102,7 +102,7 @@ .then(mockSensor => { return new Promise((resolve, reject) => { let wrapper = new CallbackWrapper(() => { - let configuration = mockSensor.active_sensor_configurations_[0]; + let configuration = mockSensor.activeSensorConfigurations_[0]; assert_equals(configuration.frequency, maxSupportedFrequency); sensorObject.stop(); assert_false(sensorObject.activated); @@ -126,7 +126,7 @@ .then(mockSensor => { return new Promise((resolve, reject) => { let wrapper = new CallbackWrapper(() => { - let configuration = mockSensor.active_sensor_configurations_[0]; + let configuration = mockSensor.activeSensorConfigurations_[0]; assert_equals(configuration.frequency, minSupportedFrequency); sensorObject.stop(); assert_false(sensorObject.activated); @@ -379,12 +379,12 @@ slowSensorNotifiedCounter++; if (slowSensorNotifiedCounter == 1) { fastSensor.start(); - readingUpdatesCounter = mockSensor.reading_updates_count(); + readingUpdatesCounter = mockSensor.readingUpdatesCount(); } else if (slowSensorNotifiedCounter == 2) { // By the moment slow sensor (9 Hz) is notified for the // next time, the fast sensor (30 Hz) has been notified // for int(30/9) = 3 times. - let elapsedUpdates = mockSensor.reading_updates_count() - readingUpdatesCounter; + let elapsedUpdates = mockSensor.readingUpdatesCount() - readingUpdatesCounter; // Approximation because 'slowSensor.onreading' is sometimes // called before 'fastSensor.onreading', in this case // 'fastSensorNotifiedCounter == elapsedUpdates - 1'.
diff --git a/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js b/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js index 0aca665d..ea7322c 100644 --- a/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js +++ b/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js
@@ -1,374 +1,356 @@ 'use strict'; -// Wraps callback and calls reject_func if callback throws an error. +// Wraps callback and calls rejectFunc if callback throws an error. class CallbackWrapper { - constructor(callback, reject_func) { - this.wrapper_func_ = (args) => { + constructor(callback, rejectFunc) { + this.wrapperFunc_ = (args) => { try { callback(args); } catch(e) { - reject_func(e); + rejectFunc(e); } } } get callback() { - return this.wrapper_func_; + return this.wrapperFunc_; } } -function sensor_mocks(mojo) { - return define('Generic Sensor API mocks', [ - 'mojo/public/js/core', - 'mojo/public/js/bindings', - 'services/device/public/interfaces/sensor_provider.mojom', - 'services/device/public/interfaces/sensor.mojom', - 'services/device/public/interfaces/constants.mojom', - ], (core, bindings, sensor_provider, sensor, deviceConstants) => { +function sensorMocks() { + // Helper function that returns resolved promise with result. + function sensorResponse(success) { + return Promise.resolve({success}); + } - // Helper function that returns resolved promise with result. - function sensorResponse(success) { - return Promise.resolve({success}); + // Class that mocks Sensor interface defined in sensor.mojom + class MockSensor { + constructor(sensorRequest, handle, offset, size, reportingMode) { + this.client_ = null; + this.startShouldFail_ = false; + this.reportingMode_ = reportingMode; + this.sensorReadingTimerId_ = null; + this.updateReadingFunction_ = null; + this.readingUpdatesCount_ = 0; + this.suspendCalled_ = null; + this.resumeCalled_ = null; + this.addConfigurationCalled_ = null; + this.removeConfigurationCalled_ = null; + this.activeSensorConfigurations_ = []; + let rv = handle.mapBuffer(offset, size); + assert_equals(rv.result, Mojo.RESULT_OK, "Failed to map shared buffer"); + this.bufferArray_ = rv.buffer; + this.buffer_ = new Float64Array(this.bufferArray_); + this.resetBuffer(); + this.binding_ = new mojo.Binding(device.mojom.Sensor, this, + sensorRequest); + this.binding_.setConnectionErrorHandler(() => { + this.reset(); + }); } - // Class that mocks Sensor interface defined in sensor.mojom - class MockSensor { - constructor(sensorRequest, handle, offset, size, reportingMode) { - this.client_ = null; - this.start_should_fail_ = false; - this.reporting_mode_ = reportingMode; - this.sensor_reading_timer_id_ = null; - this.update_reading_function_ = null; - this.reading_updates_count_ = 0; - this.suspend_called_ = null; - this.resume_called_ = null; - this.add_configuration_called_ = null; - this.remove_configuration_called_ = null; - this.active_sensor_configurations_ = []; - let rv = core.mapBuffer(handle, offset, size, - core.MAP_BUFFER_FLAG_NONE); - assert_equals(rv.result, core.RESULT_OK, "Failed to map shared buffer"); - this.buffer_array_ = rv.buffer; - this.buffer_ = new Float64Array(this.buffer_array_); - this.resetBuffer(); - this.binding_ = new bindings.Binding(sensor.Sensor, this, - sensorRequest); - this.binding_.setConnectionErrorHandler(() => { - this.reset(); - }); - } + // Returns default configuration. + getDefaultConfiguration() { + return Promise.resolve({frequency: 5}); + } - // Returns default configuration. - getDefaultConfiguration() { - return Promise.resolve({frequency: 5}); - } + readingUpdatesCount() { + return this.readingUpdatesCount_; + } + // Adds configuration for the sensor and starts reporting fake data + // through updateReadingFunction_ callback. + addConfiguration(configuration) { + assert_not_equals(configuration, null, "Invalid sensor configuration."); - reading_updates_count() { - return this.reading_updates_count_; - } - // Adds configuration for the sensor and starts reporting fake data - // through update_reading_function_ callback. - addConfiguration(configuration) { - assert_not_equals(configuration, null, "Invalid sensor configuration."); + this.activeSensorConfigurations_.push(configuration); + // Sort using descending order. + this.activeSensorConfigurations_.sort( + (first, second) => { return second.frequency - first.frequency }); - this.active_sensor_configurations_.push(configuration); - // Sort using descending order. - this.active_sensor_configurations_.sort( - (first, second) => { return second.frequency - first.frequency }); - - if (!this.start_should_fail_ ) - this.startReading(); - - if (this.add_configuration_called_ != null) - this.add_configuration_called_(this); - - return sensorResponse(!this.start_should_fail_); - } - - // Removes sensor configuration from the list of active configurations and - // stops notification about sensor reading changes if - // active_sensor_configurations_ is empty. - removeConfiguration(configuration) { - if (this.remove_configuration_called_ != null) { - this.remove_configuration_called_(this); - } - - let index = this.active_sensor_configurations_.indexOf(configuration); - if (index !== -1) { - this.active_sensor_configurations_.splice(index, 1); - } else { - return sensorResponse(false); - } - - if (this.active_sensor_configurations_.length === 0) - this.stopReading(); - - return sensorResponse(true); - } - - // Suspends sensor. - suspend() { - this.stopReading(); - if (this.suspend_called_ != null) { - this.suspend_called_(this); - } - } - - // Resumes sensor. - resume() { - assert_equals(this.sensor_reading_timer_id_, null); + if (!this.startShouldFail_ ) this.startReading(); - if (this.resume_called_ != null) { - this.resume_called_(this); - } + + if (this.addConfigurationCalled_ != null) + this.addConfigurationCalled_(this); + + return sensorResponse(!this.startShouldFail_); + } + + // Removes sensor configuration from the list of active configurations and + // stops notification about sensor reading changes if + // activeSensorConfigurations_ is empty. + removeConfiguration(configuration) { + if (this.removeConfigurationCalled_ != null) { + this.removeConfigurationCalled_(this); } - // Mock functions + let index = this.activeSensorConfigurations_.indexOf(configuration); + if (index !== -1) { + this.activeSensorConfigurations_.splice(index, 1); + } else { + return sensorResponse(false); + } - // Resets mock Sensor state. - reset() { + if (this.activeSensorConfigurations_.length === 0) this.stopReading(); - this.reading_updates_count_ = 0; - this.start_should_fail_ = false; - this.update_reading_function_ = null; - this.active_sensor_configurations_ = []; - this.suspend_called_ = null; - this.resume_called_ = null; - this.add_configuration_called_ = null; - this.remove_configuration_called_ = null; - this.resetBuffer(); - core.unmapBuffer(this.buffer_array_); - this.buffer_array_ = null; - this.binding_.close(); - } - - // Zeroes shared buffer. - resetBuffer() { - for (let i = 0; i < this.buffer_.length; ++i) { - this.buffer_[i] = 0; - } - } - - // Sets callback that is used to deliver sensor reading updates. - setUpdateSensorReadingFunction(update_reading_function) { - this.update_reading_function_ = update_reading_function; - return Promise.resolve(this); - } - - // Sets flag that forces sensor to fail when addConfiguration is invoked. - setStartShouldFail(should_fail) { - this.start_should_fail_ = should_fail; - } - - // Returns resolved promise if suspend() was called, rejected otherwise. - suspendCalled() { - return new Promise((resolve, reject) => { - this.suspend_called_ = resolve; - }); - } - - // Returns resolved promise if resume() was called, rejected otherwise. - resumeCalled() { - return new Promise((resolve, reject) => { - this.resume_called_ = resolve; - }); - } - - // Resolves promise when addConfiguration() is called. - addConfigurationCalled() { - return new Promise((resolve, reject) => { - this.add_configuration_called_ = resolve; - }); - } - - // Resolves promise when removeConfiguration() is called. - removeConfigurationCalled() { - return new Promise((resolve, reject) => { - this.remove_configuration_called_ = resolve; - }); - } - - startReading() { - if (this.update_reading_function_ != null) { - this.stopReading(); - let max_frequency_used = - this.active_sensor_configurations_[0].frequency; - let timeout = (1 / max_frequency_used) * 1000; - this.sensor_reading_timer_id_ = window.setInterval(() => { - if (this.update_reading_function_) { - this.update_reading_function_(this.buffer_); - // For all tests sensor reading should have monotonically - // increasing timestamp in seconds. - this.buffer_[1] = window.performance.now() * 0.001; - this.reading_updates_count_++; - } - if (this.reporting_mode_ === sensor.ReportingMode.ON_CHANGE) { - this.client_.sensorReadingChanged(); - } - }, timeout); - } - } - - stopReading() { - if (this.sensor_reading_timer_id_ != null) { - window.clearInterval(this.sensor_reading_timer_id_); - this.sensor_reading_timer_id_ = null; - } - } - + return sensorResponse(true); } - // Helper function that returns resolved promise for getSensor() function. - function getSensorResponse(init_params, client_request) { - return Promise.resolve({init_params, client_request}); - } - - // Class that mocks SensorProvider interface defined in - // sensor_provider.mojom - class MockSensorProvider { - constructor() { - this.reading_size_in_bytes_ = - sensor_provider.SensorInitParams.kReadBufferSizeForTests; - this.shared_buffer_size_in_bytes_ = this.reading_size_in_bytes_ * - sensor.SensorType.LAST; - let rv = - core.createSharedBuffer( - this.shared_buffer_size_in_bytes_, - core.CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE); - assert_equals(rv.result, core.RESULT_OK, "Failed to create buffer"); - this.shared_buffer_handle_ = rv.handle; - this.active_sensor_ = null; - this.get_sensor_should_fail_ = false; - this.resolve_func_ = null; - this.is_continuous_ = false; - this.max_frequency_ = 60; - this.min_frequency_ = 1; - this.binding_ = new bindings.Binding(sensor_provider.SensorProvider, - this); - } - - // Returns initialized Sensor proxy to the client. - getSensor(type, request) { - if (this.get_sensor_should_fail_) { - var ignored = new sensor.SensorClientPtr(); - return getSensorResponse(null, bindings.makeRequest(ignored)); - } - - let offset = - (sensor.SensorType.LAST - type) * this.reading_size_in_bytes_; - let reporting_mode = sensor.ReportingMode.ON_CHANGE; - if (this.is_continuous_) { - reporting_mode = sensor.ReportingMode.CONTINUOUS; - } - - if (this.active_sensor_ == null) { - let mockSensor = new MockSensor(request, this.shared_buffer_handle_, - offset, this.reading_size_in_bytes_, reporting_mode); - this.active_sensor_ = mockSensor; - } - - let rv = - core.duplicateBufferHandle( - this.shared_buffer_handle_, - core.DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE); - - assert_equals(rv.result, core.RESULT_OK); - - let default_config = {frequency: 5}; - - let init_params = - new sensor_provider.SensorInitParams( - { memory: rv.handle, - buffer_offset: offset, - mode: reporting_mode, - default_configuration: default_config, - minimum_frequency: this.min_frequency_, - maximum_frequency: this.max_frequency_}); - - if (this.resolve_func_ !== null) { - this.resolve_func_(this.active_sensor_); - } - - this.active_sensor_.client_ = new sensor.SensorClientPtr(); - return getSensorResponse( - init_params, bindings.makeRequest(this.active_sensor_.client_)); - } - - // Binds object to mojo message pipe - bindToPipe(pipe) { - this.binding_.bind(pipe); - this.binding_.setConnectionErrorHandler(() => { - this.reset(); - }); - } - - // Mock functions - - // Resets state of mock SensorProvider between test runs. - reset() { - if (this.active_sensor_ != null) { - this.active_sensor_.reset(); - this.active_sensor_ = null; - } - - this.get_sensor_should_fail_ = false; - this.resolve_func_ = null; - this.max_frequency_ = 60; - this.min_frequency_ = 1; - this.is_continuous_ = false; - this.binding_.close(); - } - - // Sets flag that forces mock SensorProvider to fail when getSensor() is - // invoked. - setGetSensorShouldFail(should_fail) { - this.get_sensor_should_fail_ = should_fail; - } - - // Returns mock sensor that was created in getSensor to the layout test. - getCreatedSensor() { - if (this.active_sensor_ != null) { - return Promise.resolve(this.active_sensor_); - } - - return new Promise((resolve, reject) => { - this.resolve_func_ = resolve; - }); - } - - // Forces sensor to use |reporting_mode| as an update mode. - setContinuousReportingMode() { - this.is_continuous_ = true; - } - - // Sets the maximum frequency for a concrete sensor. - setMaximumSupportedFrequency(frequency) { - this.max_frequency_ = frequency; - } - - // Sets the minimum frequency for a concrete sensor. - setMinimumSupportedFrequency(frequency) { - this.min_frequency_ = frequency; + // Suspends sensor. + suspend() { + this.stopReading(); + if (this.suspendCalled_ != null) { + this.suspendCalled_(this); } } - let mockSensorProvider = new MockSensorProvider; - mojo.connector.addInterfaceOverrideForTesting( - deviceConstants.kServiceName, - sensor_provider.SensorProvider.name, - pipe => { - mockSensorProvider.bindToPipe(pipe); - }); + // Resumes sensor. + resume() { + assert_equals(this.sensorReadingTimerId_, null); + this.startReading(); + if (this.resumeCalled_ != null) { + this.resumeCalled_(this); + } + } - return Promise.resolve({ - mockSensorProvider: mockSensorProvider, - }); - }); + // Mock functions + + // Resets mock Sensor state. + reset() { + this.stopReading(); + + this.readingUpdatesCount_ = 0; + this.startShouldFail_ = false; + this.updateReadingFunction_ = null; + this.activeSensorConfigurations_ = []; + this.suspendCalled_ = null; + this.resumeCalled_ = null; + this.addConfigurationCalled_ = null; + this.removeConfigurationCalled_ = null; + this.resetBuffer(); + this.bufferArray_ = null; + this.binding_.close(); + } + + // Zeroes shared buffer. + resetBuffer() { + for (let i = 0; i < this.buffer_.length; ++i) { + this.buffer_[i] = 0; + } + } + + // Sets callback that is used to deliver sensor reading updates. + setUpdateSensorReadingFunction(updateReadingFunction) { + this.updateReadingFunction_ = updateReadingFunction; + return Promise.resolve(this); + } + + // Sets flag that forces sensor to fail when addConfiguration is invoked. + setStartShouldFail(shouldFail) { + this.startShouldFail_ = shouldFail; + } + + // Returns resolved promise if suspend() was called, rejected otherwise. + suspendCalled() { + return new Promise((resolve, reject) => { + this.suspendCalled_ = resolve; + }); + } + + // Returns resolved promise if resume() was called, rejected otherwise. + resumeCalled() { + return new Promise((resolve, reject) => { + this.resumeCalled_ = resolve; + }); + } + + // Resolves promise when addConfiguration() is called. + addConfigurationCalled() { + return new Promise((resolve, reject) => { + this.addConfigurationCalled_ = resolve; + }); + } + + // Resolves promise when removeConfiguration() is called. + removeConfigurationCalled() { + return new Promise((resolve, reject) => { + this.removeConfigurationCalled_ = resolve; + }); + } + + startReading() { + if (this.updateReadingFunction_ != null) { + this.stopReading(); + let maxFrequencyUsed = this.activeSensorConfigurations_[0].frequency; + let timeout = (1 / maxFrequencyUsed) * 1000; + this.sensorReadingTimerId_ = window.setInterval(() => { + if (this.updateReadingFunction_) { + this.updateReadingFunction_(this.buffer_); + // For all tests sensor reading should have monotonically + // increasing timestamp in seconds. + this.buffer_[1] = window.performance.now() * 0.001; + this.readingUpdatesCount_++; + } + if (this.reportingMode_ === device.mojom.ReportingMode.ON_CHANGE) { + this.client_.sensorReadingChanged(); + } + }, timeout); + } + } + + stopReading() { + if (this.sensorReadingTimerId_ != null) { + window.clearInterval(this.sensorReadingTimerId_); + this.sensorReadingTimerId_ = null; + } + } + + } + + // Helper function that returns resolved promise for getSensor() function. + function getSensorResponse(initParams, clientRequest) { + return Promise.resolve({initParams, clientRequest}); + } + + // Class that mocks SensorProvider interface defined in + // sensor_provider.mojom + class MockSensorProvider { + constructor() { + this.readingSizeInBytes_ = + device.mojom.SensorInitParams.kReadBufferSizeForTests; + this.sharedBufferSizeInBytes_ = this.readingSizeInBytes_ * + device.mojom.SensorType.LAST; + let rv = Mojo.createSharedBuffer(this.sharedBufferSizeInBytes_); + assert_equals(rv.result, Mojo.RESULT_OK, "Failed to create buffer"); + this.sharedBufferHandle_ = rv.handle; + this.activeSensor_ = null; + this.getSensorShouldFail_ = false; + this.resolveFunc_ = null; + this.isContinuous_ = false; + this.maxFrequency_ = 60; + this.minFrequency_ = 1; + this.binding_ = new mojo.Binding(device.mojom.SensorProvider, this); + + this.interceptor_ = new MojoInterfaceInterceptor( + device.mojom.SensorProvider.name); + this.interceptor_.oninterfacerequest = e => { + this.bindToPipe(e.handle); + }; + this.interceptor_.start(); + } + + // Returns initialized Sensor proxy to the client. + getSensor(type, request) { + if (this.getSensorShouldFail_) { + var ignored = new device.mojom.SensorClientPtr(); + return getSensorResponse(null, mojo.makeRequest(ignored)); + } + + let offset = (device.mojom.SensorType.LAST - type) * + this.readingSizeInBytes_; + let reportingMode = device.mojom.ReportingMode.ON_CHANGE; + if (this.isContinuous_) { + reportingMode = device.mojom.ReportingMode.CONTINUOUS; + } + + if (this.activeSensor_ == null) { + let mockSensor = new MockSensor(request, this.sharedBufferHandle_, + offset, this.readingSizeInBytes_, reportingMode); + this.activeSensor_ = mockSensor; + } + + let rv = this.sharedBufferHandle_.duplicateBufferHandle(); + + assert_equals(rv.result, Mojo.RESULT_OK); + + let defaultConfig = {frequency: 5}; + + let initParams = + new device.mojom.SensorInitParams( + { memory: rv.handle, + bufferOffset: offset, + mode: reportingMode, + defaultConfiguration: defaultConfig, + minimumFrequency: this.minFrequency_, + maximumFrequency: this.maxFrequency_}); + + if (this.resolveFunc_ !== null) { + this.resolveFunc_(this.activeSensor_); + } + + this.activeSensor_.client_ = new device.mojom.SensorClientPtr(); + return getSensorResponse( + initParams, mojo.makeRequest(this.activeSensor_.client_)); + } + + // Binds object to mojo message pipe + bindToPipe(pipe) { + this.binding_.bind(pipe); + this.binding_.setConnectionErrorHandler(() => { + this.reset(); + }); + } + + // Mock functions + + // Resets state of mock SensorProvider between test runs. + reset() { + if (this.activeSensor_ != null) { + this.activeSensor_.reset(); + this.activeSensor_ = null; + } + + this.getSensorShouldFail_ = false; + this.resolveFunc_ = null; + this.maxFrequency_ = 60; + this.minFrequency_ = 1; + this.isContinuous_ = false; + this.binding_.close(); + this.interceptor_.stop(); + } + + // Sets flag that forces mock SensorProvider to fail when getSensor() is + // invoked. + setGetSensorShouldFail(shouldFail) { + this.getSensorShouldFail_ = shouldFail; + } + + // Returns mock sensor that was created in getSensor to the layout test. + getCreatedSensor() { + if (this.activeSensor_ != null) { + return Promise.resolve(this.activeSensor_); + } + + return new Promise((resolve, reject) => { + this.resolveFunc_ = resolve; + }); + } + + // Forces sensor to use |reportingMode| as an update mode. + setContinuousReportingMode() { + this.isContinuous_ = true; + } + + // Sets the maximum frequency for a concrete sensor. + setMaximumSupportedFrequency(frequency) { + this.maxFrequency_ = frequency; + } + + // Sets the minimum frequency for a concrete sensor. + setMinimumSupportedFrequency(frequency) { + this.minFrequency_ = frequency; + } + } + + let mockSensorProvider = new MockSensorProvider; + return {mockSensorProvider: mockSensorProvider}; } function sensor_test(func, name, properties) { - mojo_test(mojo => sensor_mocks(mojo).then(sensor => { + mojo_test(() => { + let sensor = sensorMocks(); + // Clean up and reset mock sensor stubs asynchronously, so that the blink // side closes its proxies and notifies JS sensor objects before new test is // started. @@ -383,5 +365,5 @@ }; return Promise.resolve(func(sensor)).then(onSuccess, onFailure); - }), name, properties); + }, name, properties); }
diff --git a/third_party/WebKit/Source/core/html/parser/XSSAuditor.cpp b/third_party/WebKit/Source/core/html/parser/XSSAuditor.cpp index c3fb7f9..d9c41486 100644 --- a/third_party/WebKit/Source/core/html/parser/XSSAuditor.cpp +++ b/third_party/WebKit/Source/core/html/parser/XSSAuditor.cpp
@@ -135,6 +135,15 @@ script); } +static bool StartsClosingScriptTagAt(const String& string, size_t start) { + if (start + 7 >= string.length()) + return false; + // TODO(esprehn): StringView should probably have startsWith. + StringView script("</script"); + return EqualIgnoringASCIICase(StringView(string, start, script.length()), + script); +} + // If other files need this, we should move this to // core/html/parser/HTMLParserIdioms.h template <size_t inlineCapacity> @@ -880,7 +889,8 @@ break; if (last_non_space_position != kNotFound && - StartsOpeningScriptTagAt(string, found_position)) { + (StartsOpeningScriptTagAt(string, found_position) || + StartsClosingScriptTagAt(string, found_position))) { found_position = last_non_space_position + 1; break; }
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp index 025d62c..1c653af 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -502,6 +502,16 @@ SetChildrenInline(true); SetContainsInlineWithOutlineAndContinuation(false); + // Text truncation kicks in if overflow isn't visible and text-overflow isn't + // 'clip'. If this is an anonymous block, we have to examine the parent. + // FIXME: CSS3 says that descendants that are clipped must also know how to + // truncate. This is insanely difficult to figure out in general (especially + // in the middle of doing layout), so we only handle the simple case of an + // anonymous block truncating when its parent is clipped. + // Walk all the lines and delete our ellipsis line boxes if they exist. + if (ChildrenInline() && ShouldTruncateOverflowingText(this)) + DeleteEllipsisLineBoxes(); + RebuildFloatsFromIntruding(); // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg,
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h index 90683dda..8a0e092 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h +++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h
@@ -877,6 +877,8 @@ bool IsSelfCollapsingBlock() const override; bool CheckIfIsSelfCollapsingBlock() const; + bool ShouldTruncateOverflowingText(const LayoutBlockFlow*) const; + protected: std::unique_ptr<LayoutBlockFlowRareData> rare_data_; std::unique_ptr<FloatingObjects> floating_objects_;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp index 694df3c..1380f19d 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp
@@ -1914,7 +1914,7 @@ !o.IsElementContinuation() && ToLayoutInline(o).Continuation(); } -static inline bool ShouldTruncateOverflowingText(const LayoutBlockFlow* block) { +bool LayoutBlockFlow::ShouldTruncateOverflowingText(const LayoutBlockFlow* block) const { const LayoutObject* object_to_check = block; if (block->IsAnonymousBlock()) { const LayoutObject* parent = block->Parent(); @@ -1947,18 +1947,6 @@ layout_state.SetNeedsPaginationStrutRecalculation(); } - // Text truncation kicks in if overflow isn't visible and text-overflow isn't - // 'clip'. If this is an anonymous block, we have to examine the parent. - // FIXME: CSS3 says that descendants that are clipped must also know how to - // truncate. This is insanely difficult to figure out in general (especially - // in the middle of doing layout), so we only handle the simple case of an - // anonymous block truncating when its parent is clipped. - bool has_text_overflow = ShouldTruncateOverflowingText(this); - - // Walk all the lines and delete our ellipsis line boxes if they exist. - if (has_text_overflow) - DeleteEllipsisLineBoxes(); - if (FirstChild()) { for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.AtEnd(); walker.Advance()) { @@ -2035,9 +2023,7 @@ IsHorizontalWritingMode() ? kHorizontalLine : kVerticalLine, kPositionOfInteriorLineBoxes)); - // See if we have any lines that spill out of our block. If we do, then we - // will possibly need to truncate text. - if (has_text_overflow) + if (ShouldTruncateOverflowingText(this)) CheckLinesForTextOverflow(); // Ensure the new line boxes will be painted.
diff --git a/third_party/WebKit/Source/core/layout/LayoutListItem.cpp b/third_party/WebKit/Source/core/layout/LayoutListItem.cpp index 3271727..92af3053 100644 --- a/third_party/WebKit/Source/core/layout/LayoutListItem.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutListItem.cpp
@@ -228,7 +228,7 @@ // FIXME: This recurses to a possible depth of the length of the list. // That's not good -- we need to change this to an iterative algorithm. if (LayoutListItem* previous_item = PreviousListItem(list, this)) - return SaturatedAddition(previous_item->Value(), value_step); + return ClampAdd(previous_item->Value(), value_step); if (o_list_element) return o_list_element->start();
diff --git a/third_party/WebKit/Source/core/loader/NetworkQuietDetector.cpp b/third_party/WebKit/Source/core/loader/NetworkQuietDetector.cpp index 3504d07..9c98ce0 100644 --- a/third_party/WebKit/Source/core/loader/NetworkQuietDetector.cpp +++ b/third_party/WebKit/Source/core/loader/NetworkQuietDetector.cpp
@@ -73,8 +73,8 @@ auto frame_resource_coordinator = GetSupplementable()->GetFrame()->GetFrameResourceCoordinator(); if (frame_resource_coordinator) { - frame_resource_coordinator->SendEvent( - resource_coordinator::mojom::EventType::kOnLocalFrameNetworkIdle); + frame_resource_coordinator->SetProperty( + resource_coordinator::mojom::PropertyType::kNetworkIdle, true); } }
diff --git a/third_party/WebKit/Source/core/paint/NinePieceImageGrid.cpp b/third_party/WebKit/Source/core/paint/NinePieceImageGrid.cpp index 7367e716..b8053383 100644 --- a/third_party/WebKit/Source/core/paint/NinePieceImageGrid.cpp +++ b/third_party/WebKit/Source/core/paint/NinePieceImageGrid.cpp
@@ -62,10 +62,8 @@ // as its height, and Wside as the border image width offset for the side, let // f = min(Lwidth/(Wleft+Wright), Lheight/(Wtop+Wbottom)). If f < 1, then all // W are reduced by multiplying them by f. - int border_side_width = - std::max(1, SaturatedAddition(left_.width, right_.width)); - int border_side_height = - std::max(1, SaturatedAddition(top_.width, bottom_.width)); + int border_side_width = ClampAdd(left_.width, right_.width).Max(1); + int border_side_height = ClampAdd(top_.width, bottom_.width).Max(1); float border_side_scale_factor = std::min((float)border_image_area.Width() / border_side_width, (float)border_image_area.Height() / border_side_height);
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp index f77bb4c..4c8ba37f 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp +++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -1898,7 +1898,7 @@ return GraphicsContext::FocusRingOutsetExtent( OutlineOffset(), std::ceil(GetOutlineStrokeWidthForFocusRing())); } - return std::max(0, SaturatedAddition(OutlineWidth(), OutlineOffset())); + return ClampAdd(OutlineWidth(), OutlineOffset()).Max(0); } float ComputedStyle::GetOutlineStrokeWidthForFocusRing() const {
diff --git a/third_party/WebKit/Source/core/timing/Performance.cpp b/third_party/WebKit/Source/core/timing/Performance.cpp index e32c306..2520de2 100644 --- a/third_party/WebKit/Source/core/timing/Performance.cpp +++ b/third_party/WebKit/Source/core/timing/Performance.cpp
@@ -46,7 +46,7 @@ #include "platform/loader/fetch/ResourceTimingInfo.h" #include "platform/RuntimeEnabledFeatures.h" -static const double kLongTaskThreshold = 0.05; +static const double kLongTaskObserverThreshold = 0.05; static const char kUnknownAttribution[] = "unknown"; static const char kAmbiguousAttribution[] = "multiple-contexts"; @@ -162,7 +162,7 @@ UseCounter::Count(&GetFrame()->LocalFrameRoot(), WebFeature::kLongTaskObserver); GetFrame()->GetPerformanceMonitor()->Subscribe( - PerformanceMonitor::kLongTask, kLongTaskThreshold, this); + PerformanceMonitor::kLongTask, kLongTaskObserverThreshold, this); } else { GetFrame()->GetPerformanceMonitor()->UnsubscribeAll(this); }
diff --git a/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp b/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp index 87ae80d..34e8a1e 100644 --- a/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp
@@ -81,6 +81,8 @@ ThreadableLoaderOptions options; ResourceLoaderOptions resource_loader_options; + resource_loader_options.parser_disposition = + ParserDisposition::kNotParserInserted; WorkerThreadableLoader::LoadResourceSynchronously( ToWorkerGlobalScope(execution_context), request, *this, options,
diff --git a/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js b/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js index d7dce91e0..f48a3ba0 100644 --- a/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js +++ b/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js
@@ -248,6 +248,8 @@ if (!executionContext) return Promise.resolve(); + // Evaluate location.href for a more specific URL than inspectedURL provides so that SPA hash navigation routes + // will be respected and audited. return new Promise(resolve => { executionContext.evaluate('window.location.href', 'audits', false, false, true, false, false, (object, err) => { if (!err && object) {
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js index 4da1164..9081df8 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js
@@ -113,7 +113,7 @@ * @return {?SDK.ExecutionContext} */ defaultExecutionContext() { - for (var context of this._executionContextById.values()) { + for (var context of this.executionContexts()) { if (context.isDefault) return context; }
diff --git a/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp b/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp index dd2ba69..e576aa0 100644 --- a/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp +++ b/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp
@@ -9,12 +9,14 @@ #include "bindings/core/v8/CallbackPromiseAdapter.h" #include "bindings/core/v8/ScriptPromise.h" #include "bindings/core/v8/ScriptPromiseResolver.h" +#include "build/build_config.h" #include "core/dom/DOMException.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" #include "core/dom/UserGestureIndicator.h" #include "core/frame/LocalFrame.h" +#include "core/inspector/ConsoleMessage.h" #include "modules/bluetooth/BluetoothDevice.h" #include "modules/bluetooth/BluetoothError.h" #include "modules/bluetooth/BluetoothRemoteGATTCharacteristic.h" @@ -153,6 +155,15 @@ ExceptionState& exception_state) { ExecutionContext* context = ExecutionContext::From(script_state); +// Remind developers when they are using Web Bluetooth on unsupported platforms. +#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) + context->AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, kInfoMessageLevel, + "Web Bluetooth is experimental on this platform. See " + "https://github.com/WebBluetoothCG/web-bluetooth/blob/gh-pages/" + "implementation-status.md")); +#endif + // If the Relevant settings object is not a secure context, reject promise // with a SecurityError and abort these steps. String error_message;
diff --git a/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.cpp b/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.cpp index 3e8d3300..5b9bc61 100644 --- a/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.cpp +++ b/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.cpp
@@ -366,7 +366,7 @@ // initializeNewSession() is called in response to the user calling // generateRequest(). WebContentDecryptionModule* cdm = media_keys->ContentDecryptionModule(); - session_ = WTF::WrapUnique(cdm->CreateSession()); + session_ = cdm->CreateSession(); session_->SetClientInterface(this); // From https://w3c.github.io/encrypted-media/#createSession:
diff --git a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h index cd4e2eac..77843fa 100644 --- a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h +++ b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h
@@ -30,7 +30,6 @@ #include "core/frame/LocalDOMWindow.h" #include "core/frame/Navigator.h" #include "core/frame/PlatformEventController.h" -#include "device/gamepad/public/cpp/gamepads.h" #include "modules/ModulesExport.h" #include "platform/AsyncMethodRunner.h" #include "platform/Supplementable.h" @@ -61,10 +60,6 @@ DECLARE_VIRTUAL_TRACE(); - void DidConnectOrDisconnectGamepad(unsigned index, - const device::Gamepad&, - bool connected); - private: explicit NavigatorGamepad(Navigator&);
diff --git a/third_party/WebKit/Source/modules/sensor/SensorProviderProxy.cpp b/third_party/WebKit/Source/modules/sensor/SensorProviderProxy.cpp index 408e833..3a7663a 100644 --- a/third_party/WebKit/Source/modules/sensor/SensorProviderProxy.cpp +++ b/third_party/WebKit/Source/modules/sensor/SensorProviderProxy.cpp
@@ -6,9 +6,8 @@ #include "modules/sensor/SensorProxy.h" #include "platform/mojo/MojoHelper.h" -#include "public/platform/Platform.h" #include "services/device/public/interfaces/constants.mojom-blink.h" -#include "services/service_manager/public/cpp/connector.h" +#include "services/service_manager/public/cpp/interface_provider.h" namespace blink { @@ -20,8 +19,8 @@ if (IsInitialized()) return; - Platform::Current()->GetConnector()->BindInterface( - device::mojom::blink::kServiceName, mojo::MakeRequest(&sensor_provider_)); + GetSupplementable()->GetInterfaceProvider().GetInterface( + mojo::MakeRequest(&sensor_provider_)); sensor_provider_.set_connection_error_handler(ConvertToBaseCallback( WTF::Bind(&SensorProviderProxy::OnSensorProviderConnectionError, WrapWeakPersistent(this))));
diff --git a/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp b/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp index c1ddf208..1d8fb80 100644 --- a/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp +++ b/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp
@@ -114,14 +114,11 @@ void SensorProxy::UpdateSensorReading() { DCHECK(ShouldProcessReadings()); - int read_attempts = 0; - const int kMaxReadAttemptsCount = 10; device::SensorReading reading_data; - while (!TryReadFromBuffer(reading_data)) { - if (++read_attempts == kMaxReadAttemptsCount) { - HandleSensorError(); - return; - } + if (!shared_buffer_handle_->is_valid() || + !shared_buffer_reader_->GetReading(&reading_data)) { + HandleSensorError(); + return; } if (reading_.timestamp != reading_data.timestamp) { @@ -202,6 +199,11 @@ HandleSensorError(); return; } + + const auto* buffer = static_cast<const device::SensorReadingSharedBuffer*>( + shared_buffer_.get()); + shared_buffer_reader_.reset( + new device::SensorReadingSharedBufferReader(buffer)); frequency_limits_.first = params->minimum_frequency; frequency_limits_.second = params->maximum_frequency; @@ -254,19 +256,6 @@ UpdatePollingStatus(); } -bool SensorProxy::TryReadFromBuffer(device::SensorReading& result) { - DCHECK(IsInitialized()); - const ReadingBuffer* buffer = - static_cast<const ReadingBuffer*>(shared_buffer_.get()); - const device::OneWriterSeqLock& seqlock = buffer->seqlock.value(); - auto version = seqlock.ReadBegin(); - auto reading_data = buffer->reading; - if (seqlock.ReadRetry(version)) - return false; - result = reading_data; - return true; -} - void SensorProxy::OnPollingTimer(TimerBase*) { UpdateSensorReading(); }
diff --git a/third_party/WebKit/Source/modules/sensor/SensorProxy.h b/third_party/WebKit/Source/modules/sensor/SensorProxy.h index 939bcea3..0057978 100644 --- a/third_party/WebKit/Source/modules/sensor/SensorProxy.h +++ b/third_party/WebKit/Source/modules/sensor/SensorProxy.h
@@ -14,6 +14,7 @@ #include "platform/heap/Handle.h" #include "platform/wtf/Vector.h" #include "services/device/public/cpp/generic_sensor/sensor_reading.h" +#include "services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h" #include "services/device/public/interfaces/sensor.mojom-blink.h" #include "services/device/public/interfaces/sensor_provider.mojom-blink.h" @@ -112,8 +113,6 @@ bool result); void OnRemoveConfigurationCompleted(double frequency, bool result); - bool TryReadFromBuffer(device::SensorReading& result); - void OnPollingTimer(TimerBase*); // Returns 'true' if readings should be propagated to Observers @@ -141,6 +140,8 @@ State state_; mojo::ScopedSharedBufferHandle shared_buffer_handle_; mojo::ScopedSharedBufferMapping shared_buffer_; + std::unique_ptr<device::SensorReadingSharedBufferReader> + shared_buffer_reader_; bool suspended_; device::SensorReading reading_; std::pair<double, double> frequency_limits_;
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index d1974c0e..db78d784b 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -1970,6 +1970,7 @@ "text/ICUErrorTest.cpp", "text/PlatformLocaleTest.cpp", "text/SegmentedStringTest.cpp", + "text/SuffixTreeTest.cpp", "text/TextBreakIteratorTest.cpp", "text/TextEncodingDetectorTest.cpp", "text/UnicodeUtilitiesTest.cpp",
diff --git a/third_party/WebKit/Source/platform/LayoutUnit.h b/third_party/WebKit/Source/platform/LayoutUnit.h index dfefdea..534496a 100644 --- a/third_party/WebKit/Source/platform/LayoutUnit.h +++ b/third_party/WebKit/Source/platform/LayoutUnit.h
@@ -53,7 +53,7 @@ #define REPORT_OVERFLOW(doesOverflow) ((void)0) #endif -static const int kLayoutUnitFractionalBits = 6; +static const unsigned kLayoutUnitFractionalBits = 6; static const int kFixedPointDenominator = 1 << kLayoutUnitFractionalBits; const int kIntMaxForLayoutUnit = INT_MAX / kFixedPointDenominator; @@ -154,7 +154,7 @@ return ToInt(); } ALWAYS_INLINE int Round() const { - return SaturatedAddition(RawValue(), kFixedPointDenominator / 2) >> + return ClampAdd(RawValue(), kFixedPointDenominator / 2) >> kLayoutUnitFractionalBits; } @@ -516,7 +516,7 @@ ALWAYS_INLINE LayoutUnit operator+(const LayoutUnit& a, const LayoutUnit& b) { LayoutUnit return_val; - return_val.SetRawValue(SaturatedAddition(a.RawValue(), b.RawValue())); + return_val.SetRawValue(ClampAdd(a.RawValue(), b.RawValue()).RawValue()); return return_val; } @@ -546,7 +546,7 @@ ALWAYS_INLINE LayoutUnit operator-(const LayoutUnit& a, const LayoutUnit& b) { LayoutUnit return_val; - return_val.SetRawValue(SaturatedSubtraction(a.RawValue(), b.RawValue())); + return_val.SetRawValue(ClampSub(a.RawValue(), b.RawValue()).RawValue()); return return_val; } @@ -576,7 +576,7 @@ inline LayoutUnit operator-(const LayoutUnit& a) { LayoutUnit return_val; - return_val.SetRawValue(SaturatedNegative(a.RawValue())); + return_val.SetRawValue((-MakeClampedNum(a.RawValue())).RawValue()); return return_val; } @@ -608,7 +608,7 @@ } inline LayoutUnit& operator+=(LayoutUnit& a, const LayoutUnit& b) { - a.SetRawValue(SaturatedAddition(a.RawValue(), b.RawValue())); + a.SetRawValue(ClampAdd(a.RawValue(), b.RawValue()).RawValue()); return a; } @@ -633,7 +633,7 @@ } inline LayoutUnit& operator-=(LayoutUnit& a, const LayoutUnit& b) { - a.SetRawValue(SaturatedSubtraction(a.RawValue(), b.RawValue())); + a.SetRawValue(ClampSub(a.RawValue(), b.RawValue()).RawValue()); return a; }
diff --git a/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolver.cpp b/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolver.cpp index 031e8f3f..26898c5 100644 --- a/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolver.cpp +++ b/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolver.cpp
@@ -9,14 +9,9 @@ namespace blink { -static String& CurrentAcceptLanguages() { - DEFINE_STATIC_LOCAL(String, current, ()); - return current; -} - void AcceptLanguagesResolver::AcceptLanguagesChanged( const String& accept_languages) { - String& current_value = CurrentAcceptLanguages(); + String& current_value = FontGlobalContext::CurrentAcceptLanguages(); if (current_value == accept_languages) return; @@ -25,7 +20,8 @@ } const LayoutLocale* AcceptLanguagesResolver::LocaleForHan() { - return LocaleForHanFromAcceptLanguages(CurrentAcceptLanguages()); + return LocaleForHanFromAcceptLanguages( + FontGlobalContext::CurrentAcceptLanguages()); } const LayoutLocale* AcceptLanguagesResolver::LocaleForHanFromAcceptLanguages(
diff --git a/third_party/WebKit/Source/platform/fonts/FontCache.cpp b/third_party/WebKit/Source/platform/fonts/FontCache.cpp index 2e5ebc8..0dc5a27 100644 --- a/third_party/WebKit/Source/platform/fonts/FontCache.cpp +++ b/third_party/WebKit/Source/platform/fonts/FontCache.cpp
@@ -206,17 +206,6 @@ return result; } -typedef HashMap<FontCache::FontFileKey, - RefPtr<OpenTypeVerticalData>, - IntHash<FontCache::FontFileKey>, - UnsignedWithZeroKeyHashTraits<FontCache::FontFileKey>> - FontVerticalDataCache; - -FontVerticalDataCache& FontVerticalDataCacheInstance() { - DEFINE_STATIC_LOCAL(FontVerticalDataCache, font_vertical_data_cache, ()); - return font_vertical_data_cache; -} - void FontCache::SetFontManager(sk_sp<SkFontMgr> font_manager) { DCHECK(!static_font_manager_); static_font_manager_ = font_manager.release(); @@ -226,7 +215,7 @@ const FontFileKey& key, const FontPlatformData& platform_data) { FontVerticalDataCache& font_vertical_data_cache = - FontVerticalDataCacheInstance(); + FontGlobalContext::GetFontVerticalDataCache(); FontVerticalDataCache::iterator result = font_vertical_data_cache.find(key); if (result != font_vertical_data_cache.end()) return result.Get()->value; @@ -330,7 +319,7 @@ void FontCache::PurgeFontVerticalDataCache() { FontVerticalDataCache& font_vertical_data_cache = - FontVerticalDataCacheInstance(); + FontGlobalContext::GetFontVerticalDataCache(); if (!font_vertical_data_cache.IsEmpty()) { // Mark & sweep unused verticalData FontVerticalDataCache::iterator vertical_data_end =
diff --git a/third_party/WebKit/Source/platform/fonts/FontFamilyNames.json5 b/third_party/WebKit/Source/platform/fonts/FontFamilyNames.json5 index 4d86dc7..638bf799 100644 --- a/third_party/WebKit/Source/platform/fonts/FontFamilyNames.json5 +++ b/third_party/WebKit/Source/platform/fonts/FontFamilyNames.json5
@@ -19,6 +19,7 @@ "Courier New", "Courier", "Helvetica", + "Lucida Grande", "Microsoft Sans Serif", "MS Sans Serif", "MS Serif", @@ -33,5 +34,7 @@ "monospace", "sans-serif", "serif", + + "BlinkMacSystemFont", ], }
diff --git a/third_party/WebKit/Source/platform/fonts/FontGlobalContext.h b/third_party/WebKit/Source/platform/fonts/FontGlobalContext.h index 4571cd3..8084733 100644 --- a/third_party/WebKit/Source/platform/fonts/FontGlobalContext.h +++ b/third_party/WebKit/Source/platform/fonts/FontGlobalContext.h
@@ -23,6 +23,12 @@ using LayoutLocaleMap = HashMap<AtomicString, RefPtr<LayoutLocale>, CaseFoldingHash>; +typedef HashMap<FontCache::FontFileKey, + RefPtr<OpenTypeVerticalData>, + IntHash<FontCache::FontFileKey>, + WTF::UnsignedWithZeroKeyHashTraits<FontCache::FontFileKey>> + FontVerticalDataCache; + enum CreateIfNeeded { kDoNotCreate, kCreate }; // FontGlobalContext contains non-thread-safe, thread-specific data used for @@ -83,6 +89,14 @@ return Get()->has_default_locale_for_han_; } + static inline String& CurrentAcceptLanguages() { + return Get()->current_accept_languages_; + } + + static inline FontVerticalDataCache& GetFontVerticalDataCache() { + return Get()->font_vertical_data_cache_; + } + // Called by MemoryCoordinator to clear memory. static void ClearMemory(); @@ -105,6 +119,10 @@ const LayoutLocale* system_locale_; const LayoutLocale* default_locale_for_han_; bool has_default_locale_for_han_; + + String current_accept_languages_; + + FontVerticalDataCache font_vertical_data_cache_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/OrientationIteratorTest.cpp b/third_party/WebKit/Source/platform/fonts/OrientationIteratorTest.cpp index a792987..a5c5269 100644 --- a/third_party/WebKit/Source/platform/fonts/OrientationIteratorTest.cpp +++ b/third_party/WebKit/Source/platform/fonts/OrientationIteratorTest.cpp
@@ -9,28 +9,29 @@ namespace blink { -struct TestRun { +struct OrientationTestRun { std::string text; OrientationIterator::RenderOrientation code; }; -struct ExpectedRun { +struct OrientationExpectedRun { unsigned limit; OrientationIterator::RenderOrientation render_orientation; - ExpectedRun(unsigned the_limit, - OrientationIterator::RenderOrientation the_render_orientation) + OrientationExpectedRun( + unsigned the_limit, + OrientationIterator::RenderOrientation the_render_orientation) : limit(the_limit), render_orientation(the_render_orientation) {} }; class OrientationIteratorTest : public ::testing::Test { protected: - void CheckRuns(const Vector<TestRun>& runs) { + void CheckRuns(const Vector<OrientationTestRun>& runs) { String text(g_empty_string16_bit); - Vector<ExpectedRun> expect; + Vector<OrientationExpectedRun> expect; for (auto& run : runs) { text.append(String::FromUTF8(run.text.c_str())); - expect.push_back(ExpectedRun(text.length(), run.code)); + expect.push_back(OrientationExpectedRun(text.length(), run.code)); } OrientationIterator orientation_iterator(text.Characters16(), text.length(), FontOrientation::kVerticalMixed); @@ -38,7 +39,7 @@ } void VerifyRuns(OrientationIterator* orientation_iterator, - const Vector<ExpectedRun>& expect) { + const Vector<OrientationExpectedRun>& expect) { unsigned limit; OrientationIterator::RenderOrientation render_orientation; unsigned long run_count = 0; @@ -53,9 +54,9 @@ }; // TODO(esprehn): WTF::Vector should allow initialization from a literal. -#define CHECK_RUNS(...) \ - static const TestRun kRunsArray[] = __VA_ARGS__; \ - Vector<TestRun> runs; \ +#define CHECK_ORIENTATION(...) \ + static const OrientationTestRun kRunsArray[] = __VA_ARGS__; \ + Vector<OrientationTestRun> runs; \ runs.Append(kRunsArray, sizeof(kRunsArray) / sizeof(*kRunsArray)); \ CheckRuns(runs); @@ -72,42 +73,44 @@ } TEST_F(OrientationIteratorTest, OneCharLatin) { - CHECK_RUNS({{"A", OrientationIterator::kOrientationRotateSideways}}); + CHECK_ORIENTATION({{"A", OrientationIterator::kOrientationRotateSideways}}); } TEST_F(OrientationIteratorTest, OneAceOfSpades) { - CHECK_RUNS({{"🂡", OrientationIterator::kOrientationKeep}}); + CHECK_ORIENTATION({{"🂡", OrientationIterator::kOrientationKeep}}); } TEST_F(OrientationIteratorTest, CombiningCircle) { - CHECK_RUNS({{"◌́◌̀◌̈◌̂◌̄◌̊", OrientationIterator::kOrientationKeep}}); + CHECK_ORIENTATION({{"◌́◌̀◌̈◌̂◌̄◌̊", OrientationIterator::kOrientationKeep}}); } TEST_F(OrientationIteratorTest, OneEthiopicSyllable) { - CHECK_RUNS({{"ጀ", OrientationIterator::kOrientationRotateSideways}}); + CHECK_ORIENTATION({{"ጀ", OrientationIterator::kOrientationRotateSideways}}); } TEST_F(OrientationIteratorTest, JapaneseLetterlikeEnd) { - CHECK_RUNS( + CHECK_ORIENTATION( {{"いろは", OrientationIterator::kOrientationKeep}, {"ℐℒℐℒℐℒℐℒℐℒℐℒℐℒ", OrientationIterator::kOrientationRotateSideways}}); } TEST_F(OrientationIteratorTest, LetterlikeJapaneseEnd) { - CHECK_RUNS({{"ℐ", OrientationIterator::kOrientationRotateSideways}, - {"いろは", OrientationIterator::kOrientationKeep}}); + CHECK_ORIENTATION({{"ℐ", OrientationIterator::kOrientationRotateSideways}, + {"いろは", OrientationIterator::kOrientationKeep}}); } TEST_F(OrientationIteratorTest, OneCharJapanese) { - CHECK_RUNS({{"い", OrientationIterator::kOrientationKeep}}); + CHECK_ORIENTATION({{"い", OrientationIterator::kOrientationKeep}}); } TEST_F(OrientationIteratorTest, Japanese) { - CHECK_RUNS({{"いろはにほへと", OrientationIterator::kOrientationKeep}}); + CHECK_ORIENTATION( + {{"いろはにほへと", OrientationIterator::kOrientationKeep}}); } TEST_F(OrientationIteratorTest, IVS) { - CHECK_RUNS({{"愉\xF3\xA0\x84\x81", OrientationIterator::kOrientationKeep}}); + CHECK_ORIENTATION( + {{"愉\xF3\xA0\x84\x81", OrientationIterator::kOrientationKeep}}); } TEST_F(OrientationIteratorTest, MarkAtFirstCharRotated) { @@ -117,47 +120,50 @@ // http://www.unicode.org/reports/tr50/#grapheme_clusters // https://drafts.csswg.org/css-writing-modes-3/#vertical-orientations // U+0300 COMBINING GRAVE ACCENT is Mn (Mark, Nonspacing) with Rotated. - CHECK_RUNS({{"\xCC\x80", OrientationIterator::kOrientationRotateSideways}}); + CHECK_ORIENTATION( + {{"\xCC\x80", OrientationIterator::kOrientationRotateSideways}}); } TEST_F(OrientationIteratorTest, MarkAtFirstCharUpright) { // U+20DD COMBINING ENCLOSING CIRCLE is Me (Mark, Enclosing) with Upright. - CHECK_RUNS({{"\xE2\x83\x9D", OrientationIterator::kOrientationKeep}}); + CHECK_ORIENTATION({{"\xE2\x83\x9D", OrientationIterator::kOrientationKeep}}); } TEST_F(OrientationIteratorTest, MarksAtFirstCharUpright) { // U+20DD COMBINING ENCLOSING CIRCLE is Me (Mark, Enclosing) with Upright. // U+0300 COMBINING GRAVE ACCENT is Mn (Mark, Nonspacing) with Rotated. - CHECK_RUNS({{"\xE2\x83\x9D\xCC\x80", OrientationIterator::kOrientationKeep}}); + CHECK_ORIENTATION( + {{"\xE2\x83\x9D\xCC\x80", OrientationIterator::kOrientationKeep}}); } TEST_F(OrientationIteratorTest, MarksAtFirstCharUprightThenBase) { // U+20DD COMBINING ENCLOSING CIRCLE is Me (Mark, Enclosing) with Upright. // U+0300 COMBINING GRAVE ACCENT is Mn (Mark, Nonspacing) with Rotated. - CHECK_RUNS( + CHECK_ORIENTATION( {{"\xE2\x83\x9D\xCC\x80", OrientationIterator::kOrientationKeep}, {"ABC\xE2\x83\x9D", OrientationIterator::kOrientationRotateSideways}}); } TEST_F(OrientationIteratorTest, JapaneseLatinMixedInside) { - CHECK_RUNS({{"いろはに", OrientationIterator::kOrientationKeep}, - {"Abc", OrientationIterator::kOrientationRotateSideways}, - {"ほへと", OrientationIterator::kOrientationKeep}}); + CHECK_ORIENTATION({{"いろはに", OrientationIterator::kOrientationKeep}, + {"Abc", OrientationIterator::kOrientationRotateSideways}, + {"ほへと", OrientationIterator::kOrientationKeep}}); } TEST_F(OrientationIteratorTest, PunctuationJapanese) { - CHECK_RUNS({{".…¡", OrientationIterator::kOrientationRotateSideways}, - {"ほへと", OrientationIterator::kOrientationKeep}}); + CHECK_ORIENTATION({{".…¡", OrientationIterator::kOrientationRotateSideways}, + {"ほへと", OrientationIterator::kOrientationKeep}}); } TEST_F(OrientationIteratorTest, JapaneseLatinMixedOutside) { - CHECK_RUNS({{"Abc", OrientationIterator::kOrientationRotateSideways}, - {"ほへと", OrientationIterator::kOrientationKeep}, - {"Xyz", OrientationIterator::kOrientationRotateSideways}}); + CHECK_ORIENTATION({{"Abc", OrientationIterator::kOrientationRotateSideways}, + {"ほへと", OrientationIterator::kOrientationKeep}, + {"Xyz", OrientationIterator::kOrientationRotateSideways}}); } TEST_F(OrientationIteratorTest, JapaneseMahjonggMixed) { - CHECK_RUNS({{"いろはに🀤ほへと", OrientationIterator::kOrientationKeep}}); + CHECK_ORIENTATION( + {{"いろはに🀤ほへと", OrientationIterator::kOrientationKeep}}); } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/ScriptRunIteratorTest.cpp b/third_party/WebKit/Source/platform/fonts/ScriptRunIteratorTest.cpp index 6bb487e..7691c31 100644 --- a/third_party/WebKit/Source/platform/fonts/ScriptRunIteratorTest.cpp +++ b/third_party/WebKit/Source/platform/fonts/ScriptRunIteratorTest.cpp
@@ -12,16 +12,16 @@ namespace blink { -struct TestRun { +struct ScriptTestRun { std::string text; UScriptCode code; }; -struct ExpectedRun { +struct ScriptExpectedRun { unsigned limit; UScriptCode code; - ExpectedRun(unsigned the_limit, UScriptCode the_code) + ScriptExpectedRun(unsigned the_limit, UScriptCode the_code) : limit(the_limit), code(the_code) {} }; @@ -286,12 +286,12 @@ class ScriptRunIteratorTest : public ::testing::Test { protected: - void CheckRuns(const Vector<TestRun>& runs) { + void CheckRuns(const Vector<ScriptTestRun>& runs) { String text(g_empty_string16_bit); - Vector<ExpectedRun> expect; + Vector<ScriptExpectedRun> expect; for (auto& run : runs) { text.append(String::FromUTF8(run.text.c_str())); - expect.push_back(ExpectedRun(text.length(), run.code)); + expect.push_back(ScriptExpectedRun(text.length(), run.code)); } ScriptRunIterator script_run_iterator(text.Characters16(), text.length()); VerifyRuns(&script_run_iterator, expect); @@ -299,12 +299,12 @@ // FIXME crbug.com/527329 - CheckMockRuns should be replaced by finding // suitable equivalent real codepoint sequences instead. - void CheckMockRuns(const Vector<TestRun>& runs) { + void CheckMockRuns(const Vector<ScriptTestRun>& runs) { String text(g_empty_string16_bit); - Vector<ExpectedRun> expect; - for (const TestRun& run : runs) { + Vector<ScriptExpectedRun> expect; + for (const ScriptTestRun& run : runs) { text.append(MockScriptData::ToTestString(run.text)); - expect.push_back(ExpectedRun(text.length(), run.code)); + expect.push_back(ScriptExpectedRun(text.length(), run.code)); } ScriptRunIterator script_run_iterator(text.Characters16(), text.length(), @@ -313,7 +313,7 @@ } void VerifyRuns(ScriptRunIterator* script_run_iterator, - const Vector<ExpectedRun>& expect) { + const Vector<ScriptExpectedRun>& expect) { unsigned limit; UScriptCode code; unsigned long run_count = 0; @@ -338,134 +338,136 @@ } // Some of our compilers cannot initialize a vector from an array yet. -#define DECLARE_RUNSVECTOR(...) \ - static const TestRun kRunsArray[] = __VA_ARGS__; \ - Vector<TestRun> runs; \ +#define DECLARE_SCRIPT_RUNSVECTOR(...) \ + static const ScriptTestRun kRunsArray[] = __VA_ARGS__; \ + Vector<ScriptTestRun> runs; \ runs.Append(kRunsArray, sizeof(kRunsArray) / sizeof(*kRunsArray)); -#define CHECK_RUNS(...) \ - DECLARE_RUNSVECTOR(__VA_ARGS__); \ +#define CHECK_SCRIPT_RUNS(...) \ + DECLARE_SCRIPT_RUNSVECTOR(__VA_ARGS__); \ CheckRuns(runs); -#define CHECK_MOCK_RUNS(...) \ - DECLARE_RUNSVECTOR(__VA_ARGS__); \ +#define CHECK_MOCK_SCRIPT_RUNS(...) \ + DECLARE_SCRIPT_RUNSVECTOR(__VA_ARGS__); \ CheckMockRuns(runs); TEST_F(ScriptRunIteratorTest, Whitespace) { - CHECK_RUNS({{" \t ", USCRIPT_COMMON}}); + CHECK_SCRIPT_RUNS({{" \t ", USCRIPT_COMMON}}); } TEST_F(ScriptRunIteratorTest, Common) { - CHECK_RUNS({{" ... !?", USCRIPT_COMMON}}); + CHECK_SCRIPT_RUNS({{" ... !?", USCRIPT_COMMON}}); } TEST_F(ScriptRunIteratorTest, CombiningCircle) { - CHECK_RUNS({{"◌́◌̀◌̈◌̂◌̄◌̊", USCRIPT_COMMON}}); + CHECK_SCRIPT_RUNS({{"◌́◌̀◌̈◌̂◌̄◌̊", USCRIPT_COMMON}}); } TEST_F(ScriptRunIteratorTest, Latin) { - CHECK_RUNS({{"latin", USCRIPT_LATIN}}); + CHECK_SCRIPT_RUNS({{"latin", USCRIPT_LATIN}}); } TEST_F(ScriptRunIteratorTest, Chinese) { - CHECK_RUNS({{"萬國碼", USCRIPT_HAN}}); + CHECK_SCRIPT_RUNS({{"萬國碼", USCRIPT_HAN}}); } // Close bracket without matching open is ignored TEST_F(ScriptRunIteratorTest, UnbalancedParens1) { - CHECK_RUNS({{"(萬", USCRIPT_HAN}, {"a]", USCRIPT_LATIN}, {")", USCRIPT_HAN}}); + CHECK_SCRIPT_RUNS( + {{"(萬", USCRIPT_HAN}, {"a]", USCRIPT_LATIN}, {")", USCRIPT_HAN}}); } // Open bracket without matching close is popped when inside // matching close brackets, so doesn't match later close. TEST_F(ScriptRunIteratorTest, UnbalancedParens2) { - CHECK_RUNS( + CHECK_SCRIPT_RUNS( {{"(萬", USCRIPT_HAN}, {"a[", USCRIPT_LATIN}, {")]", USCRIPT_HAN}}); } // space goes with leading script TEST_F(ScriptRunIteratorTest, LatinHan) { - CHECK_RUNS({{"Unicode ", USCRIPT_LATIN}, {"萬國碼", USCRIPT_HAN}}); + CHECK_SCRIPT_RUNS({{"Unicode ", USCRIPT_LATIN}, {"萬國碼", USCRIPT_HAN}}); } // space goes with leading script TEST_F(ScriptRunIteratorTest, HanLatin) { - CHECK_RUNS({{"萬國碼 ", USCRIPT_HAN}, {"Unicode", USCRIPT_LATIN}}); + CHECK_SCRIPT_RUNS({{"萬國碼 ", USCRIPT_HAN}, {"Unicode", USCRIPT_LATIN}}); } TEST_F(ScriptRunIteratorTest, ParenEmptyParen) { - CHECK_RUNS({{"()", USCRIPT_COMMON}}); + CHECK_SCRIPT_RUNS({{"()", USCRIPT_COMMON}}); } TEST_F(ScriptRunIteratorTest, ParenChineseParen) { - CHECK_RUNS({{"(萬國碼)", USCRIPT_HAN}}); + CHECK_SCRIPT_RUNS({{"(萬國碼)", USCRIPT_HAN}}); } TEST_F(ScriptRunIteratorTest, ParenLatinParen) { - CHECK_RUNS({{"(Unicode)", USCRIPT_LATIN}}); + CHECK_SCRIPT_RUNS({{"(Unicode)", USCRIPT_LATIN}}); } // open paren gets leading script TEST_F(ScriptRunIteratorTest, LatinParenChineseParen) { - CHECK_RUNS({{"Unicode (", USCRIPT_LATIN}, - {"萬國碼", USCRIPT_HAN}, - {")", USCRIPT_LATIN}}); + CHECK_SCRIPT_RUNS({{"Unicode (", USCRIPT_LATIN}, + {"萬國碼", USCRIPT_HAN}, + {")", USCRIPT_LATIN}}); } // open paren gets first trailing script if no leading script TEST_F(ScriptRunIteratorTest, ParenChineseParenLatin) { - CHECK_RUNS({{"(萬國碼) ", USCRIPT_HAN}, {"Unicode", USCRIPT_LATIN}}); + CHECK_SCRIPT_RUNS({{"(萬國碼) ", USCRIPT_HAN}, {"Unicode", USCRIPT_LATIN}}); } // leading common and open paren get first trailing script. // TODO(dougfelt): we don't do quote matching, but probably should figure out // something better then doing nothing. TEST_F(ScriptRunIteratorTest, QuoteParenChineseParenLatinQuote) { - CHECK_RUNS({{"\"(萬國碼) ", USCRIPT_HAN}, {"Unicode\"", USCRIPT_LATIN}}); + CHECK_SCRIPT_RUNS( + {{"\"(萬國碼) ", USCRIPT_HAN}, {"Unicode\"", USCRIPT_LATIN}}); } // Emojies are resolved to the leading script. TEST_F(ScriptRunIteratorTest, EmojiCommon) { - CHECK_RUNS({{"百家姓🌱🌲🌳🌴", USCRIPT_HAN}}); + CHECK_SCRIPT_RUNS({{"百家姓🌱🌲🌳🌴", USCRIPT_HAN}}); } // Unmatched close brace gets leading context TEST_F(ScriptRunIteratorTest, UnmatchedClose) { - CHECK_RUNS({{"Unicode (", USCRIPT_LATIN}, - {"萬國碼] ", USCRIPT_HAN}, - {") Unicode\"", USCRIPT_LATIN}}); + CHECK_SCRIPT_RUNS({{"Unicode (", USCRIPT_LATIN}, + {"萬國碼] ", USCRIPT_HAN}, + {") Unicode\"", USCRIPT_LATIN}}); } // Match up to 32 bracket pairs TEST_F(ScriptRunIteratorTest, Match32Brackets) { - CHECK_RUNS({{"[萬國碼 ", USCRIPT_HAN}, - {"Unicode (((((((((((((((((((((((((((((((!" - ")))))))))))))))))))))))))))))))", - USCRIPT_LATIN}, - {"]", USCRIPT_HAN}}); + CHECK_SCRIPT_RUNS({{"[萬國碼 ", USCRIPT_HAN}, + {"Unicode (((((((((((((((((((((((((((((((!" + ")))))))))))))))))))))))))))))))", + USCRIPT_LATIN}, + {"]", USCRIPT_HAN}}); } // Matches 32 most recent bracket pairs. More than that, and we revert to // surrounding script. TEST_F(ScriptRunIteratorTest, Match32MostRecentBrackets) { - CHECK_RUNS({{"((([萬國碼 ", USCRIPT_HAN}, - {"Unicode (((((((((((((((((((((((((((((((", USCRIPT_LATIN}, - {"萬國碼!", USCRIPT_HAN}, - {")))))))))))))))))))))))))))))))", USCRIPT_LATIN}, - {"]", USCRIPT_HAN}, - {"But )))", USCRIPT_LATIN}}); + CHECK_SCRIPT_RUNS({{"((([萬國碼 ", USCRIPT_HAN}, + {"Unicode (((((((((((((((((((((((((((((((", USCRIPT_LATIN}, + {"萬國碼!", USCRIPT_HAN}, + {")))))))))))))))))))))))))))))))", USCRIPT_LATIN}, + {"]", USCRIPT_HAN}, + {"But )))", USCRIPT_LATIN}}); } // A char with multiple scripts that match both leading and trailing context // gets the leading context. TEST_F(ScriptRunIteratorTest, ExtensionsPreferLeadingContext) { - CHECK_MOCK_RUNS({{"h<lh>", USCRIPT_HAN}, {"l", USCRIPT_LATIN}}); + CHECK_MOCK_SCRIPT_RUNS({{"h<lh>", USCRIPT_HAN}, {"l", USCRIPT_LATIN}}); } // A char with multiple scripts that only match trailing context gets the // trailing context. TEST_F(ScriptRunIteratorTest, ExtensionsMatchTrailingContext) { - CHECK_MOCK_RUNS({{"h", USCRIPT_HAN}, {"<gl>l", USCRIPT_LATIN}}); + CHECK_MOCK_SCRIPT_RUNS({{"h", USCRIPT_HAN}, {"<gl>l", USCRIPT_LATIN}}); } // Retain first established priority script. <lhg><gh> produce the script <gh> @@ -473,23 +475,23 @@ // remains. Then <gh><hgl> retains g as priority, because of the two priority // scripts g and h that remain, g was encountered first. TEST_F(ScriptRunIteratorTest, ExtensionsRetainFirstPriorityScript) { - CHECK_MOCK_RUNS({{"<lhg><gh><hgl>", USCRIPT_GREEK}}); + CHECK_MOCK_SCRIPT_RUNS({{"<lhg><gh><hgl>", USCRIPT_GREEK}}); } // Parens can have scripts that break script runs. TEST_F(ScriptRunIteratorTest, ExtensionsParens) { - CHECK_MOCK_RUNS({{"<gl><(lg>", USCRIPT_GREEK}, - {"h<[hl>", USCRIPT_HAN}, - {"l", USCRIPT_LATIN}, - {"<]hl>", USCRIPT_HAN}, - {"<)lg>", USCRIPT_GREEK}}); + CHECK_MOCK_SCRIPT_RUNS({{"<gl><(lg>", USCRIPT_GREEK}, + {"h<[hl>", USCRIPT_HAN}, + {"l", USCRIPT_LATIN}, + {"<]hl>", USCRIPT_HAN}, + {"<)lg>", USCRIPT_GREEK}}); } // The close paren might be encountered before we've established the open // paren's script, but when this is the case the current set is still valid, so // this doesn't affect it nor break the run. TEST_F(ScriptRunIteratorTest, ExtensionsParens2) { - CHECK_MOCK_RUNS({{"<(lhg><gh><)lhg>", USCRIPT_GREEK}}); + CHECK_MOCK_SCRIPT_RUNS({{"<(lhg><gh><)lhg>", USCRIPT_GREEK}}); } // A common script with a single extension should be treated as common, but @@ -497,15 +499,15 @@ // common, that takes priority. If we encounter other common scripts with a // single extension, the current priority remains. TEST_F(ScriptRunIteratorTest, CommonWithPriority) { - CHECK_MOCK_RUNS({{"<ch>", USCRIPT_HAN}}); + CHECK_MOCK_SCRIPT_RUNS({{"<ch>", USCRIPT_HAN}}); } TEST_F(ScriptRunIteratorTest, CommonWithPriority2) { - CHECK_MOCK_RUNS({{"<ch><lh>", USCRIPT_LATIN}}); + CHECK_MOCK_SCRIPT_RUNS({{"<ch><lh>", USCRIPT_LATIN}}); } TEST_F(ScriptRunIteratorTest, CommonWithPriority3) { - CHECK_MOCK_RUNS({{"<ch><cl><cg>", USCRIPT_HAN}}); + CHECK_MOCK_SCRIPT_RUNS({{"<ch><cl><cg>", USCRIPT_HAN}}); } // UDatta (\xE0\xA5\x91) is inherited with LATIN, DEVANAGARI, BENGALI and @@ -513,7 +515,7 @@ // dotted circle U+25CC (\xE2\x97\x8C) is COMMON and has adopted the // preceding LATIN, it gets the LATIN. This is standard. TEST_F(ScriptRunIteratorTest, LatinDottedCircleUdatta) { - CHECK_RUNS({{"Latin \xE2\x97\x8C\xE0\xA5\x91", USCRIPT_LATIN}}); + CHECK_SCRIPT_RUNS({{"Latin \xE2\x97\x8C\xE0\xA5\x91", USCRIPT_LATIN}}); } // In this situation, UDatta U+0951 (\xE0\xA5\x91) doesn't share a script @@ -526,8 +528,8 @@ // Taking into account a Unicode block and returning DEVANAGARI would be // slightly better. TEST_F(ScriptRunIteratorTest, HanDottedCircleUdatta) { - CHECK_RUNS({{"萬國碼 ", USCRIPT_HAN}, - {"\xE2\x97\x8C\xE0\xA5\x91", USCRIPT_BENGALI}}); + CHECK_SCRIPT_RUNS({{"萬國碼 ", USCRIPT_HAN}, + {"\xE2\x97\x8C\xE0\xA5\x91", USCRIPT_BENGALI}}); } // Tatweel is \xD9\x80 Lm, Fathatan is \xD9\x8B Mn. The script of tatweel is @@ -537,7 +539,8 @@ // heuristic. This is exactly analogous to the Udatta tests above, except // Tatweel is Lm. But we don't take properties into account, only scripts. TEST_F(ScriptRunIteratorTest, LatinTatweelFathatan) { - CHECK_RUNS({{"Latin ", USCRIPT_LATIN}, {"\xD9\x80\xD9\x8B", USCRIPT_ARABIC}}); + CHECK_SCRIPT_RUNS( + {{"Latin ", USCRIPT_LATIN}, {"\xD9\x80\xD9\x8B", USCRIPT_ARABIC}}); } // Another case where if the mark accepts a script that was inherited by the @@ -546,26 +549,27 @@ // ARABIC TATWEEL \xD9\x80 // ARABIC FATHATAN \xD9\x82 TEST_F(ScriptRunIteratorTest, SyriacTatweelFathatan) { - CHECK_RUNS({{"\xDC\xA2\xD9\x80\xD9\x8B", USCRIPT_SYRIAC}}); + CHECK_SCRIPT_RUNS({{"\xDC\xA2\xD9\x80\xD9\x8B", USCRIPT_SYRIAC}}); } // The Udatta (\xE0\xA5\x91) is inherited, so will share runs with anything that // is not common. TEST_F(ScriptRunIteratorTest, HanUdatta) { - CHECK_RUNS({{"萬國碼\xE0\xA5\x91", USCRIPT_HAN}}); + CHECK_SCRIPT_RUNS({{"萬國碼\xE0\xA5\x91", USCRIPT_HAN}}); } // The Udatta U+0951 (\xE0\xA5\x91) is inherited, and will capture the space // and turn it into Bengali because SCRIPT_BENAGLI is 4 and SCRIPT_DEVANAGARI // is 10. See TODO comment for |getScripts| and HanDottedCircleUdatta. TEST_F(ScriptRunIteratorTest, HanSpaceUdatta) { - CHECK_RUNS({{"萬國碼", USCRIPT_HAN}, {" \xE0\xA5\x91", USCRIPT_BENGALI}}); + CHECK_SCRIPT_RUNS( + {{"萬國碼", USCRIPT_HAN}, {" \xE0\xA5\x91", USCRIPT_BENGALI}}); } // Corresponds to one test in RunSegmenter, where orientation of the // space character is sidesways in vertical. TEST_F(ScriptRunIteratorTest, Hangul) { - CHECK_RUNS({{"키스의 고유조건은", USCRIPT_HANGUL}}); + CHECK_SCRIPT_RUNS({{"키스의 고유조건은", USCRIPT_HANGUL}}); } // Corresponds to one test in RunSegmenter, which tests that the punctuation @@ -573,45 +577,45 @@ // should report one run, but the RunSegmenter should report three, with the // middle one rotated sideways. TEST_F(ScriptRunIteratorTest, HiraganaMixedPunctuation) { - CHECK_RUNS({{"いろはに.…¡ほへと", USCRIPT_HIRAGANA}}); + CHECK_SCRIPT_RUNS({{"いろはに.…¡ほへと", USCRIPT_HIRAGANA}}); } // Make sure Mock code works too. TEST_F(ScriptRunIteratorTest, MockHanInheritedGL) { - CHECK_MOCK_RUNS({{"h<igl>", USCRIPT_HAN}}); + CHECK_MOCK_SCRIPT_RUNS({{"h<igl>", USCRIPT_HAN}}); } TEST_F(ScriptRunIteratorTest, MockHanCommonInheritedGL) { - CHECK_MOCK_RUNS({{"h", USCRIPT_HAN}, {"c<igl>", USCRIPT_GREEK}}); + CHECK_MOCK_SCRIPT_RUNS({{"h", USCRIPT_HAN}, {"c<igl>", USCRIPT_GREEK}}); } // Leading inherited just act like common, except there's no preferred script. TEST_F(ScriptRunIteratorTest, MockLeadingInherited) { - CHECK_MOCK_RUNS({{"<igl>", USCRIPT_COMMON}}); + CHECK_MOCK_SCRIPT_RUNS({{"<igl>", USCRIPT_COMMON}}); } // Leading inherited just act like common, except there's no preferred script. TEST_F(ScriptRunIteratorTest, MockLeadingInherited2) { - CHECK_MOCK_RUNS({{"<igl><ih>", USCRIPT_COMMON}}); + CHECK_MOCK_SCRIPT_RUNS({{"<igl><ih>", USCRIPT_COMMON}}); } TEST_F(ScriptRunIteratorTest, LeadingInheritedHan) { // DEVANAGARI STRESS SIGN UDATTA \xE0\xA5\x91 - CHECK_RUNS({{"\xE0\xA5\x91萬國碼", USCRIPT_HAN}}); + CHECK_SCRIPT_RUNS({{"\xE0\xA5\x91萬國碼", USCRIPT_HAN}}); } TEST_F(ScriptRunIteratorTest, LeadingInheritedHan2) { // DEVANAGARI STRESS SIGN UDATTA \xE0\xA5\x91 // ARABIC FATHATAN \xD9\x8B - CHECK_RUNS({{"\xE0\xA5\x91\xD9\x8B萬國碼", USCRIPT_HAN}}); + CHECK_SCRIPT_RUNS({{"\xE0\xA5\x91\xD9\x8B萬國碼", USCRIPT_HAN}}); } TEST_F(ScriptRunIteratorTest, OddLatinString) { - CHECK_RUNS({{"ç̈", USCRIPT_LATIN}}); + CHECK_SCRIPT_RUNS({{"ç̈", USCRIPT_LATIN}}); } TEST_F(ScriptRunIteratorTest, CommonMalayalam) { - CHECK_RUNS({{"100-ാം", USCRIPT_MALAYALAM}}); + CHECK_SCRIPT_RUNS({{"100-ാം", USCRIPT_MALAYALAM}}); } class ScriptRunIteratorICUDataTest : public ::testing::Test {
diff --git a/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp b/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp index d837015..a5e84b4e 100644 --- a/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp +++ b/third_party/WebKit/Source/platform/fonts/SimpleFontData.cpp
@@ -39,6 +39,7 @@ #include "SkTypes.h" #include "build/build_config.h" +#include "platform/FontFamilyNames.h" #include "platform/fonts/FontDescription.h" #include "platform/fonts/VDMXParser.h" #include "platform/fonts/skia/SkiaTextMetrics.h" @@ -184,12 +185,10 @@ // web standard. The AppKit adjustment of 20% is too big and is // incorrectly added to line spacing, so we use a 15% adjustment instead // and add it to the ascent. - DEFINE_STATIC_LOCAL(AtomicString, times_name, ("Times")); - DEFINE_STATIC_LOCAL(AtomicString, helvetica_name, ("Helvetica")); - DEFINE_STATIC_LOCAL(AtomicString, courier_name, ("Courier")); String family_name = platform_data_.FontFamilyName(); - if (family_name == times_name || family_name == helvetica_name || - family_name == courier_name) + if (family_name == FontFamilyNames::Times || + family_name == FontFamilyNames::Helvetica || + family_name == FontFamilyNames::Courier) ascent += floorf(((ascent + descent) * 0.15f) + 0.5f); #endif
diff --git a/third_party/WebKit/Source/platform/fonts/SmallCapsIteratorTest.cpp b/third_party/WebKit/Source/platform/fonts/SmallCapsIteratorTest.cpp index 8728265..5f51a87 100644 --- a/third_party/WebKit/Source/platform/fonts/SmallCapsIteratorTest.cpp +++ b/third_party/WebKit/Source/platform/fonts/SmallCapsIteratorTest.cpp
@@ -9,35 +9,36 @@ namespace blink { -struct TestRun { +struct SmallCapsTestRun { std::string text; SmallCapsIterator::SmallCapsBehavior code; }; -struct ExpectedRun { +struct SmallCapsExpectedRun { unsigned limit; SmallCapsIterator::SmallCapsBehavior small_caps_behavior; - ExpectedRun(unsigned the_limit, - SmallCapsIterator::SmallCapsBehavior the_small_caps_behavior) + SmallCapsExpectedRun( + unsigned the_limit, + SmallCapsIterator::SmallCapsBehavior the_small_caps_behavior) : limit(the_limit), small_caps_behavior(the_small_caps_behavior) {} }; class SmallCapsIteratorTest : public ::testing::Test { protected: - void CheckRuns(const Vector<TestRun>& runs) { + void CheckRuns(const Vector<SmallCapsTestRun>& runs) { String text(g_empty_string16_bit); - Vector<ExpectedRun> expect; + Vector<SmallCapsExpectedRun> expect; for (auto& run : runs) { text.append(String::FromUTF8(run.text.c_str())); - expect.push_back(ExpectedRun(text.length(), run.code)); + expect.push_back(SmallCapsExpectedRun(text.length(), run.code)); } SmallCapsIterator small_caps_iterator(text.Characters16(), text.length()); VerifyRuns(&small_caps_iterator, expect); } void VerifyRuns(SmallCapsIterator* small_caps_iterator, - const Vector<ExpectedRun>& expect) { + const Vector<SmallCapsExpectedRun>& expect) { unsigned limit; SmallCapsIterator::SmallCapsBehavior small_caps_behavior; unsigned long run_count = 0; @@ -52,13 +53,13 @@ }; // Some of our compilers cannot initialize a vector from an array yet. -#define DECLARE_RUNSVECTOR(...) \ - static const TestRun kRunsArray[] = __VA_ARGS__; \ - Vector<TestRun> runs; \ +#define DECLARE_SMALL_CAPS_RUNSVECTOR(...) \ + static const SmallCapsTestRun kRunsArray[] = __VA_ARGS__; \ + Vector<SmallCapsTestRun> runs; \ runs.Append(kRunsArray, sizeof(kRunsArray) / sizeof(*kRunsArray)); -#define CHECK_RUNS(...) \ - DECLARE_RUNSVECTOR(__VA_ARGS__); \ +#define CHECK_SMALL_CAPS_RUN(...) \ + DECLARE_SMALL_CAPS_RUNSVECTOR(__VA_ARGS__); \ CheckRuns(runs); TEST_F(SmallCapsIteratorTest, Empty) { @@ -73,44 +74,44 @@ } TEST_F(SmallCapsIteratorTest, UppercaseA) { - CHECK_RUNS({{"A", SmallCapsIterator::kSmallCapsSameCase}}); + CHECK_SMALL_CAPS_RUN({{"A", SmallCapsIterator::kSmallCapsSameCase}}); } TEST_F(SmallCapsIteratorTest, LowercaseA) { - CHECK_RUNS({{"a", SmallCapsIterator::kSmallCapsUppercaseNeeded}}); + CHECK_SMALL_CAPS_RUN({{"a", SmallCapsIterator::kSmallCapsUppercaseNeeded}}); } TEST_F(SmallCapsIteratorTest, UppercaseLowercaseA) { - CHECK_RUNS({{"A", SmallCapsIterator::kSmallCapsSameCase}, - {"a", SmallCapsIterator::kSmallCapsUppercaseNeeded}}); + CHECK_SMALL_CAPS_RUN({{"A", SmallCapsIterator::kSmallCapsSameCase}, + {"a", SmallCapsIterator::kSmallCapsUppercaseNeeded}}); } TEST_F(SmallCapsIteratorTest, UppercasePunctuationMixed) { - CHECK_RUNS({{"AAA??", SmallCapsIterator::kSmallCapsSameCase}}); + CHECK_SMALL_CAPS_RUN({{"AAA??", SmallCapsIterator::kSmallCapsSameCase}}); } TEST_F(SmallCapsIteratorTest, LowercasePunctuationMixed) { - CHECK_RUNS({{"aaa", SmallCapsIterator::kSmallCapsUppercaseNeeded}, - {"===", SmallCapsIterator::kSmallCapsSameCase}}); + CHECK_SMALL_CAPS_RUN({{"aaa", SmallCapsIterator::kSmallCapsUppercaseNeeded}, + {"===", SmallCapsIterator::kSmallCapsSameCase}}); } TEST_F(SmallCapsIteratorTest, LowercasePunctuationInterleaved) { - CHECK_RUNS({{"aaa", SmallCapsIterator::kSmallCapsUppercaseNeeded}, - {"===", SmallCapsIterator::kSmallCapsSameCase}, - {"bbb", SmallCapsIterator::kSmallCapsUppercaseNeeded}}); + CHECK_SMALL_CAPS_RUN({{"aaa", SmallCapsIterator::kSmallCapsUppercaseNeeded}, + {"===", SmallCapsIterator::kSmallCapsSameCase}, + {"bbb", SmallCapsIterator::kSmallCapsUppercaseNeeded}}); } TEST_F(SmallCapsIteratorTest, Japanese) { - CHECK_RUNS({{"ほへと", SmallCapsIterator::kSmallCapsSameCase}}); + CHECK_SMALL_CAPS_RUN({{"ほへと", SmallCapsIterator::kSmallCapsSameCase}}); } TEST_F(SmallCapsIteratorTest, Armenian) { - CHECK_RUNS({{"աբգդ", SmallCapsIterator::kSmallCapsUppercaseNeeded}, - {"ԵԶԷԸ", SmallCapsIterator::kSmallCapsSameCase}}); + CHECK_SMALL_CAPS_RUN({{"աբգդ", SmallCapsIterator::kSmallCapsUppercaseNeeded}, + {"ԵԶԷԸ", SmallCapsIterator::kSmallCapsSameCase}}); } TEST_F(SmallCapsIteratorTest, CombiningCharacterSequence) { - CHECK_RUNS({{"èü", SmallCapsIterator::kSmallCapsUppercaseNeeded}}); + CHECK_SMALL_CAPS_RUN({{"èü", SmallCapsIterator::kSmallCapsUppercaseNeeded}}); } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/SymbolsIteratorTest.cpp b/third_party/WebKit/Source/platform/fonts/SymbolsIteratorTest.cpp index 0e0e377..c44c3220 100644 --- a/third_party/WebKit/Source/platform/fonts/SymbolsIteratorTest.cpp +++ b/third_party/WebKit/Source/platform/fonts/SymbolsIteratorTest.cpp
@@ -9,35 +9,36 @@ namespace blink { -struct TestRun { +struct FallbackTestRun { std::string text; FontFallbackPriority font_fallback_priority; }; -struct ExpectedRun { +struct FallbackExpectedRun { unsigned limit; FontFallbackPriority font_fallback_priority; - ExpectedRun(unsigned the_limit, - FontFallbackPriority the_font_fallback_priority) + FallbackExpectedRun(unsigned the_limit, + FontFallbackPriority the_font_fallback_priority) : limit(the_limit), font_fallback_priority(the_font_fallback_priority) {} }; class SymbolsIteratorTest : public ::testing::Test { protected: - void CheckRuns(const Vector<TestRun>& runs) { + void CheckRuns(const Vector<FallbackTestRun>& runs) { String text(g_empty_string16_bit); - Vector<ExpectedRun> expect; + Vector<FallbackExpectedRun> expect; for (auto& run : runs) { text.append(String::FromUTF8(run.text.c_str())); - expect.push_back(ExpectedRun(text.length(), run.font_fallback_priority)); + expect.push_back( + FallbackExpectedRun(text.length(), run.font_fallback_priority)); } SymbolsIterator symbols_iterator(text.Characters16(), text.length()); VerifyRuns(&symbols_iterator, expect); } void VerifyRuns(SymbolsIterator* symbols_iterator, - const Vector<ExpectedRun>& expect) { + const Vector<FallbackExpectedRun>& expect) { unsigned limit; FontFallbackPriority font_fallback_priority; unsigned long run_count = 0; @@ -53,13 +54,13 @@ }; // Some of our compilers cannot initialize a vector from an array yet. -#define DECLARE_RUNSVECTOR(...) \ - static const TestRun kRunsArray[] = __VA_ARGS__; \ - Vector<TestRun> runs; \ +#define DECLARE_FALLBACK_RUNSVECTOR(...) \ + static const FallbackTestRun kRunsArray[] = __VA_ARGS__; \ + Vector<FallbackTestRun> runs; \ runs.Append(kRunsArray, sizeof(kRunsArray) / sizeof(*kRunsArray)); -#define CHECK_RUNS(...) \ - DECLARE_RUNSVECTOR(__VA_ARGS__); \ +#define CHECK_RUNS(...) \ + DECLARE_FALLBACK_RUNSVECTOR(__VA_ARGS__); \ CheckRuns(runs); TEST_F(SymbolsIteratorTest, Empty) {
diff --git a/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp b/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp index 370603eb..6a321713 100644 --- a/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp +++ b/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp
@@ -30,10 +30,11 @@ #include "platform/fonts/FontCache.h" +#include "platform/FontFamilyNames.h" #include "platform/Language.h" -#include "platform/fonts/SimpleFontData.h" #include "platform/fonts/FontDescription.h" #include "platform/fonts/FontFaceCreationParams.h" +#include "platform/fonts/SimpleFontData.h" #include "third_party/skia/include/core/SkTypeface.h" #include "third_party/skia/include/ports/SkFontMgr.h" @@ -55,7 +56,7 @@ // do here, use "Arial", the value LayoutTheme uses for CSS system font // keywords such as "menu". NOTREACHED(); - return "Arial"; + return FontFamilyNames::Arial; } static AtomicString DefaultFontFamily() { @@ -67,7 +68,8 @@ // static const AtomicString& FontCache::SystemFontFamily() { - DEFINE_STATIC_LOCAL(AtomicString, system_font_family, (DefaultFontFamily())); + DEFINE_THREAD_SAFE_STATIC_LOCAL(AtomicString, system_font_family, + (DefaultFontFamily())); return system_font_family; }
diff --git a/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp b/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp index b034c71e..4328823 100644 --- a/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp +++ b/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp
@@ -39,7 +39,7 @@ : purge_prevent_count_(0), font_manager_(sk_ref_sp(static_font_manager_)) {} static AtomicString& MutableSystemFontFamily() { - DEFINE_STATIC_LOCAL(AtomicString, system_font_family, ()); + DEFINE_THREAD_SAFE_STATIC_LOCAL(AtomicString, system_font_family, ()); return system_font_family; }
diff --git a/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm b/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm index ad0cd39..2f91a0bb 100644 --- a/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm +++ b/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm
@@ -31,6 +31,7 @@ #import <AppKit/AppKit.h> #include <memory> +#include "platform/FontFamilyNames.h" #include "platform/LayoutTestSupport.h" #include "platform/RuntimeEnabledFeatures.h" #include "platform/WebTaskRunner.h" @@ -63,9 +64,7 @@ // static const AtomicString& FontCache::LegacySystemFontFamily() { - DEFINE_STATIC_LOCAL(AtomicString, legacy_system_font_family, - ("BlinkMacSystemFont")); - return legacy_system_font_family; + return FontFamilyNames::BlinkMacSystemFont; } static void InvalidateFontCache() { @@ -232,13 +231,11 @@ PassRefPtr<SimpleFontData> FontCache::GetLastResortFallbackFont( const FontDescription& font_description, ShouldRetain should_retain) { - DEFINE_STATIC_LOCAL(AtomicString, times_str, ("Times")); - // FIXME: Would be even better to somehow get the user's default font here. // For now we'll pick the default that the user would get without changing // any prefs. RefPtr<SimpleFontData> simple_font_data = - GetFontData(font_description, times_str, + GetFontData(font_description, FontFamilyNames::Times, AlternateFontName::kAllowAlternate, should_retain); if (simple_font_data) return simple_font_data; @@ -247,8 +244,7 @@ // where the user doesn't have it, we fall back on Lucida Grande because // that's guaranteed to be there, according to Nathan Taylor. This is good // enough to avoid a crash at least. - DEFINE_STATIC_LOCAL(AtomicString, lucida_grande_str, ("Lucida Grande")); - return GetFontData(font_description, lucida_grande_str, + return GetFontData(font_description, FontFamilyNames::Lucida_Grande, AlternateFontName::kAllowAlternate, should_retain); }
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFace.cpp b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFace.cpp index 7c27533..e67ebcb 100644 --- a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFace.cpp +++ b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzFace.cpp
@@ -96,12 +96,6 @@ FontGlobalContext::GetHarfBuzzFontCache().erase(unique_id_); } -static hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value) { - // We treat HarfBuzz hb_position_t as 16.16 fixed-point. - static constexpr int kHbPosition1 = 1 << 16; - return clampTo<int>(value * kHbPosition1); -} - static hb_bool_t HarfBuzzGetGlyph(hb_font_t* hb_font, void* font_data, hb_codepoint_t unicode, @@ -149,8 +143,8 @@ Glyph the_glyph = glyph; vertical_data->GetVerticalTranslationsForGlyphs( hb_font_data->simple_font_data_, &the_glyph, 1, result); - *x = SkiaScalarToHarfBuzzPosition(-result[0]); - *y = SkiaScalarToHarfBuzzPosition(-result[1]); + *x = SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(-result[0]); + *y = SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(-result[1]); return true; } @@ -163,13 +157,14 @@ const OpenTypeVerticalData* vertical_data = hb_font_data->simple_font_data_->VerticalData(); if (!vertical_data) - return SkiaScalarToHarfBuzzPosition( + return SkiaTextMetrics::SkiaScalarToHarfBuzzPosition( hb_font_data->simple_font_data_->GetFontMetrics().Height()); Glyph the_glyph = glyph; float advance_height = -vertical_data->AdvanceHeight(hb_font_data->simple_font_data_, the_glyph); - return SkiaScalarToHarfBuzzPosition(SkFloatToScalar(advance_height)); + return SkiaTextMetrics::SkiaScalarToHarfBuzzPosition( + SkFloatToScalar(advance_height)); } static hb_position_t HarfBuzzGetGlyphHorizontalKerning( @@ -194,8 +189,8 @@ if (typeface->getKerningPairAdjustments(glyphs, 2, kerning_adjustments)) { SkScalar upm = SkIntToScalar(typeface->getUnitsPerEm()); SkScalar size = hb_font_data->paint_.getTextSize(); - return SkiaScalarToHarfBuzzPosition(SkIntToScalar(kerning_adjustments[0]) * - size / upm); + return SkiaTextMetrics::SkiaScalarToHarfBuzzPosition( + SkIntToScalar(kerning_adjustments[0]) * size / upm); } return 0; @@ -343,7 +338,8 @@ harf_buzz_font_data_->UpdateSimpleFontData(platform_data_); DCHECK(harf_buzz_font_data_->simple_font_data_); - int scale = SkiaScalarToHarfBuzzPosition(platform_data_->size()); + int scale = + SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(platform_data_->size()); hb_font_set_scale(unscaled_font_, scale, scale); SkTypeface* typeface = harf_buzz_font_data_->paint_.getTypeface();
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenterTest.cpp b/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenterTest.cpp index 11a6a12..7ea7607 100644 --- a/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenterTest.cpp +++ b/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenterTest.cpp
@@ -77,17 +77,17 @@ }; // Some of our compilers cannot initialize a vector from an array yet. -#define DECLARE_RUNSVECTOR(...) \ +#define DECLARE_SEGMENTER_RUNSVECTOR(...) \ static const SegmenterTestRun kRunsArray[] = __VA_ARGS__; \ Vector<SegmenterTestRun> runs; \ runs.Append(kRunsArray, sizeof(kRunsArray) / sizeof(*kRunsArray)); -#define CHECK_RUNS_MIXED(...) \ - DECLARE_RUNSVECTOR(__VA_ARGS__); \ +#define CHECK_RUNS_MIXED(...) \ + DECLARE_SEGMENTER_RUNSVECTOR(__VA_ARGS__); \ CheckRuns(runs, FontOrientation::kVerticalMixed); -#define CHECK_RUNS_HORIZONTAL(...) \ - DECLARE_RUNSVECTOR(__VA_ARGS__); \ +#define CHECK_RUNS_HORIZONTAL(...) \ + DECLARE_SEGMENTER_RUNSVECTOR(__VA_ARGS__); \ CheckRuns(runs, FontOrientation::kHorizontal); TEST_F(RunSegmenterTest, Empty) {
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultSpacing.h b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultSpacing.h index da429606..4c30d2f 100644 --- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultSpacing.h +++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultSpacing.h
@@ -65,6 +65,11 @@ bool is_vertical_offset_; }; +// Forward declare so no implicit instantiations happen before the +// first explicit instantiation (which would be a C++ violation). +template <> +void ShapeResultSpacing<TextRun>::SetSpacingAndExpansion( + const FontDescription&); } // namespace blink #endif
diff --git a/third_party/WebKit/Source/platform/fonts/skia/SkiaTextMetrics.cpp b/third_party/WebKit/Source/platform/fonts/skia/SkiaTextMetrics.cpp index df2ecfb..f0d04dc 100644 --- a/third_party/WebKit/Source/platform/fonts/skia/SkiaTextMetrics.cpp +++ b/third_party/WebKit/Source/platform/fonts/skia/SkiaTextMetrics.cpp
@@ -11,12 +11,6 @@ namespace blink { -static hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value) { - // We treat HarfBuzz hb_position_t as 16.16 fixed-point. - static const int kHbPosition1 = 1 << 16; - return clampTo<int>(value * kHbPosition1); -} - SkiaTextMetrics::SkiaTextMetrics(const SkPaint* paint) : paint_(paint) { CHECK(paint_->getTextEncoding() == SkPaint::kGlyphID_TextEncoding); } @@ -88,4 +82,10 @@ return SkScalarToFloat(sk_width); } +hb_position_t SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(SkScalar value) { + // We treat HarfBuzz hb_position_t as 16.16 fixed-point. + static const int kHbPosition1 = 1 << 16; + return clampTo<int>(value * kHbPosition1); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/skia/SkiaTextMetrics.h b/third_party/WebKit/Source/platform/fonts/skia/SkiaTextMetrics.h index 25fb260..c76f9c4 100644 --- a/third_party/WebKit/Source/platform/fonts/skia/SkiaTextMetrics.h +++ b/third_party/WebKit/Source/platform/fonts/skia/SkiaTextMetrics.h
@@ -22,6 +22,8 @@ void GetSkiaBoundsForGlyph(Glyph, SkRect* bounds); float GetSkiaWidthForGlyph(Glyph); + static hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value); + private: const SkPaint* paint_; };
diff --git a/third_party/WebKit/Source/platform/geometry/IntPoint.h b/third_party/WebKit/Source/platform/geometry/IntPoint.h index f11a140..420e87c 100644 --- a/third_party/WebKit/Source/platform/geometry/IntPoint.h +++ b/third_party/WebKit/Source/platform/geometry/IntPoint.h
@@ -69,8 +69,8 @@ y_ += dy; } void SaturatedMove(int dx, int dy) { - x_ = SaturatedAddition(x_, dx); - y_ = SaturatedAddition(y_, dy); + x_ = ClampAdd(x_, dx); + y_ = ClampAdd(y_, dy); } void Scale(float sx, float sy) {
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTest.cpp index c2a7b08..436069b 100644 --- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTest.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTest.cpp
@@ -239,7 +239,7 @@ decoder->ClearCacheExceptFrame(kNotFound); for (size_t i = 0; i < kNumFrames; ++i) { - SCOPED_TRACE(testing::Message() << i); + SCOPED_TRACE(::testing::Message() << i); EXPECT_EQ(ImageFrame::kFrameEmpty, frame_buffers[i].GetStatus()); } } @@ -256,7 +256,7 @@ decoder->ResetRequiredPreviousFrames(); decoder->ClearCacheExceptFrame(5); for (size_t i = 0; i < kNumFrames; ++i) { - SCOPED_TRACE(testing::Message() << i); + SCOPED_TRACE(::testing::Message() << i); if (i == 5) EXPECT_EQ(ImageFrame::kFrameComplete, frame_buffers[i].GetStatus()); else
diff --git a/third_party/WebKit/Source/platform/instrumentation/resource_coordinator/FrameResourceCoordinator.cpp b/third_party/WebKit/Source/platform/instrumentation/resource_coordinator/FrameResourceCoordinator.cpp index 23627c7..68d5b7d 100644 --- a/third_party/WebKit/Source/platform/instrumentation/resource_coordinator/FrameResourceCoordinator.cpp +++ b/third_party/WebKit/Source/platform/instrumentation/resource_coordinator/FrameResourceCoordinator.cpp
@@ -33,22 +33,14 @@ service_.set_connection_error_handler( ConvertToBaseCallback(WTF::Bind(&onConnectionError))); - - resource_coordinator::mojom::blink::EventPtr event = - resource_coordinator::mojom::blink::Event::New(); - event->type = resource_coordinator::mojom::EventType::kOnRendererFrameCreated; - service_->SendEvent(std::move(event)); } FrameResourceCoordinator::~FrameResourceCoordinator() = default; -void FrameResourceCoordinator::SendEvent( - const resource_coordinator::mojom::blink::EventType& event_type) { - resource_coordinator::mojom::blink::EventPtr event = - resource_coordinator::mojom::blink::Event::New(); - event->type = event_type; - - service_->SendEvent(std::move(event)); +void FrameResourceCoordinator::SetProperty( + const resource_coordinator::mojom::blink::PropertyType property_type, + const bool value) { + service_->SetProperty(property_type, base::MakeUnique<base::Value>(value)); } DEFINE_TRACE(FrameResourceCoordinator) {}
diff --git a/third_party/WebKit/Source/platform/instrumentation/resource_coordinator/FrameResourceCoordinator.h b/third_party/WebKit/Source/platform/instrumentation/resource_coordinator/FrameResourceCoordinator.h index 810706f09..fa58ec7 100644 --- a/third_party/WebKit/Source/platform/instrumentation/resource_coordinator/FrameResourceCoordinator.h +++ b/third_party/WebKit/Source/platform/instrumentation/resource_coordinator/FrameResourceCoordinator.h
@@ -22,7 +22,8 @@ static bool IsEnabled(); static FrameResourceCoordinator* Create(service_manager::InterfaceProvider*); virtual ~FrameResourceCoordinator(); - void SendEvent(const resource_coordinator::mojom::blink::EventType&); + void SetProperty(const resource_coordinator::mojom::blink::PropertyType, + const bool); DECLARE_TRACE();
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp index dd6c295..7a35234 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
@@ -836,7 +836,18 @@ // // request_initiator_context is benign (indicates document vs. worker). - if (new_options.synchronous_policy != options_.synchronous_policy) + // Reuse only if both the existing Resource and the new request are + // asynchronous. Particularly, + // 1. Sync and async Resource/requests shouldn't be mixed (crbug.com/652172), + // 2. Sync existing Resources shouldn't be revalidated, and + // 3. Sync new requests shouldn't revalidate existing Resources. + // + // 2. and 3. are because SyncResourceHandler handles redirects without + // calling WillFollowRedirect, and causes response URL mismatch + // (crbug.com/618967) and bypassing redirect restriction around revalidation + // (crbug.com/613971 for 2. and crbug.com/614989 for 3.). + if (new_options.synchronous_policy == kRequestSynchronously || + options_.synchronous_policy == kRequestSynchronously) return false; if (resource_request_.GetKeepalive() || new_request.GetKeepalive()) {
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc index 0108188..95f5d2d4 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
@@ -19,6 +19,8 @@ #include "platform/scheduler/base/work_queue_sets.h" #include "platform/wtf/PtrUtil.h" +static const double kLongTaskTraceEventThreshold = 0.05; + namespace blink { namespace scheduler { @@ -535,11 +537,11 @@ currently_executing_task_queue_ = prev_executing_task_queue; - + double task_end_time = 0; if (queue->GetShouldNotifyObservers()) { if (task_start_time) { *time_after_task = real_time_domain()->Now(); - double task_end_time = MonotonicTimeInSeconds(*time_after_task); + task_end_time = MonotonicTimeInSeconds(*time_after_task); queue->OnTaskCompleted( base::TimeTicks() + base::TimeDelta::FromSecondsD(task_start_time), @@ -554,6 +556,12 @@ queue->NotifyDidProcessTask(pending_task); } + if (task_start_time && task_end_time && + task_end_time - task_start_time > kLongTaskTraceEventThreshold) { + TRACE_EVENT_INSTANT1("blink", "LongTask", TRACE_EVENT_SCOPE_THREAD, + "duration", task_end_time - task_start_time); + } + return ProcessTaskResult::EXECUTED; }
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc index 9bf2ad2..2a6584d0 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc
@@ -220,10 +220,10 @@ selector_.EnableQueue(task_queues_[2].get()); selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::BEST_EFFORT_PRIORITY); - EXPECT_THAT(PopTasks(), testing::ElementsAre(2)); + EXPECT_THAT(PopTasks(), ::testing::ElementsAre(2)); task_queues_[4]->SetQueueEnabledForTest(true); selector_.EnableQueue(task_queues_[4].get()); - EXPECT_THAT(PopTasks(), testing::ElementsAre(4)); + EXPECT_THAT(PopTasks(), ::testing::ElementsAre(4)); } TEST_F(TaskQueueSelectorTest, TestDisableChangePriorityThenEnable) {
diff --git a/third_party/WebKit/Source/platform/text/SuffixTree.h b/third_party/WebKit/Source/platform/text/SuffixTree.h index 2723d546..1caf5269 100644 --- a/third_party/WebKit/Source/platform/text/SuffixTree.h +++ b/third_party/WebKit/Source/platform/text/SuffixTree.h
@@ -26,6 +26,9 @@ #ifndef SuffixTree_h #define SuffixTree_h +#include <algorithm> +#include <utility> + #include "platform/wtf/Allocator.h" #include "platform/wtf/Noncopyable.h" #include "platform/wtf/Vector.h" @@ -63,9 +66,10 @@ Node* current = &root_; int limit = std::min(depth_, query.length()); for (int i = 0; i < limit; ++i) { - current = current->at(Codebook::CodeWord(query[i])); - if (!current) + auto iter = current->Find(Codebook::CodeWord(query[i])); + if (iter == current->End()) return false; + current = iter->second; } return true; } @@ -76,27 +80,39 @@ WTF_MAKE_NONCOPYABLE(Node); public: - Node(bool is_leaf = false) { - children_.resize(Codebook::kCodeSize); - children_.Fill(0); - is_leaf_ = is_leaf; - } + Node(bool is_leaf = false) : is_leaf_(is_leaf) {} ~Node() { - for (unsigned i = 0; i < children_.size(); ++i) { - Node* child = children_.at(i); + for (const auto& pair : children_) { + Node* child = pair.second; if (child && !child->is_leaf_) delete child; } } - Node*& at(int code_word) { return children_.at(code_word); } + Node*& At(int key) { + auto it = Find(key); + if (it != children_.end()) + return it->second; + children_.emplace_back(key, nullptr); + return children_.back().second; + } + + typename Vector<std::pair<int, Node*>>::iterator Find(int key) { + return std::find_if(children_.begin(), children_.end(), + [key](const std::pair<int, Node*>& entry) { + return entry.first == key; + }); + } + + typename Vector<std::pair<int, Node*>>::iterator End() { + return children_.end(); + } private: - typedef Vector<Node*, Codebook::kCodeSize> ChildrenVector; - - ChildrenVector children_; - bool is_leaf_; + // TODO(tsepez): convert to base::flat_map when allowed in blink. + Vector<std::pair<int, Node*>> children_; + const bool is_leaf_; }; void Build(const String& text) { @@ -105,7 +121,7 @@ unsigned limit = std::min(base + depth_, text.length()); for (unsigned offset = 0; base + offset < limit; ++offset) { DCHECK_NE(current, &leaf_); - Node*& child = current->at(Codebook::CodeWord(text[base + offset])); + Node*& child = current->At(Codebook::CodeWord(text[base + offset])); if (!child) child = base + offset + 1 == limit ? &leaf_ : new Node(); current = child;
diff --git a/third_party/WebKit/Source/platform/text/SuffixTreeTest.cpp b/third_party/WebKit/Source/platform/text/SuffixTreeTest.cpp new file mode 100644 index 0000000..b1348c2 --- /dev/null +++ b/third_party/WebKit/Source/platform/text/SuffixTreeTest.cpp
@@ -0,0 +1,32 @@ +// 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 "platform/text/SuffixTree.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace blink { + +TEST(SuffixTreeTest, EmptyString) { + SuffixTree<ASCIICodebook> tree("", 16); + EXPECT_TRUE(tree.MightContain("")); + EXPECT_FALSE(tree.MightContain("potato")); +} + +TEST(SuffixTreeTest, NormalString) { + SuffixTree<ASCIICodebook> tree("banana", 16); + EXPECT_TRUE(tree.MightContain("")); + EXPECT_TRUE(tree.MightContain("a")); + EXPECT_TRUE(tree.MightContain("na")); + EXPECT_TRUE(tree.MightContain("ana")); + EXPECT_TRUE(tree.MightContain("nana")); + EXPECT_TRUE(tree.MightContain("anana")); + EXPECT_TRUE(tree.MightContain("banana")); + EXPECT_FALSE(tree.MightContain("ab")); + EXPECT_FALSE(tree.MightContain("bananan")); + EXPECT_FALSE(tree.MightContain("abanana")); + EXPECT_FALSE(tree.MightContain("potato")); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/platform/weborigin/KURL.h b/third_party/WebKit/Source/platform/weborigin/KURL.h index 2ed5360..26e4d1e 100644 --- a/third_party/WebKit/Source/platform/weborigin/KURL.h +++ b/third_party/WebKit/Source/platform/weborigin/KURL.h
@@ -36,6 +36,28 @@ #include "url/third_party/mozilla/url_parse.h" #include "url/url_canon.h" +// KURL is Blink's main URL class, and is the analog to GURL in other Chromium +// code. It is not thread safe but is generally cheap to copy and compare KURLs +// to each other. +// +// KURL and GURL both share the same underlying URL parser, whose code is +// located in //url, but KURL is backed by Blink specific WTF::Strings. This +// means that KURLs are usually cheap to copy due to WTF::Strings being +// internally ref-counted. However, please don't copy KURLs if you can use a +// const ref, since the size of the parsed structure and related metadata is +// non-trivial. +// +// In fact, for the majority of KURLs (i.e. those not copied across threads), +// the backing string is an AtomicString, meaning that it is stored in the +// thread-local AtomicString table, allowing optimizations like fast comparison. +// See platform/wtf/text/AtomicString.h for information on the performance +// characteristics of AtomicStrings. +// +// KURL also has a few other optimizations, including: +// - Cached bit for whether the KURL is http/https +// - Internal reference to the URL protocol (scheme) to avoid String allocation +// for the callers that require it. Common protocols like http and https are +// stored as static strings which can be shared across threads. namespace WTF { class TextEncoding; }
diff --git a/third_party/WebKit/Source/platform/wtf/SaturatedArithmetic.h b/third_party/WebKit/Source/platform/wtf/SaturatedArithmetic.h index c85f2916..11ca582 100644 --- a/third_party/WebKit/Source/platform/wtf/SaturatedArithmetic.h +++ b/third_party/WebKit/Source/platform/wtf/SaturatedArithmetic.h
@@ -31,18 +31,19 @@ #ifndef SaturatedArithmetic_h #define SaturatedArithmetic_h +#include "base/numerics/clamped_math.h" #include "base/numerics/saturated_arithmetic.h" namespace WTF { -using base::SaturatedAddition; -using base::SaturatedSubtraction; -using base::SaturatedNegative; +using base::ClampAdd; +using base::ClampSub; +using base::MakeClampedNum; using base::SaturatedSet; } // namespace WTF -using WTF::SaturatedAddition; -using WTF::SaturatedSubtraction; -using WTF::SaturatedNegative; +using WTF::ClampAdd; +using WTF::ClampSub; +using WTF::MakeClampedNum; using WTF::SaturatedSet; #endif // SaturatedArithmetic_h
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py index d1fe40c6..93446f5 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
@@ -175,7 +175,15 @@ def additional_driver_flag(self): if self.driver_name() == self.CONTENT_SHELL_NAME: - return ['--run-layout-test'] + # This is the fingerprint of wpt's certificate found in thirdparty/wpt/certs. Use + # + # openssl x509 -noout -pubkey -in 127.0.0.1.pem | + # openssl pkey -pubin -outform der | + # openssl dgst -sha256 -binary | + # base64 + # + # to regenerate. + return ['--run-layout-test', '--ignore-certificate-errors-spki-list=Nxvaj3+bY3oVrTc+Jp7m3E3sB1n3lXtnMDCyBsqEXiY='] return [] def supports_per_test_timeout(self):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py index 25bb5a7..097417da 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py
@@ -238,7 +238,10 @@ 'the WPT Importer is blocked from operating.\n\n' '(There is ongoing work to 1. prevent CLs with red upstream PRs from landing ' '(https://crbug.com/711447) and 2. prevent the importer from being blocked on ' - 'stuck exportable changes (https://crbug.com/734121))' + 'stuck exportable changes (https://crbug.com/734121))\n\n' + 'WPT Export docs:\n' + 'https://chromium.googlesource.com/chromium/src/+/master' + '/docs/testing/web_platform_tests.md#Automatic-export-process' ).format( pr_url='%spull/%d' % (WPT_GH_URL, response_data['number']) ))
diff --git a/third_party/WebKit/public/platform/WebContentDecryptionModule.h b/third_party/WebKit/public/platform/WebContentDecryptionModule.h index 11f96c7..fc25730 100644 --- a/third_party/WebKit/public/platform/WebContentDecryptionModule.h +++ b/third_party/WebKit/public/platform/WebContentDecryptionModule.h
@@ -31,6 +31,8 @@ #ifndef WebContentDecryptionModule_h #define WebContentDecryptionModule_h +#include <memory> + #include "public/platform/WebContentDecryptionModuleResult.h" #include "public/platform/WebContentDecryptionModuleSession.h" @@ -41,7 +43,8 @@ virtual ~WebContentDecryptionModule(); // Must return non-null. - virtual WebContentDecryptionModuleSession* CreateSession() = 0; + virtual std::unique_ptr<WebContentDecryptionModuleSession> + CreateSession() = 0; virtual void SetServerCertificate(const unsigned char* certificate, size_t certificate_length,
diff --git a/third_party/gvr-android-sdk/test-apks/daydream_home/apk_version_history.txt b/third_party/gvr-android-sdk/test-apks/daydream_home/apk_version_history.txt index 04d47f04..9200f48 100644 --- a/third_party/gvr-android-sdk/test-apks/daydream_home/apk_version_history.txt +++ b/third_party/gvr-android-sdk/test-apks/daydream_home/apk_version_history.txt
@@ -6,3 +6,4 @@ v1.4 9afe32eb4676d4bcceae81605a3be6aa0e5be3d5 v1.5 a02e2f95aa6f741f2be0ae03a4829e21fd749cf3 v1.6 43b876df3398687dfa1ae059ef2f64009c76254e +v1.7 d5c72438acffe723e7717c45deedd8431bc613e7
diff --git a/third_party/gvr-android-sdk/test-apks/daydream_home/daydream_home_current.apk.sha1 b/third_party/gvr-android-sdk/test-apks/daydream_home/daydream_home_current.apk.sha1 index 5c6216fb6..31836cd7 100644 --- a/third_party/gvr-android-sdk/test-apks/daydream_home/daydream_home_current.apk.sha1 +++ b/third_party/gvr-android-sdk/test-apks/daydream_home/daydream_home_current.apk.sha1
@@ -1 +1 @@ -43b876df3398687dfa1ae059ef2f64009c76254e \ No newline at end of file +d5c72438acffe723e7717c45deedd8431bc613e7 \ No newline at end of file
diff --git a/third_party/gvr-android-sdk/test-apks/vr_services/apk_version_history.txt b/third_party/gvr-android-sdk/test-apks/vr_services/apk_version_history.txt index 7b87608..4831ae6 100644 --- a/third_party/gvr-android-sdk/test-apks/vr_services/apk_version_history.txt +++ b/third_party/gvr-android-sdk/test-apks/vr_services/apk_version_history.txt
@@ -9,3 +9,4 @@ v1.4 3e0cc24655847c7b922149754324a189e7092310 v1.5 5d6d55728c7c728cef5416f37b0b71615719474e v1.6 abcdae2281956a76aa3b98d2e8f05a1975170dd0 +v1.7 fcfa178173a2c0cab9c7d51829c2ee76ab66e1d9
diff --git a/third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk.sha1 b/third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk.sha1 index 2877b099..fb68207 100644 --- a/third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk.sha1 +++ b/third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk.sha1
@@ -1 +1 @@ -abcdae2281956a76aa3b98d2e8f05a1975170dd0 \ No newline at end of file +fcfa178173a2c0cab9c7d51829c2ee76ab66e1d9 \ No newline at end of file
diff --git a/tools/copyright_scanner/OWNERS b/tools/copyright_scanner/OWNERS deleted file mode 100644 index 90a3cbe..0000000 --- a/tools/copyright_scanner/OWNERS +++ /dev/null
@@ -1,3 +0,0 @@ -phajdan.jr@chromium.org -sgurun@chromium.org -torne@chromium.org
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 756d74f..2edf298 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -259,7 +259,8 @@ 'GPU Win x64 Builder': 'gpu_tests_deqp_gles_release_trybot', 'GPU Win x64 Builder (dbg)': 'gpu_tests_deqp_gles_debug_trybot', 'Linux ChromiumOS Builder': 'gpu_fyi_tests_chromeos_release_trybot', - 'Linux ChromiumOS Ozone Builder': 'gpu_fyi_tests_chromeos_release_trybot', + # This is, confusingly, apparently not actually building ChromiumOS. + 'Linux ChromiumOS Ozone Builder': 'gpu_fyi_tests_ozone_linux_system_gbm_libdrm_release_trybot', 'Linux GPU TSAN Release': 'gpu_fyi_tests_release_trybot_tsan', 'Mac GPU ASAN Release': 'gpu_fyi_tests_release_trybot_asan', }, @@ -1234,6 +1235,10 @@ 'gpu_fyi_tests', 'debug_trybot', ], + 'gpu_fyi_tests_ozone_linux_system_gbm_libdrm_release_trybot': [ + 'gpu_fyi_tests', 'ozone_linux', 'system_gbm_libdrm', 'release_trybot', + ], + 'gpu_fyi_tests_release_trybot': [ 'gpu_fyi_tests', 'release_trybot', ],
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 389d9cc..5ec7b17 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -68709,6 +68709,36 @@ </summary> </histogram> +<histogram name="Search.ContextualSearchTapDurationNotSeen" units="ms"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The duration of a tap that triggered a Contextual Search when the user does + not open the panel. Implemented for Android. Logged when the panel closes + after being triggered by a tap. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchTapDurationSeen" units="ms"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The duration of a tap that triggered a Contextual Search when the user does + open the panel. Implemented for Android. Logged when the panel closes after + being triggered by a tap and subsequently opened. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchTapLongDurationSeen" + enum="ContextualSearchResultsSeen"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + Whether results were seen for a Tap that was of long duration. Recorded when + the UX is hidden. Implemented for Android. + </summary> +</histogram> + <histogram name="Search.ContextualSearchTapLongWordSeen" enum="ContextualSearchResultsSeen"> <owner>donnd@chromium.org</owner> @@ -68719,6 +68749,16 @@ </summary> </histogram> +<histogram name="Search.ContextualSearchTapShortDurationSeen" + enum="ContextualSearchResultsSeen"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + Whether results were seen for a Tap that was of short duration. Recorded + when the UX is hidden. Implemented for Android. + </summary> +</histogram> + <histogram name="Search.ContextualSearchTapShortWordSeen" enum="ContextualSearchResultsSeen"> <owner>donnd@chromium.org</owner>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index 951ca4ef..271b3175 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -278,67 +278,61 @@ Ranker. These metrics are recorded each time the user triggers the Contextual Search UI via a tap gesture (when enabled). </summary> - <metric name="DURATION_AFTER_SCROLL_MS"> + <metric name="DurationAfterScrollMs"> <summary> Duration in MS between showing the UI and a subsequent scroll event, or not recorded if there was no subsequent scroll. </summary> </metric> - <metric name="DURATION_BEFORE_SCROLL_MS"> - <summary> - Duration in MS between showing the most recent scroll event and showing - the UI, or 0 if no previous scroll event occurred. - </summary> - </metric> - <metric name="OUTCOME_WAS_PANEL_OPENED"> + <metric name="OutcomeWasPanelOpened"> <summary> Whether the user opened the overlay panel. This is the primary outcome metric. </summary> </metric> - <metric name="OUTCOME_WAS_QUICK_ACTION_CLICKED"> + <metric name="OutcomeWasQuickActionClicked"> <summary> Whether the user clicked within the overlay panel when a Quick-Action was shown. This is a secondary outcome metric. </summary> </metric> - <metric name="OUTCOME_WAS_QUICK_ANSWER_SEEN"> + <metric name="OutcomeWasQuickAnswerSeen"> <summary> Whether the user could see a Quick-Answer caption within the overlay panel. This is a tertiary outcome metric. </summary> </metric> - <metric name="PREVIOUS_28DAY_CTR_PERCENT"> + <metric name="Previous28DayCtrPercent"> <summary> The CTR of the overlay panel for this user, aggregated over a previous 28 day period, expressed as an integer between 0-99. </summary> </metric> - <metric name="PREVIOUS_28DAY_IMPRESSIONS_COUNT"> + <metric name="Previous28DayImpressionsCount"> <summary> The count of views of the overlay panel for this user, aggregated over a previous 28 day period. </summary> </metric> - <metric name="PREVIOUS_WEEK_CTR_PERCENT"> + <metric name="PreviousWeekCtrPercent"> <summary> The CTR of the overlay panel for this user, aggregated over the previous week, expressed as an integer between 0-99. </summary> </metric> - <metric name="PREVIOUS_WEEK_IMPRESSIONS_COUNT"> + <metric name="PreviousWeekImpressionsCount"> <summary> The count of views of the overlay panel for this user, aggregated over the previous week. </summary> </metric> - <metric name="SCREEN_TOP_DPS"> + <metric name="ScreenTopDps"> <summary> The location of the tap relative to the top of the screen, expressed in DPs. </summary> </metric> - <metric name="WAS_SCREEN_BOTTOM"> + <metric name="WasScreenBottom"> <summary> The location of the tap relative to the bottom of the screen, expressed as an integer with 0 meaning not at the bottom and 1 meaning at the bottom.
diff --git a/tools/perf/benchmarks/battor.py b/tools/perf/benchmarks/battor.py index 3480b0c..b6bf1df 100644 --- a/tools/perf/benchmarks/battor.py +++ b/tools/perf/benchmarks/battor.py
@@ -13,7 +13,7 @@ # are the primary means of benchmarking power. class _BattOrBenchmark(perf_benchmark.PerfBenchmark): - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): category_filter = chrome_trace_category_filter.ChromeTraceCategoryFilter( filter_string='toplevel') options = timeline_based_measurement.Options(category_filter)
diff --git a/tools/perf/benchmarks/blob_storage.py b/tools/perf/benchmarks/blob_storage.py index 40e2f13..05b8ad2 100644 --- a/tools/perf/benchmarks/blob_storage.py +++ b/tools/perf/benchmarks/blob_storage.py
@@ -21,7 +21,7 @@ page_set = page_sets.BlobWorkshopPageSet - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): cat_filter = chrome_trace_category_filter.ChromeTraceCategoryFilter() cat_filter.AddIncludedCategory(BLOB_CATEGORY) cat_filter.AddIncludedCategory(TIMELINE_REQUIRED_CATEGORY)
diff --git a/tools/perf/benchmarks/indexeddb_perf.py b/tools/perf/benchmarks/indexeddb_perf.py index d04c88d..a065ddd 100644 --- a/tools/perf/benchmarks/indexeddb_perf.py +++ b/tools/perf/benchmarks/indexeddb_perf.py
@@ -107,7 +107,7 @@ """IndexedDB Performance tests that use tracing.""" page_set = page_sets.IndexedDBEndurePageSet - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): cat_filter = chrome_trace_category_filter.ChromeTraceCategoryFilter() cat_filter.AddIncludedCategory(IDB_CATEGORY) cat_filter.AddIncludedCategory(TIMELINE_REQUIRED_CATEGORY)
diff --git a/tools/perf/benchmarks/loading.py b/tools/perf/benchmarks/loading.py index 0c217119..fdbff12 100644 --- a/tools/perf/benchmarks/loading.py +++ b/tools/perf/benchmarks/loading.py
@@ -17,7 +17,7 @@ options = {'pageset_repeat': 2} - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): tbm_options = timeline_based_measurement.Options() loading_metrics_category.AugmentOptionsForLoadingMetrics(tbm_options) return tbm_options
diff --git a/tools/perf/benchmarks/media.py b/tools/perf/benchmarks/media.py index 4200606..3b1e09d 100644 --- a/tools/perf/benchmarks/media.py +++ b/tools/perf/benchmarks/media.py
@@ -92,7 +92,7 @@ def CreateStorySet(self, options): return page_sets.ToughVideoCasesPageSet(measure_memory=True) - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): category_filter = chrome_trace_category_filter.ChromeTraceCategoryFilter() # 'toplevel' category provides CPU time slices used by # cpuTimeMetric.
diff --git a/tools/perf/benchmarks/memory.py b/tools/perf/benchmarks/memory.py index cea629c..4824036 100644 --- a/tools/perf/benchmarks/memory.py +++ b/tools/perf/benchmarks/memory.py
@@ -27,7 +27,7 @@ is part of chrome tracing, and extracts it using timeline-based measurements. """ - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): # Enable only memory-infra, to get memory dumps, and blink.console, to get # the timeline markers used for mapping threads to tabs. trace_memory = chrome_trace_category_filter.ChromeTraceCategoryFilter( @@ -161,7 +161,7 @@ r'renderer_processes:' r'(reported_by_chrome:v8|reported_by_os:system_memory:[^:]+$)') - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): v8_categories = [ 'blink.console', 'renderer.scheduler', 'v8', 'webkit.console'] memory_categories = ['blink.console', 'disabled-by-default-memory-infra']
diff --git a/tools/perf/benchmarks/oopif.py b/tools/perf/benchmarks/oopif.py index a657346a..413f1b09 100644 --- a/tools/perf/benchmarks/oopif.py +++ b/tools/perf/benchmarks/oopif.py
@@ -15,7 +15,7 @@ class _OopifBase(perf_benchmark.PerfBenchmark): options = {'pageset_repeat': 2} - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): tbm_options = timeline_based_measurement.Options() loading_metrics_category.AugmentOptionsForLoadingMetrics(tbm_options) return tbm_options
diff --git a/tools/perf/benchmarks/oortonline.py b/tools/perf/benchmarks/oortonline.py index f6a98a0..f335f04 100644 --- a/tools/perf/benchmarks/oortonline.py +++ b/tools/perf/benchmarks/oortonline.py
@@ -79,7 +79,7 @@ pass # http://oortonline.gl/#run not disabled. return StoryExpectations() - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): categories = [ # Implicitly disable all categories. '-*',
diff --git a/tools/perf/benchmarks/power.py b/tools/perf/benchmarks/power.py index ee78b23f..7a98df2a 100644 --- a/tools/perf/benchmarks/power.py +++ b/tools/perf/benchmarks/power.py
@@ -76,7 +76,7 @@ Our power benchmarks are prone to noise caused by other things running on the system. This benchmark is intended to help find the sources of noise. """ - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): options = timeline_based_measurement.Options( chrome_trace_category_filter.ChromeTraceCategoryFilter()) options.config.enable_battor_trace = True
diff --git a/tools/perf/benchmarks/start_with_url.py b/tools/perf/benchmarks/start_with_url.py index 56d23c3..ec426fe 100644 --- a/tools/perf/benchmarks/start_with_url.py +++ b/tools/perf/benchmarks/start_with_url.py
@@ -19,7 +19,7 @@ '--enable-stats-collection-bindings' ]) - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): startup_category_filter = ( chrome_trace_category_filter.ChromeTraceCategoryFilter( filter_string='startup,blink.user_timing'))
diff --git a/tools/perf/benchmarks/system_health.py b/tools/perf/benchmarks/system_health.py index c5a8dab..e0515f8 100644 --- a/tools/perf/benchmarks/system_health.py +++ b/tools/perf/benchmarks/system_health.py
@@ -33,7 +33,7 @@ https://goo.gl/Jek2NL. """ - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): options = timeline_based_measurement.Options( chrome_trace_category_filter.ChromeTraceCategoryFilter( filter_string='rail,toplevel')) @@ -97,7 +97,7 @@ """ options = {'pageset_repeat': 3} - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): options = timeline_based_measurement.Options( chrome_trace_category_filter.ChromeTraceCategoryFilter( '-*,disabled-by-default-memory-infra')) @@ -178,7 +178,7 @@ def GetExpectations(self): return page_sets.SystemHealthWebviewStartupExpectations() - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): options = timeline_based_measurement.Options() options.SetTimelineBasedMetrics(['webviewStartupMetric']) options.config.enable_atrace_trace = True
diff --git a/tools/perf/benchmarks/tracing.py b/tools/perf/benchmarks/tracing.py index 7e39d103..10d12c6d 100644 --- a/tools/perf/benchmarks/tracing.py +++ b/tools/perf/benchmarks/tracing.py
@@ -20,7 +20,7 @@ page_set = page_sets.Top10PageSet - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): options = timeline_based_measurement.Options( timeline_based_measurement.DEBUG_OVERHEAD_LEVEL) options.SetTimelineBasedMetrics(['tracingMetric']) @@ -45,7 +45,7 @@ """Measures the overhead of background memory-infra dumps""" page_set = page_sets.Top10PageSet - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): # Enable only memory-infra category with periodic background mode dumps # every 200 milliseconds. trace_memory = chrome_trace_category_filter.ChromeTraceCategoryFilter(
diff --git a/tools/perf/benchmarks/v8.py b/tools/perf/benchmarks/v8.py index f5d8241..4e46990 100644 --- a/tools/perf/benchmarks/v8.py +++ b/tools/perf/benchmarks/v8.py
@@ -46,7 +46,7 @@ options.AppendExtraBrowserArgs( '--enable-blink-features=BlinkRuntimeCallStats') - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): # TODO(fmeawad): most of the cat_filter information is extracted from # page_cycler_v2 TimelineBasedMeasurementOptionsForLoadingMetric because # used by the loadingMetric because the runtimeStatsMetric uses the
diff --git a/tools/perf/benchmarks/v8_browsing.py b/tools/perf/benchmarks/v8_browsing.py index 40fd920..d8b40ed 100644 --- a/tools/perf/benchmarks/v8_browsing.py +++ b/tools/perf/benchmarks/v8_browsing.py
@@ -53,7 +53,7 @@ See browsing_stories._BrowsingStory for workload description. """ - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): categories = [ # Disable all categories by default. '-*', @@ -109,7 +109,7 @@ See browsing_stories._BrowsingStory for workload description. """ - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): categories = [ # Disable all categories by default. '-*',
diff --git a/tools/perf/benchmarks/webrtc.py b/tools/perf/benchmarks/webrtc.py index ffc2e453..b74a749 100644 --- a/tools/perf/benchmarks/webrtc.py +++ b/tools/perf/benchmarks/webrtc.py
@@ -21,7 +21,7 @@ def Name(cls): return 'webrtc' - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): categories = [ # Disable all categories by default. '-*',
diff --git a/tools/perf/contrib/cros_benchmarks/page_cycler_v2.py b/tools/perf/contrib/cros_benchmarks/page_cycler_v2.py index da191a9..29588dc 100644 --- a/tools/perf/contrib/cros_benchmarks/page_cycler_v2.py +++ b/tools/perf/contrib/cros_benchmarks/page_cycler_v2.py
@@ -19,7 +19,7 @@ class _PageCyclerV2(perf_benchmark.PerfBenchmark): options = {'pageset_repeat': 2} - def CreateTimelineBasedMeasurementOptions(self): + def CreateCoreTimelineBasedMeasurementOptions(self): tbm_options = timeline_based_measurement.Options() loading_metrics_category.AugmentOptionsForLoadingMetrics(tbm_options) return tbm_options
diff --git a/tools/ubsan/vptr_blacklist.txt b/tools/ubsan/vptr_blacklist.txt index 755a48e..c88a77b 100644 --- a/tools/ubsan/vptr_blacklist.txt +++ b/tools/ubsan/vptr_blacklist.txt
@@ -99,7 +99,7 @@ ############################################################################# # LLVM is not UBSan vptr clean. src:*third_party/swiftshader/third_party/LLVM* -src:*third_party/swiftshader/third_party/llvm-subzero* +src:*third_party/swiftshader/third_party/llvm\-subzero* ############################################################################# # UBSan yields false positives in SwiftShader's libEGL when objects created in
diff --git a/ui/android/java/src/org/chromium/ui/UiUtils.java b/ui/android/java/src/org/chromium/ui/UiUtils.java index 59cfb82..2d36381 100644 --- a/ui/android/java/src/org/chromium/ui/UiUtils.java +++ b/ui/android/java/src/org/chromium/ui/UiUtils.java
@@ -22,7 +22,7 @@ import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; -import android.widget.LinearLayout; +import android.widget.AbsListView; import android.widget.ListAdapter; import org.chromium.base.ApiCompatibilityUtils; @@ -429,8 +429,8 @@ public static int computeMaxWidthOfListAdapterItems(ListAdapter adapter) { final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); + AbsListView.LayoutParams params = new AbsListView.LayoutParams( + AbsListView.LayoutParams.WRAP_CONTENT, AbsListView.LayoutParams.WRAP_CONTENT); int maxWidth = 0; View[] itemViews = new View[adapter.getViewTypeCount()];
diff --git a/ui/app_list/BUILD.gn b/ui/app_list/BUILD.gn index 0ad11643..465478a 100644 --- a/ui/app_list/BUILD.gn +++ b/ui/app_list/BUILD.gn
@@ -289,6 +289,7 @@ ] deps += [ "//ui/accessibility", + "//ui/app_list/vector_icons", "//ui/views", "//ui/views:test_support", ]
diff --git a/ui/app_list/app_list_constants.cc b/ui/app_list/app_list_constants.cc index 12c3ad2..d97a15dc 100644 --- a/ui/app_list/app_list_constants.cc +++ b/ui/app_list/app_list_constants.cc
@@ -127,6 +127,12 @@ const int kSearchBoxTopPadding = 24; const int kSearchBoxBottomPadding = 21; +// The preferred height of the search box. +const int kSearchBoxPreferredHeight = 48; + +// The background border corner radius of the search box in fullscreen mode. +const int kSearchBoxBorderCornerRadiusFullscreen = 24; + // Max items allowed in a folder. size_t kMaxFolderItems = 16; @@ -160,6 +166,14 @@ // The height of tiles in search result. const int kSearchTileHeight = 92; +// The size of the search icon in the search box. +const int kSearchIconSize = 24; + +// Default color used when wallpaper customized color is not available for +// searchbox, #000 at 87% opacity. +const SkColor kDefaultSearchboxColor = + SkColorSetARGBMacro(0xDE, 0x00, 0x00, 0x00); + gfx::ShadowValue GetShadowForZHeight(int z_height) { if (z_height <= 0) return gfx::ShadowValue();
diff --git a/ui/app_list/app_list_constants.h b/ui/app_list/app_list_constants.h index 807a31e..36d0be2 100644 --- a/ui/app_list/app_list_constants.h +++ b/ui/app_list/app_list_constants.h
@@ -96,6 +96,8 @@ APP_LIST_EXPORT extern const int kSearchBoxPadding; APP_LIST_EXPORT extern const int kSearchBoxTopPadding; APP_LIST_EXPORT extern const int kSearchBoxBottomPadding; +APP_LIST_EXPORT extern const int kSearchBoxPreferredHeight; +APP_LIST_EXPORT extern const int kSearchBoxBorderCornerRadiusFullscreen; APP_LIST_EXPORT extern size_t kMaxFolderItems; APP_LIST_EXPORT extern const size_t kNumFolderTopItems; @@ -110,6 +112,9 @@ APP_LIST_EXPORT extern const int kSearchTileHeight; +APP_LIST_EXPORT extern const int kSearchIconSize; +APP_LIST_EXPORT extern const SkColor kDefaultSearchboxColor; + // Returns the shadow values for a view at |z_height|. APP_LIST_EXPORT gfx::ShadowValue GetShadowForZHeight(int z_height);
diff --git a/ui/app_list/test/app_list_test_view_delegate.cc b/ui/app_list/test/app_list_test_view_delegate.cc index 9202127b..6133b93 100644 --- a/ui/app_list/test/app_list_test_view_delegate.cc +++ b/ui/app_list/test/app_list_test_view_delegate.cc
@@ -89,5 +89,9 @@ model_->PopulateApps(item_count); } +void AppListTestViewDelegate::SetSearchEngineIsGoogle(bool is_google) { + model_->SetSearchEngineIsGoogle(is_google); +} + } // namespace test } // namespace app_list
diff --git a/ui/app_list/test/app_list_test_view_delegate.h b/ui/app_list/test/app_list_test_view_delegate.h index 5cafa04f..d3d73afb 100644 --- a/ui/app_list/test/app_list_test_view_delegate.h +++ b/ui/app_list/test/app_list_test_view_delegate.h
@@ -47,6 +47,9 @@ // value to 0. int GetStopSpeechRecognitionCountAndReset(); + // Sets whether the search engine is Google or not. + void SetSearchEngineIsGoogle(bool is_google); + // AppListViewDelegate overrides: AppListModel* GetModel() override; SpeechUIModel* GetSpeechUI() override;
diff --git a/ui/app_list/vector_icons/BUILD.gn b/ui/app_list/vector_icons/BUILD.gn index 9951785..c0f775f 100644 --- a/ui/app_list/vector_icons/BUILD.gn +++ b/ui/app_list/vector_icons/BUILD.gn
@@ -22,6 +22,8 @@ "ic_google_black.icon", "ic_mic_black.1x.icon", "ic_mic_black.icon", + "ic_search_engine_not_google.1x.icon", + "ic_search_engine_not_google.icon", ] }
diff --git a/ui/app_list/vector_icons/ic_search_engine_not_google.1x.icon b/ui/app_list/vector_icons/ic_search_engine_not_google.1x.icon new file mode 100644 index 0000000..5606e25c --- /dev/null +++ b/ui/app_list/vector_icons/ic_search_engine_not_google.1x.icon
@@ -0,0 +1,26 @@ +// 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. + +CANVAS_DIMENSIONS, 24, +MOVE_TO, 15.5f, 14, +LINE_TO, 14.71f, 14, +LINE_TO, 14.43f, 13.73f, +CUBIC_TO, 15.41f, 12.59f, 16, 11.11f, 16, 9.5f, +CUBIC_TO, 16, 5.91f, 13.09f, 3, 9.5f, 3, +CUBIC_TO, 5.91f, 3, 3, 5.91f, 3, 9.5f, +CUBIC_TO, 3, 13.09f, 5.91f, 16, 9.5f, 16, +CUBIC_TO, 11.11f, 16, 12.59f, 15.41f, 13.73f, 14.43f, +LINE_TO, 14, 14.71f, +LINE_TO, 14, 15.5f, +LINE_TO, 19, 20.49f, +LINE_TO, 20.49f, 19, +LINE_TO, 15.5f, 14, +CLOSE, +MOVE_TO, 9.5f, 14, +CUBIC_TO, 7.01f, 14, 5, 11.99f, 5, 9.5f, +CUBIC_TO, 5, 7.01f, 7.01f, 5, 9.5f, 5, +CUBIC_TO, 11.99f, 5, 14, 7.01f, 14, 9.5f, +CUBIC_TO, 14, 11.99f, 11.99f, 14, 9.5f, 14, +CLOSE, +END
diff --git a/ui/app_list/vector_icons/ic_search_engine_not_google.icon b/ui/app_list/vector_icons/ic_search_engine_not_google.icon new file mode 100644 index 0000000..3fd6c52c --- /dev/null +++ b/ui/app_list/vector_icons/ic_search_engine_not_google.icon
@@ -0,0 +1,25 @@ +// 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. + +MOVE_TO, 31, 28, +LINE_TO, 29.42f, 28, +LINE_TO, 28.86f, 27.46f, +CUBIC_TO, 30.82f, 25.18f, 32, 22.22f, 32, 19, +CUBIC_TO, 32, 11.82f, 26.18f, 6, 19, 6, +CUBIC_TO, 11.82f, 6, 6, 11.82f, 6, 19, +CUBIC_TO, 6, 26.18f, 11.82f, 32, 19, 32, +CUBIC_TO, 22.22f, 32, 25.18f, 30.82f, 27.46f, 28.86f, +LINE_TO, 28, 29.42f, +LINE_TO, 28, 31, +LINE_TO, 38, 40.98f, +LINE_TO, 40.98f, 38, +LINE_TO, 31, 28, +CLOSE, +MOVE_TO, 19, 28, +CUBIC_TO, 14.02f, 28, 10, 23.98f, 10, 19, +CUBIC_TO, 10, 14.02f, 14.02f, 10, 19, 10, +CUBIC_TO, 23.98f, 10, 28, 14.02f, 28, 19, +CUBIC_TO, 28, 23.98f, 23.98f, 28, 19, 28, +CLOSE, +END
diff --git a/ui/app_list/views/app_list_page.h b/ui/app_list/views/app_list_page.h index d64b615..c20d374f 100644 --- a/ui/app_list/views/app_list_page.h +++ b/ui/app_list/views/app_list_page.h
@@ -43,6 +43,7 @@ // Returns the z height of the search box for this page. virtual int GetSearchBoxZHeight() const; + const ContentsView* contents_view() const { return contents_view_; } void set_contents_view(ContentsView* contents_view) { contents_view_ = contents_view; }
diff --git a/ui/app_list/views/contents_view.cc b/ui/app_list/views/contents_view.cc index 0ab0ae3..23a4465 100644 --- a/ui/app_list/views/contents_view.cc +++ b/ui/app_list/views/contents_view.cc
@@ -214,10 +214,7 @@ const bool folder_active = state == AppListModel::STATE_APPS && apps_container_view_->IsInFolderView(); - if (is_fullscreen_app_list_enabled_) { - app_list_main_view_->search_box_view()->UpdateBackground( - state == AppListModel::STATE_SEARCH_RESULTS); - } else { + if (!is_fullscreen_app_list_enabled_) { app_list_main_view_->search_box_view()->back_button()->SetVisible( state != AppListModel::STATE_START); app_list_main_view_->search_box_view()->Layout(); @@ -327,6 +324,8 @@ gfx::Tween::ColorValueBetween(progress, original_shadow.color(), target_shadow.color()))); } + if (is_fullscreen_app_list_enabled_) + search_box->UpdateBackground(progress, current_state, target_state); search_box->GetWidget()->SetBounds( search_box->GetViewBoundsForSearchBoxContentsBounds( ConvertRectToWidget(search_box_rect)));
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc index 8d5bf841..b335bf7 100644 --- a/ui/app_list/views/search_box_view.cc +++ b/ui/app_list/views/search_box_view.cc
@@ -13,7 +13,6 @@ #include "third_party/skia/include/core/SkPath.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" -#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_switches.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/app_list/resources/grit/app_list_resources.h" @@ -53,22 +52,14 @@ constexpr int kInnerPadding = 24; constexpr int kPreferredWidth = 360; constexpr int kPreferredWidthFullscreen = 544; -constexpr int kPreferredHeight = 48; constexpr SkColor kHintTextColor = SkColorSetARGBMacro(0xFF, 0xA0, 0xA0, 0xA0); -constexpr int kBackgroundBorderCornerRadius = 2; -constexpr int kBackgroundBorderCornerRadiusFullscreen = 24; -constexpr int kBackgroundBorderCornerRadiusSearchResult = 4; -constexpr int kGoogleIconSize = 24; +constexpr int kSearchBoxBorderCornerRadius = 2; +constexpr int kSearchBoxBorderCornerRadiusSearchResult = 4; constexpr int kMicIconSize = 24; constexpr int kCloseIconSize = 24; -// Default color used when wallpaper customized color is not available for -// searchbox, #000 at 87% opacity. -constexpr SkColor kDefaultSearchboxColor = - SkColorSetARGBMacro(0xDE, 0x00, 0x00, 0x00); - constexpr int kLightVibrantBlendAlpha = 0xB3; // Color of placeholder text in zero query state. @@ -78,45 +69,29 @@ // A background that paints a solid white rounded rect with a thin grey border. class SearchBoxBackground : public views::Background { public: - explicit SearchBoxBackground(SkColor color) : color_(color) { - const int corner_radius = features::IsFullscreenAppListEnabled() - ? kBackgroundBorderCornerRadiusFullscreen - : kBackgroundBorderCornerRadius; - SetCornerRadius(corner_radius, corner_radius, corner_radius, corner_radius); - } + explicit SearchBoxBackground( + SkColor color, + int corner_radius = features::IsFullscreenAppListEnabled() + ? kSearchBoxBorderCornerRadiusFullscreen + : kSearchBoxBorderCornerRadius) + : corner_radius_(corner_radius), color_(color) {} ~SearchBoxBackground() override {} - void SetCornerRadius(int top_left, - int top_right, - int bottom_right, - int bottom_left) { - DCHECK(top_left >= 0 && top_right >= 0 && bottom_right >= 0 && - bottom_left >= 0); - corner_radius_[0] = top_left; - corner_radius_[1] = top_right; - corner_radius_[2] = bottom_right; - corner_radius_[3] = bottom_left; - } + void set_corner_radius(int corner_radius) { corner_radius_ = corner_radius; } + void set_color(SkColor color) { color_ = color; } private: // views::Background overrides: void Paint(gfx::Canvas* canvas, views::View* view) const override { gfx::Rect bounds = view->GetContentsBounds(); - const SkScalar kRadius[8] = { - SkIntToScalar(corner_radius_[0]), SkIntToScalar(corner_radius_[0]), - SkIntToScalar(corner_radius_[1]), SkIntToScalar(corner_radius_[1]), - SkIntToScalar(corner_radius_[2]), SkIntToScalar(corner_radius_[2]), - SkIntToScalar(corner_radius_[3]), SkIntToScalar(corner_radius_[3])}; - SkPath path; - path.addRoundRect(gfx::RectToSkRect(bounds), kRadius); cc::PaintFlags flags; flags.setAntiAlias(true); flags.setColor(color_); - canvas->DrawPath(path, flags); + canvas->DrawRoundRect(bounds, corner_radius_, flags); } - int corner_radius_[4]; + int corner_radius_; SkColor color_; DISALLOW_COPY_AND_ASSIGN(SearchBoxBackground); @@ -181,7 +156,7 @@ SetPreferredSize(gfx::Size(is_fullscreen_app_list_enabled_ ? kPreferredWidthFullscreen : kPreferredWidth, - kPreferredHeight)); + kSearchBoxPreferredHeight)); AddChildView(content_container_); SetShadow(GetShadowForZHeight(2)); @@ -194,7 +169,7 @@ content_container_->SetLayoutManager(layout); layout->set_cross_axis_alignment( views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); - layout->set_minimum_cross_axis_size(kPreferredHeight); + layout->set_minimum_cross_axis_size(kSearchBoxPreferredHeight); search_box_->SetBorder(views::NullBorder()); search_box_->SetTextColor(kSearchTextColor); @@ -212,11 +187,10 @@ content_container_->AddChildView(back_button_); if (is_fullscreen_app_list_enabled_) { - google_icon_ = new views::ImageView(); - google_icon_->SetImage(gfx::CreateVectorIcon( - kIcGoogleBlackIcon, kGoogleIconSize, kDefaultSearchboxColor)); - content_container_->AddChildView(google_icon_); - + search_icon_ = new views::ImageView(); + UpdateSearchIcon(view_delegate_->GetModel()->search_engine_is_google(), + kDefaultSearchboxColor); + content_container_->AddChildView(search_icon_); search_box_->set_placeholder_text_color(kDefaultSearchboxColor); search_box_->set_placeholder_text_draw_flags( gfx::Canvas::TEXT_ALIGN_CENTER); @@ -253,6 +227,8 @@ model_ = view_delegate_->GetModel(); DCHECK(model_); + if (is_fullscreen_app_list_enabled_) + UpdateSearchIcon(model_->search_engine_is_google(), kDefaultSearchboxColor); model_->search_box()->AddObserver(this); SpeechRecognitionButtonPropChanged(); HintTextChanged(); @@ -399,7 +375,7 @@ if (!is_fullscreen_app_list_enabled_) return; - google_icon_->SetVisible(!show_back_button); + search_icon_->SetVisible(!show_back_button); back_button_->SetVisible(show_back_button); content_container_->Layout(); } @@ -484,19 +460,47 @@ HandleSearchBoxEvent(event); } -void SearchBoxView::UpdateBackground(bool search_results_state) { - if (!search_results_state) { - WallpaperProminentColorsChanged(); - return; - } +int SearchBoxView::GetSearchBoxBorderCornerRadiusForState( + AppListModel::State state) { + if (state == AppListModel::STATE_SEARCH_RESULTS) + return kSearchBoxBorderCornerRadiusSearchResult; + return kSearchBoxBorderCornerRadiusFullscreen; +} +SkColor SearchBoxView::GetSearchBoxColorForState( + AppListModel::State state) const { + if (state == AppListModel::STATE_SEARCH_RESULTS) + return kSearchBoxBackgroundDefault; + + // Uses wallpaper prominent color for other states. + const std::vector<SkColor> prominent_colors = + model_->search_box()->wallpaper_prominent_colors(); + if (prominent_colors.empty()) + return kSearchBoxBackgroundDefault; + + DCHECK_EQ(static_cast<size_t>(ColorProfileType::NUM_OF_COLOR_PROFILES), + prominent_colors.size()); + const SkColor light_vibrant = + prominent_colors[static_cast<int>(ColorProfileType::LIGHT_VIBRANT)]; + const SkColor light_vibrant_mixed = color_utils::AlphaBlend( + SK_ColorWHITE, light_vibrant, kLightVibrantBlendAlpha); + return SK_ColorTRANSPARENT == light_vibrant ? kSearchBoxBackgroundDefault + : light_vibrant_mixed; +} + +void SearchBoxView::UpdateBackground(double progress, + AppListModel::State current_state, + AppListModel::State target_state) { SearchBoxBackground* background = - new SearchBoxBackground(kSearchBoxBackgroundDefault); - background->SetCornerRadius(kBackgroundBorderCornerRadiusSearchResult, - kBackgroundBorderCornerRadiusSearchResult, 0, 0); - content_container_->SetBackground( - base::WrapUnique<SearchBoxBackground>(background)); - search_box_->SetBackgroundColor(kSearchBoxBackgroundDefault); + static_cast<SearchBoxBackground*>(content_container_->background()); + background->set_corner_radius(gfx::Tween::LinearIntValueBetween( + progress, GetSearchBoxBorderCornerRadiusForState(current_state), + GetSearchBoxBorderCornerRadiusForState(target_state))); + const SkColor color = gfx::Tween::ColorValueBetween( + progress, GetSearchBoxColorForState(current_state), + GetSearchBoxColorForState(target_state)); + background->set_color(color); + search_box_->SetBackgroundColor(color); } void SearchBoxView::UpdateModel() { @@ -675,35 +679,27 @@ prominent_colors.size()); const SkColor dark_muted = prominent_colors[static_cast<int>(ColorProfileType::DARK_MUTED)]; - const bool dark_muted_available = SK_ColorTRANSPARENT != dark_muted; - google_icon_->SetImage(gfx::CreateVectorIcon( - kIcGoogleBlackIcon, kGoogleIconSize, - dark_muted_available ? dark_muted : kDefaultSearchboxColor)); + const SkColor search_box_color = + SK_ColorTRANSPARENT == dark_muted ? kDefaultSearchboxColor : dark_muted; + UpdateSearchIcon(model_->search_engine_is_google(), search_box_color); speech_button_->SetImage( views::Button::STATE_NORMAL, - gfx::CreateVectorIcon( - kIcMicBlackIcon, kMicIconSize, - dark_muted_available ? dark_muted : kDefaultSearchboxColor)); + gfx::CreateVectorIcon(kIcMicBlackIcon, kMicIconSize, search_box_color)); close_button_->SetImage( views::Button::STATE_NORMAL, - gfx::CreateVectorIcon( - kIcCloseIcon, kCloseIconSize, - dark_muted_available ? dark_muted : kDefaultSearchboxColor)); - search_box_->set_placeholder_text_color( - dark_muted_available ? dark_muted : kDefaultSearchboxColor); - + gfx::CreateVectorIcon(kIcCloseIcon, kCloseIconSize, search_box_color)); + search_box_->set_placeholder_text_color(search_box_color); const SkColor light_vibrant = prominent_colors[static_cast<int>(ColorProfileType::LIGHT_VIBRANT)]; const SkColor light_vibrant_mixed = color_utils::AlphaBlend( SK_ColorWHITE, light_vibrant, kLightVibrantBlendAlpha); - const bool light_vibrant_available = SK_ColorTRANSPARENT != light_vibrant; - content_container_->SetBackground(base::MakeUnique<SearchBoxBackground>( - light_vibrant_available ? light_vibrant_mixed - : kSearchBoxBackgroundDefault)); - search_box_->SetBackgroundColor(light_vibrant_available - ? light_vibrant_mixed - : kSearchBoxBackgroundDefault); - + const SkColor background_color = SK_ColorTRANSPARENT == light_vibrant + ? kSearchBoxBackgroundDefault + : light_vibrant_mixed; + SearchBoxBackground* background = + static_cast<SearchBoxBackground*>(content_container_->background()); + background->set_color(background_color); + search_box_->SetBackgroundColor(background_color); SchedulePaint(); } @@ -713,4 +709,12 @@ SchedulePaint(); } +void SearchBoxView::UpdateSearchIcon(bool is_google, + const SkColor& search_box_color) { + const gfx::VectorIcon& icon = + is_google ? kIcGoogleBlackIcon : kIcSearchEngineNotGoogleIcon; + search_icon_->SetImage( + gfx::CreateVectorIcon(icon, kSearchIconSize, search_box_color)); +} + } // namespace app_list
diff --git a/ui/app_list/views/search_box_view.h b/ui/app_list/views/search_box_view.h index 63e124f2..bc553da 100644 --- a/ui/app_list/views/search_box_view.h +++ b/ui/app_list/views/search_box_view.h
@@ -8,6 +8,7 @@ #include <string> #include "base/macros.h" +#include "ui/app_list/app_list_model.h" #include "ui/app_list/search_box_model_observer.h" #include "ui/app_list/speech_ui_model_observer.h" #include "ui/gfx/shadow_value.h" @@ -32,7 +33,6 @@ FOCUS_CONTENTS_VIEW, // Something outside the SearchBox is selected }; -class AppListModel; class AppListView; class AppListViewDelegate; class SearchBoxModel; @@ -109,8 +109,19 @@ void OnGestureEvent(ui::GestureEvent* event) override; void OnMouseEvent(ui::MouseEvent* event) override; - // Updates the |content_container_|'s background corner radius. - void UpdateBackground(bool search_results_state); + // Returns background border corner radius in the given state. + static int GetSearchBoxBorderCornerRadiusForState(AppListModel::State state); + + // Returns search box color in the given state. + SkColor GetSearchBoxColorForState(AppListModel::State state) const; + + // Updates the search box's background corner radius and color. + void UpdateBackground(double progress, + AppListModel::State current_state, + AppListModel::State target_state); + + // Used only in the tests to get the current search icon. + views::ImageView* get_search_icon_for_test() { return search_icon_; } private: // Updates model text and selection model with current Textfield info. @@ -119,6 +130,9 @@ // Fires query change notification. void NotifyQueryChanged(); + // Updates the search icon. + void UpdateSearchIcon(bool is_google, const SkColor& search_box_color); + // Overridden from views::TextfieldController: void ContentsChanged(views::Textfield* sender, const base::string16& new_contents) override; @@ -149,7 +163,7 @@ // Owned by views hierarchy. views::View* content_container_; - views::ImageView* google_icon_ = nullptr; + views::ImageView* search_icon_ = nullptr; SearchBoxImageButton* back_button_ = nullptr; SearchBoxImageButton* speech_button_ = nullptr; SearchBoxImageButton* close_button_ = nullptr;
diff --git a/ui/app_list/views/search_box_view_unittest.cc b/ui/app_list/views/search_box_view_unittest.cc index 69cd479..672a5fbd 100644 --- a/ui/app_list/views/search_box_view_unittest.cc +++ b/ui/app_list/views/search_box_view_unittest.cc
@@ -10,10 +10,16 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" +#include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" #include "ui/app_list/test/app_list_test_view_delegate.h" +#include "ui/app_list/vector_icons/vector_icons.h" #include "ui/app_list/views/app_list_view.h" #include "ui/app_list/views/search_box_view_delegate.h" +#include "ui/gfx/image/image_skia.h" +#include "ui/gfx/image/image_unittest_util.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/views/controls/image_view.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/test/widget_test.h" @@ -45,6 +51,8 @@ DISALLOW_COPY_AND_ASSIGN(KeyPressCounterView); }; +// These tests run with both FullscreenAppList enabled and disabled. +// TODO(crbug.com/743113) Unify the two test classes. class SearchBoxViewTest : public views::test::WidgetTest, public SearchBoxViewDelegate, public testing::WithParamInterface<bool> { @@ -67,24 +75,26 @@ gfx::NativeView parent = GetContext(); app_list_view_ = new AppListView(&view_delegate_); - app_list_view_->Initialize(parent, 0, false, false); + app_list_view()->Initialize(parent, 0, false, false); widget_ = CreateTopLevelPlatformWidget(); - view_ = new SearchBoxView(this, &view_delegate_, app_list_view_); + view_.reset(new SearchBoxView(this, &view_delegate_, app_list_view())); counter_view_ = new KeyPressCounterView(); - widget_->GetContentsView()->AddChildView(view_); + widget_->GetContentsView()->AddChildView(view()); widget_->GetContentsView()->AddChildView(counter_view_); - view_->set_contents_view(counter_view_); + view()->set_contents_view(counter_view_); } void TearDown() override { + view_.reset(); app_list_view_->GetWidget()->Close(); widget_->CloseNow(); views::test::WidgetTest::TearDown(); } protected: - SearchBoxView* view() { return view_; } + SearchBoxView* view() { return view_.get(); } + AppListView* app_list_view() { return app_list_view_; } bool test_with_fullscreen() { return test_with_fullscreen_; } @@ -107,11 +117,11 @@ void KeyPress(ui::KeyboardCode key_code) { ui::KeyEvent event(ui::ET_KEY_PRESSED, key_code, ui::EF_NONE); - view_->search_box()->OnKeyEvent(&event); + view()->search_box()->OnKeyEvent(&event); // Emulates the input method. if (::isalnum(static_cast<int>(key_code))) { base::char16 character = ::tolower(static_cast<int>(key_code)); - view_->search_box()->InsertText(base::string16(1, character)); + view()->search_box()->InsertText(base::string16(1, character)); } } @@ -140,8 +150,8 @@ AppListTestViewDelegate view_delegate_; views::Widget* widget_; - SearchBoxView* view_; AppListView* app_list_view_ = nullptr; + std::unique_ptr<SearchBoxView> view_; KeyPressCounterView* counter_view_; base::string16 last_query_; int query_changed_count_ = 0; @@ -151,6 +161,71 @@ DISALLOW_COPY_AND_ASSIGN(SearchBoxViewTest); }; +class SearchBoxViewFullscreenTest : public views::test::WidgetTest, + public SearchBoxViewDelegate { + public: + SearchBoxViewFullscreenTest() {} + ~SearchBoxViewFullscreenTest() override {} + + // Overridden from testing::Test: + void SetUp() override { + views::test::WidgetTest::SetUp(); + scoped_feature_list_.InitAndEnableFeature( + app_list::features::kEnableFullscreenAppList); + + gfx::NativeView parent = GetContext(); + app_list_view_ = new AppListView(&view_delegate_); + app_list_view_->Initialize(parent, 0, false, false); + + widget_ = CreateTopLevelPlatformWidget(); + view_.reset(new SearchBoxView(this, &view_delegate_, app_list_view())); + widget_->SetBounds(gfx::Rect(0, 0, 300, 200)); + widget_->GetContentsView()->AddChildView(view()); + } + + void TearDown() override { + view_.reset(); + app_list_view_->GetWidget()->Close(); + widget_->CloseNow(); + views::test::WidgetTest::TearDown(); + } + + protected: + SearchBoxView* view() { return view_.get(); } + AppListView* app_list_view() { return app_list_view_; } + + void SetSearchEngineIsGoogle(bool is_google) { + view_delegate_.SetSearchEngineIsGoogle(is_google); + } + + void KeyPress(ui::KeyboardCode key_code) { + ui::KeyEvent event(ui::ET_KEY_PRESSED, key_code, ui::EF_NONE); + view()->search_box()->OnKeyEvent(&event); + // Emulates the input method. + if (::isalnum(static_cast<int>(key_code))) { + base::char16 character = ::tolower(static_cast<int>(key_code)); + view()->search_box()->InsertText(base::string16(1, character)); + } + } + + private: + // Overridden from SearchBoxViewDelegate: + void QueryChanged(SearchBoxView* sender) override {} + + void BackButtonPressed() override {} + + void SetSearchResultSelection(bool select) override {} + + base::test::ScopedFeatureList scoped_feature_list_; + + AppListTestViewDelegate view_delegate_; + views::Widget* widget_; + AppListView* app_list_view_ = nullptr; + std::unique_ptr<SearchBoxView> view_; + + DISALLOW_COPY_AND_ASSIGN(SearchBoxViewFullscreenTest); +}; + // Instantiate the Boolean which is used to toggle the Fullscreen app list in // the parameterized tests. INSTANTIATE_TEST_CASE_P(, SearchBoxViewTest, testing::Bool()); @@ -192,10 +267,7 @@ EXPECT_EQ(base::TimeDelta(), GetAutoLaunchTimeout()); } -TEST_P(SearchBoxViewTest, CloseButtonTest) { - if (!test_with_fullscreen()) - return; - +TEST_F(SearchBoxViewFullscreenTest, CloseButtonTest) { KeyPress(ui::VKEY_A); EXPECT_TRUE(view()->IsCloseButtonVisible()); @@ -203,5 +275,29 @@ EXPECT_FALSE(view()->IsCloseButtonVisible()); } +TEST_F(SearchBoxViewFullscreenTest, SearchEngineGoogle) { + SetSearchEngineIsGoogle(true); + gfx::ImageSkia expected_icon = gfx::CreateVectorIcon( + kIcGoogleBlackIcon, kSearchIconSize, kDefaultSearchboxColor); + view()->ModelChanged(); + + gfx::ImageSkia actual_icon = view()->get_search_icon_for_test()->GetImage(); + + EXPECT_TRUE(gfx::test::AreBitmapsEqual(*expected_icon.bitmap(), + *actual_icon.bitmap())); +} + +TEST_F(SearchBoxViewFullscreenTest, SearchEngineNotGoogle) { + SetSearchEngineIsGoogle(false); + gfx::ImageSkia expected_icon = gfx::CreateVectorIcon( + kIcSearchEngineNotGoogleIcon, kSearchIconSize, kDefaultSearchboxColor); + view()->ModelChanged(); + + gfx::ImageSkia actual_icon = view()->get_search_icon_for_test()->GetImage(); + + EXPECT_TRUE(gfx::test::AreBitmapsEqual(*expected_icon.bitmap(), + *actual_icon.bitmap())); +} + } // namespace test } // namespace app_list
diff --git a/ui/app_list/views/search_result_page_view.cc b/ui/app_list/views/search_result_page_view.cc index 7388968d..92162c4d 100644 --- a/ui/app_list/views/search_result_page_view.cc +++ b/ui/app_list/views/search_result_page_view.cc
@@ -13,6 +13,7 @@ #include "ui/app_list/app_list_features.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/app_list/views/app_list_main_view.h" +#include "ui/app_list/views/contents_view.h" #include "ui/app_list/views/search_box_view.h" #include "ui/app_list/views/search_result_list_view.h" #include "ui/app_list/views/search_result_tile_item_list_view.h" @@ -37,11 +38,10 @@ // The z-height of the search box and cards in this view. constexpr int kSearchResultZHeight = 1; -constexpr int kBackgroundCornerRadius = 4; +// The horizontal padding of the separator. constexpr int kSeparatorPadding = 12; constexpr int kSeparatorThickness = 1; -constexpr SkColor kBackgroundColor = SK_ColorWHITE; constexpr SkColor kSeparatorColor = SkColorSetARGBMacro(0x1F, 0x00, 0x00, 0x00); // A container view that ensures the card background and the shadow are painted @@ -52,10 +52,10 @@ if (!features::IsFullscreenAppListEnabled()) { SetBorder(base::MakeUnique<views::ShadowBorder>( GetShadowForZHeight(kSearchResultZHeight))); + content_view->SetBackground( + views::CreateSolidBackground(kCardBackgroundColor)); } SetLayoutManager(new views::FillLayout()); - content_view->SetBackground( - views::CreateSolidBackground(kCardBackgroundColor)); AddChildView(content_view); } @@ -78,34 +78,28 @@ class SearchResultPageBackground : public views::Background { public: - SearchResultPageBackground() {} + SearchResultPageBackground(SkColor color, int corner_radius) + : color_(color), corner_radius_(corner_radius) {} ~SearchResultPageBackground() override {} private: // views::Background overrides: void Paint(gfx::Canvas* canvas, views::View* view) const override { gfx::Rect bounds = view->GetContentsBounds(); - const SkScalar kCornerRadiusScalar = SkIntToScalar(kBackgroundCornerRadius); - const SkScalar kRadius[8] = {0, - 0, - 0, - 0, - kCornerRadiusScalar, - kCornerRadiusScalar, - kCornerRadiusScalar, - kCornerRadiusScalar}; - SkPath path; - path.addRoundRect(gfx::RectToSkRect(bounds), kRadius); cc::PaintFlags flags; flags.setAntiAlias(true); - flags.setColor(kBackgroundColor); - canvas->DrawPath(path, flags); + flags.setColor(color_); + canvas->DrawRoundRect(bounds, corner_radius_, flags); // Draws a separator between SearchBoxView and SearchResultPageView. + bounds.set_y(kSearchBoxPreferredHeight); bounds.set_height(kSeparatorThickness); canvas->FillRect(bounds, kSeparatorColor); } + const SkColor color_; + const int corner_radius_; + DISALLOW_COPY_AND_ASSIGN(SearchResultPageBackground); }; @@ -147,7 +141,11 @@ if (is_fullscreen_app_list_enabled_) { contents_view_->SetLayoutManager( new views::BoxLayout(views::BoxLayout::kVertical, gfx::Insets(), 0)); - SetBackground(base::MakeUnique<SearchResultPageBackground>()); + + // Hides this view behind the search box by using the same color and + // background border corner radius. + SetBackground(base::MakeUnique<SearchResultPageBackground>( + kSearchBoxBackgroundDefault, kSearchBoxBorderCornerRadiusFullscreen)); } else { gfx::ShadowValue shadow = GetShadowForZHeight(kSearchResultZHeight); std::unique_ptr<views::Border> border(new views::ShadowBorder(shadow)); @@ -164,8 +162,9 @@ views::ScrollView* const scroller = new views::ScrollView; if (is_fullscreen_app_list_enabled_) { - scroller->SetBorder( - views::CreateEmptyBorder(gfx::Insets(kSeparatorThickness, 0, 0, 0))); + // Leaves a placeholder area for the search box and the separator below it. + scroller->SetBorder(views::CreateEmptyBorder( + gfx::Insets(kSearchBoxPreferredHeight + kSeparatorThickness, 0, 0, 0))); } scroller->SetContents(contents_view_); // Setting clip height is necessary to make ScrollView take into account its @@ -348,20 +347,22 @@ gfx::Rect SearchResultPageView::GetPageBoundsForState( AppListModel::State state) const { - gfx::Rect onscreen_bounds = GetDefaultContentsBounds(); - - if (is_fullscreen_app_list_enabled_) { - gfx::Rect search_box_bounds = GetSearchBoxBounds(); - onscreen_bounds.set_y(search_box_bounds.bottom()); - onscreen_bounds.set_height(kFullscreenHeight - search_box_bounds.height()); + if (!is_fullscreen_app_list_enabled_) { + return (state == AppListModel::STATE_SEARCH_RESULTS + ? GetDefaultContentsBounds() + : GetAboveContentsOffscreenBounds( + GetDefaultContentsBounds().size())); } - switch (state) { - case AppListModel::STATE_SEARCH_RESULTS: - return onscreen_bounds; - default: - return GetAboveContentsOffscreenBounds(onscreen_bounds.size()); + if (state != AppListModel::STATE_SEARCH_RESULTS) { + // Hides this view behind the search box by using the same bounds. + return AppListPage::GetSearchBoxBounds(); } + + gfx::Rect onscreen_bounds(GetDefaultContentsBounds()); + onscreen_bounds.set_y(AppListPage::GetSearchBoxBounds().y()); + onscreen_bounds.set_height(kFullscreenHeight); + return onscreen_bounds; } void SearchResultPageView::OnAnimationUpdated(double progress, @@ -372,6 +373,23 @@ return; } + if (is_fullscreen_app_list_enabled_) { + const SearchBoxView* search_box = + AppListPage::contents_view()->GetSearchBoxView(); + const SkColor color = gfx::Tween::ColorValueBetween( + progress, search_box->GetSearchBoxColorForState(from_state), + search_box->GetSearchBoxColorForState(to_state)); + + // Grows this view in the same pace as the search box to make them look + // like a single view. + SetBackground(base::MakeUnique<SearchResultPageBackground>( + color, + gfx::Tween::LinearIntValueBetween( + progress, + SearchBoxView::GetSearchBoxBorderCornerRadiusForState(from_state), + SearchBoxView::GetSearchBoxBorderCornerRadiusForState(to_state)))); + } + gfx::Rect onscreen_bounds( GetPageBoundsForState(AppListModel::STATE_SEARCH_RESULTS)); onscreen_bounds -= bounds().OffsetFromOrigin(); @@ -391,8 +409,9 @@ gfx::Rect SearchResultPageView::GetSearchBoxBounds() const { gfx::Rect rect(AppListPage::GetSearchBoxBounds()); if (is_fullscreen_app_list_enabled_) { - rect.set_x(bounds().x()); - rect.set_width(bounds().width()); + gfx::Rect contents_bounds(GetDefaultContentsBounds()); + rect.set_x(contents_bounds.x()); + rect.set_width(contents_bounds.width()); } return rect; }
diff --git a/ui/app_list/views/search_result_view.cc b/ui/app_list/views/search_result_view.cc index 67c16872..71aaec5b 100644 --- a/ui/app_list/views/search_result_view.cc +++ b/ui/app_list/views/search_result_view.cc
@@ -255,7 +255,8 @@ const bool selected = list_view_->IsResultViewSelected(this); const bool hover = state() == STATE_HOVERED || state() == STATE_PRESSED; - canvas->FillRect(content_rect, kCardBackgroundColor); + if (!is_fullscreen_app_list_enabled_) + canvas->FillRect(content_rect, kCardBackgroundColor); // Possibly call FillRect a second time (these colours are partially // transparent, so the previous FillRect is not redundant).
diff --git a/ui/aura/mus/window_manager_delegate.h b/ui/aura/mus/window_manager_delegate.h index fca8b6c..09bb4e1f4 100644 --- a/ui/aura/mus/window_manager_delegate.h +++ b/ui/aura/mus/window_manager_delegate.h
@@ -103,6 +103,14 @@ std::vector<ui::mojom::WmViewportMetricsPtr> viewport_metrics, int64_t primary_display_id) = 0; + // Adds |display| as a new display moving |window_tree_host| to the new + // display. This results in closing the previous display |window_tree_host| + // was associated with. + virtual void AddDisplayReusingWindowTreeHost( + WindowTreeHostMus* window_tree_host, + const display::Display& display, + ui::mojom::WmViewportMetricsPtr viewport_metrics) = 0; + protected: virtual ~WindowManagerClient() {} };
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc index f5ee045..4b3ad83 100644 --- a/ui/aura/mus/window_tree_client.cc +++ b/ui/aura/mus/window_tree_client.cc
@@ -1917,6 +1917,25 @@ } } +void WindowTreeClient::AddDisplayReusingWindowTreeHost( + WindowTreeHostMus* window_tree_host, + const display::Display& display, + ui::mojom::WmViewportMetricsPtr viewport_metrics) { + DCHECK_NE(display.id(), window_tree_host->display_id()); + window_tree_host->set_display_id(display.id()); + if (window_manager_client_) { + // NOTE: The value of |is_primary_display| doesn't really matter as shortly + // after this SetDisplayConfiguration() is called. + const bool is_primary_display = true; + WindowMus* display_root_window = WindowMus::Get(window_tree_host->window()); + window_manager_client_->SetDisplayRoot( + display, std::move(viewport_metrics), is_primary_display, + display_root_window->server_id(), + base::Bind(&WindowTreeClient::OnSetDisplayRootDone, + base::Unretained(this), display_root_window->server_id())); + } +} + void WindowTreeClient::OnWindowTreeHostBoundsWillChange( WindowTreeHostMus* window_tree_host, const gfx::Rect& bounds) {
diff --git a/ui/aura/mus/window_tree_client.h b/ui/aura/mus/window_tree_client.h index b8a61205..97261c37 100644 --- a/ui/aura/mus/window_tree_client.h +++ b/ui/aura/mus/window_tree_client.h
@@ -496,6 +496,10 @@ const std::vector<display::Display>& displays, std::vector<ui::mojom::WmViewportMetricsPtr> viewport_metrics, int64_t primary_display_id) override; + void AddDisplayReusingWindowTreeHost( + WindowTreeHostMus* window_tree_host, + const display::Display& display, + ui::mojom::WmViewportMetricsPtr viewport_metrics) override; // Overriden from WindowTreeHostMusDelegate: void OnWindowTreeHostBoundsWillChange(WindowTreeHostMus* window_tree_host,
diff --git a/ui/display/display_observer.cc b/ui/display/display_observer.cc index b25f1fa8..276c9ab 100644 --- a/ui/display/display_observer.cc +++ b/ui/display/display_observer.cc
@@ -8,6 +8,10 @@ DisplayObserver::~DisplayObserver() {} +void DisplayObserver::OnWillProcessDisplayChanges() {} + +void DisplayObserver::OnDidProcessDisplayChanges() {} + void DisplayObserver::OnDisplayAdded(const Display& new_display) {} void DisplayObserver::OnDisplayRemoved(const Display& old_display) {}
diff --git a/ui/display/display_observer.h b/ui/display/display_observer.h index 3398b50..568852d 100644 --- a/ui/display/display_observer.h +++ b/ui/display/display_observer.h
@@ -28,6 +28,14 @@ DISPLAY_METRIC_COLOR_SPACE = 1 << 6, }; + // This may be called before other methods to signal changes are about to + // happen. Not all classes that support DisplayObserver call this. + virtual void OnWillProcessDisplayChanges(); + + // Called after OnWillProcessDisplayChanges() to indicate display changes have + // completed. Not all classes that support DisplayObserver call this. + virtual void OnDidProcessDisplayChanges(); + // Called when |new_display| has been added. virtual void OnDisplayAdded(const Display& new_display);
diff --git a/ui/display/manager/display_manager.cc b/ui/display/manager/display_manager.cc index f8be65d0..e5e3951 100644 --- a/ui/display/manager/display_manager.cc +++ b/ui/display/manager/display_manager.cc
@@ -140,6 +140,22 @@ using std::string; using std::vector; +DisplayManager::BeginEndNotifier::BeginEndNotifier( + DisplayManager* display_manager) + : display_manager_(display_manager) { + if (display_manager_->notify_depth_++ == 0) { + for (auto& observer : display_manager_->observers_) + observer.OnWillProcessDisplayChanges(); + } +} + +DisplayManager::BeginEndNotifier::~BeginEndNotifier() { + if (--display_manager_->notify_depth_ == 0) { + for (auto& observer : display_manager_->observers_) + observer.OnDidProcessDisplayChanges(); + } +} + // static int64_t DisplayManager::kUnifiedDisplayId = -10; @@ -246,6 +262,8 @@ std::unique_ptr<DisplayLayout> layout) { if (GetNumDisplays() == 1) return; + BeginEndNotifier notifier(this); + const DisplayIdList list = GetCurrentDisplayIdList(); DCHECK(DisplayLayout::Validate(list, *layout)); @@ -294,14 +312,14 @@ bool DisplayManager::UpdateWorkAreaOfDisplay(int64_t display_id, const gfx::Insets& insets) { + BeginEndNotifier notifier(this); Display* display = FindDisplayForId(display_id); DCHECK(display); gfx::Rect old_work_area = display->work_area(); display->UpdateWorkAreaFromInsets(insets); bool workarea_changed = old_work_area != display->work_area(); - if (workarea_changed) { + if (workarea_changed) NotifyMetricsChanged(*display, DisplayObserver::DISPLAY_METRIC_WORK_AREA); - } return workarea_changed; } @@ -680,6 +698,8 @@ void DisplayManager::UpdateDisplaysWith( const DisplayInfoList& updated_display_info_list) { + BeginEndNotifier notifier(this); + #if defined(OS_WIN) DCHECK_EQ(1u, updated_display_info_list.size()) << ": Multiple display test does not work on Windows bots. Please " @@ -1130,6 +1150,7 @@ Display* display = FindDisplayForId(display_id); DCHECK(display); display->SetSize(display_info_[display_id].size_in_pixel()); + BeginEndNotifier notifier(this); NotifyMetricsChanged(*display, DisplayObserver::DISPLAY_METRIC_BOUNDS); return true; }
diff --git a/ui/display/manager/display_manager.h b/ui/display/manager/display_manager.h index 8c28cbf..71d3cc6 100644 --- a/ui/display/manager/display_manager.h +++ b/ui/display/manager/display_manager.h
@@ -377,6 +377,18 @@ private: friend class test::DisplayManagerTestApi; + // See description above |notify_depth_| for details. + class BeginEndNotifier { + public: + explicit BeginEndNotifier(DisplayManager* display_manager); + ~BeginEndNotifier(); + + private: + DisplayManager* display_manager_; + + DISALLOW_COPY_AND_ASSIGN(BeginEndNotifier); + }; + bool software_mirroring_enabled() const { return multi_display_mode_ == MIRRORING; } @@ -500,6 +512,11 @@ base::ObserverList<DisplayObserver> observers_; + // This is incremented whenever a BeginEndNotifier is created and decremented + // when destroyed. BeginEndNotifier uses this to track when it should call + // OnWillProcessDisplayChanges() and OnDidProcessDisplayChanges(). + int notify_depth_ = 0; + base::WeakPtrFactory<DisplayManager> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(DisplayManager);
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn index 278bd5f..e369ae8 100644 --- a/ui/gfx/BUILD.gn +++ b/ui/gfx/BUILD.gn
@@ -578,6 +578,8 @@ static_library("test_support") { testonly = true sources = [ + "animation/animation_test_api.cc", + "animation/animation_test_api.h", "animation/test_animation_delegate.h", "geometry/test/rect_test_util.cc", "geometry/test/rect_test_util.h",
diff --git a/ui/gfx/animation/animation.h b/ui/gfx/animation/animation.h index e26bb21..bc5e6461 100644 --- a/ui/gfx/animation/animation.h +++ b/ui/gfx/animation/animation.h
@@ -19,6 +19,7 @@ class AnimationContainer; class AnimationDelegate; +class AnimationTestApi; // Base class used in implementing animations. You only need use this class if // you're implementing a new animation type, otherwise you'll likely want one of @@ -92,6 +93,8 @@ base::TimeDelta GetTimerInterval() const override; private: + friend class AnimationTestApi; + // Interval for the animation. const base::TimeDelta timer_interval_;
diff --git a/ui/gfx/animation/animation_test_api.cc b/ui/gfx/animation/animation_test_api.cc new file mode 100644 index 0000000..e2d093f --- /dev/null +++ b/ui/gfx/animation/animation_test_api.cc
@@ -0,0 +1,25 @@ +// 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 "ui/gfx/animation/animation_test_api.h" + +#include "base/time/time.h" +#include "ui/gfx/animation/animation.h" + +namespace gfx { + +AnimationTestApi::AnimationTestApi(Animation* animation) + : animation_(animation) {} + +AnimationTestApi::~AnimationTestApi() {} + +void AnimationTestApi::SetStartTime(base::TimeTicks ticks) { + animation_->SetStartTime(ticks); +} + +void AnimationTestApi::Step(base::TimeTicks ticks) { + animation_->Step(ticks); +} + +} // namespace gfx
diff --git a/ui/gfx/animation/animation_test_api.h b/ui/gfx/animation/animation_test_api.h new file mode 100644 index 0000000..04e8a67a --- /dev/null +++ b/ui/gfx/animation/animation_test_api.h
@@ -0,0 +1,33 @@ +// 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 UI_GFX_ANIMATION_ANIMATION_TEST_API_H_ +#define UI_GFX_ANIMATION_ANIMATION_TEST_API_H_ + +#include "base/macros.h" +#include "ui/gfx/animation/animation.h" + +namespace gfx { + +// Class to provide access to Animation internals for testing. +class AnimationTestApi { + public: + explicit AnimationTestApi(Animation* animation); + ~AnimationTestApi(); + + // Sets the start of the animation. + void SetStartTime(base::TimeTicks ticks); + + // Manually steps the animation forward + void Step(base::TimeTicks ticks); + + private: + Animation* animation_; + + DISALLOW_COPY_AND_ASSIGN(AnimationTestApi); +}; + +} // namespace gfx + +#endif // UI_GFX_ANIMATION_ANIMATION_TEST_API_H_
diff --git a/ui/gfx/animation/slide_animation_unittest.cc b/ui/gfx/animation/slide_animation_unittest.cc index 5de1700..2516ec09 100644 --- a/ui/gfx/animation/slide_animation_unittest.cc +++ b/ui/gfx/animation/slide_animation_unittest.cc
@@ -10,32 +10,14 @@ #include "base/test/scoped_task_environment.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/animation/animation_test_api.h" #include "ui/gfx/animation/test_animation_delegate.h" namespace gfx { -// Class to provide access to SlideAnimation internals for testing. -class SlideAnimation::TestApi { - public: - explicit TestApi(SlideAnimation* animation) : animation_(animation) {} - - void SetStartTime(base::TimeTicks ticks) { - animation_->SetStartTime(ticks); - } - - void Step(base::TimeTicks ticks) { - animation_->Step(ticks); - } - - private: - SlideAnimation* animation_; - - DISALLOW_COPY_AND_ASSIGN(TestApi); -}; - //////////////////////////////////////////////////////////////////////////////// // SlideAnimationTest -class SlideAnimationTest: public testing::Test { +class SlideAnimationTest : public testing::Test { protected: SlideAnimationTest() : scoped_task_environment_( @@ -62,7 +44,7 @@ TEST_F(SlideAnimationTest, Basics) { SlideAnimation animation(nullptr); - SlideAnimation::TestApi test_api(&animation); + AnimationTestApi test_api(&animation); // Use linear tweening to make the math easier below. animation.SetTweenType(Tween::LINEAR);
diff --git a/ui/gfx/geometry/point.h b/ui/gfx/geometry/point.h index bb248d543..b1ba5065 100644 --- a/ui/gfx/geometry/point.h +++ b/ui/gfx/geometry/point.h
@@ -9,7 +9,7 @@ #include <string> #include <tuple> -#include "base/numerics/saturated_arithmetic.h" +#include "base/numerics/clamped_math.h" #include "build/build_config.h" #include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/gfx_export.h" @@ -56,18 +56,18 @@ } void Offset(int delta_x, int delta_y) { - x_ = base::SaturatedAddition(x_, delta_x); - y_ = base::SaturatedAddition(y_, delta_y); + x_ = base::ClampAdd(x_, delta_x); + y_ = base::ClampAdd(y_, delta_y); } void operator+=(const Vector2d& vector) { - x_ = base::SaturatedAddition(x_, vector.x()); - y_ = base::SaturatedAddition(y_, vector.y()); + x_ = base::ClampAdd(x_, vector.x()); + y_ = base::ClampAdd(y_, vector.y()); } void operator-=(const Vector2d& vector) { - x_ = base::SaturatedSubtraction(x_, vector.x()); - y_ = base::SaturatedSubtraction(y_, vector.y()); + x_ = base::ClampSub(x_, vector.x()); + y_ = base::ClampSub(y_, vector.y()); } void SetToMin(const Point& other); @@ -116,8 +116,8 @@ } inline Vector2d operator-(const Point& lhs, const Point& rhs) { - return Vector2d(base::SaturatedSubtraction(lhs.x(), rhs.x()), - base::SaturatedSubtraction(lhs.y(), rhs.y())); + return Vector2d(base::ClampSub(lhs.x(), rhs.x()), + base::ClampSub(lhs.y(), rhs.y())); } inline Point PointAtOffsetFromOrigin(const Vector2d& offset_from_origin) {
diff --git a/ui/gfx/geometry/rect.cc b/ui/gfx/geometry/rect.cc index b5ceda5..a1735d0 100644 --- a/ui/gfx/geometry/rect.cc +++ b/ui/gfx/geometry/rect.cc
@@ -15,7 +15,7 @@ #endif #include "base/logging.h" -#include "base/numerics/saturated_arithmetic.h" +#include "base/numerics/clamped_math.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "ui/gfx/geometry/insets.h" @@ -69,8 +69,8 @@ return; } - int effective_span = base::SaturatedSubtraction(max, min); - int span_loss = base::SaturatedSubtraction(max, min + effective_span); + int effective_span = base::ClampSub(max, min); + int span_loss = base::ClampSub(max, base::ClampAdd(min, effective_span)); // If the desired width is within the limits of ints, we can just // use the simple computations to represent the range precisely. @@ -83,12 +83,13 @@ // Now we have to approximate. If one of min or max is close enough // to zero we choose to represent that one precisely. The other side is // probably practically "infinite", so we move it. - if (base::SaturatedAbsolute(max) < std::numeric_limits<int>::max() / 2) { + if (base::SafeUnsignedAbs(max) < + base::as_unsigned(std::numeric_limits<int>::max() / 2)) { // Maintain origin + span == max. *span = effective_span; *origin = max - effective_span; - } else if (base::SaturatedAbsolute(min) < - std::numeric_limits<int>::max() / 2) { + } else if (base::SafeUnsignedAbs(min) < + base::as_unsigned(std::numeric_limits<int>::max() / 2)) { // Maintain origin == min. *span = effective_span; *origin = min; @@ -116,10 +117,8 @@ origin_ += Vector2d(left, top); // left+right might overflow/underflow, but width() - (left+right) might // overflow as well. - set_width(base::SaturatedSubtraction(width(), - base::SaturatedAddition(left, right))); - set_height(base::SaturatedSubtraction(height(), - base::SaturatedAddition(top, bottom))); + set_width(base::ClampSub(width(), base::ClampAdd(left, right))); + set_height(base::ClampSub(height(), base::ClampAdd(top, bottom))); } void Rect::Offset(int horizontal, int vertical) {
diff --git a/ui/gfx/geometry/rect.h b/ui/gfx/geometry/rect.h index 1858d44d..4e914b8 100644 --- a/ui/gfx/geometry/rect.h +++ b/ui/gfx/geometry/rect.h
@@ -227,7 +227,7 @@ // Clamp the size to avoid integer overflow in bottom() and right(). // This returns the width given an origin and a width. - // TODO(enne): this should probably use base::SaturatedAddition, but that + // TODO(enne): this should probably use base::ClampAdd, but that // function is not a constexpr. static constexpr int GetClampedValue(int origin, int size) { return AddWouldOverflow(origin, size)
diff --git a/ui/gfx/geometry/size.cc b/ui/gfx/geometry/size.cc index 6948672..781b84d 100644 --- a/ui/gfx/geometry/size.cc +++ b/ui/gfx/geometry/size.cc
@@ -12,8 +12,8 @@ #include <ApplicationServices/ApplicationServices.h> #endif +#include "base/numerics/clamped_math.h" #include "base/numerics/safe_math.h" -#include "base/numerics/saturated_arithmetic.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "ui/gfx/geometry/safe_integer_conversions.h" @@ -58,8 +58,8 @@ } void Size::Enlarge(int grow_width, int grow_height) { - SetSize(base::SaturatedAddition(width(), grow_width), - base::SaturatedAddition(height(), grow_height)); + SetSize(base::ClampAdd(width(), grow_width), + base::ClampAdd(height(), grow_height)); } void Size::SetToMin(const Size& other) {
diff --git a/ui/gfx/geometry/vector2d.cc b/ui/gfx/geometry/vector2d.cc index 2b4875c..0ce3b20b 100644 --- a/ui/gfx/geometry/vector2d.cc +++ b/ui/gfx/geometry/vector2d.cc
@@ -6,7 +6,7 @@ #include <cmath> -#include "base/numerics/saturated_arithmetic.h" +#include "base/numerics/clamped_math.h" #include "base/strings/stringprintf.h" namespace gfx { @@ -16,13 +16,13 @@ } void Vector2d::Add(const Vector2d& other) { - x_ = base::SaturatedAddition(other.x_, x_); - y_ = base::SaturatedAddition(other.y_, y_); + x_ = base::ClampAdd(other.x_, x_); + y_ = base::ClampAdd(other.y_, y_); } void Vector2d::Subtract(const Vector2d& other) { - x_ = base::SaturatedSubtraction(x_, other.x_); - y_ = base::SaturatedSubtraction(y_, other.y_); + x_ = base::ClampSub(x_, other.x_); + y_ = base::ClampSub(y_, other.y_); } int64_t Vector2d::LengthSquared() const {
diff --git a/ui/gfx/native_pixmap.h b/ui/gfx/native_pixmap.h index 33def81..1677dc0 100644 --- a/ui/gfx/native_pixmap.h +++ b/ui/gfx/native_pixmap.h
@@ -50,17 +50,6 @@ const gfx::Rect& display_bounds, const gfx::RectF& crop_rect) = 0; - // This represents a callback function pointing to processing unit like VPP to - // do post-processing operations like scaling and color space conversion on - // |source_pixmap| and save processed result to |target_pixmap|. - typedef base::Callback<bool(const scoped_refptr<NativePixmap>& source_pixmap, - scoped_refptr<NativePixmap> target_pixmap)> - ProcessingCallback; - - // Set callback function for the pixmap used for post processing. - virtual void SetProcessingCallback( - const ProcessingCallback& processing_callback) = 0; - // Export the buffer for sharing across processes. // Any file descriptors in the exported handle are owned by the caller. virtual gfx::NativePixmapHandle ExportHandle() = 0;
diff --git a/ui/ozone/platform/cast/surface_factory_cast.cc b/ui/ozone/platform/cast/surface_factory_cast.cc index fca7ae8..6cc1392 100644 --- a/ui/ozone/platform/cast/surface_factory_cast.cc +++ b/ui/ozone/platform/cast/surface_factory_cast.cc
@@ -72,8 +72,6 @@ parent_->OnOverlayScheduled(display_bounds); return true; } - void SetProcessingCallback( - const ProcessingCallback& processing_callback) override {} gfx::NativePixmapHandle ExportHandle() override { return gfx::NativePixmapHandle(); }
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc b/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc index 60993857..c3dfd1a 100644 --- a/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc +++ b/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
@@ -137,8 +137,7 @@ params.buffer_size); ui::OverlayPlane plane(std::move(scanout_buffer), params.plane_z_order, params.transform, params.display_rect, - params.crop_rect, - ui::OverlayPlane::ProcessBufferCallback()); + params.crop_rect); plane_list_.push_back(plane); }
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/ui/ozone/platform/drm/gpu/gbm_buffer.cc index 12927573..332f0cc 100644 --- a/ui/ozone/platform/drm/gpu/gbm_buffer.cc +++ b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -298,12 +298,6 @@ const scoped_refptr<GbmBuffer>& buffer) : surface_manager_(surface_manager), buffer_(buffer) {} -void GbmPixmap::SetProcessingCallback( - const ProcessingCallback& processing_callback) { - DCHECK(processing_callback_.is_null()); - processing_callback_ = processing_callback; -} - gfx::NativePixmapHandle GbmPixmap::ExportHandle() { gfx::NativePixmapHandle handle; gfx::BufferFormat format = @@ -373,44 +367,10 @@ const gfx::Rect& display_bounds, const gfx::RectF& crop_rect) { DCHECK(buffer_->GetFlags() & GBM_BO_USE_SCANOUT); - OverlayPlane::ProcessBufferCallback processing_callback; - if (!processing_callback_.is_null()) - processing_callback = base::Bind(&GbmPixmap::ProcessBuffer, this); - - surface_manager_->GetSurface(widget)->QueueOverlayPlane( - OverlayPlane(buffer_, plane_z_order, plane_transform, display_bounds, - crop_rect, processing_callback)); + surface_manager_->GetSurface(widget)->QueueOverlayPlane(OverlayPlane( + buffer_, plane_z_order, plane_transform, display_bounds, crop_rect)); return true; } -scoped_refptr<ScanoutBuffer> GbmPixmap::ProcessBuffer(const gfx::Size& size, - uint32_t format) { - DCHECK(GetBufferSize() != size || - buffer_->GetFramebufferPixelFormat() != format); - - if (!processed_pixmap_ || size != processed_pixmap_->GetBufferSize() || - format != processed_pixmap_->buffer()->GetFramebufferPixelFormat()) { - // Release any old processed pixmap. - processed_pixmap_ = nullptr; - scoped_refptr<GbmBuffer> buffer = GbmBuffer::CreateBuffer( - buffer_->drm().get(), format, size, buffer_->GetFlags()); - if (!buffer) - return nullptr; - - // ProcessBuffer is called on DrmThread. We could have used - // CreateNativePixmap to initialize the pixmap, however it posts a - // synchronous task to DrmThread resulting in a deadlock. - processed_pixmap_ = new GbmPixmap(surface_manager_, buffer); - } - - DCHECK(!processing_callback_.is_null()); - if (!processing_callback_.Run(this, processed_pixmap_)) { - LOG(ERROR) << "Failed processing NativePixmap"; - return nullptr; - } - - return processed_pixmap_->buffer(); -} - } // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.h b/ui/ozone/platform/drm/gpu/gbm_buffer.h index a8b8476..6715274 100644 --- a/ui/ozone/platform/drm/gpu/gbm_buffer.h +++ b/ui/ozone/platform/drm/gpu/gbm_buffer.h
@@ -109,9 +109,6 @@ GbmPixmap(GbmSurfaceFactory* surface_manager, const scoped_refptr<GbmBuffer>& buffer); - void SetProcessingCallback( - const ProcessingCallback& processing_callback) override; - // NativePixmap: void* GetEGLClientBuffer() const override; bool AreDmaBufFdsValid() const override; @@ -139,11 +136,6 @@ GbmSurfaceFactory* surface_manager_; scoped_refptr<GbmBuffer> buffer_; - // OverlayValidator can request scaling or format conversions as needed for - // this Pixmap. This holds the processed buffer. - scoped_refptr<GbmPixmap> processed_pixmap_; - ProcessingCallback processing_callback_; - DISALLOW_COPY_AND_ASSIGN(GbmPixmap); };
diff --git a/ui/ozone/platform/drm/gpu/overlay_plane.cc b/ui/ozone/platform/drm/gpu/overlay_plane.cc index ceecb6f..e1420720 100644 --- a/ui/ozone/platform/drm/gpu/overlay_plane.cc +++ b/ui/ozone/platform/drm/gpu/overlay_plane.cc
@@ -32,19 +32,6 @@ OverlayPlane::~OverlayPlane() { } -OverlayPlane::OverlayPlane(const scoped_refptr<ScanoutBuffer>& buffer, - int z_order, - gfx::OverlayTransform plane_transform, - const gfx::Rect& display_bounds, - const gfx::RectF& crop_rect, - const ProcessBufferCallback& processing_callback) - : buffer(buffer), - z_order(z_order), - plane_transform(plane_transform), - display_bounds(display_bounds), - crop_rect(crop_rect), - processing_callback(processing_callback) {} - bool OverlayPlane::operator<(const OverlayPlane& plane) const { return std::tie(z_order, display_bounds, crop_rect, plane_transform) < std::tie(plane.z_order, plane.display_bounds, plane.crop_rect,
diff --git a/ui/ozone/platform/drm/gpu/overlay_plane.h b/ui/ozone/platform/drm/gpu/overlay_plane.h index cccf075..4bd0fcab 100644 --- a/ui/ozone/platform/drm/gpu/overlay_plane.h +++ b/ui/ozone/platform/drm/gpu/overlay_plane.h
@@ -31,19 +31,6 @@ const gfx::RectF& crop_rect); OverlayPlane(const OverlayPlane& other); - // This represents a callback function which can handle post processing - // operations like scaling, format conversion etc of the buffer bound to this - // plane and return the processed buffer. - typedef base::Callback<scoped_refptr<ScanoutBuffer>(const gfx::Size& size, - uint32_t format)> - ProcessBufferCallback; - OverlayPlane(const scoped_refptr<ScanoutBuffer>& buffer, - int z_order, - gfx::OverlayTransform plane_transform, - const gfx::Rect& display_bounds, - const gfx::RectF& crop_rect, - const ProcessBufferCallback& processing_callback); - bool operator<(const OverlayPlane& plane) const; ~OverlayPlane(); @@ -56,8 +43,6 @@ gfx::OverlayTransform plane_transform; gfx::Rect display_bounds; gfx::RectF crop_rect; - // TODO(dshwang): remove unused |processing_callback|. crbug.com/683347 - ProcessBufferCallback processing_callback; }; } // namespace ui
diff --git a/ui/ozone/platform/headless/headless_surface_factory.cc b/ui/ozone/platform/headless/headless_surface_factory.cc index 56f06819..d3c9f35 100644 --- a/ui/ozone/platform/headless/headless_surface_factory.cc +++ b/ui/ozone/platform/headless/headless_surface_factory.cc
@@ -89,8 +89,6 @@ const gfx::RectF& crop_rect) override { return true; } - void SetProcessingCallback( - const ProcessingCallback& processing_callback) override {} gfx::NativePixmapHandle ExportHandle() override { return gfx::NativePixmapHandle(); }