diff --git a/DEPS b/DEPS index c475edc..3b9e41e 100644 --- a/DEPS +++ b/DEPS
@@ -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': 'dee2ad3570ce578a81ad73a1acbf4f4c7bf5cdf0', + 'catapult_revision': '9026a6670297e11f65ca2cb662ae71f94cdf403e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -416,7 +416,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': - Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '19dc69036d1af1e6ad00f1993f8c3a2b7a770e3e', + Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '07d4626c40a501866d7c01954f8cabef7b50f482', # Dependency of chromite.git and skia. 'src/third_party/pyelftools':
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java index 9b0f2c09..f094c9a 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java
@@ -160,6 +160,16 @@ @MediumTest @Feature({"AndroidWebView", "Privacy"}) + public void testSetSecureCookieForHttpUrl() throws Throwable { + String url = "http://www.example.com"; + String secureUrl = "https://www.example.com"; + String cookie = "name=test"; + mCookieManager.setCookie(url, cookie + ";secure"); + assertEquals(cookie, mCookieManager.getCookie(secureUrl)); + } + + @MediumTest + @Feature({"AndroidWebView", "Privacy"}) public void testHasCookie() throws Throwable { assertFalse(mCookieManager.hasCookies()); mCookieManager.setCookie("http://www.example.com", "name=test");
diff --git a/android_webview/native/cookie_manager.cc b/android_webview/native/cookie_manager.cc index fc75336..33c24db6 100644 --- a/android_webview/native/cookie_manager.cc +++ b/android_webview/native/cookie_manager.cc
@@ -388,12 +388,20 @@ options.set_include_httponly(); // Log message for catching strict secure cookies related bugs. - if (!host.has_scheme() || host.SchemeIs(url::kHttpScheme)) { + // TODO(sgurun) temporary. Add UMA stats to monitor, and remove afterwards. + if (host.is_valid() && + (!host.has_scheme() || host.SchemeIs(url::kHttpScheme))) { net::ParsedCookie parsed_cookie(value); if (parsed_cookie.IsValid() && parsed_cookie.IsSecure()) { LOG(WARNING) << "Strict Secure Cookie policy does not allow setting a " "secure cookie for " << host.spec(); + GURL::Replacements replace_host; + replace_host.SetSchemeStr("https"); + GURL new_host = host.ReplaceComponents(replace_host); + GetCookieStore()->SetCookieWithOptionsAsync(new_host, value, options, + callback); + return; } }
diff --git a/ash/devtools/ash_devtools_unittest.cc b/ash/devtools/ash_devtools_unittest.cc index 5ebb719c..29d7ca1 100644 --- a/ash/devtools/ash_devtools_unittest.cc +++ b/ash/devtools/ash_devtools_unittest.cc
@@ -4,6 +4,7 @@ #include "ash/devtools/ash_devtools_css_agent.h" #include "ash/devtools/ash_devtools_dom_agent.h" +#include "ash/public/cpp/shell_window_ids.h" #include "ash/root_window_controller.h" #include "ash/shell.h" #include "ash/shell_port.h" @@ -176,6 +177,10 @@ ->get_color()); } +WmWindow* GetPrimaryRootWindow() { + return ShellPort::Get()->GetPrimaryRootWindow(); +} + } // namespace class AshDevToolsTest : public AshTest { @@ -346,8 +351,9 @@ std::unique_ptr<ui::devtools::protocol::DOM::Node> root; dom_agent()->getDocument(&root); - WmWindow* parent_window = ShellPort::Get()->GetPrimaryRootWindow(); - DOM::Node* parent_node = root->getChildren(nullptr)->get(0); + WmWindow* root_window = GetPrimaryRootWindow(); + WmWindow* parent_window = root_window->GetChildren()[0]; + DOM::Node* parent_node = FindInRoot(parent_window, root.get()); Array<DOM::Node>* parent_node_children = parent_node->getChildren(nullptr); DOM::Node* sibling_node = parent_node_children->get(parent_node_children->length() - 1); @@ -361,10 +367,12 @@ std::unique_ptr<ui::devtools::protocol::DOM::Node> root; dom_agent()->getDocument(&root); - WmWindow* parent_window = - ShellPort::Get()->GetPrimaryRootWindow()->GetChildren()[0]; + WmWindow* root_window = GetPrimaryRootWindow(); + WmWindow* rotation_window = root_window->GetChildren()[0]; + WmWindow* parent_window = rotation_window->GetChildren()[0]; WmWindow* child_window = parent_window->GetChildren()[0]; - DOM::Node* root_node = root->getChildren(nullptr)->get(0); + DOM::Node* root_node = + root->getChildren(nullptr)->get(0)->getChildren(nullptr)->get(0); DOM::Node* parent_node = root_node->getChildren(nullptr)->get(0); DOM::Node* child_node = parent_node->getChildren(nullptr)->get(0); @@ -379,11 +387,14 @@ std::unique_ptr<ui::devtools::protocol::DOM::Node> root; dom_agent()->getDocument(&root); - WmWindow* root_window = ShellPort::Get()->GetPrimaryRootWindow(); - WmWindow* target_window = root_window->GetChildren()[1]; - WmWindow* child_window = root_window->GetChildren()[0]->GetChildren()[0]; + WmWindow* root_window = GetPrimaryRootWindow(); + WmWindow* rotation_window = root_window->GetChildren()[0]; + WmWindow* parent_window = rotation_window->GetChildren()[0]; + WmWindow* target_window = rotation_window->GetChildren()[1]; + WmWindow* child_window = parent_window->GetChildren()[0]; - DOM::Node* root_node = root->getChildren(nullptr)->get(0); + DOM::Node* root_node = + root->getChildren(nullptr)->get(0)->getChildren(nullptr)->get(0); DOM::Node* parent_node = root_node->getChildren(nullptr)->get(0); DOM::Node* target_node = root_node->getChildren(nullptr)->get(1); Array<DOM::Node>* target_node_children = target_node->getChildren(nullptr); @@ -391,6 +402,7 @@ target_node_children->get(target_node_children->length() - 1); DOM::Node* child_node = parent_node->getChildren(nullptr)->get(0); + Compare(parent_window, parent_node); Compare(target_window, target_node); Compare(child_window, child_node); target_window->AddChild(child_window); @@ -399,17 +411,18 @@ } TEST_F(AshDevToolsTest, WindowReorganizedChildNodeRemovedAndInserted) { - WmWindow* root_window = ShellPort::Get()->GetPrimaryRootWindow(); - WmWindow* target_window = root_window->GetChildren()[1]; - WmWindow* parent_window = root_window->GetChildren()[0]; + WmWindow* root_window = GetPrimaryRootWindow(); + WmWindow* rotation_window = root_window->GetChildren()[0]; + WmWindow* parent_window = rotation_window->GetChildren()[0]; + WmWindow* target_window = rotation_window->GetChildren()[1]; std::unique_ptr<WindowOwner> child_owner(CreateChildWindow(parent_window)); WmWindow* child_window = child_owner->window(); // Initialize DOMAgent std::unique_ptr<ui::devtools::protocol::DOM::Node> root; dom_agent()->getDocument(&root); - DOM::Node* root_node = root->getChildren(nullptr)->get(0); - + DOM::Node* root_node = + root->getChildren(nullptr)->get(0)->getChildren(nullptr)->get(0); DOM::Node* parent_node = root_node->getChildren(nullptr)->get(0); DOM::Node* target_node = root_node->getChildren(nullptr)->get(1); Array<DOM::Node>* target_node_children = target_node->getChildren(nullptr); @@ -419,6 +432,7 @@ DOM::Node* child_node = parent_node_children->get(parent_node_children->length() - 1); + Compare(parent_window, parent_node); Compare(target_window, target_node); Compare(child_window, child_node); parent_window->RemoveChild(child_window); @@ -432,11 +446,13 @@ std::unique_ptr<ui::devtools::protocol::DOM::Node> root; dom_agent()->getDocument(&root); - WmWindow* parent_window = ShellPort::Get()->GetPrimaryRootWindow(); + WmWindow* root_window = GetPrimaryRootWindow(); + WmWindow* parent_window = root_window->GetChildren()[0]; WmWindow* child_window = parent_window->GetChildren()[0]; WmWindow* target_window = parent_window->GetChildren()[1]; - DOM::Node* parent_node = root->getChildren(nullptr)->get(0); + DOM::Node* parent_node = + root->getChildren(nullptr)->get(0)->getChildren(nullptr)->get(0); Array<DOM::Node>* parent_node_children = parent_node->getChildren(nullptr); DOM::Node* child_node = parent_node_children->get(0); DOM::Node* sibling_node = parent_node_children->get(1);
diff --git a/ash/public/cpp/shell_window_ids.h b/ash/public/cpp/shell_window_ids.h index f5f1fc2..38f2771 100644 --- a/ash/public/cpp/shell_window_ids.h +++ b/ash/public/cpp/shell_window_ids.h
@@ -17,93 +17,97 @@ // Used to indicate no shell window id. const int32_t kShellWindowId_Invalid = -1; +// The screen rotation container in between root window and its children, used +// for screen rotation animation. +const int32_t kShellWindowId_ScreenRotationContainer = 0; + // A higher-level container that holds all of the containers stacked below // kShellWindowId_LockScreenContainer. Only used by PowerButtonController for // animating lower-level containers. -const int32_t kShellWindowId_NonLockScreenContainersContainer = 0; +const int32_t kShellWindowId_NonLockScreenContainersContainer = 1; // A higher-level container that holds containers that hold lock-screen // windows. Only used by PowerButtonController for animating lower-level // containers. -const int32_t kShellWindowId_LockScreenContainersContainer = 1; +const int32_t kShellWindowId_LockScreenContainersContainer = 2; // A higher-level container that holds containers that hold lock-screen-related // windows (which we want to display while the screen is locked; effectively // containers stacked above kShellWindowId_LockSystemModalContainer). Only used // by PowerButtonController for animating lower-level containers. -const int32_t kShellWindowId_LockScreenRelatedContainersContainer = 2; +const int32_t kShellWindowId_LockScreenRelatedContainersContainer = 3; // A container used for windows of WINDOW_TYPE_CONTROL that have no parent. // This container is not visible. -const int32_t kShellWindowId_UnparentedControlContainer = 3; +const int32_t kShellWindowId_UnparentedControlContainer = 4; // The wallpaper (desktop background) window. -const int32_t kShellWindowId_WallpaperContainer = 4; +const int32_t kShellWindowId_WallpaperContainer = 5; // The virtual keyboard container. // NOTE: this is lazily created. -const int32_t kShellWindowId_VirtualKeyboardContainer = 5; +const int32_t kShellWindowId_VirtualKeyboardContainer = 6; // The container for standard top-level windows. -const int32_t kShellWindowId_DefaultContainer = 6; +const int32_t kShellWindowId_DefaultContainer = 7; // The container for top-level windows with the 'always-on-top' flag set. -const int32_t kShellWindowId_AlwaysOnTopContainer = 7; +const int32_t kShellWindowId_AlwaysOnTopContainer = 8; // The container for the shelf. -const int32_t kShellWindowId_ShelfContainer = 8; +const int32_t kShellWindowId_ShelfContainer = 9; // The container for bubbles which float over the shelf. -const int32_t kShellWindowId_ShelfBubbleContainer = 9; +const int32_t kShellWindowId_ShelfBubbleContainer = 10; // The container for panel windows. -const int32_t kShellWindowId_PanelContainer = 10; +const int32_t kShellWindowId_PanelContainer = 11; // The container for the app list. -const int32_t kShellWindowId_AppListContainer = 11; +const int32_t kShellWindowId_AppListContainer = 12; // The container for user-specific modal windows. -const int32_t kShellWindowId_SystemModalContainer = 12; +const int32_t kShellWindowId_SystemModalContainer = 13; // The container for the lock screen wallpaper (lock screen background). -const int32_t kShellWindowId_LockScreenWallpaperContainer = 13; +const int32_t kShellWindowId_LockScreenWallpaperContainer = 14; // The container for the lock screen. -const int32_t kShellWindowId_LockScreenContainer = 14; +const int32_t kShellWindowId_LockScreenContainer = 15; // The container for the lock screen modal windows. -const int32_t kShellWindowId_LockSystemModalContainer = 15; +const int32_t kShellWindowId_LockSystemModalContainer = 16; // The container for the status area. -const int32_t kShellWindowId_StatusContainer = 16; +const int32_t kShellWindowId_StatusContainer = 17; // A parent container that holds the virtual keyboard container and ime windows // if any. This is to ensure that the virtual keyboard or ime window is stacked // above most containers but below the mouse cursor and the power off animation. -const int32_t kShellWindowId_ImeWindowParentContainer = 17; +const int32_t kShellWindowId_ImeWindowParentContainer = 18; // The container for menus. -const int32_t kShellWindowId_MenuContainer = 18; +const int32_t kShellWindowId_MenuContainer = 19; // The container for drag/drop images and tooltips. -const int32_t kShellWindowId_DragImageAndTooltipContainer = 19; +const int32_t kShellWindowId_DragImageAndTooltipContainer = 20; // The container for bubbles briefly overlaid onscreen to show settings changes // (volume, brightness, input method bubbles, etc.). -const int32_t kShellWindowId_SettingBubbleContainer = 20; +const int32_t kShellWindowId_SettingBubbleContainer = 21; // The container for special components overlaid onscreen, such as the // region selector for partial screenshots. -const int32_t kShellWindowId_OverlayContainer = 21; +const int32_t kShellWindowId_OverlayContainer = 22; // ID of the window created by PhantomWindowController or DragWindowController. -const int32_t kShellWindowId_PhantomWindow = 22; +const int32_t kShellWindowId_PhantomWindow = 23; // The container for mouse cursor. -const int32_t kShellWindowId_MouseCursorContainer = 23; +const int32_t kShellWindowId_MouseCursorContainer = 24; // The topmost container, used for power off animation. -const int32_t kShellWindowId_PowerButtonAnimationContainer = 24; +const int32_t kShellWindowId_PowerButtonAnimationContainer = 25; const int32_t kShellWindowId_Min = 0; const int32_t kShellWindowId_Max = kShellWindowId_PowerButtonAnimationContainer; @@ -111,31 +115,32 @@ // A list of all the above valid container IDs. Add any new ID to this list. // This list is needed to validate we have no duplicate IDs. const int32_t kAllShellContainerIds[] = { - kShellWindowId_NonLockScreenContainersContainer, - kShellWindowId_LockScreenContainersContainer, - kShellWindowId_LockScreenRelatedContainersContainer, - kShellWindowId_UnparentedControlContainer, - kShellWindowId_WallpaperContainer, - kShellWindowId_VirtualKeyboardContainer, - kShellWindowId_DefaultContainer, - kShellWindowId_AlwaysOnTopContainer, - kShellWindowId_ShelfContainer, - kShellWindowId_ShelfBubbleContainer, - kShellWindowId_PanelContainer, - kShellWindowId_AppListContainer, - kShellWindowId_SystemModalContainer, - kShellWindowId_LockScreenWallpaperContainer, - kShellWindowId_LockScreenContainer, - kShellWindowId_LockSystemModalContainer, - kShellWindowId_StatusContainer, - kShellWindowId_ImeWindowParentContainer, - kShellWindowId_MenuContainer, - kShellWindowId_DragImageAndTooltipContainer, - kShellWindowId_SettingBubbleContainer, - kShellWindowId_OverlayContainer, - kShellWindowId_PhantomWindow, - kShellWindowId_MouseCursorContainer, - kShellWindowId_PowerButtonAnimationContainer, + kShellWindowId_ScreenRotationContainer, + kShellWindowId_NonLockScreenContainersContainer, + kShellWindowId_LockScreenContainersContainer, + kShellWindowId_LockScreenRelatedContainersContainer, + kShellWindowId_UnparentedControlContainer, + kShellWindowId_WallpaperContainer, + kShellWindowId_VirtualKeyboardContainer, + kShellWindowId_DefaultContainer, + kShellWindowId_AlwaysOnTopContainer, + kShellWindowId_ShelfContainer, + kShellWindowId_ShelfBubbleContainer, + kShellWindowId_PanelContainer, + kShellWindowId_AppListContainer, + kShellWindowId_SystemModalContainer, + kShellWindowId_LockScreenWallpaperContainer, + kShellWindowId_LockScreenContainer, + kShellWindowId_LockSystemModalContainer, + kShellWindowId_StatusContainer, + kShellWindowId_ImeWindowParentContainer, + kShellWindowId_MenuContainer, + kShellWindowId_DragImageAndTooltipContainer, + kShellWindowId_SettingBubbleContainer, + kShellWindowId_OverlayContainer, + kShellWindowId_PhantomWindow, + kShellWindowId_MouseCursorContainer, + kShellWindowId_PowerButtonAnimationContainer, }; // These are the list of container ids of containers which may contain windows
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc index fa9d48b..aceb5340 100644 --- a/ash/root_window_controller.cc +++ b/ash/root_window_controller.cc
@@ -867,37 +867,46 @@ void RootWindowController::CreateContainers() { WmWindow* root = GetWindow(); + // For screen rotation animation: add a NOT_DRAWN layer in between the + // root_window's layer and its current children so that we only need to + // initiate two LayerAnimationSequences. One for the new layers and one for + // the old layers. + WmWindow* screen_rotation_container = CreateContainer( + kShellWindowId_ScreenRotationContainer, "ScreenRotationContainer", root); + // These containers are just used by PowerButtonController to animate groups // of containers simultaneously without messing up the current transformations - // on those containers. These are direct children of the root window; all of - // the other containers are their children. + // on those containers. These are direct children of the + // screen_rotation_container window; all of the other containers are their + // children. // The wallpaper container is not part of the lock animation, so it is not // included in those animate groups. When the screen is locked, the wallpaper // is moved to the lock screen wallpaper container (and moved back on unlock). // Ensure that there's an opaque layer occluding the non-lock-screen layers. - WmWindow* wallpaper_container = CreateContainer( - kShellWindowId_WallpaperContainer, "WallpaperContainer", root); + WmWindow* wallpaper_container = + CreateContainer(kShellWindowId_WallpaperContainer, "WallpaperContainer", + screen_rotation_container); wallpaper_container->SetChildWindowVisibilityChangesAnimated(); - WmWindow* non_lock_screen_containers = - CreateContainer(kShellWindowId_NonLockScreenContainersContainer, - "NonLockScreenContainersContainer", root); + WmWindow* non_lock_screen_containers = CreateContainer( + kShellWindowId_NonLockScreenContainersContainer, + "NonLockScreenContainersContainer", screen_rotation_container); // Clip all windows inside this container, as half pixel of the window's // texture may become visible when the screen is scaled. crbug.com/368591. non_lock_screen_containers->SetMasksToBounds(true); - WmWindow* lock_wallpaper_containers = - CreateContainer(kShellWindowId_LockScreenWallpaperContainer, - "LockScreenWallpaperContainer", root); + WmWindow* lock_wallpaper_containers = CreateContainer( + kShellWindowId_LockScreenWallpaperContainer, + "LockScreenWallpaperContainer", screen_rotation_container); lock_wallpaper_containers->SetChildWindowVisibilityChangesAnimated(); - WmWindow* lock_screen_containers = - CreateContainer(kShellWindowId_LockScreenContainersContainer, - "LockScreenContainersContainer", root); - WmWindow* lock_screen_related_containers = - CreateContainer(kShellWindowId_LockScreenRelatedContainersContainer, - "LockScreenRelatedContainersContainer", root); + WmWindow* lock_screen_containers = CreateContainer( + kShellWindowId_LockScreenContainersContainer, + "LockScreenContainersContainer", screen_rotation_container); + WmWindow* lock_screen_related_containers = CreateContainer( + kShellWindowId_LockScreenRelatedContainersContainer, + "LockScreenRelatedContainersContainer", screen_rotation_container); CreateContainer(kShellWindowId_UnparentedControlContainer, "UnparentedControlContainer", non_lock_screen_containers); @@ -1024,13 +1033,14 @@ overlay_container->SetBoundsInScreenBehaviorForChildren( WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); - WmWindow* mouse_cursor_container = CreateContainer( - kShellWindowId_MouseCursorContainer, "MouseCursorContainer", root); + WmWindow* mouse_cursor_container = + CreateContainer(kShellWindowId_MouseCursorContainer, + "MouseCursorContainer", screen_rotation_container); mouse_cursor_container->SetBoundsInScreenBehaviorForChildren( WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); CreateContainer(kShellWindowId_PowerButtonAnimationContainer, - "PowerButtonAnimationContainer", root); + "PowerButtonAnimationContainer", screen_rotation_container); } void RootWindowController::CreateSystemWallpaper(
diff --git a/ash/rotator/screen_rotation_animator.cc b/ash/rotator/screen_rotation_animator.cc index 279238d..f1c51a4 100644 --- a/ash/rotator/screen_rotation_animator.cc +++ b/ash/rotator/screen_rotation_animator.cc
@@ -10,6 +10,7 @@ #include "ash/ash_switches.h" #include "ash/display/window_tree_host_manager.h" +#include "ash/public/cpp/shell_window_ids.h" #include "ash/rotator/screen_rotation_animation.h" #include "ash/rotator/screen_rotation_animator_observer.h" #include "ash/shell.h" @@ -52,14 +53,6 @@ const int kCounterClockWiseRotationFactor = 1; const int kClockWiseRotationFactor = -1; -// Aborts the active animations of the layer, and recurses upon its child -// layers. -void AbortAnimations(ui::Layer* layer) { - for (ui::Layer* child_layer : layer->children()) - AbortAnimations(child_layer); - layer->GetAnimator()->AbortAllAnimations(); -} - display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) { return Shell::Get() ->display_manager() @@ -317,31 +310,25 @@ const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, rotated_screen_bounds.height() / 2); - // We must animate each non-cloned child layer individually because the cloned - // layer was added as a child to |root_window|'s layer so that it will be - // rendered. - // TODO(bruthig): Add a NOT_DRAWN layer in between the root_window's layer and - // its current children so that we only need to initiate two - // LayerAnimationSequences. One for the new layers and one for the old layer. - for (ui::Layer* child_layer : root_window->layer()->children()) { - // Skip the cloned layer because it has a different animation. - if (child_layer == old_root_layer) - continue; + ui::Layer* screen_rotation_container_layer = + root_window->GetChildById(kShellWindowId_ScreenRotationContainer) + ->layer(); + std::unique_ptr<ScreenRotationAnimation> current_layer_screen_rotation = + base::MakeUnique<ScreenRotationAnimation>( + screen_rotation_container_layer, kRotationDegrees * rotation_factor, + 0 /* end_degrees */, screen_rotation_container_layer->opacity(), + screen_rotation_container_layer->opacity() /* target_opacity */, + pivot, duration, tween_type); - std::unique_ptr<ScreenRotationAnimation> screen_rotation = - base::MakeUnique<ScreenRotationAnimation>( - child_layer, kRotationDegrees * rotation_factor, - 0 /* end_degrees */, child_layer->opacity(), - 1.0f /* target_opacity */, pivot, duration, tween_type); - - ui::LayerAnimator* animator = child_layer->GetAnimator(); - animator->set_preemption_strategy( - ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); - std::unique_ptr<ui::LayerAnimationSequence> animation_sequence = - base::MakeUnique<ui::LayerAnimationSequence>( - std::move(screen_rotation)); - animator->StartAnimation(animation_sequence.release()); - } + ui::LayerAnimator* current_layer_animator = + screen_rotation_container_layer->GetAnimator(); + current_layer_animator->set_preemption_strategy( + ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); + std::unique_ptr<ui::LayerAnimationSequence> current_layer_animation_sequence = + base::MakeUnique<ui::LayerAnimationSequence>( + std::move(current_layer_screen_rotation)); + current_layer_animator->StartAnimation( + current_layer_animation_sequence.release()); // The old layer will also be transformed into the new orientation. We will // translate it so that the old layer's center point aligns with the new @@ -353,7 +340,7 @@ (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); old_root_layer->SetTransform(translate_transform); - std::unique_ptr<ScreenRotationAnimation> screen_rotation = + std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation = base::MakeUnique<ScreenRotationAnimation>( old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, (old_layer_initial_rotation_degrees - kRotationDegrees) * @@ -361,20 +348,25 @@ old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, tween_type); - ui::LayerAnimator* animator = old_root_layer->GetAnimator(); - animator->set_preemption_strategy( + ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator(); + old_layer_animator->set_preemption_strategy( ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); - std::unique_ptr<ui::LayerAnimationSequence> animation_sequence = - base::MakeUnique<ui::LayerAnimationSequence>(std::move(screen_rotation)); + std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence = + base::MakeUnique<ui::LayerAnimationSequence>( + std::move(old_layer_screen_rotation)); // Add an observer so that the cloned layers can be cleaned up with the // animation completes/aborts. - animation_sequence->AddObserver(old_layer_cleanup_observer.release()); + old_layer_animation_sequence->AddObserver( + old_layer_cleanup_observer.release()); // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to // control the animation. if (disable_animation_timers_for_test_) - animator->set_disable_timer_for_test(true); - animation_sequence->SetAnimationMetricsReporter(metrics_reporter_.get()); - animator->StartAnimation(animation_sequence.release()); + old_layer_animator->set_disable_timer_for_test(true); + old_layer_animation_sequence->SetAnimationMetricsReporter( + metrics_reporter_.get()); + old_layer_animator->StartAnimation(old_layer_animation_sequence.release()); + + rotation_request.reset(); } void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, @@ -434,15 +426,13 @@ } void ScreenRotationAnimator::StopAnimating() { - aura::Window* root_window = GetRootWindow(display_id_); - for (ui::Layer* child_layer : root_window->layer()->children()) { - if (child_layer == old_layer_tree_owner_->root()) - continue; - - child_layer->GetAnimator()->StopAnimating(); - } - - old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); + GetRootWindow(display_id_) + ->GetChildById(kShellWindowId_ScreenRotationContainer) + ->layer() + ->GetAnimator() + ->StopAnimating(); + if (old_layer_tree_owner_) + old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); } } // namespace ash
diff --git a/ash/wm/root_window_layout_manager.cc b/ash/wm/root_window_layout_manager.cc index aa7301d..40b4df6 100644 --- a/ash/wm/root_window_layout_manager.cc +++ b/ash/wm/root_window_layout_manager.cc
@@ -9,6 +9,34 @@ #include "ui/aura/window_tracker.h" namespace ash { + +namespace { + +// Resize all container windows that RootWindowLayoutManager is responsible for. +// That includes all container windows up to three depth except that top level +// window which has a delegate. We cannot simply check top level window, because +// we need to skip other windows without a delegate, such as ScreenDimmer +// windows. +// TODO(wutao): The above logic is error prone. Consider using a Shell window id +// to indentify such a container. +void ResizeWindow(const aura::Window::Windows& children, + const gfx::Rect& fullscreen_bounds, + int depth) { + if (depth > 2) + return; + const int child_depth = depth + 1; + aura::WindowTracker children_tracker(children); + while (!children_tracker.windows().empty()) { + aura::Window* child = children_tracker.Pop(); + if (child->GetToplevelWindow()) + continue; + child->SetBounds(fullscreen_bounds); + ResizeWindow(child->children(), fullscreen_bounds, child_depth); + } +} + +} // namespace + namespace wm { //////////////////////////////////////////////////////////////////////////////// @@ -23,26 +51,8 @@ // RootWindowLayoutManager, aura::LayoutManager implementation: void RootWindowLayoutManager::OnWindowResized() { - const gfx::Rect fullscreen_bounds = gfx::Rect(owner_->GetBounds().size()); - - // Resize both our immediate children (the containers-of-containers animated - // by PowerButtonController) and their children (the actual containers). - aura::WindowTracker children_tracker(owner_->aura_window()->children()); - while (!children_tracker.windows().empty()) { - aura::Window* child = children_tracker.Pop(); - // Skip descendants of top-level windows, i.e. only resize containers and - // other windows without a delegate, such as ScreenDimmer windows. - if (child->GetToplevelWindow()) - continue; - - child->SetBounds(fullscreen_bounds); - aura::WindowTracker grandchildren_tracker(child->children()); - while (!grandchildren_tracker.windows().empty()) { - child = grandchildren_tracker.Pop(); - if (!child->GetToplevelWindow()) - child->SetBounds(fullscreen_bounds); - } - } + ResizeWindow(owner_->aura_window()->children(), + gfx::Rect(owner_->GetBounds().size()), 0); } void RootWindowLayoutManager::OnWindowAddedToLayout(WmWindow* child) {}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index c62ac3a..f7918544 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -647,8 +647,6 @@ "test/test_occlusion_tracker.h", "test/test_shared_bitmap_manager.cc", "test/test_shared_bitmap_manager.h", - "test/test_skcanvas.cc", - "test/test_skcanvas.h", "test/test_task_graph_runner.cc", "test/test_task_graph_runner.h", "test/test_texture.cc", @@ -766,7 +764,6 @@ "output/texture_mailbox_deleter_unittest.cc", "paint/discardable_image_map_unittest.cc", "paint/display_item_list_unittest.cc", - "paint/paint_op_buffer_unittest.cc", "quads/draw_polygon_unittest.cc", "quads/draw_quad_unittest.cc", "quads/nine_patch_generator_unittest.cc", @@ -937,7 +934,6 @@ "//cc/ipc", "//cc/ipc:interfaces", "//cc/paint", - "//cc/paint", "//cc/surfaces", "//cc/surfaces:surface_id", "//gpu",
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn index 11f9fdac..3af5dee 100644 --- a/cc/paint/BUILD.gn +++ b/cc/paint/BUILD.gn
@@ -32,19 +32,13 @@ "paint_canvas.cc", "paint_canvas.h", "paint_export.h", - "paint_flags.cc", "paint_flags.h", "paint_image.cc", "paint_image.h", - "paint_op_buffer.cc", - "paint_op_buffer.h", - "paint_record.cc", "paint_record.h", "paint_recorder.cc", "paint_recorder.h", "paint_shader.h", - "record_paint_canvas.cc", - "record_paint_canvas.h", "skia_paint_canvas.cc", "skia_paint_canvas.h", "transform_display_item.cc",
diff --git a/cc/paint/display_item_list.cc b/cc/paint/display_item_list.cc index c1b069548..8359948 100644 --- a/cc/paint/display_item_list.cc +++ b/cc/paint/display_item_list.cc
@@ -100,13 +100,9 @@ if (canvas->quickReject(item.picture->cullRect())) break; - // TODO(enne): Maybe the PaintRecord itself could know whether this - // was needed? It's not clear whether these save/restore semantics - // that SkPicture handles during playback are things that should be - // kept around. - canvas->save(); + // SkPicture always does a wrapping save/restore on the canvas, so it is + // not necessary here. item.picture->playback(canvas, callback); - canvas->restore(); break; } case DisplayItem::FLOAT_CLIP: { @@ -180,33 +176,6 @@ canvas->restore(); } -// Atttempts to merge a CompositingDisplayItem and DrawingDisplayItem -// into a single "draw with alpha". This function returns true if -// it was successful. If false, then the caller is responsible for -// drawing these items. This is a DisplayItemList version of the -// SkRecord optimization SkRecordNoopSaveLayerDrawRestores. -static bool MergeAndDrawIfPossible(const CompositingDisplayItem& save_item, - const DrawingDisplayItem& draw_item, - SkCanvas* canvas) { - if (save_item.color_filter) - return false; - if (save_item.xfermode != SkBlendMode::kSrcOver) - return false; - // TODO(enne): I believe that lcd_text_requires_opaque_layer is not - // relevant here and that lcd text is preserved post merge, but I haven't - // tested that. - const PaintRecord* record = draw_item.picture.get(); - if (record->approximateOpCount() != 1) - return false; - - const PaintOp* op = record->GetFirstOp(); - if (!op->IsDrawOp()) - return false; - - op->RasterWithAlpha(canvas, save_item.alpha); - return true; -} - void DisplayItemList::Raster(SkCanvas* canvas, SkPicture::AbortCallback* callback) const { gfx::Rect canvas_playback_rect; @@ -215,33 +184,14 @@ std::vector<size_t> indices; rtree_.Search(canvas_playback_rect, &indices); - for (size_t i = 0; i < indices.size(); ++i) { + for (size_t index : indices) { + RasterItem(items_[index], canvas, callback); + // We use a callback during solid color analysis on the compositor thread to // break out early. Since we're handling a sequence of pictures via rtree // query results ourselves, we have to respect the callback and early out. if (callback && callback->abort()) break; - - const DisplayItem& item = items_[indices[i]]; - // Optimize empty begin/end compositing and merge begin/draw/end compositing - // where possible. - // TODO(enne): remove empty clips here too? - // TODO(enne): does this happen recursively? Or is this good enough? - if (i < indices.size() - 2 && item.type == DisplayItem::COMPOSITING) { - const DisplayItem& second = items_[indices[i + 1]]; - const DisplayItem& third = items_[indices[i + 2]]; - if (second.type == DisplayItem::DRAWING && - third.type == DisplayItem::END_COMPOSITING) { - if (MergeAndDrawIfPossible( - static_cast<const CompositingDisplayItem&>(item), - static_cast<const DrawingDisplayItem&>(second), canvas)) { - i += 2; - continue; - } - } - } - - RasterItem(item, canvas, callback); } }
diff --git a/cc/paint/display_item_list_unittest.cc b/cc/paint/display_item_list_unittest.cc index b166229c6..f1b9e75 100644 --- a/cc/paint/display_item_list_unittest.cc +++ b/cc/paint/display_item_list_unittest.cc
@@ -17,17 +17,16 @@ #include "cc/paint/compositing_display_item.h" #include "cc/paint/drawing_display_item.h" #include "cc/paint/filter_display_item.h" + #include "cc/paint/float_clip_display_item.h" #include "cc/paint/paint_canvas.h" #include "cc/paint/paint_flags.h" #include "cc/paint/paint_record.h" #include "cc/paint/paint_recorder.h" -#include "cc/paint/skia_paint_canvas.h" #include "cc/paint/transform_display_item.h" #include "cc/test/geometry_test_utils.h" #include "cc/test/pixel_test_utils.h" #include "cc/test/skia_common.h" -#include "cc/test/test_skcanvas.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -81,19 +80,6 @@ return recorder.finishRecordingAsPicture(); } -sk_sp<const PaintRecord> CreateRectPictureWithAlpha(const gfx::Rect& bounds, - uint8_t alpha) { - PaintRecorder recorder; - PaintCanvas* canvas = - recorder.beginRecording(bounds.width(), bounds.height()); - PaintFlags flags; - flags.setAlpha(alpha); - canvas->drawRect( - SkRect::MakeXYWH(bounds.x(), bounds.y(), bounds.width(), bounds.height()), - flags); - return recorder.finishRecordingAsPicture(); -} - void AppendFirstSerializationTestPicture(scoped_refptr<DisplayItemList> list, const gfx::Size& layer_size) { gfx::PointF offset(2.f, 3.f); @@ -718,110 +704,4 @@ EXPECT_RECT_EQ(filter_bounds, list->VisualRectForTesting(3)); } -// Verify that raster time optimizations for compositing item / draw single op / -// end compositing item can be collapsed together into a single draw op -// with the opacity from the compositing item folded in. -TEST(DisplayItemListTest, SaveDrawRestore) { - auto list = make_scoped_refptr(new DisplayItemList); - - list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>( - 80, SkBlendMode::kSrcOver, nullptr, nullptr, false); - list->CreateAndAppendDrawingItem<DrawingDisplayItem>( - kVisualRect, CreateRectPictureWithAlpha(kVisualRect, 40)); - list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>(); - list->Finalize(); - - SaveCountingCanvas canvas; - list->Raster(&canvas, nullptr); - - EXPECT_EQ(0, canvas.save_count_); - EXPECT_EQ(0, canvas.restore_count_); - EXPECT_EQ(gfx::RectToSkRect(kVisualRect), canvas.draw_rect_); - - float expected_alpha = 80 * 40 / 255.f; - EXPECT_LE(std::abs(expected_alpha - canvas.paint_.getAlpha()), 1.f); -} - -// Verify that compositing item / end compositing item is a noop. -// Here we're testing that Skia does an optimization that skips -// save/restore with nothing in between. If skia stops doing this -// then we should reimplement this optimization in display list raster. -TEST(DisplayItemListTest, SaveRestoreNoops) { - auto list = make_scoped_refptr(new DisplayItemList); - - list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>( - 80, SkBlendMode::kSrcOver, nullptr, nullptr, false); - list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>(); - list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>( - 255, SkBlendMode::kSrcOver, nullptr, nullptr, false); - list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>(); - list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>( - 255, SkBlendMode::kSrc, nullptr, nullptr, false); - list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>(); - list->Finalize(); - - SaveCountingCanvas canvas; - list->Raster(&canvas, nullptr); - - EXPECT_EQ(0, canvas.save_count_); - EXPECT_EQ(0, canvas.restore_count_); -} - -// The same as SaveDrawRestore, but with save flags that prevent the -// optimization. -TEST(DisplayItemListTest, SaveDrawRestoreFail_BadSaveFlags) { - auto list = make_scoped_refptr(new DisplayItemList); - - // Use a blend mode that's not compatible with the SaveDrawRestore - // optimization. - list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>( - 80, SkBlendMode::kSrc, nullptr, nullptr, false); - list->CreateAndAppendDrawingItem<DrawingDisplayItem>( - kVisualRect, CreateRectPictureWithAlpha(kVisualRect, 40)); - list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>(); - list->Finalize(); - - SaveCountingCanvas canvas; - list->Raster(&canvas, nullptr); - - EXPECT_EQ(1, canvas.save_count_); - EXPECT_EQ(1, canvas.restore_count_); - EXPECT_EQ(gfx::RectToSkRect(kVisualRect), canvas.draw_rect_); - EXPECT_LE(40, canvas.paint_.getAlpha()); -} - -// The same as SaveDrawRestore, but with too many ops in the PaintRecord. -TEST(DisplayItemListTest, SaveDrawRestoreFail_TooManyOps) { - sk_sp<const PaintRecord> record; - { - PaintRecorder recorder; - PaintCanvas* canvas = - recorder.beginRecording(kVisualRect.width(), kVisualRect.height()); - PaintFlags flags; - flags.setAlpha(40); - canvas->drawRect(gfx::RectToSkRect(kVisualRect), flags); - // Add an extra op here. - canvas->drawRect(gfx::RectToSkRect(kVisualRect), flags); - record = recorder.finishRecordingAsPicture(); - } - EXPECT_GT(record->approximateOpCount(), 1); - - auto list = make_scoped_refptr(new DisplayItemList); - - list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>( - 80, SkBlendMode::kSrcOver, nullptr, nullptr, false); - list->CreateAndAppendDrawingItem<DrawingDisplayItem>(kVisualRect, - std::move(record)); - list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>(); - list->Finalize(); - - SaveCountingCanvas canvas; - list->Raster(&canvas, nullptr); - - EXPECT_EQ(1, canvas.save_count_); - EXPECT_EQ(1, canvas.restore_count_); - EXPECT_EQ(gfx::RectToSkRect(kVisualRect), canvas.draw_rect_); - EXPECT_LE(40, canvas.paint_.getAlpha()); -} - } // namespace cc
diff --git a/cc/paint/paint_canvas.h b/cc/paint/paint_canvas.h index d45e84b..6b9a0df 100644 --- a/cc/paint/paint_canvas.h +++ b/cc/paint/paint_canvas.h
@@ -11,24 +11,19 @@ #include "build/build_config.h" #include "cc/paint/paint_export.h" #include "cc/paint/paint_image.h" +#include "cc/paint/paint_record.h" #include "third_party/skia/include/core/SkCanvas.h" namespace cc { class DisplayItemList; class PaintFlags; -class PaintOpBuffer; - -using PaintRecord = PaintOpBuffer; class CC_PAINT_EXPORT PaintCanvas { public: virtual ~PaintCanvas() {} virtual SkMetaData& getMetaData() = 0; - - // TODO(enne): this only appears to mostly be used to determine if this is - // recording or not, so could be simplified or removed. virtual SkImageInfo imageInfo() const = 0; // TODO(enne): It would be nice to get rid of flush() entirely, as it @@ -47,7 +42,7 @@ int y) = 0; virtual int save() = 0; virtual int saveLayer(const SkRect* bounds, const PaintFlags* flags) = 0; - virtual int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) = 0; + virtual int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) = 0; virtual void restore() = 0; virtual int getSaveCount() const = 0; @@ -98,8 +93,6 @@ virtual bool getDeviceClipBounds(SkIRect* bounds) const = 0; virtual void drawColor(SkColor color, SkBlendMode mode) = 0; void drawColor(SkColor color) { drawColor(color, SkBlendMode::kSrcOver); } - - // TODO(enne): This is a synonym for drawColor with kSrc. Remove it. virtual void clear(SkColor color) = 0; virtual void drawLine(SkScalar x0,
diff --git a/cc/paint/paint_flags.cc b/cc/paint/paint_flags.cc deleted file mode 100644 index e16a8bb..0000000 --- a/cc/paint/paint_flags.cc +++ /dev/null
@@ -1,42 +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 "cc/paint/paint_flags.h" - -namespace cc { - -bool PaintFlags::IsSimpleOpacity() const { - uint32_t color = getColor(); - if (SK_ColorTRANSPARENT != SkColorSetA(color, SK_AlphaTRANSPARENT)) - return false; - if (!isSrcOver()) - return false; - if (getLooper()) - return false; - if (getPathEffect()) - return false; - if (getShader()) - return false; - if (getMaskFilter()) - return false; - if (getColorFilter()) - return false; - if (getImageFilter()) - return false; - return true; -} - -bool PaintFlags::SupportsFoldingAlpha() const { - if (!isSrcOver()) - return false; - if (getColorFilter()) - return false; - if (getImageFilter()) - return false; - if (getLooper()) - return false; - return true; -} - -} // namespace cc
diff --git a/cc/paint/paint_flags.h b/cc/paint/paint_flags.h index 37b460d6..b7e96c6 100644 --- a/cc/paint/paint_flags.h +++ b/cc/paint/paint_flags.h
@@ -7,6 +7,7 @@ #include "base/compiler_specific.h" #include "cc/paint/paint_export.h" +#include "cc/paint/paint_shader.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/core/SkDrawLooper.h" @@ -18,8 +19,6 @@ namespace cc { -using PaintShader = SkShader; - class CC_PAINT_EXPORT PaintFlags { public: enum Style { @@ -199,14 +198,6 @@ return paint_.computeFastBounds(orig, storage); } - bool operator==(const PaintFlags& flags) { return flags.paint_ == paint_; } - bool operator!=(const PaintFlags& flags) { return flags.paint_ != paint_; } - - // Returns true if this just represents an opacity blend when - // used as saveLayer flags. - bool IsSimpleOpacity() const; - bool SupportsFoldingAlpha() const; - private: friend const SkPaint& ToSkPaint(const PaintFlags& flags); friend const SkPaint* ToSkPaint(const PaintFlags* flags);
diff --git a/cc/paint/paint_image.cc b/cc/paint/paint_image.cc index d34d05d..70644ed 100644 --- a/cc/paint/paint_image.cc +++ b/cc/paint/paint_image.cc
@@ -12,9 +12,6 @@ : sk_image_(std::move(sk_image)), animation_type_(animation_type), completion_state_(completion_state) {} - -PaintImage::PaintImage(const PaintImage& image) = default; - PaintImage::~PaintImage() = default; } // namespace cc
diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h index c772316..0ed1edd 100644 --- a/cc/paint/paint_image.h +++ b/cc/paint/paint_image.h
@@ -23,7 +23,6 @@ PaintImage(sk_sp<const SkImage> sk_image, AnimationType animation_type, CompletionState completion_state); - PaintImage(const PaintImage& image); ~PaintImage(); const sk_sp<const SkImage>& sk_image() const { return sk_image_; }
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc deleted file mode 100644 index a98392a..0000000 --- a/cc/paint/paint_op_buffer.cc +++ /dev/null
@@ -1,556 +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 "cc/paint/paint_op_buffer.h" - -#include "cc/paint/display_item_list.h" -#include "cc/paint/paint_record.h" -#include "third_party/skia/include/core/SkAnnotation.h" - -namespace cc { - -#define TYPES(M) \ - M(AnnotateOp) \ - M(ClipPathOp) \ - M(ClipRectOp) \ - M(ClipRRectOp) \ - M(ConcatOp) \ - M(DrawArcOp) \ - M(DrawCircleOp) \ - M(DrawColorOp) \ - M(DrawDisplayItemListOp) \ - M(DrawDRRectOp) \ - M(DrawImageOp) \ - M(DrawImageRectOp) \ - M(DrawIRectOp) \ - M(DrawLineOp) \ - M(DrawOvalOp) \ - M(DrawPathOp) \ - M(DrawPosTextOp) \ - M(DrawRecordOp) \ - M(DrawRectOp) \ - M(DrawRRectOp) \ - M(DrawTextOp) \ - M(DrawTextBlobOp) \ - M(NoopOp) \ - M(RestoreOp) \ - M(RotateOp) \ - M(SaveOp) \ - M(SaveLayerOp) \ - M(SaveLayerAlphaOp) \ - M(ScaleOp) \ - M(SetMatrixOp) \ - M(TranslateOp) - -// Helper template to share common code for RasterWithAlpha when paint ops -// have or don't have PaintFlags. -template <typename T, bool HasFlags> -struct Rasterizer { - static void Raster(const T* op, - SkCanvas* canvas, - const SkMatrix& original_ctm) { - // Paint ops with kHasPaintFlags need to declare RasterWithPaintFlags - // otherwise, the paint op needs its own Raster function. Without its - // own, this becomes an infinite loop as PaintOp::Raster calls itself. - static_assert( - !std::is_same<decltype(&PaintOp::Raster), decltype(&T::Raster)>::value, - "No Raster function"); - - op->Raster(canvas); - } - static void RasterWithAlpha(const T* op, SkCanvas* canvas, uint8_t alpha) { - DCHECK(T::kIsDrawOp); - // TODO(enne): is it ok to just drop the bounds here? - canvas->saveLayerAlpha(nullptr, alpha); - op->Raster(canvas); - canvas->restore(); - } -}; - -template <typename T> -struct Rasterizer<T, true> { - static void Raster(const T* op, - SkCanvas* canvas, - const SkMatrix& original_ctm) { - op->RasterWithFlags(canvas, op->flags); - } - static void RasterWithAlpha(const T* op, SkCanvas* canvas, uint8_t alpha) { - DCHECK(T::kIsDrawOp); - SkMatrix unused_matrix; - if (alpha == 255) { - Raster(op, canvas, unused_matrix); - } else if (op->flags.SupportsFoldingAlpha()) { - PaintFlags flags = op->flags; - flags.setAlpha(SkMulDiv255Round(flags.getAlpha(), alpha)); - op->RasterWithFlags(canvas, flags); - } else { - canvas->saveLayerAlpha(nullptr, alpha); - op->RasterWithFlags(canvas, op->flags); - canvas->restore(); - } - } -}; - -template <> -struct Rasterizer<SetMatrixOp, false> { - static void Raster(const SetMatrixOp* op, - SkCanvas* canvas, - const SkMatrix& original_ctm) { - op->Raster(canvas, original_ctm); - } - static void RasterWithAlpha(const SetMatrixOp* op, - SkCanvas* canvas, - uint8_t alpha) { - NOTREACHED(); - } -}; - -template <> -struct Rasterizer<DrawRecordOp, false> { - static void Raster(const DrawRecordOp* op, - SkCanvas* canvas, - const SkMatrix& original_ctm) { - op->Raster(canvas); - } - static void RasterWithAlpha(const DrawRecordOp* op, - SkCanvas* canvas, - uint8_t alpha) { - // This "looking into records" optimization is done here instead of - // in the PaintOpBuffer::Raster function as DisplayItemList calls - // into RasterWithAlpha directly. - if (op->record->approximateOpCount() == 1) { - op->record->GetFirstOp()->RasterWithAlpha(canvas, alpha); - return; - } - - canvas->saveLayerAlpha(nullptr, alpha); - op->Raster(canvas); - canvas->restore(); - } -}; - -// TODO(enne): partially specialize RasterWithAlpha for draw color? - -static constexpr size_t kNumOpTypes = - static_cast<size_t>(PaintOpType::LastPaintOpType) + 1; - -// Verify that every op is in the TYPES macro. -#define M(T) +1 -static_assert(kNumOpTypes == TYPES(M), "Missing op in list"); -#undef M - -using RasterFunction = void (*)(const PaintOp* op, - SkCanvas* canvas, - const SkMatrix& original_ctm); -#define M(T) \ - [](const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm) { \ - Rasterizer<T, T::kHasPaintFlags>::Raster(static_cast<const T*>(op), \ - canvas, original_ctm); \ - }, -static const RasterFunction g_raster_functions[kNumOpTypes] = {TYPES(M)}; -#undef M - -using RasterAlphaFunction = void (*)(const PaintOp* op, - SkCanvas* canvas, - uint8_t alpha); -#define M(T) \ - T::kIsDrawOp ? \ - [](const PaintOp* op, SkCanvas* canvas, uint8_t alpha) { \ - Rasterizer<T, T::kHasPaintFlags>::RasterWithAlpha( \ - static_cast<const T*>(op), canvas, alpha); \ - } : static_cast<RasterAlphaFunction>(nullptr), -static const RasterAlphaFunction g_raster_alpha_functions[kNumOpTypes] = { - TYPES(M)}; -#undef M - -// Most state ops (matrix, clip, save, restore) have a trivial destructor. -// TODO(enne): evaluate if we need the nullptr optimization or if -// we even need to differentiate trivial destructors here. -using VoidFunction = void (*)(PaintOp* op); -#define M(T) \ - !std::is_trivially_destructible<T>::value \ - ? [](PaintOp* op) { static_cast<T*>(op)->~T(); } \ - : static_cast<VoidFunction>(nullptr), -static const VoidFunction g_destructor_functions[kNumOpTypes] = {TYPES(M)}; -#undef M - -#define M(T) T::kIsDrawOp, -static bool g_is_draw_op[kNumOpTypes] = {TYPES(M)}; -#undef M - -#define M(T) \ - static_assert(sizeof(T) <= sizeof(LargestPaintOp), \ - #T " must be no bigger than LargestPaintOp"); -TYPES(M); -#undef M - -#undef TYPES - -SkRect PaintOp::kUnsetRect = {SK_ScalarInfinity, 0, 0, 0}; - -void AnnotateOp::Raster(SkCanvas* canvas) const { - switch (annotation_type) { - case PaintCanvas::AnnotationType::URL: - SkAnnotateRectWithURL(canvas, rect, data.get()); - break; - case PaintCanvas::AnnotationType::LINK_TO_DESTINATION: - SkAnnotateLinkToDestination(canvas, rect, data.get()); - break; - case PaintCanvas::AnnotationType::NAMED_DESTINATION: { - SkPoint point = SkPoint::Make(rect.x(), rect.y()); - SkAnnotateNamedDestination(canvas, point, data.get()); - break; - } - } -} - -void ClipPathOp::Raster(SkCanvas* canvas) const { - canvas->clipPath(path, op, antialias); -} - -void ClipRectOp::Raster(SkCanvas* canvas) const { - canvas->clipRect(rect, op, antialias); -} - -void ClipRRectOp::Raster(SkCanvas* canvas) const { - canvas->clipRRect(rrect, op, antialias); -} - -void ConcatOp::Raster(SkCanvas* canvas) const { - canvas->concat(matrix); -} - -void DrawArcOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - canvas->drawArc(oval, start_angle, sweep_angle, use_center, ToSkPaint(flags)); -} - -void DrawCircleOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - canvas->drawCircle(cx, cy, radius, ToSkPaint(flags)); -} - -void DrawColorOp::Raster(SkCanvas* canvas) const { - canvas->drawColor(color, mode); -} - -void DrawDisplayItemListOp::Raster(SkCanvas* canvas) const { - list->Raster(canvas, nullptr); -} - -void DrawDRRectOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - canvas->drawDRRect(outer, inner, ToSkPaint(flags)); -} - -void DrawImageOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - canvas->drawImage(image.sk_image().get(), left, top, ToSkPaint(&flags)); -} - -void DrawImageRectOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - // TODO(enne): Probably PaintCanvas should just use the skia enum directly. - SkCanvas::SrcRectConstraint skconstraint = - static_cast<SkCanvas::SrcRectConstraint>(constraint); - canvas->drawImageRect(image.sk_image().get(), src, dst, ToSkPaint(&flags), - skconstraint); -} - -void DrawIRectOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - canvas->drawIRect(rect, ToSkPaint(flags)); -} - -void DrawLineOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - canvas->drawLine(x0, y0, x1, y1, ToSkPaint(flags)); -} - -void DrawOvalOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - canvas->drawOval(oval, ToSkPaint(flags)); -} - -void DrawPathOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - canvas->drawPath(path, ToSkPaint(flags)); -} - -void DrawPosTextOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - canvas->drawPosText(paint_op_data(this), bytes, paint_op_array<SkPoint>(this), - ToSkPaint(flags)); -} - -void DrawRecordOp::Raster(SkCanvas* canvas) const { - record->playback(canvas); -} - -void DrawRectOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - canvas->drawRect(rect, ToSkPaint(flags)); -} - -void DrawRRectOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - canvas->drawRRect(rrect, ToSkPaint(flags)); -} - -void DrawTextOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - canvas->drawText(paint_op_data(this), bytes, x, y, ToSkPaint(flags)); -} - -void DrawTextBlobOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - canvas->drawTextBlob(blob.get(), x, y, ToSkPaint(flags)); -} - -void RestoreOp::Raster(SkCanvas* canvas) const { - canvas->restore(); -} - -void RotateOp::Raster(SkCanvas* canvas) const { - canvas->rotate(degrees); -} - -void SaveOp::Raster(SkCanvas* canvas) const { - canvas->save(); -} - -void SaveLayerOp::RasterWithFlags(SkCanvas* canvas, - const PaintFlags& flags) const { - // See PaintOp::kUnsetRect - bool unset = bounds.left() == SK_ScalarInfinity; - - canvas->saveLayer(unset ? nullptr : &bounds, ToSkPaint(&flags)); -} - -void SaveLayerAlphaOp::Raster(SkCanvas* canvas) const { - // See PaintOp::kUnsetRect - bool unset = bounds.left() == SK_ScalarInfinity; - canvas->saveLayerAlpha(unset ? nullptr : &bounds, alpha); -} - -void ScaleOp::Raster(SkCanvas* canvas) const { - canvas->scale(sx, sy); -} - -void SetMatrixOp::Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const { - canvas->setMatrix(SkMatrix::Concat(original_ctm, matrix)); -} - -void TranslateOp::Raster(SkCanvas* canvas) const { - canvas->translate(dx, dy); -} - -bool PaintOp::IsDrawOp() const { - return g_is_draw_op[type]; -} - -void PaintOp::Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const { - g_raster_functions[type](this, canvas, original_ctm); -} - -void PaintOp::RasterWithAlpha(SkCanvas* canvas, uint8_t alpha) const { - g_raster_alpha_functions[type](this, canvas, alpha); -} - -DrawDisplayItemListOp::DrawDisplayItemListOp( - scoped_refptr<DisplayItemList> list) - : list(list) {} - -size_t DrawDisplayItemListOp::AdditionalBytesUsed() const { - return list->ApproximateMemoryUsage(); -} - -int ClipPathOp::CountSlowPaths() const { - return antialias && !path.isConvex() ? 1 : 0; -} - -int DrawLineOp::CountSlowPaths() const { - if (const SkPathEffect* effect = flags.getPathEffect()) { - SkPathEffect::DashInfo info; - SkPathEffect::DashType dashType = effect->asADash(&info); - if (flags.getStrokeCap() != PaintFlags::kRound_Cap && - dashType == SkPathEffect::kDash_DashType && info.fCount == 2) { - // The PaintFlags will count this as 1, so uncount that here as - // this kind of line is special cased and not slow. - return -1; - } - } - return 0; -} - -int DrawPathOp::CountSlowPaths() const { - // This logic is copied from SkPathCounter instead of attempting to expose - // that from Skia. - if (!flags.isAntiAlias() || path.isConvex()) - return 0; - - PaintFlags::Style paintStyle = flags.getStyle(); - const SkRect& pathBounds = path.getBounds(); - if (paintStyle == PaintFlags::kStroke_Style && flags.getStrokeWidth() == 0) { - // AA hairline concave path is not slow. - return 0; - } else if (paintStyle == PaintFlags::kFill_Style && - pathBounds.width() < 64.f && pathBounds.height() < 64.f && - !path.isVolatile()) { - // AADF eligible concave path is not slow. - return 0; - } else { - return 1; - } -} - -AnnotateOp::AnnotateOp(PaintCanvas::AnnotationType annotation_type, - const SkRect& rect, - sk_sp<SkData> data) - : annotation_type(annotation_type), rect(rect), data(std::move(data)) {} - -AnnotateOp::~AnnotateOp() = default; - -DrawDisplayItemListOp::~DrawDisplayItemListOp() = default; - -DrawImageOp::DrawImageOp(const PaintImage& image, - SkScalar left, - SkScalar top, - const PaintFlags* flags) - : image(image), - left(left), - top(top), - flags(flags ? *flags : PaintFlags()) {} - -DrawImageOp::~DrawImageOp() = default; - -DrawImageRectOp::DrawImageRectOp(const PaintImage& image, - const SkRect& src, - const SkRect& dst, - const PaintFlags* flags, - PaintCanvas::SrcRectConstraint constraint) - : image(image), - flags(flags ? *flags : PaintFlags()), - src(src), - dst(dst), - constraint(constraint) {} - -DrawImageRectOp::~DrawImageRectOp() = default; - -DrawPosTextOp::DrawPosTextOp(size_t bytes, - size_t count, - const PaintFlags& flags) - : PaintOpWithDataArray(bytes, count), flags(flags) {} - -DrawPosTextOp::~DrawPosTextOp() = default; - -DrawRecordOp::DrawRecordOp(sk_sp<const PaintRecord> record) - : record(std::move(record)) {} - -DrawRecordOp::~DrawRecordOp() = default; - -size_t DrawRecordOp::AdditionalBytesUsed() const { - return record->approximateBytesUsed(); -} - -DrawTextBlobOp::DrawTextBlobOp(sk_sp<SkTextBlob> blob, - SkScalar x, - SkScalar y, - const PaintFlags& flags) - : blob(std::move(blob)), x(x), y(y), flags(flags) {} - -DrawTextBlobOp::~DrawTextBlobOp() = default; - -PaintOpBuffer::PaintOpBuffer() : cull_rect_(SkRect::MakeEmpty()) {} - -PaintOpBuffer::PaintOpBuffer(const SkRect& cull_rect) : cull_rect_(cull_rect) {} - -PaintOpBuffer::~PaintOpBuffer() { - Reset(); -} - -void PaintOpBuffer::Reset() { - for (auto* op : Iterator(this)) { - auto func = g_destructor_functions[op->type]; - if (func) - func(op); - } - - // Leave data_ allocated, reserved_ unchanged. - used_ = 0; - op_count_ = 0; - num_slow_paths_ = 0; -} - -void PaintOpBuffer::playback(SkCanvas* canvas) const { - // TODO(enne): a PaintRecord that contains a SetMatrix assumes that the - // SetMatrix is local to that PaintRecord itself. Said differently, if you - // translate(x, y), then draw a paint record with a SetMatrix(identity), - // the translation should be preserved instead of clobbering the top level - // transform. This could probably be done more efficiently. - SkMatrix original = canvas->getTotalMatrix(); - - for (Iterator iter(this); iter; ++iter) { - // Optimize out save/restores or save/draw/restore that can be a single - // draw. See also: similar code in SkRecordOpts and cc's DisplayItemList. - // TODO(enne): consider making this recursive? - const PaintOp* op = *iter; - if (op->GetType() == PaintOpType::SaveLayerAlpha) { - const PaintOp* second = iter.peek1(); - if (second) { - if (second->GetType() == PaintOpType::Restore) { - ++iter; - continue; - } - if (second->IsDrawOp()) { - const PaintOp* third = iter.peek2(); - if (third && third->GetType() == PaintOpType::Restore) { - const SaveLayerAlphaOp* save_op = - static_cast<const SaveLayerAlphaOp*>(op); - second->RasterWithAlpha(canvas, save_op->alpha); - ++iter; - ++iter; - continue; - } - } - } - } - // TODO(enne): skip SaveLayer followed by restore with nothing in - // between, however SaveLayer with image filters on it (or maybe - // other PaintFlags options) are not a noop. Figure out what these - // are so we can skip them correctly. - - op->Raster(canvas, original); - } -} - -void PaintOpBuffer::playback(SkCanvas* canvas, - SkPicture::AbortCallback* callback) const { - // The abort callback is only used for analysis, in general, so - // this playback code can be more straightforward and not do the - // optimizations in the other function. - if (!callback) { - playback(canvas); - return; - } - - SkMatrix original = canvas->getTotalMatrix(); - - // TODO(enne): ideally callers would just iterate themselves and we - // can remove the entire notion of an abort callback. - for (auto* op : Iterator(this)) { - op->Raster(canvas, original); - if (callback && callback->abort()) - return; - } -} - -void PaintOpBuffer::ShrinkToFit() { - if (!used_ || used_ == reserved_) - return; - data_.realloc(used_); - reserved_ = used_; -} - -} // namespace cc
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h deleted file mode 100644 index 5075cf4..0000000 --- a/cc/paint/paint_op_buffer.h +++ /dev/null
@@ -1,782 +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 CC_PAINT_PAINT_OP_BUFFER_H_ -#define CC_PAINT_PAINT_OP_BUFFER_H_ - -#include <stdint.h> - -#include "base/logging.h" -#include "cc/paint/paint_canvas.h" -#include "cc/paint/paint_export.h" -#include "cc/paint/paint_flags.h" -#include "third_party/skia/include/core/SkPicture.h" -#include "third_party/skia/include/core/SkRect.h" -#include "third_party/skia/include/core/SkTextBlob.h" - -// PaintOpBuffer is a reimplementation of SkLiteDL. -// See: third_party/skia/src/core/SkLiteDL.h. - -namespace cc { - -class DisplayItemList; - -class ThreadsafeMatrix : public SkMatrix { - public: - explicit ThreadsafeMatrix(const SkMatrix& matrix) : SkMatrix(matrix) { - (void)getType(); - } -}; - -class ThreadsafePath : public SkPath { - public: - explicit ThreadsafePath(const SkPath& path) : SkPath(path) { - updateBoundsCache(); - } -}; - -enum class PaintOpType : uint8_t { - Annotate, - ClipPath, - ClipRect, - ClipRRect, - Concat, - DrawArc, - DrawCircle, - DrawColor, - DrawDisplayItemList, - DrawDRRect, - DrawImage, - DrawImageRect, - DrawIRect, - DrawLine, - DrawOval, - DrawPath, - DrawPosText, - DrawRecord, - DrawRect, - DrawRRect, - DrawText, - DrawTextBlob, - Noop, - Restore, - Rotate, - Save, - SaveLayer, - SaveLayerAlpha, - Scale, - SetMatrix, - Translate, - LastPaintOpType = Translate, -}; - -struct CC_PAINT_EXPORT PaintOp { - uint32_t type : 8; - uint32_t skip : 24; - - PaintOpType GetType() const { return static_cast<PaintOpType>(type); } - - void Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const; - bool IsDrawOp() const; - - // Only valid for draw ops. - void RasterWithAlpha(SkCanvas* canvas, uint8_t alpha) const; - - int CountSlowPaths() const { return 0; } - - // Returns the number of bytes used by this op in referenced sub records - // and display lists. This doesn't count other objects like paths or blobs. - size_t AdditionalBytesUsed() const { return 0; } - - static constexpr bool kIsDrawOp = false; - // If an op has |kHasPaintFlags| set to true, it must: - // (1) Provide a PaintFlags member called |flags| - // (2) Provide a RasterWithFlags function instead of a Raster function. - static constexpr bool kHasPaintFlags = false; - static SkRect kUnsetRect; -}; - -struct PaintOpWithData : PaintOp { - // Having data is just a helper for ops that have a varying amount of data and - // want a way to store that inline. This is for ops that pass in a - // void* and a length. - explicit PaintOpWithData(size_t bytes) : bytes(bytes) {} - - // Get data out by calling paint_op_data. This can't be part of the class - // because it needs to know the size of the derived type. - size_t bytes; -}; - -template <typename T> -const void* paint_op_data(const T* op) { - static_assert(std::is_convertible<T, PaintOpWithData>::value, - "T is not a PaintOpWithData"); - // Arbitrary data for a PaintOp is stored after the PaintOp itself - // in the PaintOpBuffer. Therefore, to access this data, it's - // pointer math to increment past the size of T. Accessing the - // next op in the buffer is ((char*)op) + op->skip, with the data - // fitting between. - return op + 1; -} - -template <typename T> -void* paint_op_data(T* op) { - static_assert(std::is_convertible<T, PaintOpWithData>::value, - "T is not a PaintOpWithData"); - return op + 1; -} - -struct PaintOpWithDataArrayBase : PaintOpWithData { - // Helper class for static asserts in push functions. - using PaintOpWithData::PaintOpWithData; -}; - -template <typename T> -struct PaintOpWithDataArray : PaintOpWithDataArrayBase { - // Paint op that has a T[count] and a char[bytes]. - PaintOpWithDataArray(size_t bytes, size_t count) - : PaintOpWithDataArrayBase(bytes), count(count) {} - // Use paint_op_array to get array data. - - size_t count; -}; - -template <typename M, typename T> -const M* paint_op_array(const T* op) { - static_assert(std::is_convertible<T, PaintOpWithDataArrayBase>::value, - "T is not a PaintOpWithDataArray"); - // See comment in paint_op_data. Array data is stored after - // any void* data. Memory layout here is: |op|data|array data|next op| - return SkTAddOffset<const M>(op + 1, op->bytes); -} -template <typename M, typename T> -M* paint_op_array(T* op) { - static_assert(std::is_convertible<T, PaintOpWithDataArrayBase>::value, - "T is not a PaintOpWithDataArray"); - return SkTAddOffset<M>(op + 1, op->bytes); -} - -struct AnnotateOp final : PaintOp { - enum class AnnotationType { - URL, - LinkToDestination, - NamedDestination, - }; - - static constexpr PaintOpType kType = PaintOpType::Annotate; - AnnotateOp(PaintCanvas::AnnotationType annotation_type, - const SkRect& rect, - sk_sp<SkData> data); - ~AnnotateOp(); - void Raster(SkCanvas* canvas) const; - - PaintCanvas::AnnotationType annotation_type; - SkRect rect; - sk_sp<SkData> data; -}; - -struct ClipPathOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::ClipPath; - ClipPathOp(SkPath path, SkClipOp op, bool antialias) - : path(path), op(op), antialias(antialias) {} - void Raster(SkCanvas* canvas) const; - int CountSlowPaths() const; - - ThreadsafePath path; - SkClipOp op; - bool antialias; -}; - -struct ClipRectOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::ClipRect; - ClipRectOp(const SkRect& rect, SkClipOp op, bool antialias) - : rect(rect), op(op), antialias(antialias) {} - void Raster(SkCanvas* canvas) const; - - SkRect rect; - SkClipOp op; - bool antialias; -}; - -struct ClipRRectOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::ClipRRect; - ClipRRectOp(const SkRRect& rrect, SkClipOp op, bool antialias) - : rrect(rrect), op(op), antialias(antialias) {} - void Raster(SkCanvas* canvas) const; - - SkRRect rrect; - SkClipOp op; - bool antialias; -}; - -struct ConcatOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::Concat; - explicit ConcatOp(const SkMatrix& matrix) : matrix(matrix) {} - void Raster(SkCanvas* canvas) const; - - ThreadsafeMatrix matrix; -}; - -struct DrawArcOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawArc; - static constexpr bool kIsDrawOp = true; - static constexpr bool kHasPaintFlags = true; - DrawArcOp(const SkRect& oval, - SkScalar start_angle, - SkScalar sweep_angle, - bool use_center, - const PaintFlags& flags) - : oval(oval), - start_angle(start_angle), - sweep_angle(sweep_angle), - use_center(use_center), - flags(flags) {} - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - - SkRect oval; - SkScalar start_angle; - SkScalar sweep_angle; - bool use_center; - PaintFlags flags; -}; - -struct DrawCircleOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawCircle; - static constexpr bool kIsDrawOp = true; - static constexpr bool kHasPaintFlags = true; - DrawCircleOp(SkScalar cx, - SkScalar cy, - SkScalar radius, - const PaintFlags& flags) - : cx(cx), cy(cy), radius(radius), flags(flags) {} - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - - SkScalar cx; - SkScalar cy; - SkScalar radius; - PaintFlags flags; -}; - -struct DrawColorOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawColor; - static constexpr bool kIsDrawOp = true; - DrawColorOp(SkColor color, SkBlendMode mode) : color(color), mode(mode) {} - void Raster(SkCanvas* canvas) const; - - SkColor color; - SkBlendMode mode; -}; - -struct DrawDisplayItemListOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawDisplayItemList; - static constexpr bool kIsDrawOp = true; - explicit DrawDisplayItemListOp(scoped_refptr<DisplayItemList> list); - ~DrawDisplayItemListOp(); - void Raster(SkCanvas* canvas) const; - size_t AdditionalBytesUsed() const; - // TODO(enne): DisplayItemList should know number of slow paths. - - scoped_refptr<DisplayItemList> list; -}; - -struct DrawDRRectOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawDRRect; - static constexpr bool kIsDrawOp = true; - static constexpr bool kHasPaintFlags = true; - DrawDRRectOp(const SkRRect& outer, - const SkRRect& inner, - const PaintFlags& flags) - : outer(outer), inner(inner), flags(flags) {} - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - - SkRRect outer; - SkRRect inner; - PaintFlags flags; -}; - -struct DrawImageOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawImage; - static constexpr bool kIsDrawOp = true; - static constexpr bool kHasPaintFlags = true; - DrawImageOp(const PaintImage& image, - SkScalar left, - SkScalar top, - const PaintFlags* flags); - ~DrawImageOp(); - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - - PaintImage image; - SkScalar left; - SkScalar top; - PaintFlags flags; -}; - -struct DrawImageRectOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawImageRect; - static constexpr bool kIsDrawOp = true; - static constexpr bool kHasPaintFlags = true; - DrawImageRectOp(const PaintImage& image, - const SkRect& src, - const SkRect& dst, - const PaintFlags* flags, - PaintCanvas::SrcRectConstraint constraint); - ~DrawImageRectOp(); - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - - PaintImage image; - PaintFlags flags; - SkRect src; - SkRect dst; - PaintCanvas::SrcRectConstraint constraint; -}; - -struct DrawIRectOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawIRect; - static constexpr bool kIsDrawOp = true; - static constexpr bool kHasPaintFlags = true; - DrawIRectOp(const SkIRect& rect, const PaintFlags& flags) - : rect(rect), flags(flags) {} - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - - SkIRect rect; - PaintFlags flags; -}; - -struct DrawLineOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawLine; - static constexpr bool kIsDrawOp = true; - static constexpr bool kHasPaintFlags = true; - DrawLineOp(SkScalar x0, - SkScalar y0, - SkScalar x1, - SkScalar y1, - const PaintFlags& flags) - : x0(x0), y0(y0), x1(x1), y1(y1), flags(flags) {} - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - int CountSlowPaths() const; - - SkScalar x0; - SkScalar y0; - SkScalar x1; - SkScalar y1; - PaintFlags flags; -}; - -struct DrawOvalOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawOval; - static constexpr bool kIsDrawOp = true; - static constexpr bool kHasPaintFlags = true; - DrawOvalOp(const SkRect& oval, const PaintFlags& flags) - : oval(oval), flags(flags) {} - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - - SkRect oval; - PaintFlags flags; -}; - -struct DrawPathOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawPath; - static constexpr bool kIsDrawOp = true; - static constexpr bool kHasPaintFlags = true; - DrawPathOp(const SkPath& path, const PaintFlags& flags) - : path(path), flags(flags) {} - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - int CountSlowPaths() const; - - ThreadsafePath path; - PaintFlags flags; -}; - -struct DrawPosTextOp final : PaintOpWithDataArray<SkPoint> { - static constexpr PaintOpType kType = PaintOpType::DrawPosText; - static constexpr bool kIsDrawOp = true; - static constexpr bool kHasPaintFlags = true; - DrawPosTextOp(size_t bytes, size_t count, const PaintFlags& flags); - ~DrawPosTextOp(); - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - - PaintFlags flags; -}; - -struct DrawRecordOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawRecord; - static constexpr bool kIsDrawOp = true; - explicit DrawRecordOp(sk_sp<const PaintRecord> record); - ~DrawRecordOp(); - void Raster(SkCanvas* canvas) const; - size_t AdditionalBytesUsed() const; - - sk_sp<const PaintRecord> record; -}; - -struct DrawRectOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawRect; - static constexpr bool kIsDrawOp = true; - static constexpr bool kHasPaintFlags = true; - DrawRectOp(const SkRect& rect, const PaintFlags& flags) - : rect(rect), flags(flags) {} - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - - SkRect rect; - PaintFlags flags; -}; - -struct DrawRRectOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawRRect; - static constexpr bool kIsDrawOp = true; - static constexpr bool kHasPaintFlags = true; - DrawRRectOp(const SkRRect& rrect, const PaintFlags& flags) - : rrect(rrect), flags(flags) {} - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - - SkRRect rrect; - PaintFlags flags; -}; - -struct DrawTextOp final : PaintOpWithData { - static constexpr PaintOpType kType = PaintOpType::DrawText; - static constexpr bool kIsDrawOp = true; - static constexpr bool kHasPaintFlags = true; - DrawTextOp(size_t bytes, SkScalar x, SkScalar y, const PaintFlags& flags) - : PaintOpWithData(bytes), x(x), y(y), flags(flags) {} - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - - SkScalar x; - SkScalar y; - PaintFlags flags; -}; - -struct DrawTextBlobOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::DrawTextBlob; - static constexpr bool kIsDrawOp = true; - static constexpr bool kHasPaintFlags = true; - DrawTextBlobOp(sk_sp<SkTextBlob> blob, - SkScalar x, - SkScalar y, - const PaintFlags& flags); - ~DrawTextBlobOp(); - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - - sk_sp<SkTextBlob> blob; - SkScalar x; - SkScalar y; - PaintFlags flags; -}; - -struct NoopOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::Noop; - void Raster(SkCanvas* canvas) const {} -}; - -struct RestoreOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::Restore; - void Raster(SkCanvas* canvas) const; -}; - -struct RotateOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::Rotate; - explicit RotateOp(SkScalar degrees) : degrees(degrees) {} - void Raster(SkCanvas* canvas) const; - - SkScalar degrees; -}; - -struct SaveOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::Save; - void Raster(SkCanvas* canvas) const; -}; - -struct SaveLayerOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::SaveLayer; - static constexpr bool kHasPaintFlags = true; - SaveLayerOp(const SkRect* bounds, const PaintFlags* flags) - : bounds(bounds ? *bounds : kUnsetRect) { - if (flags) - this->flags = *flags; - } - void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const; - - SkRect bounds; - PaintFlags flags; -}; - -struct SaveLayerAlphaOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::SaveLayerAlpha; - SaveLayerAlphaOp(const SkRect* bounds, uint8_t alpha) - : bounds(bounds ? *bounds : kUnsetRect), alpha(alpha) {} - void Raster(SkCanvas* canvas) const; - - SkRect bounds; - uint8_t alpha; -}; - -struct ScaleOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::Scale; - ScaleOp(SkScalar sx, SkScalar sy) : sx(sx), sy(sy) {} - void Raster(SkCanvas* canvas) const; - - SkScalar sx; - SkScalar sy; -}; - -struct SetMatrixOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::SetMatrix; - explicit SetMatrixOp(const SkMatrix& matrix) : matrix(matrix) {} - // This is the only op that needs the original ctm of the SkCanvas - // used for raster (since SetMatrix is relative to the recording origin and - // shouldn't clobber the SkCanvas raster origin). - // - // TODO(enne): Find some cleaner way to do this, possibly by making - // all SetMatrix calls Concat?? - void Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const; - - ThreadsafeMatrix matrix; -}; - -struct TranslateOp final : PaintOp { - static constexpr PaintOpType kType = PaintOpType::Translate; - TranslateOp(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {} - void Raster(SkCanvas* canvas) const; - - SkScalar dx; - SkScalar dy; -}; - -using LargestPaintOp = DrawDRRectOp; - -class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt { - public: - enum { kPageSize = 4096 }; - - PaintOpBuffer(); - explicit PaintOpBuffer(const SkRect& cull_rect); - ~PaintOpBuffer() override; - - void Reset(); - - void playback(SkCanvas* canvas) const; - void playback(SkCanvas* canvas, SkPicture::AbortCallback* callback) const; - - // TODO(enne): These are no longer approximate. Rename these. - int approximateOpCount() const { return op_count_; } - size_t approximateBytesUsed() const { - return sizeof(*this) + reserved_ + subrecord_bytes_used_; - } - int numSlowPaths() const { return num_slow_paths_; } - - // Resize the PaintOpBuffer to exactly fit the current amount of used space. - void ShrinkToFit(); - - const SkRect& cullRect() const { return cull_rect_; } - - PaintOp* GetFirstOp() const { - return reinterpret_cast<PaintOp*>(const_cast<char*>(&first_op_[0])); - } - - template <typename T, typename... Args> - void push(Args&&... args) { - static_assert(std::is_convertible<T, PaintOp>::value, "T not a PaintOp."); - static_assert(!std::is_convertible<T, PaintOpWithData>::value, - "Type needs to use push_with_data"); - push_internal<T>(0, std::forward<Args>(args)...); - } - - template <typename T, typename... Args> - void push_with_data(const void* data, size_t bytes, Args&&... args) { - static_assert(std::is_convertible<T, PaintOpWithData>::value, - "T is not a PaintOpWithData"); -#if !defined(OS_CHROMEOS) - // TODO(enne): non-linux chromeos builds think that DrawTextOp - // can be converted to a PaintOpWithDataArrayBase. OOPS. - static_assert(!std::is_convertible<T, PaintOpWithDataArrayBase>::value, - "Type needs to use push_with_data_array"); -#endif - DCHECK_GE(bytes, 0u); - T* op = push_internal<T>(bytes, bytes, std::forward<Args>(args)...); - memcpy(paint_op_data(op), data, bytes); - -#if DCHECK_IS_ON() - // Double check the data fits between op and next op and doesn't clobber. - char* op_start = reinterpret_cast<char*>(op); - char* op_end = op_start + sizeof(T); - char* next_op = op_start + op->skip; - char* data_start = reinterpret_cast<char*>(paint_op_data(op)); - char* data_end = data_start + bytes; - DCHECK_GE(data_start, op_end); - DCHECK_LT(data_start, next_op); - DCHECK_LE(data_end, next_op); -#endif - } - - template <typename T, typename M, typename... Args> - void push_with_data_array(const void* data, - size_t bytes, - const M* array, - size_t count, - Args&&... args) { - static_assert(std::is_convertible<T, PaintOpWithDataArray<M>>::value, - "T is not a PaintOpWithDataArray"); - DCHECK_GE(bytes, 0u); - DCHECK_GE(count, 0u); - size_t array_size = sizeof(M) * count; - size_t total_size = bytes + array_size; - T* op = - push_internal<T>(total_size, bytes, count, std::forward<Args>(args)...); - memcpy(paint_op_data(op), data, bytes); - memcpy(paint_op_array<M>(op), array, array_size); - -#if DCHECK_IS_ON() - // Double check data and array don't clobber op, next op, or each other - char* op_start = reinterpret_cast<char*>(op); - char* op_end = op_start + sizeof(T); - char* next_op = op_start + op->skip; - char* data_start = reinterpret_cast<char*>(paint_op_data(op)); - char* data_end = data_start + bytes; - char* array_start = reinterpret_cast<char*>(paint_op_array<M>(op)); - char* array_end = array_start + array_size; - DCHECK_GE(data_start, op_end); - DCHECK_LE(data_start, array_start); - DCHECK_GE(array_start, data_end); - DCHECK_LE(array_end, next_op); -#endif - } - - class Iterator { - public: - explicit Iterator(const PaintOpBuffer* buffer) - : buffer_(buffer), ptr_(buffer_->data_.get()) {} - - PaintOp* operator->() const { - return op_idx_ ? reinterpret_cast<PaintOp*>(ptr_) : buffer_->GetFirstOp(); - } - PaintOp* operator*() const { return operator->(); } - Iterator begin() { return Iterator(buffer_, buffer_->data_.get(), 0); } - Iterator end() { - return Iterator(buffer_, buffer_->data_.get() + buffer_->used_, - buffer_->approximateOpCount()); - } - bool operator!=(const Iterator& other) { - // Not valid to compare iterators on different buffers. - DCHECK_EQ(other.buffer_, buffer_); - return other.op_idx_ != op_idx_; - } - Iterator& operator++() { - if (!op_idx_++) - return *this; - PaintOp* op = **this; - uint32_t type = op->type; - CHECK_LE(type, static_cast<uint32_t>(PaintOpType::LastPaintOpType)); - ptr_ += op->skip; - return *this; - } - operator bool() const { return op_idx_ < buffer_->approximateOpCount(); } - - int op_idx() const { return op_idx_; } - - // Return the next op without advancing the iterator, or nullptr if none. - PaintOp* peek1() const { - if (op_idx_ + 1 >= buffer_->approximateOpCount()) - return nullptr; - if (!op_idx_) - return reinterpret_cast<PaintOp*>(ptr_); - return reinterpret_cast<PaintOp*>(ptr_ + (*this)->skip); - } - - // Return the op two ops ahead without advancing the iterator, or nullptr if - // none. - PaintOp* peek2() const { - if (op_idx_ + 2 >= buffer_->approximateOpCount()) - return nullptr; - char* next = ptr_ + reinterpret_cast<PaintOp*>(ptr_)->skip; - PaintOp* next_op = reinterpret_cast<PaintOp*>(next); - if (!op_idx_) - return next_op; - return reinterpret_cast<PaintOp*>(next + next_op->skip); - } - - private: - Iterator(const PaintOpBuffer* buffer, char* ptr, int op_idx) - : buffer_(buffer), ptr_(ptr), op_idx_(op_idx) {} - - const PaintOpBuffer* buffer_ = nullptr; - char* ptr_ = nullptr; - int op_idx_ = 0; - }; - - private: - template <typename T, bool HasFlags> - struct CountSlowPathsFromFlags { - static int Count(const T* op) { return 0; } - }; - - template <typename T> - struct CountSlowPathsFromFlags<T, true> { - static int Count(const T* op) { return op->flags.getPathEffect() ? 1 : 0; } - }; - - template <typename T, typename... Args> - T* push_internal(size_t bytes, Args&&... args) { - size_t skip = SkAlignPtr(sizeof(T) + bytes); - DCHECK_LT(skip, static_cast<size_t>(1) << 24); - if (used_ + skip > reserved_ || !op_count_) { - if (!op_count_) { - if (bytes) { - // Internal first_op buffer doesn't have room for extra data. - // If the op wants extra bytes, then we'll just store a Noop - // in the first_op and proceed from there. This seems unlikely - // to be a common case. - push<NoopOp>(); - } else { - T* op = reinterpret_cast<T*>(&first_op_[0]); - new (op) T{std::forward<Args>(args)...}; - op->type = static_cast<uint32_t>(T::kType); - op->skip = 0; - op_count_++; - return op; - } - } - - static_assert(SkIsPow2(kPageSize), - "This math needs updating for non-pow2."); - // Next greater multiple of kPageSize. - reserved_ = (used_ + skip + kPageSize) & ~(kPageSize - 1); - data_.realloc(reserved_); - } - DCHECK_LE(used_ + skip, reserved_); - - T* op = reinterpret_cast<T*>(data_.get() + used_); - used_ += skip; - new (op) T(std::forward<Args>(args)...); - op->type = static_cast<uint32_t>(T::kType); - op->skip = skip; - op_count_++; - - num_slow_paths_ += CountSlowPathsFromFlags<T, T::kHasPaintFlags>::Count(op); - num_slow_paths_ += op->CountSlowPaths(); - - subrecord_bytes_used_ += op->AdditionalBytesUsed(); - - return op; - } - - // As a performance optimization because n=1 is an extremely common case just - // store the first op in the PaintOpBuffer itself to avoid an extra alloc. - char first_op_[sizeof(LargestPaintOp)]; - SkAutoTMalloc<char> data_; - size_t used_ = 0; - size_t reserved_ = 0; - int op_count_ = 0; - - // Record paths for veto-to-msaa for gpu raster. - int num_slow_paths_ = 0; - // Record additional bytes used by referenced sub-records and display lists. - size_t subrecord_bytes_used_ = 0; - SkRect cull_rect_; - - DISALLOW_COPY_AND_ASSIGN(PaintOpBuffer); -}; - -} // namespace cc - -#endif // CC_PAINT_PAINT_OP_BUFFER_H_
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc deleted file mode 100644 index 5e0bf2aa..0000000 --- a/cc/paint/paint_op_buffer_unittest.cc +++ /dev/null
@@ -1,259 +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 "cc/paint/paint_op_buffer.h" -#include "cc/test/test_skcanvas.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -template <typename T> -void CheckRefCnt(const T& obj, int32_t count) { -// Skia doesn't define getRefCnt in all builds. -#ifdef SK_DEBUG - EXPECT_EQ(obj->getRefCnt(), count); -#endif -} - -} // namespace - -namespace cc { - -TEST(PaintOpBufferTest, Empty) { - PaintOpBuffer buffer; - EXPECT_EQ(buffer.approximateOpCount(), 0); - EXPECT_EQ(buffer.approximateBytesUsed(), sizeof(PaintOpBuffer)); - EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false); - - buffer.Reset(); - EXPECT_EQ(buffer.approximateOpCount(), 0); - EXPECT_EQ(buffer.approximateBytesUsed(), sizeof(PaintOpBuffer)); - EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false); -} - -TEST(PaintOpBufferTest, SimpleAppend) { - SkRect rect = SkRect::MakeXYWH(2, 3, 4, 5); - PaintFlags flags; - flags.setColor(SK_ColorMAGENTA); - flags.setAlpha(100); - SkColor draw_color = SK_ColorRED; - SkBlendMode blend = SkBlendMode::kSrc; - - PaintOpBuffer buffer; - buffer.push<SaveLayerOp>(&rect, &flags); - buffer.push<SaveOp>(); - buffer.push<DrawColorOp>(draw_color, blend); - buffer.push<RestoreOp>(); - - EXPECT_EQ(buffer.approximateOpCount(), 4); - - PaintOpBuffer::Iterator iter(&buffer); - ASSERT_EQ(iter->GetType(), PaintOpType::SaveLayer); - SaveLayerOp* save_op = static_cast<SaveLayerOp*>(*iter); - EXPECT_EQ(save_op->bounds, rect); - EXPECT_TRUE(save_op->flags == flags); - ++iter; - - ASSERT_EQ(iter->GetType(), PaintOpType::Save); - ++iter; - - ASSERT_EQ(iter->GetType(), PaintOpType::DrawColor); - DrawColorOp* op = static_cast<DrawColorOp*>(*iter); - EXPECT_EQ(op->color, draw_color); - EXPECT_EQ(op->mode, blend); - ++iter; - - ASSERT_EQ(iter->GetType(), PaintOpType::Restore); - ++iter; - - EXPECT_FALSE(iter); -} - -// PaintOpBuffer has a special case for first ops stored locally, so -// make sure that appending different kind of ops as a first op works -// properly, as well as resetting and reusing the first local op. -TEST(PaintOpBufferTest, FirstOpWithAndWithoutData) { - PaintOpBuffer buffer; - char text[] = "asdf"; - - // Use a color filter and its ref count to verify that the destructor - // is called on ops after reset. - PaintFlags flags; - sk_sp<SkColorFilter> filter = - SkColorFilter::MakeModeFilter(SK_ColorMAGENTA, SkBlendMode::kSrcOver); - flags.setColorFilter(filter); - CheckRefCnt(filter, 2); - - buffer.push_with_data<DrawTextOp>(text, arraysize(text), 0.f, 0.f, flags); - CheckRefCnt(filter, 3); - - // Verify that when the first op has data, which may not fit in the - // PaintRecord internal buffer, that it adds a noop as the first op - // and then appends the "op with data" into the heap buffer. - ASSERT_EQ(buffer.approximateOpCount(), 2); - EXPECT_EQ(buffer.GetFirstOp()->GetType(), PaintOpType::Noop); - - // Verify iteration behavior and brief smoke test of op state. - { - PaintOpBuffer::Iterator iter(&buffer); - PaintOp* noop = *iter; - EXPECT_EQ(buffer.GetFirstOp(), noop); - ++iter; - - PaintOp* op = *iter; - ASSERT_EQ(op->GetType(), PaintOpType::DrawText); - DrawTextOp* draw_text_op = static_cast<DrawTextOp*>(op); - EXPECT_EQ(draw_text_op->bytes, arraysize(text)); - - void* data = paint_op_data(draw_text_op); - EXPECT_EQ(memcmp(data, text, arraysize(text)), 0); - - ++iter; - EXPECT_FALSE(iter); - } - - // Reset, verify state, and append an op that will fit in the first slot. - buffer.Reset(); - CheckRefCnt(filter, 2); - - ASSERT_EQ(buffer.approximateOpCount(), 0); - EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false); - - SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4); - buffer.push<DrawRectOp>(rect, flags); - CheckRefCnt(filter, 3); - - ASSERT_EQ(buffer.approximateOpCount(), 1); - EXPECT_EQ(buffer.GetFirstOp()->GetType(), PaintOpType::DrawRect); - - PaintOpBuffer::Iterator iter(&buffer); - ASSERT_EQ(iter->GetType(), PaintOpType::DrawRect); - DrawRectOp* draw_rect_op = static_cast<DrawRectOp*>(*iter); - EXPECT_EQ(draw_rect_op->rect, rect); - - ++iter; - EXPECT_FALSE(iter); - - buffer.Reset(); - ASSERT_EQ(buffer.approximateOpCount(), 0); - CheckRefCnt(filter, 2); -} - -TEST(PaintOpBufferTest, Peek) { - PaintOpBuffer buffer; - - uint8_t alpha = 100; - buffer.push<SaveLayerAlphaOp>(nullptr, alpha); - PaintFlags draw_flags; - buffer.push<DrawRectOp>(SkRect::MakeXYWH(1, 2, 3, 4), draw_flags); - buffer.push<RestoreOp>(); - buffer.push<SaveOp>(); - buffer.push<NoopOp>(); - buffer.push<RestoreOp>(); - - PaintOpBuffer::Iterator init_iter(&buffer); - PaintOp* peek[2] = {*init_iter, init_iter.peek1()}; - - // Expect that while iterating that next = current.peek1() and that - // next.peek1() == current.peek2(). - for (PaintOpBuffer::Iterator iter(&buffer); iter; ++iter) { - EXPECT_EQ(*iter, peek[0]) << iter.op_idx(); - EXPECT_EQ(iter.peek1(), peek[1]) << iter.op_idx(); - - peek[0] = iter.peek1(); - peek[1] = iter.peek2(); - } -} - -TEST(PaintOpBufferTest, PeekEmpty) { - PaintOpBuffer empty; - PaintOpBuffer::Iterator empty_iter(&empty); - EXPECT_EQ(nullptr, empty_iter.peek1()); - EXPECT_EQ(nullptr, empty_iter.peek2()); -} - -// Verify that a SaveLayerAlpha / Draw / Restore can be optimized to just -// a draw with opacity. -TEST(PaintOpBufferTest, SaveDrawRestore) { - PaintOpBuffer buffer; - - uint8_t alpha = 100; - buffer.push<SaveLayerAlphaOp>(nullptr, alpha); - - PaintFlags draw_flags; - draw_flags.setColor(SK_ColorMAGENTA); - draw_flags.setAlpha(50); - EXPECT_TRUE(draw_flags.SupportsFoldingAlpha()); - SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4); - buffer.push<DrawRectOp>(rect, draw_flags); - buffer.push<RestoreOp>(); - - SaveCountingCanvas canvas; - buffer.playback(&canvas); - - EXPECT_EQ(0, canvas.save_count_); - EXPECT_EQ(0, canvas.restore_count_); - EXPECT_EQ(rect, canvas.draw_rect_); - - // Expect the alpha from the draw and the save layer to be folded together. - // Since alpha is stored in a uint8_t and gets rounded, so use tolerance. - float expected_alpha = alpha * 50 / 255.f; - EXPECT_LE(std::abs(expected_alpha - canvas.paint_.getAlpha()), 1.f); -} - -// The same as SaveDrawRestore, but test that the optimization doesn't apply -// when the drawing op's flags are not compatible with being folded into the -// save layer with opacity. -TEST(PaintOpBufferTest, SaveDrawRestoreFail_BadFlags) { - PaintOpBuffer buffer; - - uint8_t alpha = 100; - buffer.push<SaveLayerAlphaOp>(nullptr, alpha); - - PaintFlags draw_flags; - draw_flags.setColor(SK_ColorMAGENTA); - draw_flags.setAlpha(50); - draw_flags.setBlendMode(SkBlendMode::kSrc); - EXPECT_FALSE(draw_flags.SupportsFoldingAlpha()); - SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4); - buffer.push<DrawRectOp>(rect, draw_flags); - buffer.push<RestoreOp>(); - - SaveCountingCanvas canvas; - buffer.playback(&canvas); - - EXPECT_EQ(1, canvas.save_count_); - EXPECT_EQ(1, canvas.restore_count_); - EXPECT_EQ(rect, canvas.draw_rect_); - EXPECT_EQ(draw_flags.getAlpha(), canvas.paint_.getAlpha()); -} - -// The same as SaveDrawRestore, but test that the optimization doesn't apply -// when there are more than one ops between the save and restore. -TEST(PaintOpBufferTest, SaveDrawRestoreFail_TooManyOps) { - PaintOpBuffer buffer; - - uint8_t alpha = 100; - buffer.push<SaveLayerAlphaOp>(nullptr, alpha); - - PaintFlags draw_flags; - draw_flags.setColor(SK_ColorMAGENTA); - draw_flags.setAlpha(50); - draw_flags.setBlendMode(SkBlendMode::kSrcOver); - EXPECT_TRUE(draw_flags.SupportsFoldingAlpha()); - SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4); - buffer.push<DrawRectOp>(rect, draw_flags); - buffer.push<NoopOp>(); - buffer.push<RestoreOp>(); - - SaveCountingCanvas canvas; - buffer.playback(&canvas); - - EXPECT_EQ(1, canvas.save_count_); - EXPECT_EQ(1, canvas.restore_count_); - EXPECT_EQ(rect, canvas.draw_rect_); - EXPECT_EQ(draw_flags.getAlpha(), canvas.paint_.getAlpha()); -} - -} // namespace cc
diff --git a/cc/paint/paint_record.cc b/cc/paint/paint_record.cc deleted file mode 100644 index 52cb2524..0000000 --- a/cc/paint/paint_record.cc +++ /dev/null
@@ -1,26 +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 "cc/paint/paint_record.h" - -#include "cc/paint/paint_op_buffer.h" -#include "third_party/skia/include/core/SkPictureRecorder.h" - -namespace cc { - -sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record) { - SkPictureRecorder recorder; - SkCanvas* canvas = recorder.beginRecording(record->cullRect()); - record->playback(canvas); - return recorder.finishRecordingAsPicture(); -} - -sk_sp<const SkPicture> ToSkPicture(sk_sp<const PaintRecord> record) { - SkPictureRecorder recorder; - SkCanvas* canvas = recorder.beginRecording(record->cullRect()); - record->playback(canvas); - return recorder.finishRecordingAsPicture(); -} - -} // namespace cc
diff --git a/cc/paint/paint_record.h b/cc/paint/paint_record.h index daeee004..8506606b 100644 --- a/cc/paint/paint_record.h +++ b/cc/paint/paint_record.h
@@ -5,22 +5,19 @@ #ifndef CC_PAINT_PAINT_RECORD_H_ #define CC_PAINT_PAINT_RECORD_H_ -#include "cc/paint/paint_export.h" -#include "cc/paint/paint_op_buffer.h" #include "third_party/skia/include/core/SkPicture.h" namespace cc { -// TODO(enne): Don't want to rename the world for this. Using these as the -// same types for now prevents an extra allocation. Probably PaintRecord -// will become an interface in the future. -using PaintRecord = PaintOpBuffer; +using PaintRecord = SkPicture; -// TODO(enne): Remove these if possible, they are really expensive. -CC_PAINT_EXPORT sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record); +inline sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record) { + return record; +} -CC_PAINT_EXPORT sk_sp<const SkPicture> ToSkPicture( - sk_sp<const PaintRecord> record); +inline sk_sp<const SkPicture> ToSkPicture(sk_sp<const PaintRecord> record) { + return record; +} } // namespace cc
diff --git a/cc/paint/paint_recorder.cc b/cc/paint/paint_recorder.cc index c43f965..672f0712 100644 --- a/cc/paint/paint_recorder.cc +++ b/cc/paint/paint_recorder.cc
@@ -4,36 +4,9 @@ #include "cc/paint/paint_recorder.h" -#include "cc/paint/paint_op_buffer.h" - namespace cc { PaintRecorder::PaintRecorder() = default; - PaintRecorder::~PaintRecorder() = default; -PaintCanvas* PaintRecorder::beginRecording(const SkRect& bounds) { - buffer_.reset(new PaintOpBuffer(bounds)); - canvas_.emplace(buffer_.get(), bounds); - return getRecordingCanvas(); -} - -sk_sp<PaintRecord> PaintRecorder::finishRecordingAsPicture() { - // SkPictureRecorder users expect that their saves are automatically - // closed for them. - // - // NOTE: Blink paint in general doesn't appear to need this, but the - // RecordingImageBufferSurface::fallBackToRasterCanvas finishing off the - // current frame depends on this. Maybe we could remove this assumption and - // just have callers do it. - canvas_->restoreToCount(1); - - // Some users (e.g. printing) use the existence of the recording canvas - // to know if recording is finished, so reset it here. - canvas_.reset(); - - buffer_->ShrinkToFit(); - return std::move(buffer_); -} - } // namespace cc
diff --git a/cc/paint/paint_recorder.h b/cc/paint/paint_recorder.h index 7f582b85..2bbea83b 100644 --- a/cc/paint/paint_recorder.h +++ b/cc/paint/paint_recorder.h
@@ -9,36 +9,47 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/optional.h" +#include "cc/paint/paint_canvas.h" #include "cc/paint/paint_record.h" -#include "cc/paint/record_paint_canvas.h" +#include "cc/paint/skia_paint_canvas.h" +#include "third_party/skia/include/core/SkPictureRecorder.h" namespace cc { -class PaintOpBuffer; - class CC_PAINT_EXPORT PaintRecorder { public: PaintRecorder(); ~PaintRecorder(); - PaintCanvas* beginRecording(const SkRect& bounds); + ALWAYS_INLINE PaintCanvas* beginRecording(const SkRect& bounds) { + uint32_t record_flags = 0; + canvas_.emplace(recorder_.beginRecording(bounds, nullptr, record_flags)); + return getRecordingCanvas(); + } - // TODO(enne): should make everything go through the non-rect version. - // See comments in RecordPaintCanvas ctor for why. - PaintCanvas* beginRecording(SkScalar width, SkScalar height) { - return beginRecording(SkRect::MakeWH(width, height)); + ALWAYS_INLINE PaintCanvas* beginRecording(SkScalar width, SkScalar height) { + uint32_t record_flags = 0; + canvas_.emplace( + recorder_.beginRecording(width, height, nullptr, record_flags)); + return getRecordingCanvas(); } // Only valid between between and finish recording. - ALWAYS_INLINE RecordPaintCanvas* getRecordingCanvas() { + ALWAYS_INLINE PaintCanvas* getRecordingCanvas() { return canvas_.has_value() ? &canvas_.value() : nullptr; } - sk_sp<PaintRecord> finishRecordingAsPicture(); + ALWAYS_INLINE sk_sp<PaintRecord> finishRecordingAsPicture() { + sk_sp<SkPicture> picture = recorder_.finishRecordingAsPicture(); + // Some users (e.g. printing) use the existence of the recording canvas + // to know if recording is finished, so reset it here. + canvas_.reset(); + return sk_ref_sp(static_cast<PaintRecord*>(picture.get())); + } private: - sk_sp<PaintOpBuffer> buffer_; - base::Optional<RecordPaintCanvas> canvas_; + SkPictureRecorder recorder_; + base::Optional<SkiaPaintCanvas> canvas_; DISALLOW_COPY_AND_ASSIGN(PaintRecorder); };
diff --git a/cc/paint/record_paint_canvas.cc b/cc/paint/record_paint_canvas.cc deleted file mode 100644 index 7f2ba61..0000000 --- a/cc/paint/record_paint_canvas.cc +++ /dev/null
@@ -1,384 +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 "cc/paint/record_paint_canvas.h" - -#include "base/memory/ptr_util.h" -#include "cc/paint/display_item_list.h" -#include "cc/paint/paint_op_buffer.h" -#include "cc/paint/paint_record.h" -#include "cc/paint/paint_recorder.h" -#include "third_party/skia/include/core/SkAnnotation.h" -#include "third_party/skia/include/core/SkMetaData.h" -#include "third_party/skia/include/utils/SkNWayCanvas.h" - -namespace cc { - -RecordPaintCanvas::RecordPaintCanvas(PaintOpBuffer* buffer, - const SkRect& cull_rect) - : buffer_(buffer), - canvas_(static_cast<int>(std::ceil(cull_rect.right())), - static_cast<int>(std::ceil(cull_rect.bottom()))) { - DCHECK(buffer_); - - // This is part of the "recording canvases have a size, but why" dance. - // By creating a canvas of size (right x bottom) and then clipping it, - // It makes getDeviceClipBounds return the original cull rect, which code - // in GraphicsContextCanvas on Mac expects. (Just creating an SkNoDrawCanvas - // with the cull_rect makes a canvas of size (width x height) instead - // which is incorrect. SkRecorder cheats with private resetForNextCanvas. - canvas_.clipRect(SkRect::Make(cull_rect.roundOut()), SkClipOp::kIntersect, - false); -} - -RecordPaintCanvas::~RecordPaintCanvas() = default; - -SkMetaData& RecordPaintCanvas::getMetaData() { - // This could just be SkMetaData owned by RecordPaintCanvas, but since - // SkCanvas already has one, we might as well use it directly. - return canvas_.getMetaData(); -} - -SkImageInfo RecordPaintCanvas::imageInfo() const { - return canvas_.imageInfo(); -} - -void RecordPaintCanvas::flush() { - // This is a noop when recording. -} - -SkISize RecordPaintCanvas::getBaseLayerSize() const { - return canvas_.getBaseLayerSize(); -} - -bool RecordPaintCanvas::writePixels(const SkImageInfo& info, - const void* pixels, - size_t row_bytes, - int x, - int y) { - NOTREACHED(); - return false; -} - -int RecordPaintCanvas::save() { - buffer_->push<SaveOp>(); - return canvas_.save(); -} - -int RecordPaintCanvas::saveLayer(const SkRect* bounds, - const PaintFlags* flags) { - if (flags) { - if (flags->IsSimpleOpacity()) { - // TODO(enne): maybe more callers should know this and call - // saveLayerAlpha instead of needing to check here. - uint8_t alpha = SkColorGetA(flags->getColor()); - return saveLayerAlpha(bounds, alpha); - } - - // TODO(enne): it appears that image filters affect matrices and color - // matrices affect transparent flags on SkCanvas layers, but it's not clear - // whether those are actually needed and we could just skip ToSkPaint here. - buffer_->push<SaveLayerOp>(bounds, flags); - const SkPaint& paint = ToSkPaint(*flags); - return canvas_.saveLayer(bounds, &paint); - } - buffer_->push<SaveLayerOp>(bounds, flags); - return canvas_.saveLayer(bounds, nullptr); -} - -int RecordPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) { - buffer_->push<SaveLayerAlphaOp>(bounds, alpha); - return canvas_.saveLayerAlpha(bounds, alpha); -} - -void RecordPaintCanvas::restore() { - buffer_->push<RestoreOp>(); - canvas_.restore(); -} - -int RecordPaintCanvas::getSaveCount() const { - return canvas_.getSaveCount(); -} - -void RecordPaintCanvas::restoreToCount(int save_count) { - DCHECK_GE(save_count, 1); - int diff = canvas_.getSaveCount() - save_count; - DCHECK_GE(diff, 0); - for (int i = 0; i < diff; ++i) - restore(); -} - -void RecordPaintCanvas::translate(SkScalar dx, SkScalar dy) { - buffer_->push<TranslateOp>(dx, dy); - canvas_.translate(dx, dy); -} - -void RecordPaintCanvas::scale(SkScalar sx, SkScalar sy) { - buffer_->push<ScaleOp>(sx, sy); - canvas_.scale(sx, sy); -} - -void RecordPaintCanvas::rotate(SkScalar degrees) { - buffer_->push<RotateOp>(degrees); - canvas_.rotate(degrees); -} - -void RecordPaintCanvas::concat(const SkMatrix& matrix) { - buffer_->push<ConcatOp>(matrix); - canvas_.concat(matrix); -} - -void RecordPaintCanvas::setMatrix(const SkMatrix& matrix) { - buffer_->push<SetMatrixOp>(matrix); - canvas_.setMatrix(matrix); -} - -void RecordPaintCanvas::clipRect(const SkRect& rect, - SkClipOp op, - bool antialias) { - buffer_->push<ClipRectOp>(rect, op, antialias); - canvas_.clipRect(rect, op, antialias); -} - -void RecordPaintCanvas::clipRRect(const SkRRect& rrect, - SkClipOp op, - bool antialias) { - // TODO(enne): does this happen? Should the caller know this? - if (rrect.isRect()) { - clipRect(rrect.getBounds(), op, antialias); - return; - } - buffer_->push<ClipRRectOp>(rrect, op, antialias); - canvas_.clipRRect(rrect, op, antialias); -} - -void RecordPaintCanvas::clipPath(const SkPath& path, - SkClipOp op, - bool antialias) { - if (!path.isInverseFillType() && canvas_.getTotalMatrix().rectStaysRect()) { - // TODO(enne): do these cases happen? should the caller know that this isn't - // a path? - SkRect rect; - if (path.isRect(&rect)) { - clipRect(rect, op, antialias); - return; - } - SkRRect rrect; - if (path.isOval(&rect)) { - rrect.setOval(rect); - clipRRect(rrect, op, antialias); - return; - } - if (path.isRRect(&rrect)) { - clipRRect(rrect, op, antialias); - return; - } - } - - buffer_->push<ClipPathOp>(path, op, antialias); - canvas_.clipPath(path, op, antialias); - return; -} - -bool RecordPaintCanvas::quickReject(const SkRect& rect) const { - return canvas_.quickReject(rect); -} - -bool RecordPaintCanvas::quickReject(const SkPath& path) const { - return canvas_.quickReject(path); -} - -SkRect RecordPaintCanvas::getLocalClipBounds() const { - return canvas_.getLocalClipBounds(); -} - -bool RecordPaintCanvas::getLocalClipBounds(SkRect* bounds) const { - return canvas_.getLocalClipBounds(bounds); -} - -SkIRect RecordPaintCanvas::getDeviceClipBounds() const { - return canvas_.getDeviceClipBounds(); -} - -bool RecordPaintCanvas::getDeviceClipBounds(SkIRect* bounds) const { - return canvas_.getDeviceClipBounds(bounds); -} - -void RecordPaintCanvas::drawColor(SkColor color, SkBlendMode mode) { - buffer_->push<DrawColorOp>(color, mode); -} - -void RecordPaintCanvas::clear(SkColor color) { - buffer_->push<DrawColorOp>(color, SkBlendMode::kSrc); -} - -void RecordPaintCanvas::drawLine(SkScalar x0, - SkScalar y0, - SkScalar x1, - SkScalar y1, - const PaintFlags& flags) { - buffer_->push<DrawLineOp>(x0, y0, x1, y1, flags); -} - -void RecordPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) { - buffer_->push<DrawRectOp>(rect, flags); -} - -void RecordPaintCanvas::drawIRect(const SkIRect& rect, - const PaintFlags& flags) { - buffer_->push<DrawIRectOp>(rect, flags); -} - -void RecordPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) { - buffer_->push<DrawOvalOp>(oval, flags); -} - -void RecordPaintCanvas::drawRRect(const SkRRect& rrect, - const PaintFlags& flags) { - buffer_->push<DrawRRectOp>(rrect, flags); -} - -void RecordPaintCanvas::drawDRRect(const SkRRect& outer, - const SkRRect& inner, - const PaintFlags& flags) { - if (outer.isEmpty()) - return; - if (inner.isEmpty()) { - drawRRect(outer, flags); - return; - } - buffer_->push<DrawDRRectOp>(outer, inner, flags); -} - -void RecordPaintCanvas::drawCircle(SkScalar cx, - SkScalar cy, - SkScalar radius, - const PaintFlags& flags) { - buffer_->push<DrawCircleOp>(cx, cy, radius, flags); -} - -void RecordPaintCanvas::drawArc(const SkRect& oval, - SkScalar start_angle, - SkScalar sweep_angle, - bool use_center, - const PaintFlags& flags) { - buffer_->push<DrawArcOp>(oval, start_angle, sweep_angle, use_center, flags); -} - -void RecordPaintCanvas::drawRoundRect(const SkRect& rect, - SkScalar rx, - SkScalar ry, - const PaintFlags& flags) { - // TODO(enne): move this into base class? - if (rx > 0 && ry > 0) { - SkRRect rrect; - rrect.setRectXY(rect, rx, ry); - drawRRect(rrect, flags); - } else { - drawRect(rect, flags); - } -} - -void RecordPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) { - buffer_->push<DrawPathOp>(path, flags); -} - -void RecordPaintCanvas::drawImage(const PaintImage& image, - SkScalar left, - SkScalar top, - const PaintFlags* flags) { - buffer_->push<DrawImageOp>(image, left, top, flags); -} - -void RecordPaintCanvas::drawImageRect(const PaintImage& image, - const SkRect& src, - const SkRect& dst, - const PaintFlags* flags, - SrcRectConstraint constraint) { - buffer_->push<DrawImageRectOp>(image, src, dst, flags, constraint); -} - -void RecordPaintCanvas::drawBitmap(const SkBitmap& bitmap, - SkScalar left, - SkScalar top, - const PaintFlags* flags) { - // TODO(enne): Move into base class? - if (bitmap.drawsNothing()) - return; - drawImage(PaintImage(SkImage::MakeFromBitmap(bitmap), - PaintImage::AnimationType::UNKNOWN, - PaintImage::CompletionState::UNKNOWN), - left, top, flags); -} - -void RecordPaintCanvas::drawText(const void* text, - size_t byte_length, - SkScalar x, - SkScalar y, - const PaintFlags& flags) { - buffer_->push_with_data<DrawTextOp>(text, byte_length, x, y, flags); -} - -void RecordPaintCanvas::drawPosText(const void* text, - size_t byte_length, - const SkPoint pos[], - const PaintFlags& flags) { - size_t count = ToSkPaint(flags).countText(text, byte_length); - buffer_->push_with_data_array<DrawPosTextOp>(text, byte_length, pos, count, - flags); -} - -void RecordPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob, - SkScalar x, - SkScalar y, - const PaintFlags& flags) { - buffer_->push<DrawTextBlobOp>(blob, x, y, flags); -} - -void RecordPaintCanvas::drawDisplayItemList( - scoped_refptr<DisplayItemList> list) { - buffer_->push<DrawDisplayItemListOp>(list); -} - -void RecordPaintCanvas::drawPicture(sk_sp<const PaintRecord> record) { - // TODO(enne): If this is small, maybe flatten it? - buffer_->push<DrawRecordOp>(record); -} - -bool RecordPaintCanvas::isClipEmpty() const { - return canvas_.isClipEmpty(); -} - -bool RecordPaintCanvas::isClipRect() const { - return canvas_.isClipRect(); -} - -const SkMatrix& RecordPaintCanvas::getTotalMatrix() const { - return canvas_.getTotalMatrix(); -} - -void RecordPaintCanvas::temporary_internal_describeTopLayer( - SkMatrix* matrix, - SkIRect* clip_bounds) { - return canvas_.temporary_internal_describeTopLayer(matrix, clip_bounds); -} - -bool RecordPaintCanvas::ToPixmap(SkPixmap* output) { - // TODO(enne): It'd be nice to make this NOTREACHED() or remove this from - // RecordPaintCanvas, but this is used by GraphicsContextCanvas for knowing - // whether or not it can raster directly into pixels with Cg. - return false; -} - -void RecordPaintCanvas::Annotate(AnnotationType type, - const SkRect& rect, - sk_sp<SkData> data) { - buffer_->push<AnnotateOp>(type, rect, data); -} - -void RecordPaintCanvas::PlaybackPaintRecord(sk_sp<const PaintRecord> record) { - drawPicture(record); -} - -} // namespace cc
diff --git a/cc/paint/record_paint_canvas.h b/cc/paint/record_paint_canvas.h deleted file mode 100644 index 15f0102..0000000 --- a/cc/paint/record_paint_canvas.h +++ /dev/null
@@ -1,160 +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 CC_PAINT_RECORD_PAINT_CANVAS_H_ -#define CC_PAINT_RECORD_PAINT_CANVAS_H_ - -#include <memory> - -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/macros.h" -#include "build/build_config.h" -#include "cc/paint/paint_canvas.h" -#include "cc/paint/paint_flags.h" -#include "cc/paint/paint_record.h" -#include "third_party/skia/include/utils/SkNoDrawCanvas.h" - -namespace cc { - -class PaintOpBuffer; -class PaintFlags; - -class CC_PAINT_EXPORT RecordPaintCanvas final : public PaintCanvas { - public: - explicit RecordPaintCanvas(PaintOpBuffer* buffer, const SkRect& cull_rect); - ~RecordPaintCanvas() override; - - SkMetaData& getMetaData() override; - SkImageInfo imageInfo() const override; - - void flush() override; - - SkISize getBaseLayerSize() const override; - bool writePixels(const SkImageInfo& info, - const void* pixels, - size_t row_bytes, - int x, - int y) override; - int save() override; - int saveLayer(const SkRect* bounds, const PaintFlags* flags) override; - int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) override; - - void restore() override; - int getSaveCount() const override; - void restoreToCount(int save_count) override; - void translate(SkScalar dx, SkScalar dy) override; - void scale(SkScalar sx, SkScalar sy) override; - void rotate(SkScalar degrees) override; - void concat(const SkMatrix& matrix) override; - void setMatrix(const SkMatrix& matrix) override; - - void clipRect(const SkRect& rect, SkClipOp op, bool antialias) override; - void clipRRect(const SkRRect& rrect, SkClipOp op, bool antialias) override; - void clipPath(const SkPath& path, SkClipOp op, bool antialias) override; - bool quickReject(const SkRect& rect) const override; - bool quickReject(const SkPath& path) const override; - SkRect getLocalClipBounds() const override; - bool getLocalClipBounds(SkRect* bounds) const override; - SkIRect getDeviceClipBounds() const override; - bool getDeviceClipBounds(SkIRect* bounds) const override; - void drawColor(SkColor color, SkBlendMode mode) override; - void clear(SkColor color) override; - - void drawLine(SkScalar x0, - SkScalar y0, - SkScalar x1, - SkScalar y1, - const PaintFlags& flags) override; - void drawRect(const SkRect& rect, const PaintFlags& flags) override; - void drawIRect(const SkIRect& rect, const PaintFlags& flags) override; - void drawOval(const SkRect& oval, const PaintFlags& flags) override; - void drawRRect(const SkRRect& rrect, const PaintFlags& flags) override; - void drawDRRect(const SkRRect& outer, - const SkRRect& inner, - const PaintFlags& flags) override; - void drawCircle(SkScalar cx, - SkScalar cy, - SkScalar radius, - const PaintFlags& flags) override; - void drawArc(const SkRect& oval, - SkScalar start_angle, - SkScalar sweep_angle, - bool use_center, - const PaintFlags& flags) override; - void drawRoundRect(const SkRect& rect, - SkScalar rx, - SkScalar ry, - const PaintFlags& flags) override; - void drawPath(const SkPath& path, const PaintFlags& flags) override; - void drawImage(const PaintImage& image, - SkScalar left, - SkScalar top, - const PaintFlags* flags) override; - void drawImageRect(const PaintImage& image, - const SkRect& src, - const SkRect& dst, - const PaintFlags* flags, - SrcRectConstraint constraint) override; - void drawBitmap(const SkBitmap& bitmap, - SkScalar left, - SkScalar top, - const PaintFlags* flags) override; - - void drawText(const void* text, - size_t byte_length, - SkScalar x, - SkScalar y, - const PaintFlags& flags) override; - void drawPosText(const void* text, - size_t byte_length, - const SkPoint pos[], - const PaintFlags& flags) override; - void drawTextBlob(sk_sp<SkTextBlob> blob, - SkScalar x, - SkScalar y, - const PaintFlags& flags) override; - - void drawDisplayItemList( - scoped_refptr<DisplayItemList> display_item_list) override; - - void drawPicture(sk_sp<const PaintRecord> record) override; - - bool isClipEmpty() const override; - bool isClipRect() const override; - const SkMatrix& getTotalMatrix() const override; - - void temporary_internal_describeTopLayer(SkMatrix* matrix, - SkIRect* clip_bounds) override; - - bool ToPixmap(SkPixmap* output) override; - void Annotate(AnnotationType type, - const SkRect& rect, - sk_sp<SkData> data) override; - - void PlaybackPaintRecord(sk_sp<const PaintRecord> record) override; - - // Don't shadow non-virtual helper functions. - using PaintCanvas::clipRect; - using PaintCanvas::clipRRect; - using PaintCanvas::clipPath; - using PaintCanvas::drawBitmap; - using PaintCanvas::drawColor; - using PaintCanvas::drawImage; - using PaintCanvas::drawPicture; - - private: - PaintOpBuffer* buffer_; - - // TODO(enne): Although RecordPaintCanvas is mostly a write-only interface - // where paint commands are stored, occasionally users of PaintCanvas want - // to ask stateful questions mid-stream of clip and transform state. - // To avoid duplicating all this code (for now?), just forward to an SkCanvas - // that's not backed by anything but can answer these questions. - SkNoDrawCanvas canvas_; -}; - -} // namespace cc - -#endif // CC_PAINT_RECORD_PAINT_CANVAS_H_
diff --git a/cc/paint/skia_paint_canvas.cc b/cc/paint/skia_paint_canvas.cc index 501ccdf..bfc38b6 100644 --- a/cc/paint/skia_paint_canvas.cc +++ b/cc/paint/skia_paint_canvas.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 "cc/paint/skia_paint_canvas.h" +#include "cc/paint/paint_canvas.h" #include "base/memory/ptr_util.h" #include "cc/paint/display_item_list.h" @@ -58,7 +58,7 @@ return canvas_->saveLayer(bounds, ToSkPaint(flags)); } -int SkiaPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) { +int SkiaPaintCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { return canvas_->saveLayerAlpha(bounds, alpha); }
diff --git a/cc/paint/skia_paint_canvas.h b/cc/paint/skia_paint_canvas.h index 1bd23f0..47dba86 100644 --- a/cc/paint/skia_paint_canvas.h +++ b/cc/paint/skia_paint_canvas.h
@@ -46,7 +46,7 @@ int y) override; int save() override; int saveLayer(const SkRect* bounds, const PaintFlags* flags) override; - int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) override; + int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) override; void restore() override; int getSaveCount() const override;
diff --git a/cc/test/test_skcanvas.cc b/cc/test/test_skcanvas.cc deleted file mode 100644 index e45f42de..0000000 --- a/cc/test/test_skcanvas.cc +++ /dev/null
@@ -1,26 +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 "cc/test/test_skcanvas.h" - -namespace cc { - -SaveCountingCanvas::SaveCountingCanvas() : SkNoDrawCanvas(100, 100) {} - -SkCanvas::SaveLayerStrategy SaveCountingCanvas::getSaveLayerStrategy( - const SaveLayerRec& rec) { - save_count_++; - return SkNoDrawCanvas::getSaveLayerStrategy(rec); -} - -void SaveCountingCanvas::willRestore() { - restore_count_++; -} - -void SaveCountingCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) { - draw_rect_ = rect; - paint_ = paint; -} - -} // namespace cc
diff --git a/cc/test/test_skcanvas.h b/cc/test/test_skcanvas.h deleted file mode 100644 index 2b130a4..0000000 --- a/cc/test/test_skcanvas.h +++ /dev/null
@@ -1,31 +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 CC_TEST_TEST_SKCANVAS_H_ -#define CC_TEST_TEST_SKCANVAS_H_ - -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/utils/SkNoDrawCanvas.h" - -namespace cc { - -class SaveCountingCanvas : public SkNoDrawCanvas { - public: - SaveCountingCanvas(); - - // Note: getSaveLayerStrategy is used as "willSave", as willSave - // is not always called. - SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override; - void willRestore() override; - void onDrawRect(const SkRect& rect, const SkPaint& paint) override; - - int save_count_ = 0; - int restore_count_ = 0; - SkRect draw_rect_; - SkPaint paint_; -}; - -} // namespace cc - -#endif // CC_TEST_TEST_SKCANVAS_H_
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index aff7e4b..36ce866 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -596,7 +596,7 @@ @Override public void onPageLoadFinished(Tab tab) { postDeferredStartupIfNeeded(); - OfflinePageUtils.showOfflineSnackbarIfNecessary(ChromeActivity.this, tab); + OfflinePageUtils.showOfflineSnackbarIfNecessary(tab); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java index d017519..04015df1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java
@@ -4,17 +4,22 @@ package org.chromium.chrome.browser.offlinepages; -import android.content.Context; +import android.app.Activity; +import org.chromium.base.ActivityState; +import org.chromium.base.ApplicationStatus; +import org.chromium.base.ApplicationStatus.ActivityStateListener; import org.chromium.base.Log; import org.chromium.base.VisibleForTesting; +import org.chromium.base.metrics.RecordUserAction; +import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.snackbar.SnackbarManager; import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver; -import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModelObserver; +import org.chromium.chrome.browser.tabmodel.TabModelSelector; +import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver; import org.chromium.net.NetworkChangeNotifier; import java.util.HashMap; @@ -52,52 +57,50 @@ } } - /** Class for observing TabModel without implementing a full interface. */ - private class TabModelObserverImpl extends EmptyTabModelObserver { - public TabModelObserverImpl(TabModel model) { - if (model != null) { - model.addObserver(this); - } - } + private static Map<Activity, OfflinePageTabObserver> sObservers; - @Override - public void tabRemoved(Tab tab) { - Log.d(TAG, "tabRemoved"); - OfflinePageTabObserver.this.stopObservingTab(tab); - OfflinePageTabObserver.this.mSnackbarManager.dismissSnackbars(mSnackbarController); - } - } - - private Context mContext; - private SnackbarManager mSnackbarManager; - private SnackbarController mSnackbarController; - private TabModelObserverImpl mTabModelObserver; - + private final SnackbarManager mSnackbarManager; + private final SnackbarController mSnackbarController; + private final TabModelSelector mTabModelSelector; + private final TabModelSelectorTabModelObserver mTabModelObserver; /** Map of observed tabs. */ private final Map<Integer, TabState> mObservedTabs = new HashMap<>(); + private boolean mIsObservingNetworkChanges; /** Current tab, kept track of for the network change notification. */ private Tab mCurrentTab; - private static OfflinePageTabObserver sInstance; - - static void init(Context context, TabModel tabModel, SnackbarManager manager, - SnackbarController controller) { - if (sInstance == null) { - sInstance = new OfflinePageTabObserver(context, tabModel, manager, controller); - return; + static OfflinePageTabObserver getObserverForActivity(ChromeActivity activity) { + ensureObserverMapInitialized(); + OfflinePageTabObserver observer = sObservers.get(activity); + if (observer == null) { + observer = new OfflinePageTabObserver(activity.getTabModelSelector(), + activity.getSnackbarManager(), + createReloadSnackbarController(activity.getTabModelSelector())); + sObservers.put(activity, observer); } - sInstance.reinitialize(context, tabModel, manager, controller); + return observer; } - static OfflinePageTabObserver getInstance() { - return sInstance; + private static void ensureObserverMapInitialized() { + if (sObservers != null) return; + sObservers = new HashMap<>(); + ApplicationStatus.registerStateListenerForAllActivities(new ActivityStateListener() { + @Override + public void onActivityStateChange(Activity activity, int newState) { + if (newState != ActivityState.DESTROYED) return; + OfflinePageTabObserver observer = sObservers.remove(activity); + if (observer == null) return; + observer.destroy(); + } + }); } @VisibleForTesting - static void setInstanceForTesting(OfflinePageTabObserver instance) { - sInstance = instance; + static void setObserverForTesting(Activity activity, OfflinePageTabObserver observer) { + ensureObserverMapInitialized(); + sObservers.put(activity, observer); } /** @@ -105,22 +108,31 @@ * @param tab The tab we are adding an observer for. */ public static void addObserverForTab(Tab tab) { - assert getInstance() != null; - getInstance().startObservingTab(tab); - getInstance().maybeShowReloadSnackbar(tab, false); + OfflinePageTabObserver observer = getObserverForActivity(tab.getActivity()); + assert observer != null; + observer.startObservingTab(tab); + observer.maybeShowReloadSnackbar(tab, false); } /** * Builds a new OfflinePageTabObserver. - * @param context Android context. - * @param tabModel Tab model managing the observerd tab. + * @param tabModelSelector Tab model selector for the activity. * @param snackbarManager The snackbar manager to show and dismiss snackbars. * @param snackbarController Controller to use to build the snackbar. */ - OfflinePageTabObserver(Context context, TabModel tabModel, SnackbarManager snackbarManager, + OfflinePageTabObserver(TabModelSelector tabModelSelector, SnackbarManager snackbarManager, SnackbarController snackbarController) { - reinitialize(context, tabModel, snackbarManager, snackbarController); - + mSnackbarManager = snackbarManager; + mSnackbarController = snackbarController; + mTabModelSelector = tabModelSelector; + mTabModelObserver = new TabModelSelectorTabModelObserver(tabModelSelector) { + @Override + public void tabRemoved(Tab tab) { + Log.d(TAG, "tabRemoved"); + stopObservingTab(tab); + mSnackbarManager.dismissSnackbars(mSnackbarController); + } + }; // The first time observer is created snackbar has net yet been shown. mIsObservingNetworkChanges = false; } @@ -209,6 +221,22 @@ } } + private void destroy() { + mTabModelObserver.destroy(); + if (!mObservedTabs.isEmpty()) { + for (Integer tabId : mObservedTabs.keySet()) { + Tab tab = mTabModelSelector.getTabById(tabId); + if (tab == null) continue; + tab.removeObserver(this); + } + mObservedTabs.clear(); + } + if (isObservingNetworkChanges()) { + stopObservingNetworkChanges(); + mIsObservingNetworkChanges = false; + } + } + // Methods from ConnectionTypeObserver. @Override public void onConnectionTypeChanged(int connectionType) { @@ -273,7 +301,7 @@ @VisibleForTesting void showReloadSnackbar(Tab tab) { OfflinePageUtils.showReloadSnackbar( - mContext, mSnackbarManager, mSnackbarController, tab.getId()); + tab.getActivity(), mSnackbarManager, mSnackbarController, tab.getId()); } @VisibleForTesting @@ -291,15 +319,31 @@ return mTabModelObserver; } - boolean isCurrentContext(Context context) { - return mContext == context; - } + /** + * Gets a snackbar controller that we can use to show our snackbar. + * @param tabModelSelector used to retrieve a tab by ID + */ + private static SnackbarController createReloadSnackbarController( + final TabModelSelector tabModelSelector) { + Log.d(TAG, "building snackbar controller"); - void reinitialize(Context context, TabModel tabModel, SnackbarManager manager, - SnackbarController controller) { - mContext = context; - mSnackbarManager = manager; - mSnackbarController = controller; - mTabModelObserver = this.new TabModelObserverImpl(tabModel); + return new SnackbarController() { + @Override + public void onAction(Object actionData) { + assert actionData != null; + int tabId = (int) actionData; + RecordUserAction.record("OfflinePages.ReloadButtonClicked"); + Tab foundTab = tabModelSelector.getTabById(tabId); + if (foundTab == null) return; + // Delegates to Tab to reload the page. Tab will send the correct header in order to + // load the right page. + foundTab.reload(); + } + + @Override + public void onDismissNoAction(Object actionData) { + RecordUserAction.record("OfflinePages.ReloadButtonNotClicked"); + } + }; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java index 17231325..47709b4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
@@ -18,7 +18,6 @@ import org.chromium.base.StreamUtil; import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; -import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.UrlConstants; @@ -196,32 +195,9 @@ /** * Shows the snackbar for the current tab to provide offline specific information if needed. - * @param activity The activity owning the tab. * @param tab The current tab. */ - public static void showOfflineSnackbarIfNecessary(ChromeActivity activity, Tab tab) { - if (OfflinePageTabObserver.getInstance() == null - || !OfflinePageTabObserver.getInstance().isCurrentContext( - activity.getBaseContext())) { - SnackbarController snackbarController = - createReloadSnackbarController(activity.getTabModelSelector()); - OfflinePageTabObserver.init(activity.getBaseContext(), - activity.getTabModelSelector().getModel(false), activity.getSnackbarManager(), - snackbarController); - } - - showOfflineSnackbarIfNecessary(tab); - } - - /** - * Shows the snackbar for the current tab to provide offline specific information if needed. - * This method is used by testing for dependency injecting a snackbar controller. - * @param context android context - * @param snackbarManager The snackbar manager to show and dismiss snackbars. - * @param tab The current tab. - * @param snackbarController The snackbar controller to control snackbar behavior. - */ - static void showOfflineSnackbarIfNecessary(Tab tab) { + public static void showOfflineSnackbarIfNecessary(Tab tab) { // Set up the tab observer to watch for the tab being shown (not hidden) and a valid // connection. When both conditions are met a snackbar is shown. OfflinePageTabObserver.addObserverForTab(tab); @@ -245,33 +221,6 @@ snackbarManager.showSnackbar(snackbar); } - /** - * Gets a snackbar controller that we can use to show our snackbar. - * @param tabModelSelector used to retrieve a tab by ID - */ - private static SnackbarController createReloadSnackbarController( - final TabModelSelector tabModelSelector) { - Log.d(TAG, "building snackbar controller"); - - return new SnackbarController() { - @Override - public void onAction(Object actionData) { - assert actionData != null; - int tabId = (int) actionData; - RecordUserAction.record("OfflinePages.ReloadButtonClicked"); - Tab foundTab = tabModelSelector.getTabById(tabId); - if (foundTab == null) return; - // Delegates to Tab to reload the page. Tab will send the correct header in order to - // load the right page. - foundTab.reload(); - } - - @Override - public void onDismissNoAction(Object actionData) { - RecordUserAction.record("OfflinePages.ReloadButtonNotClicked"); - } - }; - } /** * Records UMA data when the Offline Pages Background Load service awakens.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java index 3904cf5..a08fc8f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -244,6 +244,16 @@ @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + if (!canMoveSheet()) { + // Currently it's possible to enter the tab switcher after an onScroll() event has + // began. If that happens, reset the sheet offset and return false to end the scroll + // event. + // TODO(twellington): Remove this after it is no longer possible to close the NTP + // while moving the BottomSheet. + setSheetState(SHEET_STATE_PEEK, false); + return false; + } + // Only start scrolling if the scroll is up or down. If the user is already scrolling, // continue moving the sheet. float slope = Math.abs(distanceX) > 0f ? Math.abs(distanceY) / Math.abs(distanceX) : 0f;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java index 9e2cb362..43e5b9c9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java
@@ -168,9 +168,10 @@ ThreadUtils.runOnUiThread(new Runnable() { @Override public void run() { - OfflinePageTabObserver.init(getActivity().getBaseContext(), - getActivity().getTabModelSelector().getModel(false), - getActivity().getSnackbarManager(), mockSnackbarController); + OfflinePageTabObserver offlineObserver = + new OfflinePageTabObserver(getActivity().getTabModelSelector(), + getActivity().getSnackbarManager(), mockSnackbarController); + OfflinePageTabObserver.setObserverForTesting(getActivity(), offlineObserver); OfflinePageUtils.showOfflineSnackbarIfNecessary(getActivity().getActivityTab()); // Pretend that we went online, this should cause the snackbar to show.
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java index de01ab6c..6eb6186 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java
@@ -6,20 +6,17 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.any; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.eq; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import android.content.Context; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; - import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; @@ -27,10 +24,11 @@ import org.chromium.base.BaseChromiumApplication; import org.chromium.base.test.util.Feature; +import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.snackbar.SnackbarManager; import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tabmodel.TabModel; +import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.testing.local.LocalRobolectricTestRunner; /** @@ -43,16 +41,17 @@ // Using a null tab, as it cannot be mocked. TabHelper will help return proper mocked responses. private static final int TAB_ID = 77; - @Mock private Context mContext; @Mock - private TabModel mTabModel; + private ChromeActivity mActivity; + @Mock + private TabModelSelector mTabModelSelector; @Mock private SnackbarManager mSnackbarManager; @Mock private SnackbarController mSnackbarController; @Mock private Tab mTab; private OfflinePageTabObserver createObserver() { OfflinePageTabObserver observer = spy(new OfflinePageTabObserver( - mContext, mTabModel, mSnackbarManager, mSnackbarController)); + mTabModelSelector, mSnackbarManager, mSnackbarController)); // Mocking out all of the calls that touch on NetworkChangeNotifier, which we cannot // directly mock out. doNothing().when(observer).startObservingNetworkChanges(); @@ -78,6 +77,7 @@ doReturn(false).when(mTab).isFrozen(); doReturn(false).when(mTab).isHidden(); doReturn(true).when(mTab).isOfflinePage(); + doReturn(mActivity).when(mTab).getActivity(); // Setting up mock snackbar manager. doNothing().when(mSnackbarManager).dismissSnackbars(eq(mSnackbarController)); @@ -446,7 +446,7 @@ @Feature({"OfflinePages"}) public void testAddObserverForTab() { OfflinePageTabObserver observer = createObserver(); - OfflinePageTabObserver.setInstanceForTesting(observer); + OfflinePageTabObserver.setObserverForTesting(mActivity, observer); disconnect(observer, false); showTab(null); @@ -464,7 +464,7 @@ @Feature({"OfflinePages"}) public void testAddObserverForTab_whenConnected() { OfflinePageTabObserver observer = createObserver(); - OfflinePageTabObserver.setInstanceForTesting(observer); + OfflinePageTabObserver.setObserverForTesting(mActivity, observer); connect(observer, false); showTab(null);
diff --git a/chrome/browser/chromeos/arc/arc_util.cc b/chrome/browser/chromeos/arc/arc_util.cc index fc6ce1c..0153369 100644 --- a/chrome/browser/chromeos/arc/arc_util.cc +++ b/chrome/browser/chromeos/arc/arc_util.cc
@@ -205,9 +205,13 @@ return profile->GetPrefs()->IsManagedPreference(prefs::kArcEnabled); } -void SetArcPlayStoreEnabledForProfile(Profile* profile, bool enabled) { +bool SetArcPlayStoreEnabledForProfile(Profile* profile, bool enabled) { DCHECK(IsArcAllowedForProfile(profile)); if (IsArcPlayStoreEnabledPreferenceManagedForProfile(profile)) { + if (enabled && !IsArcPlayStoreEnabledForProfile(profile)) { + LOG(WARNING) << "Attempt to enable disabled by policy ARC."; + return false; + } VLOG(1) << "Google-Play-Store-enabled pref is managed. Request to " << (enabled ? "enable" : "disable") << " Play Store is not stored"; // Need update ARC session manager manually for managed case in order to @@ -217,14 +221,15 @@ ArcSessionManager* arc_session_manager = ArcSessionManager::Get(); // |arc_session_manager| can be nullptr in unit_tests. if (!arc_session_manager) - return; + return false; if (enabled) arc_session_manager->RequestEnable(); else arc_session_manager->RequestDisable(); - return; + return true; } profile->GetPrefs()->SetBoolean(prefs::kArcEnabled, enabled); + return true; } bool AreArcAllOptInPreferencesManagedForProfile(const Profile* profile) {
diff --git a/chrome/browser/chromeos/arc/arc_util.h b/chrome/browser/chromeos/arc/arc_util.h index 80b8a9f..d0da128 100644 --- a/chrome/browser/chromeos/arc/arc_util.h +++ b/chrome/browser/chromeos/arc/arc_util.h
@@ -92,8 +92,9 @@ // the given |profile|. // TODO(hidehiko): De-couple the concept to enable ARC system and opt-in // to use Google Play Store. Note that there is a plan to use ARC without -// Google Play Store, then ARC can run without opt-in. -void SetArcPlayStoreEnabledForProfile(Profile* profile, bool enabled); +// Google Play Store, then ARC can run without opt-in. Returns false in case +// enabled state of the Play Store cannot be changed. +bool SetArcPlayStoreEnabledForProfile(Profile* profile, bool enabled); // Returns whether all ARC related OptIn preferences (i.e. // ArcBackupRestoreEnabled and ArcLocationServiceEnabled) are managed.
diff --git a/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc b/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc index e50590e4..bea0a0e8 100644 --- a/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc +++ b/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
@@ -28,8 +28,10 @@ #include "extensions/common/permissions/permissions_data.h" #if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/login/lock/screen_locker.h" #include "chrome/browser/chromeos/system/input_device_settings.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/session_manager_client.h" #include "components/user_manager/user.h" @@ -380,6 +382,45 @@ return RespondNow(OneArgument(std::move(values))); } +ExtensionFunction::ResponseAction +AutotestPrivateGetPlayStoreStateFunction::Run() { + DVLOG(1) << "AutotestPrivateGetPlayStoreStateFunction"; + api::autotest_private::PlayStoreState play_store_state; + play_store_state.allowed = false; +#if defined(OS_CHROMEOS) + Profile* profile = ProfileManager::GetActiveUserProfile(); + if (arc::IsArcAllowedForProfile(profile)) { + play_store_state.allowed = true; + play_store_state.enabled = + base::MakeUnique<bool>(arc::IsArcPlayStoreEnabledForProfile(profile)); + play_store_state.managed = base::MakeUnique<bool>( + arc::IsArcPlayStoreEnabledPreferenceManagedForProfile(profile)); + } +#endif + return RespondNow(OneArgument(play_store_state.ToValue())); +} + +ExtensionFunction::ResponseAction +AutotestPrivateSetPlayStoreEnabledFunction::Run() { + DVLOG(1) << "AutotestPrivateSetPlayStoreEnabledFunction"; + std::unique_ptr<api::autotest_private::SetPlayStoreEnabled::Params> params( + api::autotest_private::SetPlayStoreEnabled::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params); +#if defined(OS_CHROMEOS) + Profile* profile = ProfileManager::GetActiveUserProfile(); + if (arc::IsArcAllowedForProfile(profile)) { + if (!arc::SetArcPlayStoreEnabledForProfile(profile, params->enabled)) { + return RespondNow( + Error("ARC enabled state cannot be changed for the current user")); + } + return RespondNow(NoArguments()); + } else { + return RespondNow(Error("ARC is not available for the current user")); + } +#endif + return RespondNow(Error("ARC is not available for the current platform")); +} + static base::LazyInstance<BrowserContextKeyedAPIFactory<AutotestPrivateAPI>>:: DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
diff --git a/chrome/browser/extensions/api/autotest_private/autotest_private_api.h b/chrome/browser/extensions/api/autotest_private/autotest_private_api.h index a84c368..a70c709 100644 --- a/chrome/browser/extensions/api/autotest_private/autotest_private_api.h +++ b/chrome/browser/extensions/api/autotest_private/autotest_private_api.h
@@ -172,6 +172,28 @@ ResponseAction Run() override; }; +class AutotestPrivateGetPlayStoreStateFunction + : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("autotestPrivate.getPlayStoreState", + AUTOTESTPRIVATE_GETPLAYSTORESTATE) + + private: + ~AutotestPrivateGetPlayStoreStateFunction() override {} + ResponseAction Run() override; +}; + +class AutotestPrivateSetPlayStoreEnabledFunction + : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("autotestPrivate.setPlayStoreEnabled", + AUTOTESTPRIVATE_SETPLAYSTOREENABLED) + + private: + ~AutotestPrivateSetPlayStoreEnabledFunction() override {} + ResponseAction Run() override; +}; + // Don't kill the browser when we're in a browser test. void SetAutotestPrivateTest();
diff --git a/chrome/browser/resources/plugin_metadata/plugins_linux.json b/chrome/browser/resources/plugin_metadata/plugins_linux.json index 37a64d5..2931047 100644 --- a/chrome/browser/resources/plugin_metadata/plugins_linux.json +++ b/chrome/browser/resources/plugin_metadata/plugins_linux.json
@@ -1,5 +1,5 @@ { - "x-version": 20, + "x-version": 21, "google-talk": { "mime_types": [ ], @@ -80,9 +80,9 @@ ], "versions": [ { - "version": "24.0.0.221", + "version": "25.0.0.148", "status": "up_to_date", - "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-04.html" + "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-10.html" } ], "lang": "en-US",
diff --git a/chrome/browser/resources/plugin_metadata/plugins_mac.json b/chrome/browser/resources/plugin_metadata/plugins_mac.json index 2543b4e..a07eb278 100644 --- a/chrome/browser/resources/plugin_metadata/plugins_mac.json +++ b/chrome/browser/resources/plugin_metadata/plugins_mac.json
@@ -1,5 +1,5 @@ { - "x-version": 26, + "x-version": 27, "google-talk": { "mime_types": [ ], @@ -115,9 +115,9 @@ ], "versions": [ { - "version": "24.0.0.221", + "version": "25.0.0.148", "status": "requires_authorization", - "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-04.html" + "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-10.html" } ], "lang": "en-US",
diff --git a/chrome/browser/resources/plugin_metadata/plugins_win.json b/chrome/browser/resources/plugin_metadata/plugins_win.json index c005be2..0f4a928 100644 --- a/chrome/browser/resources/plugin_metadata/plugins_win.json +++ b/chrome/browser/resources/plugin_metadata/plugins_win.json
@@ -1,5 +1,5 @@ { - "x-version": 35, + "x-version": 36, "google-talk": { "mime_types": [ ], @@ -137,9 +137,9 @@ ], "versions": [ { - "version": "24.0.0.221", + "version": "25.0.0.148", "status": "requires_authorization", - "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-04.html" + "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-10.html" } ], "lang": "en-US",
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl index be6901c..9f2191b 100644 --- a/chrome/common/extensions/api/autotest_private.idl +++ b/chrome/common/extensions/api/autotest_private.idl
@@ -63,6 +63,18 @@ }; callback NotificationArrayCallback = void (Notification[] notifications); + dictionary PlayStoreState { + // Whether the Play Store allowed for the current user. + boolean allowed; + // Whether the Play Store currently enabled. + boolean? enabled; + // Whether the Play Store managed by policy. + boolean? managed; + }; + callback PlayStoreStateCallback = void (PlayStoreState result); + + callback VoidCallback = void (); + interface Functions { // Logout of a user session. static void logout(); @@ -116,5 +128,13 @@ // Get visible notifications on the system. static void getVisibleNotifications(NotificationArrayCallback callback); + + // Get state of the Play Store. + static void getPlayStoreState(PlayStoreStateCallback callback); + + // Enable/disable the Play Store. + // |enabled|: if set, enable the Play Store. + // |callback|: Called when the operation has completed. + static void setPlayStoreEnabled(boolean enabled, VoidCallback callback); }; };
diff --git a/chrome/test/data/extensions/api_test/autotest_private/test.js b/chrome/test/data/extensions/api_test/autotest_private/test.js index 30e470f..04998278 100644 --- a/chrome/test/data/extensions/api_test/autotest_private/test.js +++ b/chrome/test/data/extensions/api_test/autotest_private/test.js
@@ -108,5 +108,22 @@ function getVisibleNotifications() { chrome.autotestPrivate.getVisibleNotifications(function(){}); chrome.test.succeed(); + }, + function getPlayStoreState() { + chrome.autotestPrivate.getPlayStoreState(function(state) { + // By default ARC is not available. Field allowed must be set to false; + // managed and enabled should be underfined. + chrome.test.assertFalse(state.allowed); + chrome.test.assertEq(undefined, state.enabled); + chrome.test.assertEq(undefined, state.managed); + chrome.test.succeed(); + }); + }, + function setPlayStoreEnabled() { + chrome.autotestPrivate.setPlayStoreEnabled(false, function() { + // By default ARC is not available. + chrome.test.assertTrue(chrome.runtime.lastError != undefined); + chrome.test.succeed(); + }); } ]);
diff --git a/components/network_session_configurator/network_session_configurator.cc b/components/network_session_configurator/network_session_configurator.cc index 00ab3d3..4f20674 100644 --- a/components/network_session_configurator/network_session_configurator.cc +++ b/components/network_session_configurator/network_session_configurator.cc
@@ -332,6 +332,13 @@ GetVariationParam(quic_trial_params, "quic_version")); } +bool ShouldEnableServerPushCancelation( + const VariationParameters& quic_trial_params) { + return base::LowerCaseEqualsASCII( + GetVariationParam(quic_trial_params, "enable_server_push_cancellation"), + "true"); +} + void ConfigureQuicParams(base::StringPiece quic_trial_group, const VariationParameters& quic_trial_params, bool is_quic_force_disabled, @@ -343,6 +350,10 @@ is_quic_force_enabled); params->mark_quic_broken_when_network_blackholes = ShouldMarkQuicBrokenWhenNetworkBlackholes(quic_trial_params); + + params->enable_server_push_cancellation = + ShouldEnableServerPushCancelation(quic_trial_params); + params->retry_without_alt_svc_on_quic_errors = ShouldRetryWithoutAltSvcOnQuicErrors(quic_trial_params); params->enable_quic_alternative_service_with_different_host =
diff --git a/components/network_session_configurator/network_session_configurator_unittest.cc b/components/network_session_configurator/network_session_configurator_unittest.cc index 799f9ca4..aa9e4c6 100644 --- a/components/network_session_configurator/network_session_configurator_unittest.cc +++ b/components/network_session_configurator/network_session_configurator_unittest.cc
@@ -75,6 +75,7 @@ EXPECT_FALSE(params_.quic_disable_connection_pooling); EXPECT_EQ(0.25f, params_.quic_load_server_info_timeout_srtt_multiplier); EXPECT_FALSE(params_.quic_enable_connection_racing); + EXPECT_FALSE(params_.enable_server_push_cancellation); EXPECT_FALSE(params_.quic_enable_non_blocking_io); EXPECT_FALSE(params_.quic_disable_disk_cache); EXPECT_FALSE(params_.quic_prefer_aes); @@ -222,6 +223,17 @@ EXPECT_TRUE(params_.quic_race_cert_verification); } +TEST_F(NetworkSessionConfiguratorTest, EnableServerPushCancellation) { + std::map<std::string, std::string> field_trial_params; + field_trial_params["enable_server_push_cancellation"] = "true"; + variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params); + base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled"); + + ParseFieldTrials(); + + EXPECT_TRUE(params_.enable_server_push_cancellation); +} + TEST_F(NetworkSessionConfiguratorTest, QuicDoNotFragment) { std::map<std::string, std::string> field_trial_params; field_trial_params["do_not_fragment"] = "true";
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc index 0f2e8e4..b3ffa387 100644 --- a/components/translate/core/browser/translate_manager.cc +++ b/components/translate/core/browser/translate_manager.cc
@@ -514,6 +514,8 @@ // Get the browser's user interface language. language = TranslateDownloadManager::GetLanguageCode( TranslateDownloadManager::GetInstance()->application_locale()); + // Map 'he', 'nb', 'fil' back to 'iw', 'no', 'tl' + translate::ToTranslateLanguageSynonym(&language); } if (TranslateDownloadManager::IsSupportedLanguage(language)) return language;
diff --git a/components/translate/core/browser/translate_manager_unittest.cc b/components/translate/core/browser/translate_manager_unittest.cc index cf28987..3efddaf 100644 --- a/components/translate/core/browser/translate_manager_unittest.cc +++ b/components/translate/core/browser/translate_manager_unittest.cc
@@ -254,6 +254,23 @@ ASSERT_TRUE(TranslateDownloadManager::IsSupportedLanguage("de")); manager_->set_application_locale("de"); EXPECT_EQ("de", TranslateManager::GetTargetLanguage(&translate_prefs_)); + + // Try a those case of non standard code. + // 'he', 'fil', 'nb' => 'iw', 'tl', 'no' + ASSERT_TRUE(TranslateDownloadManager::IsSupportedLanguage("iw")); + ASSERT_FALSE(TranslateDownloadManager::IsSupportedLanguage("he")); + manager_->set_application_locale("he"); + EXPECT_EQ("iw", TranslateManager::GetTargetLanguage(&translate_prefs_)); + + ASSERT_TRUE(TranslateDownloadManager::IsSupportedLanguage("tl")); + ASSERT_FALSE(TranslateDownloadManager::IsSupportedLanguage("fil")); + manager_->set_application_locale("fil"); + EXPECT_EQ("tl", TranslateManager::GetTargetLanguage(&translate_prefs_)); + + ASSERT_TRUE(TranslateDownloadManager::IsSupportedLanguage("no")); + ASSERT_FALSE(TranslateDownloadManager::IsSupportedLanguage("nb")); + manager_->set_application_locale("nb"); + EXPECT_EQ("no", TranslateManager::GetTargetLanguage(&translate_prefs_)); } // If the application locale's language is not supported, the target language
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index ef4dfc9..004de515 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -330,6 +330,8 @@ "audio_manager_thread.h", "background_fetch/background_fetch_context.cc", "background_fetch/background_fetch_context.h", + "background_fetch/background_fetch_cross_origin_filter.cc", + "background_fetch/background_fetch_cross_origin_filter.h", "background_fetch/background_fetch_data_manager.cc", "background_fetch/background_fetch_data_manager.h", "background_fetch/background_fetch_event_dispatcher.cc",
diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc index 151aa68..ed2742c0 100644 --- a/content/browser/accessibility/browser_accessibility_win.cc +++ b/content/browser/accessibility/browser_accessibility_win.cc
@@ -5467,9 +5467,12 @@ ia_role = ROLE_SYSTEM_PANE; } break; - case ui::AX_ROLE_ROW: - ia_role = ROLE_SYSTEM_ROW; + case ui::AX_ROLE_ROW: { + // Role changes depending on whether row is inside a treegrid + // https://www.w3.org/TR/core-aam-1.1/#role-map-row + ia_role = IsInTreeGrid(this) ? ROLE_SYSTEM_OUTLINEITEM : ROLE_SYSTEM_ROW; break; + } case ui::AX_ROLE_ROW_HEADER: ia_role = ROLE_SYSTEM_ROWHEADER; break; @@ -5645,6 +5648,23 @@ win_attributes_->ia2_state = ia2_state; } +bool BrowserAccessibilityWin::IsInTreeGrid(const BrowserAccessibility* item) { + BrowserAccessibility* container = item->PlatformGetParent(); + if (container && container->GetRole() == ui::AX_ROLE_GROUP) { + // If parent was a rowgroup, we need to look at the grandparent + container = container->PlatformGetParent(); + } + + if (!container) { + return false; + } + + const ui::AXRole role = container->GetRole(); + return role == ui::AX_ROLE_TREE_GRID || + (role == ui::AX_ROLE_TABLE && + container->GetString16Attribute(ui::AX_ATTR_ROLE) == L"treegrid"); +} + BrowserAccessibilityWin* ToBrowserAccessibilityWin(BrowserAccessibility* obj) { DCHECK(!obj || obj->IsNative()); return static_cast<BrowserAccessibilityWin*>(obj);
diff --git a/content/browser/accessibility/browser_accessibility_win.h b/content/browser/accessibility/browser_accessibility_win.h index a9f1f9cf..ccc8567 100644 --- a/content/browser/accessibility/browser_accessibility_win.h +++ b/content/browser/accessibility/browser_accessibility_win.h
@@ -920,6 +920,8 @@ ui::AXPlatformNodeWin* GetPlatformNodeWin() const; + static bool IsInTreeGrid(const BrowserAccessibility* item); + struct WinAttributes { WinAttributes(); ~WinAttributes();
diff --git a/content/browser/background_fetch/background_fetch_cross_origin_filter.cc b/content/browser/background_fetch/background_fetch_cross_origin_filter.cc new file mode 100644 index 0000000..125a4fa --- /dev/null +++ b/content/browser/background_fetch/background_fetch_cross_origin_filter.cc
@@ -0,0 +1,99 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/background_fetch/background_fetch_cross_origin_filter.h" + +#include <set> + +#include "base/strings/string_split.h" +#include "content/browser/background_fetch/background_fetch_request_info.h" +#include "url/gurl.h" + +namespace content { + +namespace { + +const char kAccessControlAllowOriginHeader[] = "access-control-allow-origin"; +const char kAnyOriginValue[] = "*"; + +// Parses the header list (including "any origin") value from a given response +// header value, writing the results in |*any_origin| or |*origins|. Returns +// whether all values included in the the |value| is valid. +bool ParseOriginListHeader(const std::string& value, + bool* any_origin, + std::set<url::Origin>* origins) { + DCHECK(any_origin); + DCHECK(origins); + + if (value == kAnyOriginValue) { + *any_origin = true; + return true; + } + + std::set<url::Origin> candidate_origins; + std::vector<std::string> origin_vector = base::SplitString( + value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + + for (const std::string& origin_string : origin_vector) { + url::Origin origin = url::Origin(GURL(origin_string)); + if (origin.unique()) + return false; + + candidate_origins.insert(origin); + } + + origins->swap(candidate_origins); + return !origins->empty(); +} + +} // namespace + +BackgroundFetchCrossOriginFilter::BackgroundFetchCrossOriginFilter( + const url::Origin& source_origin, + const BackgroundFetchRequestInfo& request) { + DCHECK(!request.GetURLChain().empty()); + + const GURL& final_url = request.GetURLChain().back(); + const auto& response_header_map = request.GetResponseHeaders(); + + // True iff |source_origin| is the same origin as the original request URL. + is_same_origin_ = source_origin.IsSameOriginWith(url::Origin(final_url)); + + // Access-Control-Allow-Origin checks. The header's values must be valid for + // it to not be completely discarded. + auto access_control_allow_origin_iter = + response_header_map.find(kAccessControlAllowOriginHeader); + + if (access_control_allow_origin_iter != response_header_map.end()) { + bool access_control_allow_any_origin = false; + std::set<url::Origin> access_control_allow_origins; + + if (ParseOriginListHeader(access_control_allow_origin_iter->second, + &access_control_allow_any_origin, + &access_control_allow_origins)) { + access_control_allow_origin_ = + access_control_allow_any_origin || + access_control_allow_origins.count(source_origin) == 1; + } + } + + // TODO(crbug.com/711354): Consider the Access-Control-Allow-Credentials + // header. + // TODO(crbug.com/711354): Consider the Access-Control-Allow-Headers header. + // TODO(crbug.com/711354): Consider the Access-Control-Allow-Methods header. + // TODO(crbug.com/711354): Consider the Access-Control-Expose-Headers header. +} + +BackgroundFetchCrossOriginFilter::~BackgroundFetchCrossOriginFilter() = default; + +bool BackgroundFetchCrossOriginFilter::CanPopulateBody() const { + // The body will be populated if: + // (1) The source and the response share their origin. + // (2) The Access-Control-Allow-Origin method allows any origin. + // (3) The Access-Control-Allow-Origin method allows the source origin. + + return is_same_origin_ || access_control_allow_origin_; +} + +} // namespace content
diff --git a/content/browser/background_fetch/background_fetch_cross_origin_filter.h b/content/browser/background_fetch/background_fetch_cross_origin_filter.h new file mode 100644 index 0000000..6fb1c499 --- /dev/null +++ b/content/browser/background_fetch/background_fetch_cross_origin_filter.h
@@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_CROSS_ORIGIN_FILTER_H_ +#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_CROSS_ORIGIN_FILTER_H_ + +#include "base/macros.h" +#include "content/common/content_export.h" + +namespace url { +class Origin; +} + +namespace content { + +class BackgroundFetchRequestInfo; + +// A filter that decides the CORS rules based on the source of a request and the +// response URL and headers included in the |request| info. +class CONTENT_EXPORT BackgroundFetchCrossOriginFilter { + public: + BackgroundFetchCrossOriginFilter(const url::Origin& source_origin, + const BackgroundFetchRequestInfo& request); + ~BackgroundFetchCrossOriginFilter(); + + // Returns whether the Response object passed to the Service Worker event + // should include the body included in the response. + bool CanPopulateBody() const; + + private: + // Whether the response comes from the same origin as the requester. + bool is_same_origin_ = false; + + // Whether the Access-Control-Allow-Origin header includes the source origin. + bool access_control_allow_origin_ = false; + + DISALLOW_COPY_AND_ASSIGN(BackgroundFetchCrossOriginFilter); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_CROSS_ORIGIN_FILTER_H_
diff --git a/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc b/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc new file mode 100644 index 0000000..0d6eb0c --- /dev/null +++ b/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc
@@ -0,0 +1,111 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/background_fetch/background_fetch_cross_origin_filter.h" + +#include "base/macros.h" +#include "content/browser/background_fetch/background_fetch_request_info.h" +#include "content/common/service_worker/service_worker_types.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { + +const char kFirstOrigin[] = "https://example.com"; +const char kFirstOriginFile[] = "https://example.com/cat.jpg"; +const char kSecondOriginFile[] = "https://chrome.com/cat.jpg"; + +const char kAccessControlAllowOriginHeader[] = "access-control-allow-origin"; + +class BackgroundFetchCrossOriginFilterTest : public ::testing::Test { + public: + BackgroundFetchCrossOriginFilterTest() + : source_(url::Origin(GURL(kFirstOrigin))) {} + ~BackgroundFetchCrossOriginFilterTest() override = default; + + // Creates a BackgroundFetchRequestInfo instance filled with the information + // required for the cross-origin filter to work. This method takes a + // |response_url| and an initializer list for key => value header pairs. + scoped_refptr<BackgroundFetchRequestInfo> CreateRequestInfo( + const char* response_url, + std::initializer_list< + typename std::map<std::string, std::string>::value_type> + response_headers) { + scoped_refptr<BackgroundFetchRequestInfo> request_info = + make_scoped_refptr(new BackgroundFetchRequestInfo( + 0 /* request_info */, ServiceWorkerFetchRequest())); + + request_info->download_state_populated_ = true; + request_info->response_headers_ = response_headers; + + request_info->response_data_populated_ = true; + request_info->url_chain_ = {GURL(response_url)}; + + return request_info; + } + + protected: + url::Origin source_; + + private: + DISALLOW_COPY_AND_ASSIGN(BackgroundFetchCrossOriginFilterTest); +}; + +TEST_F(BackgroundFetchCrossOriginFilterTest, SameOrigin) { + auto same_origin_response = CreateRequestInfo(kFirstOriginFile, {}); + + BackgroundFetchCrossOriginFilter filter(source_, *same_origin_response); + EXPECT_TRUE(filter.CanPopulateBody()); +} + +TEST_F(BackgroundFetchCrossOriginFilterTest, CrossOrigin) { + auto cross_origin_response = CreateRequestInfo(kSecondOriginFile, {}); + + BackgroundFetchCrossOriginFilter filter(source_, *cross_origin_response); + EXPECT_FALSE(filter.CanPopulateBody()); +} + +TEST_F(BackgroundFetchCrossOriginFilterTest, CrossOriginAllowAllOrigins) { + auto cross_origin_response = CreateRequestInfo( + kSecondOriginFile, {{kAccessControlAllowOriginHeader, "*"}}); + + BackgroundFetchCrossOriginFilter filter(source_, *cross_origin_response); + EXPECT_TRUE(filter.CanPopulateBody()); +} + +TEST_F(BackgroundFetchCrossOriginFilterTest, CrossOriginAllowSpecificOrigin) { + // With a single origin in the Access-Control-Allow-Origin header. + { + auto cross_origin_response = CreateRequestInfo( + kSecondOriginFile, {{kAccessControlAllowOriginHeader, kFirstOrigin}}); + + BackgroundFetchCrossOriginFilter filter(source_, *cross_origin_response); + EXPECT_TRUE(filter.CanPopulateBody()); + } + + // With multiple origins in the Access-Control-Allow-Origin header. + { + const char kOriginList[] = + "https://foo.com, https://example.com, https://bar.com:1500"; + + auto cross_origin_response = CreateRequestInfo( + kSecondOriginFile, {{kAccessControlAllowOriginHeader, kOriginList}}); + + BackgroundFetchCrossOriginFilter filter(source_, *cross_origin_response); + EXPECT_TRUE(filter.CanPopulateBody()); + } + + // With an invalid value included in the Access-Control-Allow-Origin header. + { + const char kOriginList[] = + "https://foo.com, https://example.com, INVALID, https://bar.com:1500"; + + auto cross_origin_response = CreateRequestInfo( + kSecondOriginFile, {{kAccessControlAllowOriginHeader, kOriginList}}); + + BackgroundFetchCrossOriginFilter filter(source_, *cross_origin_response); + EXPECT_FALSE(filter.CanPopulateBody()); + } +} + +} // namespace content
diff --git a/content/browser/background_fetch/background_fetch_data_manager.cc b/content/browser/background_fetch/background_fetch_data_manager.cc index bc8210ed..83e7509 100644 --- a/content/browser/background_fetch/background_fetch_data_manager.cc +++ b/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -10,6 +10,7 @@ #include "base/memory/ptr_util.h" #include "content/browser/background_fetch/background_fetch_constants.h" #include "content/browser/background_fetch/background_fetch_context.h" +#include "content/browser/background_fetch/background_fetch_cross_origin_filter.h" #include "content/browser/background_fetch/background_fetch_request_info.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/public/browser/blob_handle.h" @@ -206,22 +207,22 @@ BackgroundFetchSettledFetch settled_fetch; settled_fetch.request = request->fetch_request(); - // TODO(peter): Find the appropriate way to generalize CORS security checks. - const bool opaque = !registration_id.origin().IsSameOriginWith( - url::Origin(request->GetURLChain().back().GetOrigin())); + // The |filter| decides which values can be passed on to the Service Worker. + BackgroundFetchCrossOriginFilter filter(registration_id.origin(), *request); settled_fetch.response.url_list = request->GetURLChain(); settled_fetch.response.response_type = blink::kWebServiceWorkerResponseTypeDefault; - if (!opaque) { + // Include the status code, status text and the response's body as a blob + // when this is allowed by the CORS protocol. + if (filter.CanPopulateBody()) { settled_fetch.response.status_code = request->GetResponseCode(); settled_fetch.response.status_text = request->GetResponseText(); settled_fetch.response.headers.insert( request->GetResponseHeaders().begin(), request->GetResponseHeaders().end()); - // Include the response data as a blob backed by the downloaded file. if (request->GetFileSize() > 0) { DCHECK(!request->GetFilePath().empty()); std::unique_ptr<BlobHandle> blob_handle =
diff --git a/content/browser/background_fetch/background_fetch_request_info.cc b/content/browser/background_fetch/background_fetch_request_info.cc index e3f9608..1973d35 100644 --- a/content/browser/background_fetch/background_fetch_request_info.cc +++ b/content/browser/background_fetch/background_fetch_request_info.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/strings/string_util.h" #include "content/public/browser/download_item.h" #include "net/http/http_response_headers.h" @@ -38,7 +39,7 @@ std::string name, value; while (headers->EnumerateHeaderLines(&iter, &name, &value)) - response_headers_[name] = value; + response_headers_[base::ToLowerASCII(name)] = value; } download_state_populated_ = true;
diff --git a/content/browser/background_fetch/background_fetch_request_info.h b/content/browser/background_fetch/background_fetch_request_info.h index f01d321..e3c49f89 100644 --- a/content/browser/background_fetch/background_fetch_request_info.h +++ b/content/browser/background_fetch/background_fetch_request_info.h
@@ -74,6 +74,7 @@ private: friend class base::RefCountedThreadSafe<BackgroundFetchRequestInfo>; + friend class BackgroundFetchCrossOriginFilterTest; ~BackgroundFetchRequestInfo();
diff --git a/content/browser/bluetooth/tools/BUILD.gn b/content/browser/bluetooth/tools/BUILD.gn index 4971caa..4feb959 100644 --- a/content/browser/bluetooth/tools/BUILD.gn +++ b/content/browser/bluetooth/tools/BUILD.gn
@@ -9,6 +9,7 @@ deps = [ "//base", + "//build/config/sanitizers:deps", "//build/win:default_exe_manifest", "//device/bluetooth", ]
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 5b0a162..58969065 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1026,6 +1026,7 @@ "../browser/appcache/mock_appcache_storage.cc", "../browser/appcache/mock_appcache_storage.h", "../browser/appcache/mock_appcache_storage_unittest.cc", + "../browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc", "../browser/background_fetch/background_fetch_data_manager_unittest.cc", "../browser/background_fetch/background_fetch_event_dispatcher_unittest.cc", "../browser/background_fetch/background_fetch_job_controller_unittest.cc",
diff --git a/content/test/data/accessibility/aria/aria-level-expected-win.txt b/content/test/data/accessibility/aria/aria-level-expected-win.txt index b10d0bb..97f6f26 100644 --- a/content/test/data/accessibility/aria/aria-level-expected-win.txt +++ b/content/test/data/accessibility/aria/aria-level-expected-win.txt
@@ -21,10 +21,10 @@ ++++ROLE_SYSTEM_OUTLINEITEM name='Tree item at level 3' level:3 ++++++ROLE_SYSTEM_STATICTEXT name='Tree item at level 3' ++ROLE_SYSTEM_OUTLINE -++++ROLE_SYSTEM_ROW level:1 +++++ROLE_SYSTEM_OUTLINEITEM level:1 ++++++ROLE_SYSTEM_CELL name='Cell at level 1' ++++++++ROLE_SYSTEM_STATICTEXT name='Cell at level 1' -++++ROLE_SYSTEM_ROW level:2 +++++ROLE_SYSTEM_OUTLINEITEM level:2 ++++++ROLE_SYSTEM_CELL name='Cell at level 2' ++++++++ROLE_SYSTEM_STATICTEXT name='Cell at level 2' ++++ROLE_SYSTEM_COLUMN
diff --git a/content/test/data/accessibility/aria/aria-treegrid-expected-android.txt b/content/test/data/accessibility/aria/aria-treegrid-expected-android.txt index fa02c5ff..c703016 100644 --- a/content/test/data/accessibility/aria/aria-treegrid-expected-android.txt +++ b/content/test/data/accessibility/aria/aria-treegrid-expected-android.txt
@@ -5,4 +5,9 @@ ++++android.view.View ++++++android.view.View role_description='cell' collection_item name='Cell at level 2' row_index=1 row_span=1 column_span=1 ++++android.view.View -++++android.view.View \ No newline at end of file +++++android.view.View +++android.widget.GridView role_description='table' collection row_count=1 column_count=1 +++++android.view.View +++++++android.view.View role_description='cell' collection_item name='Cell at level 1' row_span=1 column_span=1 +++++android.view.View +++++android.view.View
diff --git a/content/test/data/accessibility/aria/aria-treegrid-expected-mac.txt b/content/test/data/accessibility/aria/aria-treegrid-expected-mac.txt index feee33b..1dabc16 100644 --- a/content/test/data/accessibility/aria/aria-treegrid-expected-mac.txt +++ b/content/test/data/accessibility/aria/aria-treegrid-expected-mac.txt
@@ -8,3 +8,9 @@ ++++++++AXStaticText AXValue='Cell at level 2' ++++AXColumn ++++AXGroup +++AXTable +++++AXRow AXDisclosureLevel='0' +++++++AXCell AXTitle='Cell at level 1' +++++++++AXStaticText AXValue='Cell at level 1' +++++AXColumn +++++AXGroup
diff --git a/content/test/data/accessibility/aria/aria-treegrid-expected-win.txt b/content/test/data/accessibility/aria/aria-treegrid-expected-win.txt index d9d10f540..1edaf72d 100644 --- a/content/test/data/accessibility/aria/aria-treegrid-expected-win.txt +++ b/content/test/data/accessibility/aria/aria-treegrid-expected-win.txt
@@ -1,10 +1,16 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ++ROLE_SYSTEM_OUTLINE xml-roles:treegrid -++++ROLE_SYSTEM_ROW xml-roles:row level:1 +++++ROLE_SYSTEM_OUTLINEITEM xml-roles:row level:1 ++++++ROLE_SYSTEM_CELL name='Cell at level 1' xml-roles:gridcell ++++++++ROLE_SYSTEM_STATICTEXT name='Cell at level 1' -++++ROLE_SYSTEM_ROW xml-roles:row level:2 +++++ROLE_SYSTEM_OUTLINEITEM xml-roles:row level:2 ++++++ROLE_SYSTEM_CELL name='Cell at level 2' xml-roles:gridcell ++++++++ROLE_SYSTEM_STATICTEXT name='Cell at level 2' ++++ROLE_SYSTEM_COLUMN ++++IA2_ROLE_SECTION +++ROLE_SYSTEM_OUTLINE xml-roles:treegrid +++++ROLE_SYSTEM_OUTLINEITEM xml-roles:row level:1 +++++++ROLE_SYSTEM_CELL name='Cell at level 1' xml-roles:gridcell +++++++++ROLE_SYSTEM_STATICTEXT name='Cell at level 1' +++++ROLE_SYSTEM_COLUMN +++++IA2_ROLE_SECTION
diff --git a/content/test/data/accessibility/aria/aria-treegrid.html b/content/test/data/accessibility/aria/aria-treegrid.html index b5923c5f..18136c3 100644 --- a/content/test/data/accessibility/aria/aria-treegrid.html +++ b/content/test/data/accessibility/aria/aria-treegrid.html
@@ -14,6 +14,13 @@ <tr role="row" aria-level="2"> <td role="gridcell">Cell at level 2</td> </tr> -</table> + </table> + <table role="treegrid"> + <tbody role="rowgroup"> + <tr role="row" aria-level="1"> + <td role="gridcell">Cell at level 1</td> + </tr> + </tbody> + </table> </body> </html>
diff --git a/device/gamepad/gamepad_provider_unittest.cc b/device/gamepad/gamepad_provider_unittest.cc index 2f1633e..cef3355 100644 --- a/device/gamepad/gamepad_provider_unittest.cc +++ b/device/gamepad/gamepad_provider_unittest.cc
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/run_loop.h" +#include "base/threading/platform_thread.h" #include "build/build_config.h" #include "device/gamepad/gamepad_data_fetcher.h" #include "device/gamepad/gamepad_test_helpers.h" @@ -49,6 +50,28 @@ return provider_.get(); } + // Sleep until the shared memory buffer's seqlock advances the buffer version, + // indicating that the gamepad provider has written to it after polling the + // gamepad fetchers. The buffer will report an odd value for the version if + // the buffer is not in a consistent state, so we also require that the value + // is even before continuing. + void WaitForData(GamepadHardwareBuffer* buffer) { + const base::subtle::Atomic32 initial_version = buffer->seqlock.ReadBegin(); + base::subtle::Atomic32 current_version; + do { + base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); + current_version = buffer->seqlock.ReadBegin(); + } while (current_version % 2 || current_version == initial_version); + } + + // The provider polls the data on the background thread and then issues + // the callback on the client thread. Waiting for it to poll twice ensures + // that it was able to issue callbacks for the first poll. + void WaitForDataAndCallbacksIssued(GamepadHardwareBuffer* buffer) { + WaitForData(buffer); + WaitForData(buffer); + } + void ReadGamepadHardwareBuffer(GamepadHardwareBuffer* buffer, WebGamepads* output) { memset(output, 0, sizeof(WebGamepads)); @@ -70,8 +93,7 @@ DISALLOW_COPY_AND_ASSIGN(GamepadProviderTest); }; -// Test is flaky. crbug.com/705367 -TEST_F(GamepadProviderTest, DISABLED_PollingAccess) { +TEST_F(GamepadProviderTest, PollingAccess) { WebGamepads test_data; memset(&test_data, 0, sizeof(WebGamepads)); test_data.items[0].connected = true; @@ -89,8 +111,6 @@ base::RunLoop().RunUntilIdle(); - mock_data_fetcher_->WaitForDataRead(); - // Renderer-side, pull data out of poll buffer. base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess( base::GetCurrentProcessHandle()); @@ -100,6 +120,10 @@ GamepadHardwareBuffer* buffer = static_cast<GamepadHardwareBuffer*>(shared_memory->memory()); + + // Wait until the shared memory buffer has been written at least once. + WaitForData(buffer); + WebGamepads output; ReadGamepadHardwareBuffer(buffer, &output); @@ -111,8 +135,7 @@ EXPECT_EQ(0.5f, output.items[0].axes[1]); } -// Flaky on all platforms: http://crbug.com/692219 -TEST_F(GamepadProviderTest, DISABLED_ConnectDisconnectMultiple) { +TEST_F(GamepadProviderTest, ConnectDisconnectMultiple) { WebGamepads test_data; test_data.items[0].connected = true; test_data.items[0].timestamp = 0; @@ -139,8 +162,6 @@ base::RunLoop().RunUntilIdle(); - mock_data_fetcher_->WaitForDataRead(); - // Renderer-side, pull data out of poll buffer. base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess( base::GetCurrentProcessHandle()); @@ -150,6 +171,10 @@ GamepadHardwareBuffer* buffer = static_cast<GamepadHardwareBuffer*>(shared_memory->memory()); + + // Wait until the shared memory buffer has been written at least once. + WaitForData(buffer); + WebGamepads output; ReadGamepadHardwareBuffer(buffer, &output); @@ -161,7 +186,9 @@ EXPECT_EQ(-0.5f, output.items[1].axes[1]); mock_data_fetcher_->SetTestData(test_data_onedisconnected); - mock_data_fetcher_->WaitForDataReadAndCallbacksIssued(); + + WaitForDataAndCallbacksIssued(buffer); + ReadGamepadHardwareBuffer(buffer, &output); EXPECT_EQ(0u, output.items[0].axes_length); @@ -192,29 +219,39 @@ provider->Resume(); provider->RegisterForUserGesture(listener.GetClosure()); - mock_data_fetcher_->WaitForDataReadAndCallbacksIssued(); + + base::RunLoop().RunUntilIdle(); + + // Renderer-side, pull data out of poll buffer. + base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess( + base::GetCurrentProcessHandle()); + std::unique_ptr<base::SharedMemory> shared_memory( + new base::SharedMemory(handle, true)); + EXPECT_TRUE(shared_memory->Map(sizeof(GamepadHardwareBuffer))); + + GamepadHardwareBuffer* buffer = + static_cast<GamepadHardwareBuffer*>(shared_memory->memory()); + + // Wait until the shared memory buffer has been written at least once. + WaitForData(buffer); // It should not have issued our callback. - base::RunLoop().RunUntilIdle(); EXPECT_FALSE(listener.has_user_gesture()); - // Set a button down and wait for it to be read twice. + // Set a button down. mock_data_fetcher_->SetTestData(button_down_data); - mock_data_fetcher_->WaitForDataReadAndCallbacksIssued(); + + // The user gesture listener callback is not called until after the buffer has + // been updated. Wait for the second update to ensure callbacks have fired. + WaitForDataAndCallbacksIssued(buffer); // It should have issued our callback. base::RunLoop().RunUntilIdle(); EXPECT_TRUE(listener.has_user_gesture()); } -// Flaky on CrOS and Linux: http://crbug.com/640086, https://crbug.com/702712 -#if defined(OS_LINUX) || defined(OS_CHROMEOS) -#define MAYBE_Sanitization DISABLED_Sanitization -#else -#define MAYBE_Sanitization Sanitization -#endif // Tests that waiting for a user gesture works properly. -TEST_F(GamepadProviderTest, MAYBE_Sanitization) { +TEST_F(GamepadProviderTest, Sanitization) { WebGamepads active_data; active_data.items[0].connected = true; active_data.items[0].timestamp = 0; @@ -240,8 +277,6 @@ base::RunLoop().RunUntilIdle(); - mock_data_fetcher_->WaitForDataRead(); - // Renderer-side, pull data out of poll buffer. base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess( base::GetCurrentProcessHandle()); @@ -251,6 +286,10 @@ GamepadHardwareBuffer* buffer = static_cast<GamepadHardwareBuffer*>(shared_memory->memory()); + + // Wait until the shared memory buffer has been written at least once. + WaitForData(buffer); + WebGamepads output; ReadGamepadHardwareBuffer(buffer, &output); @@ -264,7 +303,8 @@ // Zero out the inputs mock_data_fetcher_->SetTestData(zero_data); - mock_data_fetcher_->WaitForDataReadAndCallbacksIssued(); + + WaitForDataAndCallbacksIssued(buffer); // Read updated data from shared memory ReadGamepadHardwareBuffer(buffer, &output); @@ -278,7 +318,8 @@ // Re-set the active inputs mock_data_fetcher_->SetTestData(active_data); - mock_data_fetcher_->WaitForDataReadAndCallbacksIssued(); + + WaitForDataAndCallbacksIssued(buffer); // Read updated data from shared memory ReadGamepadHardwareBuffer(buffer, &output);
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index 531937e..d8a35fad 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1231,6 +1231,8 @@ // This does not follow the naming convesion, but follows the other APIs in // webrtcAudioPrivate. WEBRTC_AUDIO_PRIVATE_SET_AUDIO_EXPERIMENTS, + AUTOTESTPRIVATE_GETPLAYSTORESTATE, + AUTOTESTPRIVATE_SETPLAYSTOREENABLED, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/ios/clean/chrome/browser/ui/root/BUILD.gn b/ios/clean/chrome/browser/ui/root/BUILD.gn index 1eaadd7d..19133fb1 100644 --- a/ios/clean/chrome/browser/ui/root/BUILD.gn +++ b/ios/clean/chrome/browser/ui/root/BUILD.gn
@@ -27,6 +27,7 @@ deps = [ "//base", "//ios/clean/chrome/browser/ui/animators", + "//ios/clean/chrome/browser/ui/presenters", ] configs += [ "//build/config/compiler:enable_arc" ] }
diff --git a/ios/clean/chrome/browser/ui/root/root_container_view_controller.h b/ios/clean/chrome/browser/ui/root/root_container_view_controller.h index f0693941..0f3ffe0 100644 --- a/ios/clean/chrome/browser/ui/root/root_container_view_controller.h +++ b/ios/clean/chrome/browser/ui/root/root_container_view_controller.h
@@ -8,10 +8,11 @@ #import <UIKit/UIKit.h> #import "ios/clean/chrome/browser/ui/animators/zoom_transition_delegate.h" +#import "ios/clean/chrome/browser/ui/presenters/menu_presentation_delegate.h" // View controller that wholly contains a content view controller. @interface RootContainerViewController - : UIViewController<ZoomTransitionDelegate> + : UIViewController<MenuPresentationDelegate, ZoomTransitionDelegate> // View controller showing the main content. @property(nonatomic, strong) UIViewController* contentViewController;
diff --git a/ios/clean/chrome/browser/ui/root/root_container_view_controller.mm b/ios/clean/chrome/browser/ui/root/root_container_view_controller.mm index 8a7467b..9c44ebb 100644 --- a/ios/clean/chrome/browser/ui/root/root_container_view_controller.mm +++ b/ios/clean/chrome/browser/ui/root/root_container_view_controller.mm
@@ -69,4 +69,39 @@ return CGRectNull; } +#pragma mark - MenuPresentationDelegate + +- (CGRect)frameForMenuPresentation:(UIPresentationController*)presentation { + CGSize menuSize = presentation.presentedView.frame.size; + CGRect menuRect; + menuRect.size = menuSize; + + CGRect menuOriginRect = [self rectForZoomWithKey:nil inView:self.view]; + if (CGRectIsNull(menuOriginRect)) { + menuRect.origin = CGPointMake(50, 50); + return menuRect; + } + // Calculate which corner of the menu the origin rect is in. This is + // determined by comparing frames, and thus is RTL-independent. + if (CGRectGetMinX(menuOriginRect) - CGRectGetMinX(self.view.bounds) < + CGRectGetMaxX(self.view.bounds) - CGRectGetMaxX(menuOriginRect)) { + // Origin rect is closer to the left edge of |self.view| than to the right. + menuRect.origin.x = CGRectGetMinX(menuOriginRect); + } else { + // Origin rect is closer to the right edge of |self.view| than to the left. + menuRect.origin.x = CGRectGetMaxX(menuOriginRect) - menuSize.width; + } + + if (CGRectGetMinY(menuOriginRect) - CGRectGetMinY(self.view.bounds) < + CGRectGetMaxY(self.view.bounds) - CGRectGetMaxY(menuOriginRect)) { + // Origin rect is closer to the top edge of |self.view| than to the bottom. + menuRect.origin.y = CGRectGetMinY(menuOriginRect); + } else { + // Origin rect is closer to the bottom edge of |self.view| than to the top. + menuRect.origin.y = CGRectGetMaxY(menuOriginRect) - menuSize.height; + } + + return menuRect; +} + @end
diff --git a/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn b/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn index 7c35b5f..6f271877 100644 --- a/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn +++ b/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn
@@ -61,7 +61,6 @@ "//ios/clean/chrome/browser/ui/actions", "//ios/clean/chrome/browser/ui/animators", "//ios/clean/chrome/browser/ui/commands", - "//ios/clean/chrome/browser/ui/presenters", "//ios/clean/chrome/browser/ui/tab_collection:tab_collection_ui", "//ios/third_party/material_components_ios:material_components_ios", "//ui/base",
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm index bfdc1c50..be61ce7 100644 --- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm +++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -196,6 +196,8 @@ } - (void)registerForTabGridCommands { + [self.browser->dispatcher() startDispatchingToTarget:self + forSelector:@selector(showTabGrid)]; [self.browser->dispatcher() startDispatchingToTarget:self forSelector:@selector(showTabGridTabAtIndex:)];
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.h b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.h index 49fd2d1..b9a104e 100644 --- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.h +++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.h
@@ -8,7 +8,6 @@ #import "ios/clean/chrome/browser/ui/tab_collection/tab_collection_view_controller.h" #import "ios/clean/chrome/browser/ui/animators/zoom_transition_delegate.h" -#import "ios/clean/chrome/browser/ui/presenters/menu_presentation_delegate.h" #import "ios/clean/chrome/browser/ui/tab_grid/tab_grid_consumer.h" @protocol SettingsCommands; @@ -17,9 +16,7 @@ // View controller with a grid of tabs. @interface TabGridViewController - : TabCollectionViewController<MenuPresentationDelegate, - TabGridConsumer, - ZoomTransitionDelegate> + : TabCollectionViewController<TabGridConsumer, ZoomTransitionDelegate> // Dispatcher to handle commands. @property(nonatomic, weak) id<SettingsCommands, TabGridCommands, ToolsMenuCommands>
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm index dc0f9be..bdfcad6 100644 --- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm +++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -122,41 +122,6 @@ return [view convertRect:cell.bounds fromView:cell]; } -#pragma mark - MenuPresentationDelegate - -- (CGRect)frameForMenuPresentation:(UIPresentationController*)presentation { - CGSize menuSize = presentation.presentedView.frame.size; - CGRect menuRect; - menuRect.size = menuSize; - - CGRect menuOriginRect = [self rectForZoomWithKey:nil inView:self.view]; - if (CGRectIsNull(menuOriginRect)) { - menuRect.origin = CGPointMake(50, 50); - return menuRect; - } - // Calculate which corner of the menu the origin rect is in. This is - // determined by comparing frames, and thus is RTL-independent. - if (CGRectGetMinX(menuOriginRect) - CGRectGetMinX(self.view.bounds) < - CGRectGetMaxX(self.view.bounds) - CGRectGetMaxX(menuOriginRect)) { - // Origin rect is closer to the left edge of |self.view| than to the right. - menuRect.origin.x = CGRectGetMinX(menuOriginRect); - } else { - // Origin rect is closer to the right edge of |self.view| than to the left. - menuRect.origin.x = CGRectGetMaxX(menuOriginRect) - menuSize.width; - } - - if (CGRectGetMinY(menuOriginRect) - CGRectGetMinY(self.view.bounds) < - CGRectGetMaxY(self.view.bounds) - CGRectGetMaxY(menuOriginRect)) { - // Origin rect is closer to the top edge of |self.view| than to the bottom. - menuRect.origin.y = CGRectGetMinY(menuOriginRect); - } else { - // Origin rect is closer to the bottom edge of |self.view| than to the top. - menuRect.origin.y = CGRectGetMaxY(menuOriginRect) - menuSize.height; - } - - return menuRect; -} - #pragma mark - TabGridConsumer methods - (void)addNoTabsOverlay {
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h index dc1a791..7ddcd6e9 100644 --- a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h +++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h
@@ -10,8 +10,9 @@ #import "ios/clean/chrome/browser/ui/animators/zoom_transition_delegate.h" #import "ios/clean/chrome/browser/ui/toolbar/toolbar_consumer.h" -@protocol ToolsMenuCommands; @protocol NavigationCommands; +@protocol TabGridCommands; +@protocol ToolsMenuCommands; // View controller for a toolbar, which will show a horizontal row of // controls and/or labels. @@ -22,7 +23,9 @@ : UIViewController<ZoomTransitionDelegate, ToolbarConsumer> // The dispatcher for this view controller -@property(nonatomic, weak) id<ToolsMenuCommands, NavigationCommands> dispatcher; +@property(nonatomic, weak) + id<NavigationCommands, TabGridCommands, ToolsMenuCommands> + dispatcher; @property(nonatomic, strong) UIViewController* locationBarViewController;
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm index 3fed575a..4800384 100644 --- a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm +++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
@@ -5,9 +5,9 @@ #import "ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h" #import "base/mac/foundation_util.h" -#import "ios/clean/chrome/browser/ui/actions/tab_grid_actions.h" #import "ios/clean/chrome/browser/ui/actions/tab_strip_actions.h" #import "ios/clean/chrome/browser/ui/commands/navigation_commands.h" +#import "ios/clean/chrome/browser/ui/commands/tab_grid_commands.h" #import "ios/clean/chrome/browser/ui/commands/tools_menu_commands.h" #import "ios/clean/chrome/browser/ui/toolbar/toolbar_button+factory.h" #import "ios/clean/chrome/browser/ui/toolbar/toolbar_component_options.h" @@ -128,7 +128,7 @@ self.tabSwitchGridButton.visibilityMask = ToolbarComponentVisibilityCompactWidth | ToolbarComponentVisibilityRegularWidth; - [self.tabSwitchGridButton addTarget:nil + [self.tabSwitchGridButton addTarget:self action:@selector(showTabGrid:) forControlEvents:UIControlEventTouchUpInside]; self.tabSwitchGridButton.hiddenInCurrentState = YES; @@ -283,6 +283,10 @@ [self.dispatcher reloadPage]; } +- (void)showTabGrid:(id)sender { + [self.dispatcher showTabGrid]; +} + #pragma mark - TabStripEvents - (void)tabStripDidShow:(id)sender {
diff --git a/ios/showcase/toolbar/sc_toolbar_coordinator.mm b/ios/showcase/toolbar/sc_toolbar_coordinator.mm index 312aeab..21972f9 100644 --- a/ios/showcase/toolbar/sc_toolbar_coordinator.mm +++ b/ios/showcase/toolbar/sc_toolbar_coordinator.mm
@@ -5,6 +5,7 @@ #import "ios/showcase/toolbar/sc_toolbar_coordinator.h" #import "ios/clean/chrome/browser/ui/commands/navigation_commands.h" +#import "ios/clean/chrome/browser/ui/commands/tab_grid_commands.h" #import "ios/clean/chrome/browser/ui/commands/tools_menu_commands.h" #import "ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h" #import "ios/showcase/common/protocol_alerter.h" @@ -28,7 +29,8 @@ - (void)start { self.alerter = [[ProtocolAlerter alloc] initWithProtocols:@[ - @protocol(ToolsMenuCommands), @protocol(NavigationCommands) + @protocol(NavigationCommands), @protocol(TabGridCommands), + @protocol(ToolsMenuCommands) ]]; self.alerter.baseViewController = self.baseViewController; @@ -44,7 +46,8 @@ ToolbarViewController* toolbarViewController = [[ToolbarViewController alloc] init]; toolbarViewController.dispatcher = - static_cast<id<ToolsMenuCommands, NavigationCommands>>(self.alerter); + static_cast<id<NavigationCommands, TabGridCommands, ToolsMenuCommands>>( + self.alerter); [containerViewController addChildViewController:toolbarViewController]; toolbarViewController.view.frame = containerView.frame; [containerView addSubview:toolbarViewController.view];
diff --git a/net/BUILD.gn b/net/BUILD.gn index 3adf06d..58eddf6 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -2200,6 +2200,10 @@ visibility = [ ":test_support" ] testonly = true sources = [ + "data/quic_http_response_cache_data_with_push/test.example.com/favicon.ico", + "data/quic_http_response_cache_data_with_push/test.example.com/index.html", + "data/quic_http_response_cache_data_with_push/test.example.com/index2.html", + "data/quic_http_response_cache_data_with_push/test.example.com/kitten-1.jpg", "data/ssl/certificates/1024-rsa-ee-by-1024-rsa-intermediate.pem", "data/ssl/certificates/1024-rsa-ee-by-2048-rsa-intermediate.pem", "data/ssl/certificates/1024-rsa-ee-by-768-rsa-intermediate.pem",
diff --git a/net/disk_cache/simple/simple_index.cc b/net/disk_cache/simple/simple_index.cc index 4e5c833d..43869ef4 100644 --- a/net/disk_cache/simple/simple_index.cc +++ b/net/disk_cache/simple/simple_index.cc
@@ -139,7 +139,7 @@ app_on_background_(false) {} SimpleIndex::~SimpleIndex() { - DCHECK(io_thread_checker_.CalledOnValidThread()); + CHECK(io_thread_checker_.CalledOnValidThread()); // Fail all callbacks waiting for the index to come up. for (CallbackList::iterator it = to_run_when_initialized_.begin(), @@ -149,7 +149,7 @@ } void SimpleIndex::Initialize(base::Time cache_mtime) { - DCHECK(io_thread_checker_.CalledOnValidThread()); + CHECK(io_thread_checker_.CalledOnValidThread()); #if defined(OS_ANDROID) if (base::android::IsVMInitialized()) { @@ -177,7 +177,7 @@ } int SimpleIndex::ExecuteWhenReady(const net::CompletionCallback& task) { - DCHECK(io_thread_checker_.CalledOnValidThread()); + CHECK(io_thread_checker_.CalledOnValidThread()); if (initialized_) io_thread_->PostTask(FROM_HERE, base::Bind(task, net::OK)); else @@ -250,7 +250,7 @@ } void SimpleIndex::Insert(uint64_t entry_hash) { - DCHECK(io_thread_checker_.CalledOnValidThread()); + CHECK(io_thread_checker_.CalledOnValidThread()); // Upon insert we don't know yet the size of the entry. // It will be updated later when the SimpleEntryImpl finishes opening or // creating the new entry, and then UpdateEntrySize will be called. @@ -262,7 +262,7 @@ } void SimpleIndex::Remove(uint64_t entry_hash) { - DCHECK(io_thread_checker_.CalledOnValidThread()); + CHECK(io_thread_checker_.CalledOnValidThread()); EntrySet::iterator it = entries_set_.find(entry_hash); if (it != entries_set_.end()) { UpdateEntryIteratorSize(&it, 0u); @@ -281,7 +281,7 @@ } bool SimpleIndex::UseIfExists(uint64_t entry_hash) { - DCHECK(io_thread_checker_.CalledOnValidThread()); + CHECK(io_thread_checker_.CalledOnValidThread()); // Always update the last used time, even if it is during initialization. // It will be merged later. EntrySet::iterator it = entries_set_.find(entry_hash); @@ -294,7 +294,7 @@ } void SimpleIndex::StartEvictionIfNeeded() { - DCHECK(io_thread_checker_.CalledOnValidThread()); + CHECK(io_thread_checker_.CalledOnValidThread()); if (eviction_in_progress_ || cache_size_ <= high_watermark_) return; // Take all live key hashes from the index and sort them by time. @@ -351,7 +351,7 @@ bool SimpleIndex::UpdateEntrySize(uint64_t entry_hash, base::StrictNumeric<uint32_t> entry_size) { - DCHECK(io_thread_checker_.CalledOnValidThread()); + CHECK(io_thread_checker_.CalledOnValidThread()); EntrySet::iterator it = entries_set_.find(entry_hash); if (it == entries_set_.end()) return false; @@ -363,7 +363,7 @@ } void SimpleIndex::EvictionDone(int result) { - DCHECK(io_thread_checker_.CalledOnValidThread()); + CHECK(io_thread_checker_.CalledOnValidThread()); // Ignore the result of eviction. We did our best. eviction_in_progress_ = false; @@ -415,7 +415,7 @@ void SimpleIndex::MergeInitializingSet( std::unique_ptr<SimpleIndexLoadResult> load_result) { - DCHECK(io_thread_checker_.CalledOnValidThread()); + CHECK(io_thread_checker_.CalledOnValidThread()); DCHECK(load_result->did_load); EntrySet* index_file_entries = &load_result->entries; @@ -481,7 +481,7 @@ #if defined(OS_ANDROID) void SimpleIndex::OnApplicationStateChange( base::android::ApplicationState state) { - DCHECK(io_thread_checker_.CalledOnValidThread()); + CHECK(io_thread_checker_.CalledOnValidThread()); // For more info about android activities, see: // developer.android.com/training/basics/activity-lifecycle/pausing.html if (state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES) { @@ -495,7 +495,7 @@ #endif void SimpleIndex::WriteToDisk(IndexWriteToDiskReason reason) { - DCHECK(io_thread_checker_.CalledOnValidThread()); + CHECK(io_thread_checker_.CalledOnValidThread()); if (!initialized_) return; SIMPLE_CACHE_UMA(CUSTOM_COUNTS,
diff --git a/net/disk_cache/simple/simple_index.h b/net/disk_cache/simple/simple_index.h index 2fd3e1f..b573e4b 100644 --- a/net/disk_cache/simple/simple_index.h +++ b/net/disk_cache/simple/simple_index.h
@@ -228,7 +228,9 @@ // All nonstatic SimpleEntryImpl methods should always be called on the IO // thread, in all cases. |io_thread_checker_| documents and enforces this. - base::ThreadChecker io_thread_checker_; + // NOTE: Temporarily forced on to chase a crash, https://crbug.com/710994, + // turn off by 2017-04-21, also going back CHECK -> DCHECK in the impl. + base::ThreadCheckerImpl io_thread_checker_; // Timestamp of the last time we wrote the index to disk. // PostponeWritingToDisk() may give up postponing and allow the write if it
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc index bf423ec..93d39cc 100644 --- a/net/http/http_cache.cc +++ b/net/http/http_cache.cc
@@ -38,6 +38,7 @@ #include "net/base/upload_data_stream.h" #include "net/disk_cache/disk_cache.h" #include "net/http/disk_cache_based_quic_server_info.h" +#include "net/http/http_cache_lookup_manager.h" #include "net/http/http_cache_transaction.h" #include "net/http/http_network_layer.h" #include "net/http/http_network_session.h" @@ -343,14 +344,20 @@ // Session may be NULL in unittests. // TODO(mmenke): Seems like tests could be changed to provide a session, // rather than having logic only used in unit tests here. - if (session) { - net_log_ = session->net_log(); - if (is_main_cache && - !session->quic_stream_factory()->has_quic_server_info_factory()) { - // QuicStreamFactory takes ownership of QuicServerInfoFactoryAdaptor. - session->quic_stream_factory()->set_quic_server_info_factory( - new QuicServerInfoFactoryAdaptor(this)); - } + if (!session) + return; + + net_log_ = session->net_log(); + if (!is_main_cache) + return; + + session->SetServerPushDelegate( + base::MakeUnique<HttpCacheLookupManager>(this)); + + if (!session->quic_stream_factory()->has_quic_server_info_factory()) { + // QuicStreamFactory takes ownership of QuicServerInfoFactoryAdaptor. + session->quic_stream_factory()->set_quic_server_info_factory( + new QuicServerInfoFactoryAdaptor(this)); } }
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 4b7bcd3..361156b 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -105,6 +105,7 @@ : client_socket_factory(nullptr), host_resolver(nullptr), cert_verifier(nullptr), + enable_server_push_cancellation(false), channel_id_service(nullptr), transport_security_state(nullptr), cert_transparency_verifier(nullptr), @@ -396,7 +397,9 @@ void HttpNetworkSession::SetServerPushDelegate( std::unique_ptr<ServerPushDelegate> push_delegate) { - DCHECK(!push_delegate_ && push_delegate); + DCHECK(push_delegate); + if (!params_.enable_server_push_cancellation || push_delegate_) + return; push_delegate_ = std::move(push_delegate); spdy_session_pool_.set_server_push_delegate(push_delegate_.get());
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index afa78179..6adf6e4 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h
@@ -85,6 +85,7 @@ ClientSocketFactory* client_socket_factory; HostResolver* host_resolver; CertVerifier* cert_verifier; + bool enable_server_push_cancellation; ChannelIDService* channel_id_service; TransportSecurityState* transport_security_state; CTVerifier* cert_transparency_verifier;
diff --git a/net/quic/core/quic_server_session_base_test.cc b/net/quic/core/quic_server_session_base_test.cc index cbd1303..8002891 100644 --- a/net/quic/core/quic_server_session_base_test.cc +++ b/net/quic/core/quic_server_session_base_test.cc
@@ -210,6 +210,7 @@ // Send a reset (and expect the peer to send a RST in response). QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, 0); + EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); visitor_->OnRstStream(rst1); @@ -227,6 +228,7 @@ // Send a reset (and expect the peer to send a RST in response). QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, 0); + EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); visitor_->OnRstStream(rst1); @@ -253,6 +255,7 @@ // Send a reset (and expect the peer to send a RST in response). QuicRstStreamFrame rst(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, 0); + EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); visitor_->OnRstStream(rst);
diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc index 5f106f20..ab7c9b35 100644 --- a/net/quic/core/quic_session.cc +++ b/net/quic/core/quic_session.cc
@@ -94,6 +94,10 @@ return; } + if (visitor_) { + visitor_->OnRstStreamReceived(frame); + } + QuicStream* stream = GetOrCreateDynamicStream(frame.stream_id); if (!stream) { HandleRstOnValidNonexistentStream(frame);
diff --git a/net/quic/core/quic_session.h b/net/quic/core/quic_session.h index cba66a0..d3f8dda 100644 --- a/net/quic/core/quic_session.h +++ b/net/quic/core/quic_session.h
@@ -52,6 +52,9 @@ // Called when the session has become write blocked. virtual void OnWriteBlocked(QuicBlockedWriterInterface* blocked_writer) = 0; + + // Called when the session receives reset on a stream from the peer. + virtual void OnRstStreamReceived(const QuicRstStreamFrame& frame) = 0; }; // CryptoHandshakeEvent enumerates the events generated by a QuicCryptoStream.
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc index d20b365..4f12a2f 100644 --- a/net/spdy/spdy_session_pool.cc +++ b/net/spdy/spdy_session_pool.cc
@@ -271,8 +271,7 @@ DCHECK(!IsSessionAvailable(unavailable_session)); unavailable_session->net_log().AddEvent( - NetLogEventType::HTTP2_SESSION_POOL_REMOVE_SESSION, - unavailable_session->net_log().source().ToEventParametersCallback()); + NetLogEventType::HTTP2_SESSION_POOL_REMOVE_SESSION); SessionSet::iterator it = sessions_.find(unavailable_session.get()); CHECK(it != sessions_.end());
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index ecc0ad65..e3cd37a 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc
@@ -146,6 +146,7 @@ g_time_delta = base::TimeDelta(); g_time_now = base::TimeTicks::Now(); session_deps_.net_log = log_.bound().net_log(); + session_deps_.enable_server_push_cancellation = true; } void CreateNetworkSession() {
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc index a7df840..6cb1d0c 100644 --- a/net/spdy/spdy_test_util_common.cc +++ b/net/spdy/spdy_test_util_common.cc
@@ -344,6 +344,7 @@ enable_ping(false), enable_user_alternate_protocol_ports(false), enable_quic(false), + enable_server_push_cancellation(false), session_max_recv_window_size(kDefaultInitialWindowSize), time_func(&base::TimeTicks::Now), enable_http2_alternative_service_with_different_host(false), @@ -405,6 +406,8 @@ params.enable_user_alternate_protocol_ports = session_deps->enable_user_alternate_protocol_ports; params.enable_quic = session_deps->enable_quic; + params.enable_server_push_cancellation = + session_deps->enable_server_push_cancellation; params.spdy_session_max_recv_window_size = session_deps->session_max_recv_window_size; params.http2_settings = session_deps->http2_settings;
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h index d2712f8..2f104755 100644 --- a/net/spdy/spdy_test_util_common.h +++ b/net/spdy/spdy_test_util_common.h
@@ -208,6 +208,7 @@ bool enable_ping; bool enable_user_alternate_protocol_ports; bool enable_quic; + bool enable_server_push_cancellation; size_t session_max_recv_window_size; SettingsMap http2_settings; SpdySession::TimeFunc time_func;
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc index bd691ce..7731031e 100644 --- a/net/tools/quic/quic_dispatcher.cc +++ b/net/tools/quic/quic_dispatcher.cc
@@ -524,6 +524,8 @@ write_blocked_list_.insert(std::make_pair(blocked_writer, true)); } +void QuicDispatcher::OnRstStreamReceived(const QuicRstStreamFrame& frame) {} + void QuicDispatcher::OnConnectionAddedToTimeWaitList( QuicConnectionId connection_id) { QUIC_DLOG(INFO) << "Connection " << connection_id
diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h index 50d754f..0edcf78 100644 --- a/net/tools/quic/quic_dispatcher.h +++ b/net/tools/quic/quic_dispatcher.h
@@ -85,6 +85,11 @@ // Queues the blocked writer for later resumption. void OnWriteBlocked(QuicBlockedWriterInterface* blocked_writer) override; + // QuicSession::Visitor interface implementation (via inheritance of + // QuicTimeWaitListManager::Visitor): + // Collects reset error code received on streams. + void OnRstStreamReceived(const QuicRstStreamFrame& frame) override; + // QuicTimeWaitListManager::Visitor interface implementation // Called whenever the time wait list manager adds a new connection to the // time-wait list.
diff --git a/net/tools/quic/quic_simple_dispatcher.cc b/net/tools/quic/quic_simple_dispatcher.cc index cab2925..e173624 100644 --- a/net/tools/quic/quic_simple_dispatcher.cc +++ b/net/tools/quic/quic_simple_dispatcher.cc
@@ -26,6 +26,26 @@ QuicSimpleDispatcher::~QuicSimpleDispatcher() {} +int QuicSimpleDispatcher::GetRstErrorCount( + QuicRstStreamErrorCode error_code) const { + auto it = rst_error_map_.find(error_code); + if (it == rst_error_map_.end()) { + return 0; + } else { + return it->second; + } +} + +void QuicSimpleDispatcher::OnRstStreamReceived( + const QuicRstStreamFrame& frame) { + auto it = rst_error_map_.find(frame.error_code); + if (it == rst_error_map_.end()) { + rst_error_map_.insert(std::make_pair(frame.error_code, 1)); + } else { + it->second++; + } +} + QuicServerSessionBase* QuicSimpleDispatcher::CreateQuicSession( QuicConnectionId connection_id, const QuicSocketAddress& client_address) {
diff --git a/net/tools/quic/quic_simple_dispatcher.h b/net/tools/quic/quic_simple_dispatcher.h index b9df6d9..41d24cf 100644 --- a/net/tools/quic/quic_simple_dispatcher.h +++ b/net/tools/quic/quic_simple_dispatcher.h
@@ -24,6 +24,10 @@ ~QuicSimpleDispatcher() override; + int GetRstErrorCount(QuicRstStreamErrorCode rst_error_code) const; + + void OnRstStreamReceived(const QuicRstStreamFrame& frame) override; + protected: QuicServerSessionBase* CreateQuicSession( QuicConnectionId connection_id, @@ -33,6 +37,9 @@ private: QuicHttpResponseCache* response_cache_; // Unowned. + + // The map of the reset error code with its counter. + std::map<QuicRstStreamErrorCode, int> rst_error_map_; }; } // namespace net
diff --git a/net/tools/quic/quic_simple_server_session_test.cc b/net/tools/quic/quic_simple_server_session_test.cc index 2d90c26b..4cc0329 100644 --- a/net/tools/quic/quic_simple_server_session_test.cc +++ b/net/tools/quic/quic_simple_server_session_test.cc
@@ -236,6 +236,7 @@ // Receive a reset (and send a RST in response). QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, 0); + EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); visitor_->OnRstStream(rst1); @@ -253,6 +254,7 @@ // Send a reset (and expect the peer to send a RST in response). QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, 0); + EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); visitor_->OnRstStream(rst1); @@ -279,6 +281,7 @@ // Send a reset (and expect the peer to send a RST in response). QuicRstStreamFrame rst(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, 0); + EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); visitor_->OnRstStream(rst); @@ -570,6 +573,7 @@ // Reset the last stream in the queue. It should be marked cancelled. QuicStreamId stream_got_reset = num_resources * 2; QuicRstStreamFrame rst(stream_got_reset, QUIC_STREAM_CANCELLED, 0); + EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); EXPECT_CALL(*connection_, SendRstStream(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT, 0)); visitor_->OnRstStream(rst); @@ -614,6 +618,7 @@ .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false))); EXPECT_CALL(*connection_, SendBlocked(stream_to_open)); + EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); QuicRstStreamFrame rst(stream_got_reset, QUIC_STREAM_CANCELLED, 0); visitor_->OnRstStream(rst); }
diff --git a/net/tools/quic/test_tools/mock_quic_session_visitor.h b/net/tools/quic/test_tools/mock_quic_session_visitor.h index ee1a6c7..793be8d4 100644 --- a/net/tools/quic/test_tools/mock_quic_session_visitor.h +++ b/net/tools/quic/test_tools/mock_quic_session_visitor.h
@@ -23,6 +23,7 @@ const std::string& error_details)); MOCK_METHOD1(OnWriteBlocked, void(QuicBlockedWriterInterface* blocked_writer)); + MOCK_METHOD1(OnRstStreamReceived, void(const QuicRstStreamFrame& frame)); MOCK_METHOD1(OnConnectionAddedToTimeWaitList, void(QuicConnectionId connection_id));
diff --git a/net/tools/transport_security_state_generator/BUILD.gn b/net/tools/transport_security_state_generator/BUILD.gn index 06bfd8b..52ade36 100644 --- a/net/tools/transport_security_state_generator/BUILD.gn +++ b/net/tools/transport_security_state_generator/BUILD.gn
@@ -62,6 +62,7 @@ deps = [ ":transport_security_state_generator_sources", "//base", + "//build/config/sanitizers:deps", "//crypto", "//third_party/boringssl", ]
diff --git a/net/url_request/url_request_quic_unittest.cc b/net/url_request/url_request_quic_unittest.cc index 7532196..ff887060 100644 --- a/net/url_request/url_request_quic_unittest.cc +++ b/net/url_request/url_request_quic_unittest.cc
@@ -15,12 +15,17 @@ #include "net/cert/mock_cert_verifier.h" #include "net/dns/mapped_host_resolver.h" #include "net/dns/mock_host_resolver.h" +#include "net/log/net_log_event_type.h" +#include "net/log/test_net_log.h" +#include "net/log/test_net_log_entry.h" #include "net/quic/chromium/crypto/proof_source_chromium.h" #include "net/quic/test_tools/crypto_test_utils.h" #include "net/test/cert_test_util.h" #include "net/test/gtest_util.h" #include "net/test/test_data_directory.h" +#include "net/tools/quic/quic_dispatcher.h" #include "net/tools/quic/quic_http_response_cache.h" +#include "net/tools/quic/quic_simple_dispatcher.h" #include "net/tools/quic/quic_simple_server.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_test_util.h" @@ -64,14 +69,20 @@ params->origins_to_force_quic_on.insert(HostPortPair(kTestServerHost, 443)); params->cert_verifier = &cert_verifier_; params->enable_quic = true; + params->enable_server_push_cancellation = true; context_->set_host_resolver(host_resolver_.get()); context_->set_http_network_session_params(std::move(params)); context_->set_cert_verifier(&cert_verifier_); + context_->set_net_log(&net_log_); } void TearDown() override { - if (server_) + if (server_) { server_->Shutdown(); + // If possible, deliver the conncetion close packet to the client before + // destruct the TestURLRequestContext. + base::RunLoop().RunUntilIdle(); + } } // Sets a NetworkDelegate to use for |context_|. Must be done before Init(). @@ -88,11 +99,29 @@ return context_->CreateRequest(url, priority, delegate); } + void ExtractNetLog(NetLogEventType type, + TestNetLogEntry::List* entry_list) const { + net::TestNetLogEntry::List entries; + net_log_.GetEntries(&entries); + + for (const auto& entry : entries) { + if (entry.type == type) + entry_list->push_back(entry); + } + } + + unsigned int GetRstErrorCountReceivedByServer( + QuicRstStreamErrorCode error_code) const { + return (static_cast<QuicSimpleDispatcher*>(server_->dispatcher())) + ->GetRstErrorCount(error_code); + } + private: void StartQuicServer() { // Set up in-memory cache. response_cache_.AddSimpleResponse(kTestServerHost, kHelloPath, kHelloStatus, kHelloBodyValue); + response_cache_.InitializeFromDirectory(ServerPushCacheDirectory()); net::QuicConfig config; // Set up server certs. std::unique_ptr<net::ProofSourceChromium> proof_source( @@ -120,9 +149,19 @@ EXPECT_TRUE(host_resolver_->AddRuleFromString(map_rule)); } + std::string ServerPushCacheDirectory() { + base::FilePath path; + PathService::Get(base::DIR_SOURCE_ROOT, &path); + path = path.AppendASCII("net").AppendASCII("data").AppendASCII( + "quic_http_response_cache_data_with_push"); + // The file path is known to be an ascii string. + return path.MaybeAsASCII(); + } + std::unique_ptr<MappedHostResolver> host_resolver_; std::unique_ptr<QuicSimpleServer> server_; std::unique_ptr<TestURLRequestContext> context_; + TestNetLog net_log_; QuicHttpResponseCache response_cache_; MockCertVerifier cert_verifier_; }; @@ -211,6 +250,208 @@ EXPECT_EQ(kHelloBodyValue, delegate.data_received()); } +TEST_F(URLRequestQuicTest, CancelPushIfCached) { + base::RunLoop run_loop; + Init(); + + // Send a request to the pushed url: /kitten-1.jpg to pull the resource into + // cache. + CheckLoadTimingDelegate delegate_0(false); + std::string url_0 = + base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg"); + std::unique_ptr<URLRequest> request_0 = + CreateRequest(GURL(url_0), DEFAULT_PRIORITY, &delegate_0); + + request_0->Start(); + ASSERT_TRUE(request_0->is_pending()); + + // Spin the message loop until the client receives the response for the first + // request. + do { + base::RunLoop().RunUntilIdle(); + } while (request_0->status().is_io_pending()); + EXPECT_TRUE(request_0->status().is_success()); + + // Send a request to /index2.html which pushes /kitten-1.jpg and /favicon.ico. + // Should cancel push for /kitten-1.jpg. + CheckLoadTimingDelegate delegate(true); + std::string url = + base::StringPrintf("https://%s%s", kTestServerHost, "/index2.html"); + std::unique_ptr<URLRequest> request = + CreateRequest(GURL(url), DEFAULT_PRIORITY, &delegate); + + request->Start(); + ASSERT_TRUE(request->is_pending()); + + // Spin the message loop until the client receives the response for the second + // request. + do { + base::RunLoop().RunUntilIdle(); + } while (request->status().is_io_pending()); + EXPECT_TRUE(request->status().is_success()); + + // Extract net logs on client side to verify push lookup transactions. + net::TestNetLogEntry::List entries; + ExtractNetLog(NetLogEventType::SERVER_PUSH_LOOKUP_TRANSACTION, &entries); + + EXPECT_EQ(4u, entries.size()); + + std::string value; + int net_error; + std::string push_url_1 = + base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg"); + std::string push_url_2 = + base::StringPrintf("https://%s%s", kTestServerHost, "/favicon.ico"); + + EXPECT_TRUE(entries[0].GetStringValue("push_url", &value)); + EXPECT_EQ(value, push_url_1); + // No net error code for this lookup transaction, the push is found. + EXPECT_FALSE(entries[1].GetIntegerValue("net_error", &net_error)); + + EXPECT_TRUE(entries[2].GetStringValue("push_url", &value)); + EXPECT_EQ(value, push_url_2); + // Net error code -400 is found for this lookup transaction, the push is not + // found in the cache. + EXPECT_TRUE(entries[3].GetIntegerValue("net_error", &net_error)); + EXPECT_EQ(net_error, -400); + + // Verify the reset error count received on the server side. + EXPECT_LE(1u, GetRstErrorCountReceivedByServer(QUIC_STREAM_CANCELLED)); +} + +TEST_F(URLRequestQuicTest, CancelPushIfCached2) { + base::RunLoop run_loop; + Init(); + + // Send a request to the pushed url: /kitten-1.jpg to pull the resource into + // cache. + CheckLoadTimingDelegate delegate_0(false); + std::string url_0 = + base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg"); + std::unique_ptr<URLRequest> request_0 = + CreateRequest(GURL(url_0), DEFAULT_PRIORITY, &delegate_0); + + request_0->Start(); + ASSERT_TRUE(request_0->is_pending()); + + // Spin the message loop until the client receives the response for the first + // request. + do { + base::RunLoop().RunUntilIdle(); + } while (request_0->status().is_io_pending()); + EXPECT_TRUE(request_0->status().is_success()); + + // Send a request to the pushed url: /favicon.ico to pull the resource into + // cache. + CheckLoadTimingDelegate delegate_1(true); + std::string url_1 = + base::StringPrintf("https://%s%s", kTestServerHost, "/favicon.ico"); + std::unique_ptr<URLRequest> request_1 = + CreateRequest(GURL(url_1), DEFAULT_PRIORITY, &delegate_1); + + request_1->Start(); + ASSERT_TRUE(request_1->is_pending()); + + // Spin the message loop until the client receives the response for the second + // request. + do { + base::RunLoop().RunUntilIdle(); + } while (request_1->status().is_io_pending()); + EXPECT_TRUE(request_1->status().is_success()); + + // Send a request to /index2.html which pushes /kitten-1.jpg and /favicon.ico. + // Should cancel push for /kitten-1.jpg. + CheckLoadTimingDelegate delegate(true); + std::string url = + base::StringPrintf("https://%s%s", kTestServerHost, "/index2.html"); + std::unique_ptr<URLRequest> request = + CreateRequest(GURL(url), DEFAULT_PRIORITY, &delegate); + + request->Start(); + ASSERT_TRUE(request->is_pending()); + + // Spin the message loop until the client receives the response for the third + // request. + do { + base::RunLoop().RunUntilIdle(); + } while (request->status().is_io_pending()); + EXPECT_TRUE(request->status().is_success()); + + // Extract net logs on client side to verify push lookup transactions. + net::TestNetLogEntry::List entries; + ExtractNetLog(NetLogEventType::SERVER_PUSH_LOOKUP_TRANSACTION, &entries); + + EXPECT_EQ(4u, entries.size()); + + std::string value; + int net_error; + std::string push_url_1 = + base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg"); + std::string push_url_2 = + base::StringPrintf("https://%s%s", kTestServerHost, "/favicon.ico"); + + EXPECT_TRUE(entries[0].GetStringValue("push_url", &value)); + EXPECT_EQ(value, push_url_1); + // No net error code for this lookup transaction, the push is found. + EXPECT_FALSE(entries[1].GetIntegerValue("net_error", &net_error)); + + EXPECT_TRUE(entries[2].GetStringValue("push_url", &value)); + EXPECT_EQ(value, push_url_2); + // No net error code for this lookup transaction, the push is found. + EXPECT_FALSE(entries[3].GetIntegerValue("net_error", &net_error)); + + // Verify the reset error count received on the server side. + EXPECT_LE(2u, GetRstErrorCountReceivedByServer(QUIC_STREAM_CANCELLED)); +} + +TEST_F(URLRequestQuicTest, DoNotCancelPushIfNotFoundInCache) { + base::RunLoop run_loop; + Init(); + + // Send a request to /index2.hmtl which pushes /kitten-1.jpg and /favicon.ico + // and shouldn't cancel any since neither is in cache. + CheckLoadTimingDelegate delegate(false); + std::string url = + base::StringPrintf("https://%s%s", kTestServerHost, "/index2.html"); + std::unique_ptr<URLRequest> request = + CreateRequest(GURL(url), DEFAULT_PRIORITY, &delegate); + + request->Start(); + ASSERT_TRUE(request->is_pending()); + + // Spin the message loop until the client receives response. + do { + base::RunLoop().RunUntilIdle(); + } while (request->status().is_io_pending()); + EXPECT_TRUE(request->status().is_success()); + + // Extract net logs on client side to verify push lookup transactions. + net::TestNetLogEntry::List entries; + ExtractNetLog(NetLogEventType::SERVER_PUSH_LOOKUP_TRANSACTION, &entries); + + EXPECT_EQ(4u, entries.size()); + + std::string value; + int net_error; + std::string push_url_1 = + base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg"); + std::string push_url_2 = + base::StringPrintf("https://%s%s", kTestServerHost, "/favicon.ico"); + + EXPECT_TRUE(entries[0].GetStringValue("push_url", &value)); + EXPECT_EQ(value, push_url_1); + EXPECT_TRUE(entries[1].GetIntegerValue("net_error", &net_error)); + EXPECT_EQ(net_error, -400); + + EXPECT_TRUE(entries[2].GetStringValue("push_url", &value)); + EXPECT_EQ(value, push_url_2); + EXPECT_TRUE(entries[3].GetIntegerValue("net_error", &net_error)); + EXPECT_EQ(net_error, -400); + + // Verify the reset error count received on the server side. + EXPECT_EQ(0u, GetRstErrorCountReceivedByServer(QUIC_STREAM_CANCELLED)); +} + // Tests that if two requests use the same QUIC session, the second request // should not have |LoadTimingInfo::connect_timing|. TEST_F(URLRequestQuicTest, TestTwoRequests) {
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index 1e905fd..5f7f123 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc
@@ -135,7 +135,7 @@ base::MakeUnique<HttpNetworkSession>(params)); context_storage_.set_http_transaction_factory(base::MakeUnique<HttpCache>( context_storage_.http_network_session(), - HttpCache::DefaultBackend::InMemory(0), false)); + HttpCache::DefaultBackend::InMemory(0), true /* is_main_cache */)); } if (!http_user_agent_settings()) { context_storage_.set_http_user_agent_settings(
diff --git a/printing/pdf_metafile_skia.cc b/printing/pdf_metafile_skia.cc index aec4d3f..b2e914b3 100644 --- a/printing/pdf_metafile_skia.cc +++ b/printing/pdf_metafile_skia.cc
@@ -12,9 +12,9 @@ #include "base/files/file.h" #include "base/memory/ptr_util.h" #include "base/time/time.h" +#include "cc/paint/paint_canvas.h" #include "cc/paint/paint_record.h" #include "cc/paint/paint_recorder.h" -#include "cc/paint/skia_paint_canvas.h" #include "printing/print_settings.h" #include "third_party/skia/include/core/SkDocument.h" #include "third_party/skia/include/core/SkStream.h"
diff --git a/remoting/host/linux/BUILD.gn b/remoting/host/linux/BUILD.gn index 4315e87..0c7ed70e 100644 --- a/remoting/host/linux/BUILD.gn +++ b/remoting/host/linux/BUILD.gn
@@ -16,6 +16,7 @@ deps = [ "//base", + "//build/config/sanitizers:deps", ] libs = [ "pam" ]
diff --git a/services/service_manager/tests/connect/BUILD.gn b/services/service_manager/tests/connect/BUILD.gn index 38aa864..6fd272a4 100644 --- a/services/service_manager/tests/connect/BUILD.gn +++ b/services/service_manager/tests/connect/BUILD.gn
@@ -144,6 +144,7 @@ deps = [ ":interfaces", "//base", + "//build/config/sanitizers:deps", "//build/win:default_exe_manifest", "//services/service_manager/public/cpp", "//services/service_manager/public/cpp/standalone_service:main",
diff --git a/services/service_manager/tests/lifecycle/BUILD.gn b/services/service_manager/tests/lifecycle/BUILD.gn index faf41b14..403ac50c 100644 --- a/services/service_manager/tests/lifecycle/BUILD.gn +++ b/services/service_manager/tests/lifecycle/BUILD.gn
@@ -132,6 +132,7 @@ deps = [ ":app_client", "//base", + "//build/config/sanitizers:deps", "//build/win:default_exe_manifest", "//services/service_manager/public/cpp:sources", "//services/service_manager/public/cpp/standalone_service:main",
diff --git a/services/service_manager/tests/service_manager/BUILD.gn b/services/service_manager/tests/service_manager/BUILD.gn index 3a34cf5..8dee88f 100644 --- a/services/service_manager/tests/service_manager/BUILD.gn +++ b/services/service_manager/tests/service_manager/BUILD.gn
@@ -57,6 +57,7 @@ deps = [ ":interfaces", "//base", + "//build/config/sanitizers:deps", "//build/win:default_exe_manifest", "//services/service_manager/public/cpp", "//services/service_manager/public/cpp/standalone_service:main",
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 7ee554e..c3d7cab 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2786,3 +2786,7 @@ crbug.com/682753 fast/canvas-experimental [ Skip ] crbug.com/708934 fast/backgrounds/background-image-relative-url-in-iframe.html [ Failure Pass ] + +# Sheriff failures 2017-04-14 +crbug.com/711689 [ Mac ] paint/invalidation/text-match-document-change.html [ Failure ] +crbug.com/711689 [ Mac ] virtual/disable-spinvalidation/paint/invalidation/text-match-document-change.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/layers-in-multicol-expected.html b/third_party/WebKit/LayoutTests/fast/multicol/layers-in-multicol-expected.html new file mode 100644 index 0000000..97d5761f --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/layers-in-multicol-expected.html
@@ -0,0 +1,87 @@ +<!DOCTYPE html> +<style> + .multicol { + width: 300px; + height: 100px; + line-height: 20px; + border: 5px solid maroon; + } + .column { + width: 100px; + float: left; + } + .multicol[dir="rtl"] > .column { + float: right; + } + .block { + display: inline-block; + width: 1em; + height: 10px; + background-color: green; + } + .opacity { + opacity: 0.5; + color: green; + } + .relative { + position: relative; + top: -4px; + color: green; + } +</style> +<p> + Test layers which are fully contained within a single column. +</p> +LTR: +<div class="multicol"> + <div class="column"> + line1<br> + line2<br> + line3<br> + line4<br> + line5<br> + </div> + <div class="column"> + line6<br> + <div class="block"></div> line7<br> + line8<br> + <span class="relative">relative9</span><br> + line10<br> + </div> + <div class="column"> + line11<br> + line12<br> + <!-- The extra inner span below forces the creation of a transparency layer in Skia to work + around optimizations that would cause blending differences between the test and the + expectation. --> + <span class="opacity">opacity<span>13</span></span><br> + line14 + </div> +</div> + +RTL: +<div class="multicol" dir="rtl"> + <div class="column"> + line1<br> + line2<br> + line3<br> + line4<br> + line5<br> + </div> + <div class="column"> + line6<br> + <div class="block"></div> line7<br> + line8<br> + <span class="relative">relative9</span><br> + line10<br> + </div> + <div class="column"> + line11<br> + line12<br> + <!-- The extra inner span below forces the creation of a transparency layer in Skia to work + around optimizations that would cause blending differences between the test and the + expectation. --> + <span class="opacity">opacity<span>13</span></span><br> + line14 + </div> +</div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/layers-split-across-columns-expected.html b/third_party/WebKit/LayoutTests/fast/multicol/layers-split-across-columns-expected.html new file mode 100644 index 0000000..8bbd920 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/layers-split-across-columns-expected.html
@@ -0,0 +1,90 @@ +<!DOCTYPE html> +<style> + .container { + margin-right: 4px; + position: absolute; + } + .multicol { + width: 110px; + height: 150px; + border: 5px solid black; + } + .multicol > div { + float: left; + width: 50px; + height: 50px; + } + + .row1_left { background-color: black; } + .row1_right { background-color: #0000b0; } + .row2_left { background-color: #0000f0; } + .row2_right { background-color: #000090; } + .row3_left { background-color: #0000d0; } + .row3_right { background-color: black; } + + .row1_right, + .row2_right, + .row3_right { + margin-left: 10px; + } + + #opacity .row1_right, + #opacity .row2_left, + #opacity .row2_right, + #opacity .row3_left { + opacity: 0.99; + } + + .pos1 { left: 10px; top: 10px; } + .pos2 { left: 150px; top: 10px; } + .pos3 { left: 10px; top: 200px; } + .pos4 { left: 150px; top: 200px; } + +</style> +<div class="container pos1"> + Overflow: + <div class="multicol"> + <div class="row1_left"></div> + <div class="row1_right"></div> + <div class="row2_left"></div> + <div class="row2_right"></div> + <div class="row3_left"></div> + <div class="row3_right"></div> + </div> +</div> +<div class="container pos2"> + Transforms: + <div class="multicol"> + <div class="row1_left"></div> + <div class="row1_right"></div> + <div class="row2_left"></div> + <div class="row2_right"></div> + <div class="row3_left"></div> + <div class="row3_right"></div> + </div> +</div> +<div class="container pos3"> + Relative Pos.: + <div class="multicol"> + <div class="row1_left"></div> + <div class="row1_right"></div> + <div class="row2_left"></div> + <div class="row2_right"></div> + <div class="row3_left"></div> + <div class="row3_right"></div> + </div> +</div> +<div class="container pos4" id="opacity"> + Opacity: + <div class="multicol"> + <div class="row1_left"></div> + <!-- The extra s below force the creation of transparency layers in Skia to work + around optimizations that would cause blending differences between the test and the + expectation. --> + <div class="row1_right"> </div> + <div class="row2_left"> </div> + <div class="row2_right"> </div> + <div class="row3_left"> </div> + <div class="row3_right"></div> + </div> +</div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.html b/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.html new file mode 100644 index 0000000..0b67873 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.html
@@ -0,0 +1,6 @@ +<div style="position:relative; width:420px;border:2px solid black; height:200px"> +<!-- The extra below forces the creation of a transparency layer in Skia to work around + optimizations that would cause blending differences between the test and the expectation. --> +<div style="opacity:0.5; position:absolute;width:200px;height:100px;background-color:green;right:0;top:0"> </div> +</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.png b/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.png deleted file mode 100644 index 1ebb6e8..0000000 --- a/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-cross-origin-iframe-logging.html b/third_party/WebKit/LayoutTests/http/tests/inspector/console-cross-origin-iframe-logging.html index 950a8cf7..42515561 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-cross-origin-iframe-logging.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-cross-origin-iframe-logging.html
@@ -23,12 +23,8 @@ { var finishAttemptsLeft = 2; InspectorTest.addConsoleSniffer(maybeFinish, true); - InspectorTest.NetworkAgent.setMonitoringXHREnabled(true, step1); - - function step1() - { - InspectorTest.evaluateInPage("accessFrame()", maybeFinish); - } + Common.settingForTest('monitoringXHREnabled').set(true); + InspectorTest.evaluateInPage("accessFrame()", maybeFinish); function maybeFinish() { @@ -36,11 +32,7 @@ if (finishAttemptsLeft) return; - InspectorTest.NetworkAgent.setMonitoringXHREnabled(false, finish); - } - - function finish() - { + Common.settingForTest('monitoringXHREnabled').set(false); InspectorTest.dumpConsoleMessages(); InspectorTest.completeTest(); }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-fetch-logging.html b/third_party/WebKit/LayoutTests/http/tests/inspector/console-fetch-logging.html index 6ec9885..04e70bc 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-fetch-logging.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-fetch-logging.html
@@ -54,20 +54,14 @@ function step1() { - function callback() - { - InspectorTest.callFunctionInPageAsync("makeRequests").then(step2); - } - InspectorTest.NetworkAgent.setMonitoringXHREnabled(true, callback); + Common.settingForTest('monitoringXHREnabled').set(true); + InspectorTest.callFunctionInPageAsync("makeRequests").then(step2); } function step2() { - function callback() - { - InspectorTest.callFunctionInPageAsync("makeRequests").then(step3); - } - InspectorTest.NetworkAgent.setMonitoringXHREnabled(false, callback); + Common.settingForTest('monitoringXHREnabled').set(false); + InspectorTest.callFunctionInPageAsync("makeRequests").then(step3); } function step3()
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async-expected.txt index 78f8410..7604d45 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async-expected.txt
@@ -3,10 +3,10 @@ Tests that XMLHttpRequest Logging works when Enabled and doesn't show logs when Disabled for asynchronous XHRs. Bug 79229 +network-test.js:6 XHR loaded: 1 network-test.js:37 XHR finished loading: GET "http://127.0.0.1:8000/inspector/resources/xhr-exists.html". makeXHR @ network-test.js:37 makeXHRForJSONArguments @ network-test.js:43 (anonymous) @ VM:1 -network-test.js:6 XHR loaded: 1 network-test.js:6 XHR loaded: 2
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async.html b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async.html index 280d809c..b759e5be 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-async.html
@@ -15,22 +15,14 @@ function step1() { - function callback() - { - makeRequest(step2); - } - - InspectorTest.NetworkAgent.setMonitoringXHREnabled(true, callback); + Common.settingForTest('monitoringXHREnabled').set(true); + makeRequest(step2); } function step2() { - function callback() - { - makeRequest(step3); - } - - InspectorTest.NetworkAgent.setMonitoringXHREnabled(false, callback); + Common.settingForTest('monitoringXHREnabled').set(false); + makeRequest(step3); } function step3()
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-expected.txt index bb38e6e5..dd9ac27 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging-expected.txt
@@ -17,14 +17,12 @@ makeSimpleXHRWithPayload @ network-test.js:16 makeSimpleXHR @ network-test.js:11 requestHelper @ console-xhr-logging.html:6 -makeRequests @ console-xhr-logging.html:12 (anonymous) @ VM:1 network-test.js:37 XHR finished loading: GET "http://127.0.0.1:8000/inspector/resources/xhr-exists.html". makeXHR @ network-test.js:37 makeSimpleXHRWithPayload @ network-test.js:16 makeSimpleXHR @ network-test.js:11 requestHelper @ console-xhr-logging.html:6 -makeRequests @ console-xhr-logging.html:12 (anonymous) @ VM:1 console-xhr-logging.html:5 sending a GET request to resources/xhr-does-not-exist.html network-test.js:37 GET http://127.0.0.1:8000/inspector/resources/xhr-does-not-exist.html 404 (Not Found) @@ -32,14 +30,12 @@ makeSimpleXHRWithPayload @ network-test.js:16 makeSimpleXHR @ network-test.js:11 requestHelper @ console-xhr-logging.html:6 -makeRequests @ console-xhr-logging.html:14 (anonymous) @ VM:1 -network-test.js:37 XHR finished loading: GET "http://127.0.0.1:8000/inspector/resources/xhr-does-not-exist.html". +network-test.js:37 XHR failed loading: GET "http://127.0.0.1:8000/inspector/resources/xhr-does-not-exist.html". makeXHR @ network-test.js:37 makeSimpleXHRWithPayload @ network-test.js:16 makeSimpleXHR @ network-test.js:11 requestHelper @ console-xhr-logging.html:6 -makeRequests @ console-xhr-logging.html:14 (anonymous) @ VM:1 console-xhr-logging.html:5 sending a POST request to resources/post-target.cgi network-test.js:37 XHR finished loading: POST "http://127.0.0.1:8000/inspector/resources/post-target.cgi". @@ -47,7 +43,6 @@ makeSimpleXHRWithPayload @ network-test.js:16 makeSimpleXHR @ network-test.js:11 requestHelper @ console-xhr-logging.html:6 -makeRequests @ console-xhr-logging.html:16 (anonymous) @ VM:1 console-xhr-logging.html:5 sending a GET request to http://localhost:8000/inspector/resources/xhr-exists.html network-test.js:37 XMLHttpRequest cannot load http://localhost:8000/inspector/resources/xhr-exists.html. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8000' is therefore not allowed access. @@ -55,14 +50,12 @@ makeSimpleXHRWithPayload @ network-test.js:16 makeSimpleXHR @ network-test.js:11 requestHelper @ console-xhr-logging.html:6 -makeRequests @ console-xhr-logging.html:18 (anonymous) @ VM:1 -network-test.js:37 XHR failed loading: GET "http://localhost:8000/inspector/resources/xhr-exists.html". +network-test.js:37 XHR finished loading: GET "http://localhost:8000/inspector/resources/xhr-exists.html". makeXHR @ network-test.js:37 makeSimpleXHRWithPayload @ network-test.js:16 makeSimpleXHR @ network-test.js:11 requestHelper @ console-xhr-logging.html:6 -makeRequests @ console-xhr-logging.html:18 (anonymous) @ VM:1 console-xhr-logging.html:5 sending a GET request to resources/xhr-exists.html console-xhr-logging.html:5 sending a GET request to resources/xhr-does-not-exist.html @@ -71,7 +64,6 @@ makeSimpleXHRWithPayload @ network-test.js:16 makeSimpleXHR @ network-test.js:11 requestHelper @ console-xhr-logging.html:6 -makeRequests @ console-xhr-logging.html:14 (anonymous) @ VM:1 console-xhr-logging.html:5 sending a POST request to resources/post-target.cgi console-xhr-logging.html:5 sending a GET request to http://localhost:8000/inspector/resources/xhr-exists.html @@ -80,6 +72,5 @@ makeSimpleXHRWithPayload @ network-test.js:16 makeSimpleXHR @ network-test.js:11 requestHelper @ console-xhr-logging.html:6 -makeRequests @ console-xhr-logging.html:18 (anonymous) @ VM:1
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging.html b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging.html index da78e725..9bd30b4 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-xhr-logging.html
@@ -11,49 +11,23 @@ makeSimpleXHR(method, url, false); } -function makeRequests() +async function test() { - // 1. Page that exists. - requestHelper("GET", "resources/xhr-exists.html"); - // 2. Page that doesn't exist. - requestHelper("GET", "resources/xhr-does-not-exist.html"); - // 3. POST to a page. - requestHelper("POST", "resources/post-target.cgi"); - // 4. Cross-origin request - requestHelper("GET", "http://localhost:8000/inspector/resources/xhr-exists.html"); -} + Common.settingForTest('monitoringXHREnabled').set(true); + await InspectorTest.evaluateInPagePromise("requestHelper('GET', 'resources/xhr-exists.html')"); + await InspectorTest.evaluateInPagePromise("requestHelper('GET', 'resources/xhr-does-not-exist.html')"); + await InspectorTest.evaluateInPagePromise("requestHelper('POST', 'resources/post-target.cgi')"); + await InspectorTest.evaluateInPagePromise("requestHelper('GET', 'http://localhost:8000/inspector/resources/xhr-exists.html')"); + Common.settingForTest('monitoringXHREnabled').set(false); + await InspectorTest.evaluateInPagePromise("requestHelper('GET', 'resources/xhr-exists.html')"); + await InspectorTest.evaluateInPagePromise("requestHelper('GET', 'resources/xhr-does-not-exist.html')"); + await InspectorTest.evaluateInPagePromise("requestHelper('POST', 'resources/post-target.cgi')"); + await InspectorTest.evaluateInPagePromise("requestHelper('GET', 'http://localhost:8000/inspector/resources/xhr-exists.html')"); -function test() -{ - step1(); - - function step1() - { - function callback() - { - InspectorTest.evaluateInPage("makeRequests()", step2); - } - InspectorTest.NetworkAgent.setMonitoringXHREnabled(true, callback); - } - - function step2() - { - function callback() - { - InspectorTest.evaluateInPage("makeRequests()", step3); - } - InspectorTest.NetworkAgent.setMonitoringXHREnabled(false, callback); - } - - function step3() - { - function finish() - { - InspectorTest.dumpConsoleMessages(); - InspectorTest.completeTest(); - } - InspectorTest.deprecatedRunAfterPendingDispatches(finish); - } + InspectorTest.deprecatedRunAfterPendingDispatches(() => { + InspectorTest.dumpConsoleMessages(); + InspectorTest.completeTest(); + }); } //# sourceURL=console-xhr-logging.html </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/report-API-errors-expected.txt b/third_party/WebKit/LayoutTests/inspector/report-API-errors-expected.txt index 0f9a07cf5..667528b 100644 --- a/third_party/WebKit/LayoutTests/inspector/report-API-errors-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/report-API-errors-expected.txt
@@ -1,8 +1,8 @@ Tests that InspectorBackendStub is catching incorrect arguments. -Protocol Error: Invalid type of argument 'enabled' for method 'Network.setMonitoringXHREnabled' call. It must be 'boolean' but it is 'number'. -Protocol Error: Invalid number of arguments for method 'Network.setMonitoringXHREnabled' call. It must have the following arguments '[{"name":"enabled","type":"boolean","optional":false}]'. -Protocol Error: Optional callback argument for method 'Network.setMonitoringXHREnabled' call must be a function but its type is 'string'. +Protocol Error: Invalid type of argument 'userAgent' for method 'Network.setUserAgentOverride' call. It must be 'string' but it is 'number'. +Protocol Error: Invalid number of arguments for method 'Network.setUserAgentOverride' call. It must have the following arguments '[{"name":"userAgent","type":"string","optional":false}]'. +Protocol Error: Optional callback argument for method 'Network.setUserAgentOverride' call must be a function but its type is 'string'. Protocol Error: the message wrongDomain.something-strange is for non-existing domain 'wrongDomain': {"method":"wrongDomain.something-strange","params":{}} Protocol Error: Attempted to dispatch an unspecified method 'Inspector.something-strange': {"method":"Inspector.something-strange","params":{}}
diff --git a/third_party/WebKit/LayoutTests/inspector/report-API-errors.html b/third_party/WebKit/LayoutTests/inspector/report-API-errors.html index b9e40bf2..a60e7ad 100644 --- a/third_party/WebKit/LayoutTests/inspector/report-API-errors.html +++ b/third_party/WebKit/LayoutTests/inspector/report-API-errors.html
@@ -11,10 +11,10 @@ InspectorTest.addResult(String.sprintf.apply(this, arguments)); } - InspectorTest.NetworkAgent.setMonitoringXHREnabled(1); - InspectorTest.NetworkAgent.setMonitoringXHREnabled(); - InspectorTest.NetworkAgent.setMonitoringXHREnabled(false, "not a function"); - InspectorTest.NetworkAgent.setMonitoringXHREnabled(false, undefined); + InspectorTest.NetworkAgent.setUserAgentOverride(1); + InspectorTest.NetworkAgent.setUserAgentOverride(); + InspectorTest.NetworkAgent.setUserAgentOverride("123", "not a function"); + InspectorTest.NetworkAgent.setUserAgentOverride("123", undefined); InspectorTest.RuntimeAgent.evaluate("true", "test"); InspectorTest.RuntimeAgent.evaluate("true", "test", function(){}); InspectorTest.RuntimeAgent.evaluate("true", "test", undefined, function(){});
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.png b/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.png index c6cabcbb..a92e6a8 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.png +++ b/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-in-multicol-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-in-multicol-expected.png deleted file mode 100644 index 44fc4a4..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-in-multicol-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-split-across-columns-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-split-across-columns-expected.png deleted file mode 100644 index 27fbf58..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-split-across-columns-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png index 5e1fff8..b024e71 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png index 6f98684..8d5f6fd3 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png index 5e1fff8..b024e71 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png index 0acea10..3a881330 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png index 991aaf7a..07e019c 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/2d/hindi-rotated-expected.png index 84b89da..11b5d71 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/2d/hindi-rotated-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/2d/hindi-rotated-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/transformed-focused-text-input-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/transformed-focused-text-input-expected.png index 1693941..f409f9e 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/transformed-focused-text-input-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/transformed-focused-text-input-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png index 991aaf7a..07e019c 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-in-multicol-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-in-multicol-expected.png deleted file mode 100644 index 9243efa..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-in-multicol-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.png deleted file mode 100644 index 86cf379..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png index af00c64c0..56d7e380c 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png index 31dd704..ab426ac 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png index 98ce8c5..7e1243a1 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png index 556507c..8938c8b 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png index 70f55312..497919fc 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-focused-text-input-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-focused-text-input-expected.png index c57f417b..38e6870 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-focused-text-input-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-focused-text-input-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png index af00c64c0..56d7e380c 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-in-multicol-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-in-multicol-expected.png deleted file mode 100644 index 62b98ea..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-in-multicol-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-split-across-columns-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-split-across-columns-expected.png deleted file mode 100644 index 608b610..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-split-across-columns-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png index 6eb1bf6..8829276ef 100644 --- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png index 5b597ed..6837fed 100644 --- a/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png index 6eb1bf6..8829276ef 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png index 27dad6f..bbb8278 100644 --- a/third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/win7/transforms/2d/hindi-rotated-expected.png index 855bfdf8..7e9778db 100644 --- a/third_party/WebKit/LayoutTests/platform/win7/transforms/2d/hindi-rotated-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win7/transforms/2d/hindi-rotated-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png index 27dad6f..bbb8278 100644 --- a/third_party/WebKit/LayoutTests/platform/win7/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win7/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png Binary files differ
diff --git a/third_party/WebKit/Source/core/animation/AnimationTimeline.idl b/third_party/WebKit/Source/core/animation/AnimationTimeline.idl index d43ebba4..79726c0 100644 --- a/third_party/WebKit/Source/core/animation/AnimationTimeline.idl +++ b/third_party/WebKit/Source/core/animation/AnimationTimeline.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// http://www.w3.org/TR/web-animations/#the-animationtimeline-interface +// https://w3c.github.io/web-animations/#the-animationtimeline-interface [ RuntimeEnabled=WebAnimationsAPI,
diff --git a/third_party/WebKit/Source/core/animation/DocumentTimeline.idl b/third_party/WebKit/Source/core/animation/DocumentTimeline.idl index 62d7b8b8..ba3ba5b 100644 --- a/third_party/WebKit/Source/core/animation/DocumentTimeline.idl +++ b/third_party/WebKit/Source/core/animation/DocumentTimeline.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// http://www.w3.org/TR/web-animations/#the-documenttimeline-interface +// https://w3c.github.io/web-animations/#the-documenttimeline-interface [ RuntimeEnabled=WebAnimationsAPI,
diff --git a/third_party/WebKit/Source/core/animation/ElementAnimation.idl b/third_party/WebKit/Source/core/animation/ElementAnimation.idl index 018a7af..025edd4 100644 --- a/third_party/WebKit/Source/core/animation/ElementAnimation.idl +++ b/third_party/WebKit/Source/core/animation/ElementAnimation.idl
@@ -28,14 +28,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// http://www.w3.org/TR/web-animations/#the-animatable-interface -// http://www.w3.org/TR/web-animations/#extensions-to-the-element-interface +// https://w3c.github.io/web-animations/#the-animatable-interface +// https://w3c.github.io/web-animations/#extensions-to-the-element-interface // TODO(dstockwell): This should be an Animatable interface, where Element -// implements Animatable. The interface also has several changes: -// https://w3c.github.io/web-animations/#the-animatable-interface +// implements Animatable. partial interface Element { + // TODO(dstockwell): The argument types do not match the spec. [CallWith=ScriptState, Measure, RaisesException] Animation animate((sequence<Dictionary> or Dictionary)? effect, optional (unrestricted double or KeyframeEffectOptions) options); [RuntimeEnabled=WebAnimationsAPI] sequence<Animation> getAnimations(); };
diff --git a/third_party/WebKit/Source/core/css/CSSFontFaceRule.idl b/third_party/WebKit/Source/core/css/CSSFontFaceRule.idl index 480d556..88f4e8d 100644 --- a/third_party/WebKit/Source/core/css/CSSFontFaceRule.idl +++ b/third_party/WebKit/Source/core/css/CSSFontFaceRule.idl
@@ -23,8 +23,9 @@ // https://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSFontFaceRule // https://dev.w3.org/csswg/css-fonts/#om-fontface // -// The interface from DOM Level 2 Style is implemented here. -// TODO(foolip): Implement the interface from CSS Fonts. +// TODO(foolip): Make CSSFontFaceRule match new spec and/or change spec to match +// what's implemented. https://crbug.com/709013 +// https://github.com/w3c/csswg-drafts/issues/825 interface CSSFontFaceRule : CSSRule { [Measure] readonly attribute CSSStyleDeclaration style;
diff --git a/third_party/WebKit/Source/core/css/StyleMedia.idl b/third_party/WebKit/Source/core/css/StyleMedia.idl index 52b6412..7ac7b727 100644 --- a/third_party/WebKit/Source/core/css/StyleMedia.idl +++ b/third_party/WebKit/Source/core/css/StyleMedia.idl
@@ -29,7 +29,7 @@ // https://www.w3.org/TR/2009/WD-cssom-view-20090804/#the-media-interface // https://web.archive.org/web/20100206142043/http://dev.w3.org/csswg/cssom-view#the-stylemedia-interface // -// TODO(foolip): Remove this interface. +// TODO(foolip): Remove this interface. https://crbug.com/692839 [ NoInterfaceObject,
diff --git a/third_party/WebKit/Source/core/dom/Document.idl b/third_party/WebKit/Source/core/dom/Document.idl index 575e640..41e4115 100644 --- a/third_party/WebKit/Source/core/dom/Document.idl +++ b/third_party/WebKit/Source/core/dom/Document.idl
@@ -180,7 +180,7 @@ [CustomElementCallbacks, RaisesException] Element createElementNS(DOMString? namespaceURI, DOMString qualifiedName, (DOMString or Dictionary)? options); // Page Visibility - // https://www.w3.org/TR/page-visibility/#sec-document-interface + // https://w3c.github.io/page-visibility/#extensions-to-the-document-interface readonly attribute boolean hidden; readonly attribute VisibilityState visibilityState;
diff --git a/third_party/WebKit/Source/core/dom/FrameRequestCallback.idl b/third_party/WebKit/Source/core/dom/FrameRequestCallback.idl index 1e3e8a48..66dbef1 100644 --- a/third_party/WebKit/Source/core/dom/FrameRequestCallback.idl +++ b/third_party/WebKit/Source/core/dom/FrameRequestCallback.idl
@@ -32,6 +32,6 @@ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=28152 callback interface FrameRequestCallback { // highResTime is passed as high resolution timestamp, see - // http://www.w3.org/TR/hr-time/ for details. + // https://w3c.github.io/hr-time/ for details. void handleEvent(double highResTime); };
diff --git a/third_party/WebKit/Source/core/events/InputEvent.idl b/third_party/WebKit/Source/core/events/InputEvent.idl index 6db312ae..d2574da 100644 --- a/third_party/WebKit/Source/core/events/InputEvent.idl +++ b/third_party/WebKit/Source/core/events/InputEvent.idl
@@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// UI Events +// https://w3c.github.io/uievents/#idl-inputevent + [ Constructor(DOMString type, optional InputEventInit eventInitDict), RuntimeEnabled=InputEvent, ] interface InputEvent : UIEvent { - // UI Events - // https://w3c.github.io/uievents/#idl-inputevent readonly attribute DOMString? data; readonly attribute boolean isComposing;
diff --git a/third_party/WebKit/Source/core/events/InputEventInit.idl b/third_party/WebKit/Source/core/events/InputEventInit.idl index 81d0375c..9f59850 100644 --- a/third_party/WebKit/Source/core/events/InputEventInit.idl +++ b/third_party/WebKit/Source/core/events/InputEventInit.idl
@@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// UI Events +// https://w3c.github.io/uievents/#idl-inputeventinit + dictionary InputEventInit : UIEventInit { - // UI Events - // https://w3c.github.io/uievents/#idl-inputeventinit DOMString? data; boolean isComposing = false;
diff --git a/third_party/WebKit/Source/core/events/TextEvent.idl b/third_party/WebKit/Source/core/events/TextEvent.idl index 84d278a..2ae52eb 100644 --- a/third_party/WebKit/Source/core/events/TextEvent.idl +++ b/third_party/WebKit/Source/core/events/TextEvent.idl
@@ -25,8 +25,9 @@ // http://www.w3.org/TR/2011/WD-DOM-Level-3-Events-20110531/#webidl-events-TextEvent -// TODO(foolip): Remove the textinput event and the TextEvent interface. They -// were removed from the spec in 2012: +// TODO(foolip): Remove the textinput event and the TextEvent interface. +// https://crbug.com/701480 +// They were removed from the spec in 2012: // https://www.w3.org/Bugs/Public/show_bug.cgi?id=12958 // https://github.com/w3c/uievents/commit/1a2aa02b474fd4feaf43fdced06e6fd7214196a4
diff --git a/third_party/WebKit/Source/core/html/media/MediaControls.h b/third_party/WebKit/Source/core/html/media/MediaControls.h index 1fe48e7b..8fecb61d 100644 --- a/third_party/WebKit/Source/core/html/media/MediaControls.h +++ b/third_party/WebKit/Source/core/html/media/MediaControls.h
@@ -77,12 +77,6 @@ virtual void BeginScrubbing() = 0; virtual void EndScrubbing() = 0; virtual void UpdateCurrentTimeDisplay() = 0; - virtual void ToggleTextTrackList() = 0; - virtual void ShowTextTrackAtIndex(unsigned) = 0; - virtual void DisableShowingTextTracks() = 0; - virtual void EnterFullscreen() = 0; - virtual void ExitFullscreen() = 0; - virtual void ToggleOverflowMenu() = 0; virtual bool OverflowMenuVisible() = 0; virtual void OnMediaControlsEnabledChange() = 0;
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp index c5fe80b..d5e8d49 100644 --- a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp +++ b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp
@@ -38,13 +38,9 @@ #include "core/events/KeyboardEvent.h" #include "core/events/MouseEvent.h" #include "core/frame/LocalFrame.h" -#include "core/frame/Settings.h" #include "core/frame/UseCounter.h" -#include "core/html/HTMLAnchorElement.h" #include "core/html/HTMLVideoElement.h" #include "core/html/TimeRanges.h" -#include "core/html/media/HTMLMediaElementControlsList.h" -#include "core/html/media/HTMLMediaSource.h" #include "core/html/media/MediaControls.h" #include "core/html/shadow/ShadowElementNames.h" #include "core/html/track/TextTrackList.h" @@ -52,7 +48,6 @@ #include "core/layout/LayoutBoxModelObject.h" #include "core/layout/api/LayoutSliderItem.h" #include "core/page/ChromeClient.h" -#include "core/page/Page.h" #include "platform/Histogram.h" #include "platform/RuntimeEnabledFeatures.h" #include "public/platform/Platform.h" @@ -99,308 +94,8 @@ type == EventTypeNames::pointermove; } -Element* ElementFromCenter(Element& element) { - ClientRect* client_rect = element.getBoundingClientRect(); - int center_x = - static_cast<int>((client_rect->left() + client_rect->right()) / 2); - int center_y = - static_cast<int>((client_rect->top() + client_rect->bottom()) / 2); - - return element.GetDocument().ElementFromPoint(center_x, center_y); -} - } // anonymous namespace -MediaControlPlayButtonElement::MediaControlPlayButtonElement( - MediaControls& media_controls) - : MediaControlInputElement(media_controls, kMediaPlayButton) {} - -MediaControlPlayButtonElement* MediaControlPlayButtonElement::Create( - MediaControls& media_controls) { - MediaControlPlayButtonElement* button = - new MediaControlPlayButtonElement(media_controls); - button->EnsureUserAgentShadowRoot(); - button->setType(InputTypeNames::button); - button->SetShadowPseudoId(AtomicString("-webkit-media-controls-play-button")); - return button; -} - -void MediaControlPlayButtonElement::DefaultEventHandler(Event* event) { - if (event->type() == EventTypeNames::click) { - if (MediaElement().paused()) - Platform::Current()->RecordAction( - UserMetricsAction("Media.Controls.Play")); - else - Platform::Current()->RecordAction( - UserMetricsAction("Media.Controls.Pause")); - - // Allow play attempts for plain src= media to force a reload in the error - // state. This allows potential recovery for transient network and decoder - // resource issues. - const String& url = MediaElement().currentSrc().GetString(); - if (MediaElement().error() && !HTMLMediaElement::IsMediaStreamURL(url) && - !HTMLMediaSource::Lookup(url)) - MediaElement().load(); - - MediaElement().TogglePlayState(); - UpdateDisplayType(); - event->SetDefaultHandled(); - } - MediaControlInputElement::DefaultEventHandler(event); -} - -void MediaControlPlayButtonElement::UpdateDisplayType() { - SetDisplayType(MediaElement().paused() ? kMediaPlayButton - : kMediaPauseButton); - UpdateOverflowString(); -} - -WebLocalizedString::Name -MediaControlPlayButtonElement::GetOverflowStringName() { - if (MediaElement().paused()) - return WebLocalizedString::kOverflowMenuPlay; - return WebLocalizedString::kOverflowMenuPause; -} - -// ---------------------------- - -MediaControlOverlayPlayButtonElement::MediaControlOverlayPlayButtonElement( - MediaControls& media_controls) - : MediaControlInputElement(media_controls, kMediaOverlayPlayButton) {} - -MediaControlOverlayPlayButtonElement* -MediaControlOverlayPlayButtonElement::Create(MediaControls& media_controls) { - MediaControlOverlayPlayButtonElement* button = - new MediaControlOverlayPlayButtonElement(media_controls); - button->EnsureUserAgentShadowRoot(); - button->setType(InputTypeNames::button); - button->SetShadowPseudoId( - AtomicString("-webkit-media-controls-overlay-play-button")); - return button; -} - -void MediaControlOverlayPlayButtonElement::DefaultEventHandler(Event* event) { - if (event->type() == EventTypeNames::click && MediaElement().paused()) { - Platform::Current()->RecordAction( - UserMetricsAction("Media.Controls.PlayOverlay")); - MediaElement().Play(); - UpdateDisplayType(); - event->SetDefaultHandled(); - } -} - -void MediaControlOverlayPlayButtonElement::UpdateDisplayType() { - SetIsWanted(MediaElement().ShouldShowControls() && MediaElement().paused()); -} - -bool MediaControlOverlayPlayButtonElement::KeepEventInNode(Event* event) { - return IsUserInteractionEvent(event); -} - -// ---------------------------- - -MediaControlToggleClosedCaptionsButtonElement:: - MediaControlToggleClosedCaptionsButtonElement(MediaControls& media_controls) - : MediaControlInputElement(media_controls, kMediaShowClosedCaptionsButton) { -} - -MediaControlToggleClosedCaptionsButtonElement* -MediaControlToggleClosedCaptionsButtonElement::Create( - MediaControls& media_controls) { - MediaControlToggleClosedCaptionsButtonElement* button = - new MediaControlToggleClosedCaptionsButtonElement(media_controls); - button->EnsureUserAgentShadowRoot(); - button->setType(InputTypeNames::button); - button->SetShadowPseudoId( - AtomicString("-webkit-media-controls-toggle-closed-captions-button")); - button->SetIsWanted(false); - return button; -} - -void MediaControlToggleClosedCaptionsButtonElement::UpdateDisplayType() { - bool captions_visible = MediaElement().TextTracksVisible(); - SetDisplayType(captions_visible ? kMediaHideClosedCaptionsButton - : kMediaShowClosedCaptionsButton); -} - -void MediaControlToggleClosedCaptionsButtonElement::DefaultEventHandler( - Event* event) { - if (event->type() == EventTypeNames::click) { - if (MediaElement().textTracks()->length() == 1) { - // If only one track exists, toggle it on/off - if (MediaElement().textTracks()->HasShowingTracks()) { - GetMediaControls().DisableShowingTextTracks(); - } else { - GetMediaControls().ShowTextTrackAtIndex(0); - } - } else { - GetMediaControls().ToggleTextTrackList(); - } - - UpdateDisplayType(); - event->SetDefaultHandled(); - } - - MediaControlInputElement::DefaultEventHandler(event); -} - -WebLocalizedString::Name -MediaControlToggleClosedCaptionsButtonElement::GetOverflowStringName() { - return WebLocalizedString::kOverflowMenuCaptions; -} - -// ---------------------------- - -MediaControlOverflowMenuButtonElement::MediaControlOverflowMenuButtonElement( - MediaControls& media_controls) - : MediaControlInputElement(media_controls, kMediaOverflowButton) {} - -MediaControlOverflowMenuButtonElement* -MediaControlOverflowMenuButtonElement::Create(MediaControls& media_controls) { - MediaControlOverflowMenuButtonElement* button = - new MediaControlOverflowMenuButtonElement(media_controls); - button->EnsureUserAgentShadowRoot(); - button->setType(InputTypeNames::button); - button->SetShadowPseudoId( - AtomicString("-internal-media-controls-overflow-button")); - button->SetIsWanted(false); - return button; -} - -void MediaControlOverflowMenuButtonElement::DefaultEventHandler(Event* event) { - if (event->type() == EventTypeNames::click) { - if (GetMediaControls().OverflowMenuVisible()) - Platform::Current()->RecordAction( - UserMetricsAction("Media.Controls.OverflowClose")); - else - Platform::Current()->RecordAction( - UserMetricsAction("Media.Controls.OverflowOpen")); - - GetMediaControls().ToggleOverflowMenu(); - event->SetDefaultHandled(); - } - - MediaControlInputElement::DefaultEventHandler(event); -} - -// ---------------------------- -MediaControlDownloadButtonElement::MediaControlDownloadButtonElement( - MediaControls& media_controls) - : MediaControlInputElement(media_controls, kMediaDownloadButton) {} - -MediaControlDownloadButtonElement* MediaControlDownloadButtonElement::Create( - MediaControls& media_controls) { - MediaControlDownloadButtonElement* button = - new MediaControlDownloadButtonElement(media_controls); - button->EnsureUserAgentShadowRoot(); - button->setType(InputTypeNames::button); - button->SetShadowPseudoId( - AtomicString("-internal-media-controls-download-button")); - button->SetIsWanted(false); - return button; -} - -WebLocalizedString::Name -MediaControlDownloadButtonElement::GetOverflowStringName() { - return WebLocalizedString::kOverflowMenuDownload; -} - -bool MediaControlDownloadButtonElement::ShouldDisplayDownloadButton() { - const KURL& url = MediaElement().currentSrc(); - - // Check page settings to see if download is disabled. - if (GetDocument().GetPage() && - GetDocument().GetPage()->GetSettings().GetHideDownloadUI()) - return false; - - // URLs that lead to nowhere are ignored. - if (url.IsNull() || url.IsEmpty()) - return false; - - // If we have no source, we can't download. - if (MediaElement().getNetworkState() == HTMLMediaElement::kNetworkEmpty || - MediaElement().getNetworkState() == HTMLMediaElement::kNetworkNoSource) { - return false; - } - - // Local files and blobs (including MSE) should not have a download button. - if (url.IsLocalFile() || url.ProtocolIs("blob")) - return false; - - // MediaStream can't be downloaded. - if (HTMLMediaElement::IsMediaStreamURL(url.GetString())) - return false; - - // MediaSource can't be downloaded. - if (HTMLMediaSource::Lookup(url)) - return false; - - // HLS stream shouldn't have a download button. - if (HTMLMediaElement::IsHLSURL(url)) - return false; - - // Infinite streams don't have a clear end at which to finish the download - // (would require adding UI to prompt for the duration to download). - if (MediaElement().duration() == std::numeric_limits<double>::infinity()) - return false; - - // The attribute disables the download button. - if (MediaElement().ControlsListInternal()->ShouldHideDownload()) { - UseCounter::Count(MediaElement().GetDocument(), - UseCounter::kHTMLMediaElementControlsListNoDownload); - return false; - } - - return true; -} - -void MediaControlDownloadButtonElement::SetIsWanted(bool wanted) { - MediaControlElement::SetIsWanted(wanted); - - if (!IsWanted()) - return; - - DCHECK(IsWanted()); - if (!show_use_counted_) { - show_use_counted_ = true; - RecordMetrics(DownloadActionMetrics::kShown); - } -} - -void MediaControlDownloadButtonElement::DefaultEventHandler(Event* event) { - const KURL& url = MediaElement().currentSrc(); - if (event->type() == EventTypeNames::click && - !(url.IsNull() || url.IsEmpty())) { - Platform::Current()->RecordAction( - UserMetricsAction("Media.Controls.Download")); - if (!click_use_counted_) { - click_use_counted_ = true; - RecordMetrics(DownloadActionMetrics::kClicked); - } - if (!anchor_) { - HTMLAnchorElement* anchor = HTMLAnchorElement::Create(GetDocument()); - anchor->setAttribute(HTMLNames::downloadAttr, ""); - anchor_ = anchor; - } - anchor_->SetURL(url); - anchor_->DispatchSimulatedClick(event); - } - MediaControlInputElement::DefaultEventHandler(event); -} - -DEFINE_TRACE(MediaControlDownloadButtonElement) { - visitor->Trace(anchor_); - MediaControlInputElement::Trace(visitor); -} - -void MediaControlDownloadButtonElement::RecordMetrics( - DownloadActionMetrics metric) { - DEFINE_STATIC_LOCAL(EnumerationHistogram, download_action_histogram, - ("Media.Controls.Download", - static_cast<int>(DownloadActionMetrics::kCount))); - download_action_histogram.Count(static_cast<int>(metric)); -} - // ---------------------------- MediaControlTimelineElement::MediaControlTimelineElement( @@ -593,162 +288,4 @@ return IsUserInteractionEventForSlider(event, GetLayoutObject()); } -// ---------------------------- - -MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement( - MediaControls& media_controls) - : MediaControlInputElement(media_controls, kMediaEnterFullscreenButton) {} - -MediaControlFullscreenButtonElement* -MediaControlFullscreenButtonElement::Create(MediaControls& media_controls) { - MediaControlFullscreenButtonElement* button = - new MediaControlFullscreenButtonElement(media_controls); - button->EnsureUserAgentShadowRoot(); - button->setType(InputTypeNames::button); - button->SetShadowPseudoId( - AtomicString("-webkit-media-controls-fullscreen-button")); - button->SetIsFullscreen(media_controls.MediaElement().IsFullscreen()); - button->SetIsWanted(false); - return button; -} - -void MediaControlFullscreenButtonElement::DefaultEventHandler(Event* event) { - if (event->type() == EventTypeNames::click) { - bool is_embedded_experience_enabled = - GetDocument().GetSettings() && - GetDocument().GetSettings()->GetEmbeddedMediaExperienceEnabled(); - if (MediaElement().IsFullscreen()) { - Platform::Current()->RecordAction( - UserMetricsAction("Media.Controls.ExitFullscreen")); - if (is_embedded_experience_enabled) { - Platform::Current()->RecordAction(UserMetricsAction( - "Media.Controls.ExitFullscreen.EmbeddedExperience")); - } - GetMediaControls().ExitFullscreen(); - } else { - Platform::Current()->RecordAction( - UserMetricsAction("Media.Controls.EnterFullscreen")); - if (is_embedded_experience_enabled) { - Platform::Current()->RecordAction(UserMetricsAction( - "Media.Controls.EnterFullscreen.EmbeddedExperience")); - } - GetMediaControls().EnterFullscreen(); - } - event->SetDefaultHandled(); - } - MediaControlInputElement::DefaultEventHandler(event); -} - -void MediaControlFullscreenButtonElement::SetIsFullscreen(bool is_fullscreen) { - SetDisplayType(is_fullscreen ? kMediaExitFullscreenButton - : kMediaEnterFullscreenButton); -} - -WebLocalizedString::Name -MediaControlFullscreenButtonElement::GetOverflowStringName() { - if (MediaElement().IsFullscreen()) - return WebLocalizedString::kOverflowMenuExitFullscreen; - return WebLocalizedString::kOverflowMenuEnterFullscreen; -} - -// ---------------------------- - -MediaControlCastButtonElement::MediaControlCastButtonElement( - MediaControls& media_controls, - bool is_overlay_button) - : MediaControlInputElement(media_controls, kMediaCastOnButton), - is_overlay_button_(is_overlay_button) { - if (is_overlay_button_) - RecordMetrics(CastOverlayMetrics::kCreated); - SetIsPlayingRemotely(false); -} - -MediaControlCastButtonElement* MediaControlCastButtonElement::Create( - MediaControls& media_controls, - bool is_overlay_button) { - MediaControlCastButtonElement* button = - new MediaControlCastButtonElement(media_controls, is_overlay_button); - button->EnsureUserAgentShadowRoot(); - button->SetShadowPseudoId(is_overlay_button - ? "-internal-media-controls-overlay-cast-button" - : "-internal-media-controls-cast-button"); - button->setType(InputTypeNames::button); - return button; -} - -void MediaControlCastButtonElement::DefaultEventHandler(Event* event) { - if (event->type() == EventTypeNames::click) { - if (is_overlay_button_) - Platform::Current()->RecordAction( - UserMetricsAction("Media.Controls.CastOverlay")); - else - Platform::Current()->RecordAction( - UserMetricsAction("Media.Controls.Cast")); - - if (is_overlay_button_ && !click_use_counted_) { - click_use_counted_ = true; - RecordMetrics(CastOverlayMetrics::kClicked); - } - if (MediaElement().IsPlayingRemotely()) { - MediaElement().RequestRemotePlaybackControl(); - } else { - MediaElement().RequestRemotePlayback(); - } - } - MediaControlInputElement::DefaultEventHandler(event); -} - -void MediaControlCastButtonElement::SetIsPlayingRemotely( - bool is_playing_remotely) { - if (is_playing_remotely) { - if (is_overlay_button_) { - SetDisplayType(kMediaOverlayCastOnButton); - } else { - SetDisplayType(kMediaCastOnButton); - } - } else { - if (is_overlay_button_) { - SetDisplayType(kMediaOverlayCastOffButton); - } else { - SetDisplayType(kMediaCastOffButton); - } - } - UpdateOverflowString(); -} - -WebLocalizedString::Name -MediaControlCastButtonElement::GetOverflowStringName() { - if (MediaElement().IsPlayingRemotely()) - return WebLocalizedString::kOverflowMenuStopCast; - return WebLocalizedString::kOverflowMenuCast; -} - -void MediaControlCastButtonElement::TryShowOverlay() { - DCHECK(is_overlay_button_); - - SetIsWanted(true); - if (ElementFromCenter(*this) != &MediaElement()) { - SetIsWanted(false); - return; - } - - DCHECK(IsWanted()); - if (!show_use_counted_) { - show_use_counted_ = true; - RecordMetrics(CastOverlayMetrics::kShown); - } -} - -bool MediaControlCastButtonElement::KeepEventInNode(Event* event) { - return IsUserInteractionEvent(event); -} - -void MediaControlCastButtonElement::RecordMetrics(CastOverlayMetrics metric) { - DCHECK(is_overlay_button_); - DEFINE_STATIC_LOCAL( - EnumerationHistogram, overlay_histogram, - ("Cast.Sender.Overlay", static_cast<int>(CastOverlayMetrics::kCount))); - overlay_histogram.Count(static_cast<int>(metric)); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h index df74742e..de59f4b 100644 --- a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h +++ b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h
@@ -32,129 +32,9 @@ #include "core/html/shadow/MediaControlElementTypes.h" #include "core/html/shadow/MediaControlTimelineMetrics.h" -#include "public/platform/WebLocalizedString.h" namespace blink { -// ---------------------------- - -class CORE_EXPORT MediaControlPlayButtonElement final - : public MediaControlInputElement { - public: - static MediaControlPlayButtonElement* Create(MediaControls&); - - bool WillRespondToMouseClickEvents() override { return true; } - void UpdateDisplayType() override; - - WebLocalizedString::Name GetOverflowStringName() override; - - bool HasOverflowButton() override { return true; } - - private: - explicit MediaControlPlayButtonElement(MediaControls&); - - void DefaultEventHandler(Event*) override; -}; - -// ---------------------------- - -class CORE_EXPORT MediaControlOverlayPlayButtonElement final - : public MediaControlInputElement { - public: - static MediaControlOverlayPlayButtonElement* Create(MediaControls&); - - void UpdateDisplayType() override; - - private: - explicit MediaControlOverlayPlayButtonElement(MediaControls&); - - void DefaultEventHandler(Event*) override; - bool KeepEventInNode(Event*) override; -}; - -// ---------------------------- - -class CORE_EXPORT MediaControlToggleClosedCaptionsButtonElement final - : public MediaControlInputElement { - public: - static MediaControlToggleClosedCaptionsButtonElement* Create(MediaControls&); - - bool WillRespondToMouseClickEvents() override { return true; } - - void UpdateDisplayType() override; - - WebLocalizedString::Name GetOverflowStringName() override; - - bool HasOverflowButton() override { return true; } - - private: - explicit MediaControlToggleClosedCaptionsButtonElement(MediaControls&); - - void DefaultEventHandler(Event*) override; -}; - -// ---------------------------- - -// Represents the overflow menu which is displayed when the width of the media -// player is small enough that at least two buttons are no longer visible. -class CORE_EXPORT MediaControlOverflowMenuButtonElement final - : public MediaControlInputElement { - public: - static MediaControlOverflowMenuButtonElement* Create(MediaControls&); - - // The overflow button should respond to mouse clicks since we want a click - // to open up the menu. - bool WillRespondToMouseClickEvents() override { return true; } - - private: - explicit MediaControlOverflowMenuButtonElement(MediaControls&); - - void DefaultEventHandler(Event*) override; -}; - -// ---------------------------- -// Represents a button that allows users to download media if the file is -// downloadable. -class CORE_EXPORT MediaControlDownloadButtonElement final - : public MediaControlInputElement { - public: - static MediaControlDownloadButtonElement* Create(MediaControls&); - - WebLocalizedString::Name GetOverflowStringName() override; - - bool HasOverflowButton() override { return true; } - - // Returns true if the download button should be shown. We should - // show the button for only non-MSE, non-EME, and non-MediaStream content. - bool ShouldDisplayDownloadButton(); - - void SetIsWanted(bool) override; - - DECLARE_VIRTUAL_TRACE(); - - private: - explicit MediaControlDownloadButtonElement(MediaControls&); - - void DefaultEventHandler(Event*) override; - - // Points to an anchor element that contains the URL of the media file. - Member<HTMLAnchorElement> anchor_; - - // This is used for UMA histogram (Media.Controls.Download). New values should - // be appended only and must be added before |Count|. - enum class DownloadActionMetrics { - kShown = 0, - kClicked, - kCount // Keep last. - }; - void RecordMetrics(DownloadActionMetrics); - - // UMA related boolean. They are used to prevent counting something twice - // for the same media element. - bool click_use_counted_ = false; - bool show_use_counted_ = false; -}; - class CORE_EXPORT MediaControlTimelineElement final : public MediaControlInputElement { public: @@ -184,72 +64,6 @@ // ---------------------------- -class CORE_EXPORT MediaControlFullscreenButtonElement final - : public MediaControlInputElement { - public: - static MediaControlFullscreenButtonElement* Create(MediaControls&); - - bool WillRespondToMouseClickEvents() override { return true; } - - void SetIsFullscreen(bool); - - WebLocalizedString::Name GetOverflowStringName() override; - - bool HasOverflowButton() override { return true; } - - private: - explicit MediaControlFullscreenButtonElement(MediaControls&); - - void DefaultEventHandler(Event*) override; -}; - -// ---------------------------- - -class CORE_EXPORT MediaControlCastButtonElement final - : public MediaControlInputElement { - public: - static MediaControlCastButtonElement* Create(MediaControls&, - bool is_overlay_button); - - bool WillRespondToMouseClickEvents() override { return true; } - - void SetIsPlayingRemotely(bool); - - WebLocalizedString::Name GetOverflowStringName() override; - - bool HasOverflowButton() override { return true; } - - // This will show a cast button if it is not covered by another element. - // This MUST be called for cast button elements that are overlay elements. - void TryShowOverlay(); - - private: - explicit MediaControlCastButtonElement(MediaControls&, - bool is_overlay_button); - - void DefaultEventHandler(Event*) override; - bool KeepEventInNode(Event*) override; - - bool is_overlay_button_; - - // This is used for UMA histogram (Cast.Sender.Overlay). New values should - // be appended only and must be added before |Count|. - enum class CastOverlayMetrics { - kCreated = 0, - kShown, - kClicked, - kCount // Keep last. - }; - void RecordMetrics(CastOverlayMetrics); - - // UMA related boolean. They are used to prevent counting something twice - // for the same media element. - bool click_use_counted_ = false; - bool show_use_counted_ = false; -}; - -// ---------------------------- - class CORE_EXPORT MediaControlVolumeSliderElement final : public MediaControlInputElement { public:
diff --git a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp index 23e8ea41..ce8c924 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
@@ -91,7 +91,6 @@ static const char kCacheDisabled[] = "cacheDisabled"; static const char kBypassServiceWorker[] = "bypassServiceWorker"; static const char kUserAgentOverride[] = "userAgentOverride"; -static const char kMonitoringXHR[] = "monitoringXHR"; static const char kBlockedURLs[] = "blockedURLs"; static const char kTotalBufferSize[] = "totalBufferSize"; static const char kResourceBufferSize[] = "resourceBufferSize"; @@ -976,15 +975,6 @@ known_request_id_map_.Find(client); if (it == known_request_id_map_.end()) return; - - if (state_->booleanProperty(NetworkAgentState::kMonitoringXHR, false)) { - String message = - (success ? "XHR finished loading: " : "XHR failed loading: ") + method + - " \"" + url + "\"."; - ConsoleMessage* console_message = ConsoleMessage::CreateForRequest( - kNetworkMessageSource, kInfoMessageLevel, message, url, it->value); - inspected_frames_->Root()->Console().AddMessageToStorage(console_message); - } known_request_id_map_.erase(client); } @@ -1006,13 +996,6 @@ known_request_id_map_.Find(client); if (it == known_request_id_map_.end()) return; - - if (state_->booleanProperty(NetworkAgentState::kMonitoringXHR, false)) { - String message = "Fetch complete: " + method + " \"" + url + "\"."; - ConsoleMessage* console_message = ConsoleMessage::CreateForRequest( - kNetworkMessageSource, kInfoMessageLevel, message, url, it->value); - inspected_frames_->Root()->Console().AddMessageToStorage(console_message); - } known_request_id_map_.erase(client); } @@ -1391,11 +1374,6 @@ return Response::OK(); } -Response InspectorNetworkAgent::setMonitoringXHREnabled(bool enabled) { - state_->setBoolean(NetworkAgentState::kMonitoringXHR, enabled); - return Response::OK(); -} - Response InspectorNetworkAgent::canClearBrowserCache(bool* result) { *result = true; return Response::OK();
diff --git a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h index 63cd0216..33c7cff 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.h
@@ -205,7 +205,6 @@ protocol::Response setBlockedURLs( std::unique_ptr<protocol::Array<String>> urls) override; protocol::Response replayXHR(const String& request_id) override; - protocol::Response setMonitoringXHREnabled(bool) override; protocol::Response canClearBrowserCache(bool* result) override; protocol::Response canClearBrowserCookies(bool* result) override; protocol::Response emulateNetworkConditions(
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index c46593db..bf78f2e 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -1247,14 +1247,6 @@ "experimental": true }, { - "name": "setMonitoringXHREnabled", - "parameters": [ - { "name": "enabled", "type": "boolean", "description": "Monitoring enabled state." } - ], - "description": "Toggles monitoring of XMLHttpRequest. If <code>true</code>, console will receive messages upon each XHR issued.", - "experimental": true - }, - { "name": "canClearBrowserCache", "description": "Tells whether clearing browser cache is supported.", "returns": [
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc index d4e51241..dd3757ec 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc
@@ -142,7 +142,7 @@ if (!layout_opp_iter_) { layout_opp_iter_ = WTF::MakeUnique<NGLayoutOpportunityIterator>( - this, AvailableSize(), iter_offset); + Exclusions().get(), AvailableSize(), iter_offset); } return layout_opp_iter_.get(); }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_test.cc index bd57c50d..a3217b6 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_test.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_test.cc
@@ -36,7 +36,8 @@ RefPtr<NGConstraintSpace> space = ConstructConstraintSpace(kHorizontalTopBottom, TextDirection::kLtr, size); - NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize()); + NGLayoutOpportunityIterator iterator( + space->Exclusions().get(), space->AvailableSize(), NGLogicalOffset()); // 600x400 at (0,0) NGLayoutOpportunity opp1 = {{}, {LayoutUnit(600), LayoutUnit(400)}}; EXPECT_EQ(opp1, iterator.Next()); @@ -56,7 +57,8 @@ exclusion.rect.offset = {LayoutUnit(500), LayoutUnit()}; space->AddExclusion(exclusion); - NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize()); + NGLayoutOpportunityIterator iterator( + space->Exclusions().get(), space->AvailableSize(), NGLogicalOffset()); // First opportunity should be to the left of the exclusion: 500x400 at (0,0) NGLayoutOpportunity opp1 = {{}, {LayoutUnit(500), LayoutUnit(400)}}; @@ -81,7 +83,8 @@ exclusion.rect.size = {LayoutUnit(100), LayoutUnit(100)}; space->AddExclusion(exclusion); - NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize()); + NGLayoutOpportunityIterator iterator( + space->Exclusions().get(), space->AvailableSize(), NGLogicalOffset()); // First opportunity should be to the right of the exclusion: // 500x400 at (100, 0) NGLayoutOpportunity opp1 = {{LayoutUnit(100), LayoutUnit()}, @@ -135,7 +138,8 @@ exclusion2.rect.offset = {LayoutUnit(500), LayoutUnit(350)}; space->AddExclusion(exclusion2); - NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize()); + NGLayoutOpportunityIterator iterator( + space->Exclusions().get(), space->AvailableSize(), NGLogicalOffset()); NGLogicalOffset start_point1; // 600x200 at (0,0) NGLayoutOpportunity opp1 = {start_point1, {LayoutUnit(600), LayoutUnit(200)}}; @@ -168,74 +172,6 @@ EXPECT_EQ(NGLayoutOpportunity(), iterator.Next()); } -// This test is the same as LayoutOpportunitiesTwoInMiddle with the only -// difference that NGLayoutOpportunityIterator takes 2 additional arguments: -// - origin_point that changes the iterator to return Layout Opportunities that -// lay after the origin point. -// - leader_point that together with origin_point creates a temporary exclusion -// -// Expected: -// Layout opportunity iterator generates the next opportunities: -// - 1st Start Point (0, 200): 350x150, 250x400 -// - 3rd Start Point (550, 200): 50x400 -// - 4th Start Point (0, 300): 600x50, 500x300 -// - 5th Start Point (0, 400): 600x200 -// All other opportunities that are located before the origin point should be -// filtered out. -TEST(NGConstraintSpaceTest, LayoutOpportunitiesTwoInMiddleWithOriginAndLeader) { - NGLogicalSize size; - size.inline_size = LayoutUnit(600); - size.block_size = LayoutUnit(400); - RefPtr<NGConstraintSpace> space = - ConstructConstraintSpace(kHorizontalTopBottom, TextDirection::kLtr, size); - // Add exclusions - NGExclusion exclusion1; - exclusion1.rect.size = {LayoutUnit(100), LayoutUnit(100)}; - exclusion1.rect.offset = {LayoutUnit(150), LayoutUnit(200)}; - space->AddExclusion(exclusion1); - NGExclusion exclusion2; - exclusion2.rect.size = {LayoutUnit(50), LayoutUnit(50)}; - exclusion2.rect.offset = {LayoutUnit(500), LayoutUnit(350)}; - space->AddExclusion(exclusion2); - - const NGLogicalOffset origin_point = {LayoutUnit(), LayoutUnit(200)}; - const NGLogicalOffset leader_point = {LayoutUnit(250), LayoutUnit(300)}; - NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize(), - origin_point, leader_point); - - NGLogicalOffset start_point1 = {LayoutUnit(250), LayoutUnit(200)}; - // 350x150 at (250,200) - NGLayoutOpportunity opp1 = {start_point1, {LayoutUnit(350), LayoutUnit(150)}}; - EXPECT_EQ(opp1, iterator.Next()); - // 250x400 at (250,200) - NGLayoutOpportunity opp2 = {start_point1, {LayoutUnit(250), LayoutUnit(400)}}; - EXPECT_EQ(opp2, iterator.Next()); - - NGLogicalOffset start_point2 = {LayoutUnit(550), LayoutUnit(200)}; - // 50x400 at (550,200) - NGLayoutOpportunity opp3 = {start_point2, {LayoutUnit(50), LayoutUnit(400)}}; - EXPECT_EQ(opp3, iterator.Next()); - - NGLogicalOffset start_point3 = {LayoutUnit(), LayoutUnit(300)}; - // 600x50 at (0,300) - NGLayoutOpportunity opp4 = {start_point3, {LayoutUnit(600), LayoutUnit(50)}}; - EXPECT_EQ(opp4, iterator.Next()); - // 500x300 at (0,300) - NGLayoutOpportunity opp5 = {start_point3, {LayoutUnit(500), LayoutUnit(300)}}; - EXPECT_EQ(opp5, iterator.Next()); - - // 4th Start Point - NGLogicalOffset start_point4 = {LayoutUnit(), LayoutUnit(400)}; - // 600x200 at (0,400) - NGLayoutOpportunity opp6 = {start_point4, {LayoutUnit(600), LayoutUnit(200)}}; - EXPECT_EQ(opp6, iterator.Next()); - - // TODO(glebl): The opportunity below should not be generated. - EXPECT_EQ("350x200 at (250,400)", iterator.Next().ToString()); - - EXPECT_EQ(NGLayoutOpportunity(), iterator.Next()); -} - // Verifies that Layout Opportunity iterator ignores the exclusion that is not // within constraint space. // @@ -260,7 +196,8 @@ exclusion.rect.offset = {LayoutUnit(), LayoutUnit(150)}; space->AddExclusion(exclusion); - NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize()); + NGLayoutOpportunityIterator iterator( + space->Exclusions().get(), space->AvailableSize(), NGLogicalOffset()); // 600x100 at (0,0) NGLayoutOpportunity opp = {{}, size}; EXPECT_EQ(opp, iterator.Next()); @@ -288,8 +225,8 @@ big_left.type = NGExclusion::kFloatLeft; space->AddExclusion(big_left); - NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize(), - bfc_offset); + NGLayoutOpportunityIterator iterator(space->Exclusions().get(), + space->AvailableSize(), bfc_offset); NGLogicalOffset start_point1 = bfc_offset; start_point1.inline_offset += @@ -334,8 +271,8 @@ big_right.type = NGExclusion::kFloatRight; space->AddExclusion(big_right); - NGLayoutOpportunityIterator iterator(space.Get(), space->AvailableSize(), - bfc_offset); + NGLayoutOpportunityIterator iterator(space->Exclusions().get(), + space->AvailableSize(), bfc_offset); NGLogicalOffset start_point1 = bfc_offset; // 170x200 at (8, 8)
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc b/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc index d1519fd..2f77bb3 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc
@@ -46,8 +46,9 @@ NGLogicalOffset adjusted_origin_point = AdjustToTopEdgeAlignmentRule(*space, floating_object->origin_offset); - NGLayoutOpportunityIterator opportunity_iter( - space, floating_object->available_size, adjusted_origin_point); + NGLayoutOpportunityIterator opportunity_iter(space->Exclusions().get(), + floating_object->available_size, + adjusted_origin_point); NGLayoutOpportunity opportunity; NGLayoutOpportunity opportunity_candidate = opportunity_iter.Next();
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc b/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc index bb84c83e..de08081 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc
@@ -53,8 +53,8 @@ CollectAllOpportunities(node->right.get(), opportunities); } -// Creates layout opportunity from the provided space and the origin point. -NGLayoutOpportunity CreateLayoutOpportunityFromConstraintSpace( +// Creates layout opportunity from the provided size and the origin point. +NGLayoutOpportunity CreateInitialOpportunity( const NGLogicalSize& size, const NGLogicalOffset& origin_point) { NGLayoutOpportunity opportunity; @@ -257,46 +257,23 @@ // TOP and LEFT are the same -> Sort by width return rhs.size.inline_size < lhs.size.inline_size; } - -NGExclusion ToLeaderExclusion(const NGLogicalOffset& origin_point, - const NGLogicalOffset& leader_point) { - LayoutUnit inline_size = - leader_point.inline_offset - origin_point.inline_offset; - LayoutUnit block_size = leader_point.block_offset - origin_point.block_offset; - - NGExclusion leader_exclusion; - leader_exclusion.rect.offset = origin_point; - leader_exclusion.rect.size = {inline_size, block_size}; - return leader_exclusion; -} - } // namespace NGLayoutOpportunityIterator::NGLayoutOpportunityIterator( - const NGConstraintSpace* space, + const NGExclusions* exclusions, const NGLogicalSize& available_size, - const WTF::Optional<NGLogicalOffset>& opt_offset, - const WTF::Optional<NGLogicalOffset>& opt_leader_point) - : constraint_space_(space), - offset_(opt_offset ? opt_offset.value() : space->BfcOffset()) { - // TODO(chrome-layout-team): Combine exclusions that shadow each other. - auto& exclusions = constraint_space_->Exclusions(); + const NGLogicalOffset& offset) + : offset_(offset) { + DCHECK(exclusions); DCHECK(std::is_sorted(exclusions->storage.begin(), exclusions->storage.end(), &CompareNGExclusionsByTopAsc)) << "Exclusions are expected to be sorted by TOP"; NGLayoutOpportunity initial_opportunity = - CreateLayoutOpportunityFromConstraintSpace(available_size, Offset()); + CreateInitialOpportunity(available_size, Offset()); opportunity_tree_root_.reset( new NGLayoutOpportunityTreeNode(initial_opportunity)); - if (opt_leader_point) { - const NGExclusion leader_exclusion = - ToLeaderExclusion(Offset(), opt_leader_point.value()); - InsertExclusion(MutableOpportunityTreeRoot(), &leader_exclusion, - opportunities_); - } - for (const auto& exclusion : exclusions->storage) { InsertExclusion(MutableOpportunityTreeRoot(), exclusion.get(), opportunities_);
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.h b/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.h index 4226937..24e8941 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.h
@@ -6,14 +6,13 @@ #define NGLayoutOpportunityIterator_h #include "core/CoreExport.h" +#include "core/layout/ng/ng_exclusion.h" #include "core/layout/ng/ng_layout_opportunity_tree_node.h" -#include "platform/wtf/Optional.h" #include "platform/wtf/Vector.h" #include "platform/wtf/text/StringBuilder.h" namespace blink { -class NGConstraintSpace; typedef NGLogicalRect NGLayoutOpportunity; typedef Vector<NGLayoutOpportunity> NGLayoutOpportunities; @@ -21,19 +20,15 @@ public: // Default constructor. // - // @param space Constraint space with exclusions for which this iterator needs - // to generate layout opportunities. - // @param opt_offset Optional offset parameter that is used as a - // default start point for layout opportunities. - // @param opt_leader_point Optional 'leader' parameter that is used to specify - // the ending point of temporary excluded rectangle - // which starts from 'origin'. This rectangle may - // represent a text fragment for example. - NGLayoutOpportunityIterator( - const NGConstraintSpace* space, - const NGLogicalSize& available_size, - const WTF::Optional<NGLogicalOffset>& opt_offset = WTF::kNullopt, - const WTF::Optional<NGLogicalOffset>& opt_leader_point = WTF::kNullopt); + // @param exclusions List of exclusions that should be avoided by this + // iterator while generating layout opportunities. + // @param available_size Available size that represents a rectangle where this + // iterator searches layout opportunities. + // @param offset Offset used as a default starting point for layout + // opportunities. + NGLayoutOpportunityIterator(const NGExclusions* exclusions, + const NGLogicalSize& available_size, + const NGLogicalOffset& offset); // Gets the next Layout Opportunity or empty one if the search is exhausted. // TODO(chrome-layout-team): Refactor with using C++ <iterator> library. @@ -60,8 +55,6 @@ return opportunity_tree_root_.get(); } - const NGConstraintSpace* constraint_space_; - NGLayoutOpportunities opportunities_; NGLayoutOpportunities::const_iterator opportunity_iter_; std::unique_ptr<NGLayoutOpportunityTreeNode> opportunity_tree_root_;
diff --git a/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.idl b/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.idl index c4fb17b9..cbcef45 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.idl
@@ -46,9 +46,9 @@ [MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber kernelUnitLengthX; [MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber kernelUnitLengthY; - // TODO(foolip): The following was part of SVG 1.1: + // TODO(foolip): The following was part of SVG 1.1. https://crbug.com/695977 // http://www.w3.org/TR/SVG11/filters.html#InterfaceSVGFEConvolveMatrixElement - // https://www.w3.org/Bugs/Public/show_bug.cgi?id=28703 + // https://github.com/w3c/fxtf-drafts/issues/114 [Measure] readonly attribute SVGAnimatedBoolean preserveAlpha; };
diff --git a/third_party/WebKit/Source/core/svg/SVGGraphicsElement.idl b/third_party/WebKit/Source/core/svg/SVGGraphicsElement.idl index 508de310..6b28612 100644 --- a/third_party/WebKit/Source/core/svg/SVGGraphicsElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGGraphicsElement.idl
@@ -37,8 +37,8 @@ [ImplementedAs=getCTMFromJavascript] SVGMatrix getCTM(); [ImplementedAs=getScreenCTMFromJavascript] SVGMatrix getScreenCTM(); - // The following two properties existed on SVGLocatable in SVG - // 1.1, but was removed in SVG2. + // TODO(foolip): The following two properties existed on SVGLocatable in SVG + // 1.1, but were removed in SVG2. https://crbug.com/695981 // https://www.w3.org/TR/SVG11/types.html#InterfaceSVGLocatable [MeasureAs=SVGLocatableNearestViewportElement] readonly attribute SVGElement nearestViewportElement; [MeasureAs=SVGLocatableFarthestViewportElement] readonly attribute SVGElement farthestViewportElement;
diff --git a/third_party/WebKit/Source/core/svg/SVGMaskElement.idl b/third_party/WebKit/Source/core/svg/SVGMaskElement.idl index f787110c..7af69009 100644 --- a/third_party/WebKit/Source/core/svg/SVGMaskElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGMaskElement.idl
@@ -36,5 +36,5 @@ // SVGMaskElement implements SVGUnitTypes; -// TODO(foolip): The following is not part of any spec: +// TODO(foolip): The following is not part of any spec. https://crbug.com/701893 SVGMaskElement implements SVGTests;
diff --git a/third_party/WebKit/Source/core/svg/SVGMatrix.idl b/third_party/WebKit/Source/core/svg/SVGMatrix.idl index afdc651..30518786 100644 --- a/third_party/WebKit/Source/core/svg/SVGMatrix.idl +++ b/third_party/WebKit/Source/core/svg/SVGMatrix.idl
@@ -23,6 +23,7 @@ // http://www.w3.org/TR/SVG11/coords.html#InterfaceSVGMatrix // TODO(foolip): SVGMatrix is gone from SVG 2, replaced by DOMMatrix. +// https://crbug.com/709001 [ DependentLifetime, ImplementedAs=SVGMatrixTearOff,
diff --git a/third_party/WebKit/Source/core/svg/SVGPatternElement.idl b/third_party/WebKit/Source/core/svg/SVGPatternElement.idl index f8329d2..fba4f7b 100644 --- a/third_party/WebKit/Source/core/svg/SVGPatternElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGPatternElement.idl
@@ -39,6 +39,6 @@ SVGPatternElement implements SVGURIReference; // SVGPatternElement implements SVGUnitTypes; -// TODO(foolip): The following was part of SVG 1.1: +// TODO(foolip): The following was part of SVG 1.1. https://crbug.com/701893 // http://www.w3.org/TR/SVG11/pservers.html#InterfaceSVGPatternElement SVGPatternElement implements SVGTests;
diff --git a/third_party/WebKit/Source/core/svg/SVGPoint.idl b/third_party/WebKit/Source/core/svg/SVGPoint.idl index 34b2810..6cb1acf 100644 --- a/third_party/WebKit/Source/core/svg/SVGPoint.idl +++ b/third_party/WebKit/Source/core/svg/SVGPoint.idl
@@ -23,6 +23,7 @@ // http://www.w3.org/TR/SVG11/coords.html#InterfaceSVGPoint // TODO(foolip): SVGPoint is gone from SVG 2, replaced by DOMPoint. +// https://crbug.com/709001 [ DependentLifetime, ImplementedAs=SVGPointTearOff,
diff --git a/third_party/WebKit/Source/core/svg/SVGRect.idl b/third_party/WebKit/Source/core/svg/SVGRect.idl index 4868b15..fc012db 100644 --- a/third_party/WebKit/Source/core/svg/SVGRect.idl +++ b/third_party/WebKit/Source/core/svg/SVGRect.idl
@@ -23,6 +23,7 @@ // http://www.w3.org/TR/SVG11/types.html#InterfaceSVGRect // TODO(foolip): SVGRect is gone from SVG 2, replaced by DOMRect. +// https://crbug.com/709001 [ DependentLifetime, ImplementedAs=SVGRectTearOff,
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp index 39564a8..445cfe074 100644 --- a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp +++ b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
@@ -365,7 +365,7 @@ FloatRect float_bounds(FloatPoint(), size); const SkRect bounds(float_bounds); - flags.setShader(MakePaintShaderRecord( + flags.setShader(SkShader::MakePictureShader( PaintRecordForCurrentFrame(float_bounds, url), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &local_matrix, &bounds));
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js index 62a38991..8ecd437 100644 --- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js +++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
@@ -136,7 +136,6 @@ this._registerShortcuts(); this._messagesElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), false); - monitoringXHREnabledSetting.addChangeListener(this._monitoringXHREnabledSettingChanged, this); this._linkifier = new Components.Linkifier(); @@ -665,16 +664,6 @@ } /** - * @param {!Common.Event} event - */ - _monitoringXHREnabledSettingChanged(event) { - var enabled = /** @type {boolean} */ (event.data); - SDK.targetManager.targets().forEach(function(target) { - target.networkAgent().setMonitoringXHREnabled(enabled); - }); - } - - /** * @param {!Event} event */ _messagesClicked(event) {
diff --git a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js index 01e7b315..925952e 100644 --- a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js +++ b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
@@ -102,7 +102,7 @@ var networkManager = target.model(SDK.NetworkManager); if (networkManager) { eventListeners.push(networkManager.addEventListener( - SDK.NetworkManager.Events.WarningGenerated, this._networkWarningGenerated.bind(this, networkManager))); + SDK.NetworkManager.Events.MessageGenerated, this._networkMessageGenerated.bind(this, networkManager))); } target[ConsoleModel.ConsoleModel._events] = eventListeners; @@ -337,12 +337,13 @@ * @param {!SDK.NetworkManager} networkManager * @param {!Common.Event} event */ - _networkWarningGenerated(networkManager, event) { - var warning = /** @type {!SDK.NetworkManager.Warning} */ (event.data); + _networkMessageGenerated(networkManager, event) { + var message = /** @type {!SDK.NetworkManager.Message} */ (event.data); this.addMessage(new ConsoleModel.ConsoleMessage( networkManager.target().model(SDK.RuntimeModel), ConsoleModel.ConsoleMessage.MessageSource.Network, - ConsoleModel.ConsoleMessage.MessageLevel.Warning, warning.message, undefined, undefined, undefined, undefined, - warning.requestId)); + message.warning ? ConsoleModel.ConsoleMessage.MessageLevel.Warning : + ConsoleModel.ConsoleMessage.MessageLevel.Info, + message.message, undefined, undefined, undefined, undefined, message.requestId)); } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js index ad4ada9e..beaefd45 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
@@ -42,8 +42,6 @@ target.registerNetworkDispatcher(this._dispatcher); if (Common.moduleSetting('cacheDisabled').get()) this._networkAgent.setCacheDisabled(true); - if (Common.moduleSetting('monitoringXHREnabled').get()) - this._networkAgent.setMonitoringXHREnabled(true); // Limit buffer when talking to a remote device. if (Runtime.queryParam('remoteFrontend') || Runtime.queryParam('ws')) @@ -122,12 +120,12 @@ RequestFinished: Symbol('RequestFinished'), RequestUpdateDropped: Symbol('RequestUpdateDropped'), ResponseReceived: Symbol('ResponseReceived'), - WarningGenerated: Symbol('WarningGenerated'), + MessageGenerated: Symbol('MessageGenerated'), RequestRedirected: Symbol('RequestRedirected'), }; -/** @typedef {{message: string, requestId: string}} */ -SDK.NetworkManager.Warning; +/** @typedef {{message: string, requestId: string, warning: boolean}} */ +SDK.NetworkManager.Message; SDK.NetworkManager._MIMETypes = { 'text/html': {'document': true}, @@ -242,7 +240,8 @@ 'Resource interpreted as %s but transferred with MIME type %s: "%s".', networkRequest.resourceType().title(), networkRequest.mimeType, networkRequest.url()); this._manager.dispatchEventToListeners( - SDK.NetworkManager.Events.WarningGenerated, {message: message, requestId: networkRequest.requestId()}); + SDK.NetworkManager.Events.MessageGenerated, + {message: message, requestId: networkRequest.requestId(), warning: true}); } if (response.securityDetails) @@ -380,7 +379,7 @@ 'Set-Cookie header is ignored in response from url: %s. Cookie length should be less than or equal to 4096 characters.', response.url); this._manager.dispatchEventToListeners( - SDK.NetworkManager.Events.WarningGenerated, {message: message, requestId: requestId}); + SDK.NetworkManager.Events.MessageGenerated, {message: message, requestId: requestId, warning: true}); } this._updateNetworkRequestWithResponse(networkRequest, response); @@ -444,7 +443,7 @@ if (blockedReason === Protocol.Network.BlockedReason.Inspector) { var message = Common.UIString('Request was blocked by DevTools: "%s".', networkRequest.url()); this._manager.dispatchEventToListeners( - SDK.NetworkManager.Events.WarningGenerated, {message: message, requestId: requestId}); + SDK.NetworkManager.Events.MessageGenerated, {message: message, requestId: requestId, warning: true}); } } networkRequest.localizedFailDescription = localizedDescription; @@ -635,6 +634,17 @@ this._manager.dispatchEventToListeners(SDK.NetworkManager.Events.RequestFinished, networkRequest); delete this._inflightRequestsById[networkRequest.requestId()]; delete this._inflightRequestsByURL[networkRequest.url()]; + + if (Common.moduleSetting('monitoringXHREnabled').get() && + networkRequest.resourceType().category() === Common.resourceCategories.XHR) { + var message = Common.UIString( + (networkRequest.failed || networkRequest.hasErrorStatusCode()) ? '%s failed loading: %s "%s".' : + '%s finished loading: %s "%s".', + networkRequest.resourceType().title(), networkRequest.requestMethod, networkRequest.url()); + this._manager.dispatchEventToListeners( + SDK.NetworkManager.Events.MessageGenerated, + {message: message, requestId: networkRequest.requestId(), warning: false}); + } } /**
diff --git a/third_party/WebKit/Source/modules/crypto/SubtleCrypto.idl b/third_party/WebKit/Source/modules/crypto/SubtleCrypto.idl index e3947bbd1..e9807d9 100644 --- a/third_party/WebKit/Source/modules/crypto/SubtleCrypto.idl +++ b/third_party/WebKit/Source/modules/crypto/SubtleCrypto.idl
@@ -28,7 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// http://www.w3.org/TR/WebCryptoAPI/#subtlecrypto-interface +// https://w3c.github.io/webcrypto/Overview.html#subtlecrypto-interface typedef DOMString KeyFormat; typedef DOMString KeyUsage;
diff --git a/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.idl b/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.idl index 19aebde..31b60805 100644 --- a/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.idl +++ b/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.idl
@@ -4,6 +4,8 @@ // https://www.w3.org/TR/2015/WD-ambient-light-20150903/#devicelightevent-interface +// TODO(foolip): Remove DeviceLightEvent. https://crbug.com/711577 + [ RuntimeEnabled=DeviceLight, Constructor(DOMString type, optional DeviceLightEventInit eventInitDict),
diff --git a/third_party/WebKit/Source/modules/device_light/DeviceLightEventInit.idl b/third_party/WebKit/Source/modules/device_light/DeviceLightEventInit.idl index 14a9098..4d11872a 100644 --- a/third_party/WebKit/Source/modules/device_light/DeviceLightEventInit.idl +++ b/third_party/WebKit/Source/modules/device_light/DeviceLightEventInit.idl
@@ -4,6 +4,8 @@ // https://www.w3.org/TR/2015/WD-ambient-light-20150903/#devicelightevent-interface +// TODO(foolip): Remove DeviceLightEvent. https://crbug.com/711577 + dictionary DeviceLightEventInit : EventInit { unrestricted double value; };
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceAccelerationInit.idl b/third_party/WebKit/Source/modules/device_orientation/DeviceAccelerationInit.idl index 7276e85..85ece50 100644 --- a/third_party/WebKit/Source/modules/device_orientation/DeviceAccelerationInit.idl +++ b/third_party/WebKit/Source/modules/device_orientation/DeviceAccelerationInit.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://www.w3.org/TR/2016/CR-orientation-event-20160818/#devicemotion +// https://w3c.github.io/deviceorientation/spec-source-orientation.html#devicemotion dictionary DeviceAccelerationInit { double? x = null;
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.idl b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.idl index e105520..9d4636b3 100644 --- a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.idl +++ b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.idl
@@ -23,7 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// https://www.w3.org/TR/2016/CR-orientation-event-20160818/#devicemotion +// https://w3c.github.io/deviceorientation/spec-source-orientation.html#devicemotion [Constructor(DOMString type, optional DeviceMotionEventInit eventInitDict)] interface DeviceMotionEvent : Event {
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEventInit.idl b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEventInit.idl index 36411c93..5995c967 100644 --- a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEventInit.idl +++ b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEventInit.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://www.w3.org/TR/2016/CR-orientation-event-20160818/#devicemotion +// https://w3c.github.io/deviceorientation/spec-source-orientation.html#devicemotion dictionary DeviceMotionEventInit : EventInit { DeviceAccelerationInit? acceleration;
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.idl b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.idl index 0b9207ab..14a53d6b 100644 --- a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.idl +++ b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.idl
@@ -23,7 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// https://www.w3.org/TR/2016/CR-orientation-event-20160818/#deviceorientation +// https://w3c.github.io/deviceorientation/spec-source-orientation.html#deviceorientation [Constructor(DOMString type, optional DeviceOrientationEventInit eventInitDict)] interface DeviceOrientationEvent : Event {
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEventInit.idl b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEventInit.idl index 7b76ced..12d5761 100644 --- a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEventInit.idl +++ b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEventInit.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://www.w3.org/TR/2016/CR-orientation-event-20160818/#deviceorientation +// https://w3c.github.io/deviceorientation/spec-source-orientation.html#deviceorientation dictionary DeviceOrientationEventInit : EventInit { double? alpha = null;
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRateInit.idl b/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRateInit.idl index 00fc4a31..e08ef7e9 100644 --- a/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRateInit.idl +++ b/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRateInit.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://www.w3.org/TR/2016/CR-orientation-event-20160818/#devicemotion +// https://w3c.github.io/deviceorientation/spec-source-orientation.html#deviceorientation dictionary DeviceRotationRateInit { double? alpha = null;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.idl b/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.idl index b9887cd1..7755c394 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.idl +++ b/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.idl
@@ -23,7 +23,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// http://www.w3.org/TR/IndexedDB/#idl-def-IDBCursorWithValue +// https://w3c.github.io/IndexedDB/#idbcursorwithvalue [ Exposed=(Window,Worker)
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBFactory.idl b/third_party/WebKit/Source/modules/indexeddb/IDBFactory.idl index 5e94641..7ba7cfc 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBFactory.idl +++ b/third_party/WebKit/Source/modules/indexeddb/IDBFactory.idl
@@ -23,7 +23,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// http://www.w3.org/TR/IndexedDB/#idl-def-IDBFactory +// https://w3c.github.io/IndexedDB/#idbfactory [ Exposed=(Window,Worker),
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBIndexParameters.idl b/third_party/WebKit/Source/modules/indexeddb/IDBIndexParameters.idl index c6f07bac..33bd1833 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBIndexParameters.idl +++ b/third_party/WebKit/Source/modules/indexeddb/IDBIndexParameters.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// http://www.w3.org/TR/IndexedDB/#idl-def-IDBIndexParameters +// https://w3c.github.io/IndexedDB/#dictdef-idbindexparameters dictionary IDBIndexParameters { boolean unique = false;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.idl b/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.idl index aae8b02..2f34914 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.idl +++ b/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.idl
@@ -23,7 +23,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// http://www.w3.org/TR/IndexedDB/#idl-def-IDBKeyRange +// https://w3c.github.io/IndexedDB/#idbkeyrange [ Exposed=(Window,Worker),
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBObjectStoreParameters.idl b/third_party/WebKit/Source/modules/indexeddb/IDBObjectStoreParameters.idl index cd494593..32d9fff 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBObjectStoreParameters.idl +++ b/third_party/WebKit/Source/modules/indexeddb/IDBObjectStoreParameters.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// http://www.w3.org/TR/IndexedDB/#idl-def-IDBObjectStoreParameters +// https://w3c.github.io/IndexedDB/#dictdef-idbobjectstoreparameters dictionary IDBObjectStoreParameters { (DOMString or sequence<DOMString>)? keyPath = null;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.idl b/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.idl index dbb23133..9594c8a 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.idl +++ b/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.idl
@@ -23,7 +23,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// http://www.w3.org/TR/IndexedDB/#idl-def-IDBOpenDBRequest +// https://w3c.github.io/IndexedDB/#idbopendbrequest [ Exposed=(Window,Worker)
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl index d9f5b19..7fbbbc04 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl +++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl
@@ -27,14 +27,14 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// http://www.w3.org/TR/IndexedDB/#idl-def-IDBRequestReadyState +// https://w3c.github.io/IndexedDB/#enumdef-idbrequestreadystate enum IDBRequestReadyState { "pending", "done" }; -// http://www.w3.org/TR/IndexedDB/#idl-def-IDBRequest +// https://w3c.github.io/IndexedDB/#idbrequest [ ActiveScriptWrappable,
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.idl b/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.idl index b6656a7..b3bdfbb 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.idl +++ b/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.idl
@@ -23,11 +23,11 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// http://www.w3.org/TR/IndexedDB/#idl-def-IDBVersionChangeEvent +// https://w3c.github.io/IndexedDB/#events -// FIXME: This enum is non-standard, see -// https://www.w3.org/Bugs/Public/show_bug.cgi?id=22370 +// FIXME: This enum is non-standard, see https://crbug.com/711586 enum IDBDataLossAmount { "none", "total" }; + [ Exposed=(Window,Worker), Constructor(DOMString type, optional IDBVersionChangeEventInit eventInitDict) @@ -35,8 +35,7 @@ readonly attribute unsigned long long oldVersion; readonly attribute unsigned long long? newVersion; - // FIXME: These are non-standard, see - // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22370 + // FIXME: These are non-standard, see https://crbug.com/711586 readonly attribute IDBDataLossAmount dataLoss; readonly attribute DOMString dataLossMessage; };
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEventInit.idl b/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEventInit.idl index 1ee4c859..1742fae 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEventInit.idl +++ b/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEventInit.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// http://www.w3.org/TR/IndexedDB/#idl-def-IDBVersionChangeEventInit +// https://w3c.github.io/IndexedDB/#events dictionary IDBVersionChangeEventInit : EventInit { unsigned long long oldVersion = 0;
diff --git a/third_party/WebKit/Source/modules/media_controls/BUILD.gn b/third_party/WebKit/Source/modules/media_controls/BUILD.gn index fdfc1e2..7ebea559 100644 --- a/third_party/WebKit/Source/modules/media_controls/BUILD.gn +++ b/third_party/WebKit/Source/modules/media_controls/BUILD.gn
@@ -14,23 +14,37 @@ "MediaControlsOrientationLockDelegate.h", "MediaControlsWindowEventListener.cpp", "MediaControlsWindowEventListener.h", + "elements/MediaControlCastButtonElement.cpp", + "elements/MediaControlCastButtonElement.h", "elements/MediaControlCurrentTimeDisplayElement.cpp", "elements/MediaControlCurrentTimeDisplayElement.h", + "elements/MediaControlDownloadButtonElement.cpp", + "elements/MediaControlDownloadButtonElement.h", "elements/MediaControlElementsHelper.cpp", "elements/MediaControlElementsHelper.h", + "elements/MediaControlFullscreenButtonElement.cpp", + "elements/MediaControlFullscreenButtonElement.h", "elements/MediaControlMuteButtonElement.cpp", "elements/MediaControlMuteButtonElement.h", + "elements/MediaControlOverflowMenuButtonElement.cpp", + "elements/MediaControlOverflowMenuButtonElement.h", "elements/MediaControlOverflowMenuListElement.cpp", "elements/MediaControlOverflowMenuListElement.h", "elements/MediaControlOverlayEnclosureElement.cpp", "elements/MediaControlOverlayEnclosureElement.h", + "elements/MediaControlOverlayPlayButtonElement.cpp", + "elements/MediaControlOverlayPlayButtonElement.h", "elements/MediaControlPanelElement.cpp", "elements/MediaControlPanelElement.h", "elements/MediaControlPanelEnclosureElement.cpp", "elements/MediaControlPanelEnclosureElement.h", + "elements/MediaControlPlayButtonElement.cpp", + "elements/MediaControlPlayButtonElement.h", "elements/MediaControlRemainingTimeDisplayElement.cpp", "elements/MediaControlRemainingTimeDisplayElement.h", "elements/MediaControlTextTrackListElement.cpp", "elements/MediaControlTextTrackListElement.h", + "elements/MediaControlToggleClosedCaptionsButtonElement.cpp", + "elements/MediaControlToggleClosedCaptionsButtonElement.h", ] }
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp index becfd255a..227a699e5 100644 --- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp +++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
@@ -46,14 +46,21 @@ #include "modules/media_controls/MediaControlsMediaEventListener.h" #include "modules/media_controls/MediaControlsOrientationLockDelegate.h" #include "modules/media_controls/MediaControlsWindowEventListener.h" +#include "modules/media_controls/elements/MediaControlCastButtonElement.h" #include "modules/media_controls/elements/MediaControlCurrentTimeDisplayElement.h" +#include "modules/media_controls/elements/MediaControlDownloadButtonElement.h" +#include "modules/media_controls/elements/MediaControlFullscreenButtonElement.h" #include "modules/media_controls/elements/MediaControlMuteButtonElement.h" +#include "modules/media_controls/elements/MediaControlOverflowMenuButtonElement.h" #include "modules/media_controls/elements/MediaControlOverflowMenuListElement.h" #include "modules/media_controls/elements/MediaControlOverlayEnclosureElement.h" +#include "modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h" #include "modules/media_controls/elements/MediaControlPanelElement.h" #include "modules/media_controls/elements/MediaControlPanelEnclosureElement.h" +#include "modules/media_controls/elements/MediaControlPlayButtonElement.h" #include "modules/media_controls/elements/MediaControlRemainingTimeDisplayElement.h" #include "modules/media_controls/elements/MediaControlTextTrackListElement.h" +#include "modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.h" #include "platform/EventDispatchForbiddenScope.h" namespace blink { @@ -305,16 +312,12 @@ overlay_enclosure_ = new MediaControlOverlayEnclosureElement(*this); if (RuntimeEnabledFeatures::mediaControlsOverlayPlayButtonEnabled()) { - MediaControlOverlayPlayButtonElement* overlay_play_button = - MediaControlOverlayPlayButtonElement::Create(*this); - overlay_play_button_ = overlay_play_button; - overlay_enclosure_->AppendChild(overlay_play_button); + overlay_play_button_ = new MediaControlOverlayPlayButtonElement(*this); + overlay_enclosure_->AppendChild(overlay_play_button_); } - MediaControlCastButtonElement* overlay_cast_button = - MediaControlCastButtonElement::Create(*this, true); - overlay_cast_button_ = overlay_cast_button; - overlay_enclosure_->AppendChild(overlay_cast_button); + overlay_cast_button_ = new MediaControlCastButtonElement(*this, true); + overlay_enclosure_->AppendChild(overlay_cast_button_); AppendChild(overlay_enclosure_); @@ -324,10 +327,8 @@ panel_ = new MediaControlPanelElement(*this); - MediaControlPlayButtonElement* play_button = - MediaControlPlayButtonElement::Create(*this); - play_button_ = play_button; - panel_->AppendChild(play_button); + play_button_ = new MediaControlPlayButtonElement(*this); + panel_->AppendChild(play_button_); current_time_display_ = new MediaControlCurrentTimeDisplayElement(*this); current_time_display_->SetIsWanted(true); @@ -351,25 +352,18 @@ if (PreferHiddenVolumeControls(GetDocument())) volume_slider_->SetIsWanted(false); - MediaControlFullscreenButtonElement* fullscreen_button = - MediaControlFullscreenButtonElement::Create(*this); - fullscreen_button_ = fullscreen_button; - panel_->AppendChild(fullscreen_button); + fullscreen_button_ = new MediaControlFullscreenButtonElement(*this); + panel_->AppendChild(fullscreen_button_); - MediaControlDownloadButtonElement* download_button = - MediaControlDownloadButtonElement::Create(*this); - download_button_ = download_button; - panel_->AppendChild(download_button); + download_button_ = new MediaControlDownloadButtonElement(*this); + panel_->AppendChild(download_button_); - MediaControlCastButtonElement* cast_button = - MediaControlCastButtonElement::Create(*this, false); - cast_button_ = cast_button; - panel_->AppendChild(cast_button); + cast_button_ = new MediaControlCastButtonElement(*this, false); + panel_->AppendChild(cast_button_); - MediaControlToggleClosedCaptionsButtonElement* toggle_closed_captions_button = - MediaControlToggleClosedCaptionsButtonElement::Create(*this); - toggle_closed_captions_button_ = toggle_closed_captions_button; - panel_->AppendChild(toggle_closed_captions_button); + toggle_closed_captions_button_ = + new MediaControlToggleClosedCaptionsButtonElement(*this); + panel_->AppendChild(toggle_closed_captions_button_); enclosure_->AppendChild(panel_); @@ -378,10 +372,8 @@ text_track_list_ = new MediaControlTextTrackListElement(*this); AppendChild(text_track_list_); - MediaControlOverflowMenuButtonElement* overflow_menu = - MediaControlOverflowMenuButtonElement::Create(*this); - overflow_menu_ = overflow_menu; - panel_->AppendChild(overflow_menu); + overflow_menu_ = new MediaControlOverflowMenuButtonElement(*this); + panel_->AppendChild(overflow_menu_); overflow_list_ = new MediaControlOverflowMenuListElement(*this); AppendChild(overflow_list_); @@ -391,18 +383,18 @@ // relative to each other. The first item appended appears at the top of the // overflow menu. overflow_list_->AppendChild(play_button_->CreateOverflowElement( - *this, MediaControlPlayButtonElement::Create(*this))); + *this, new MediaControlPlayButtonElement(*this))); overflow_list_->AppendChild(fullscreen_button_->CreateOverflowElement( - *this, MediaControlFullscreenButtonElement::Create(*this))); + *this, new MediaControlFullscreenButtonElement(*this))); overflow_list_->AppendChild(download_button_->CreateOverflowElement( - *this, MediaControlDownloadButtonElement::Create(*this))); + *this, new MediaControlDownloadButtonElement(*this))); overflow_list_->AppendChild(mute_button_->CreateOverflowElement( *this, new MediaControlMuteButtonElement(*this))); overflow_list_->AppendChild(cast_button_->CreateOverflowElement( - *this, MediaControlCastButtonElement::Create(*this, false))); + *this, new MediaControlCastButtonElement(*this, false))); overflow_list_->AppendChild( toggle_closed_captions_button_->CreateOverflowElement( - *this, MediaControlToggleClosedCaptionsButtonElement::Create(*this))); + *this, new MediaControlToggleClosedCaptionsButtonElement(*this))); } Node::InsertionNotificationRequest MediaControlsImpl::InsertedInto(
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h index 5271632..d761f23 100644 --- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h +++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h
@@ -38,14 +38,21 @@ class MediaControlsMediaEventListener; class MediaControlsOrientationLockDelegate; class MediaControlsWindowEventListener; +class MediaControlCastButtonElement; class MediaControlCurrentTimeDisplayElement; +class MediaControlDownloadButtonElement; +class MediaControlFullscreenButtonElement; class MediaControlMuteButtonElement; +class MediaControlOverflowMenuButtonElement; class MediaControlOverflowMenuListElement; class MediaControlOverlayEnclosureElement; +class MediaControlOverlayPlayButtonElement; class MediaControlPanelElement; class MediaControlPanelEnclosureElement; +class MediaControlPlayButtonElement; class MediaControlRemainingTimeDisplayElement; class MediaControlTextTrackListElement; +class MediaControlToggleClosedCaptionsButtonElement; class ShadowRoot; // Default implementation of the core/ MediaControls interface used by @@ -98,13 +105,6 @@ void BeginScrubbing() override; void EndScrubbing() override; void UpdateCurrentTimeDisplay() override; - void ToggleTextTrackList() override; - void ShowTextTrackAtIndex(unsigned) override; - void DisableShowingTextTracks() override; - // Called by the fullscreen buttons to toggle fulllscreen on/off. - void EnterFullscreen() override; - void ExitFullscreen() override; - void ToggleOverflowMenu() override; bool OverflowMenuVisible() override; // TODO(mlamouri): this method is needed in order to notify the controls that // the `MediaControlsEnabled` setting has changed. @@ -114,6 +114,18 @@ } Document& OwnerDocument() { return GetDocument(); } + // Called by the fullscreen buttons to toggle fulllscreen on/off. + void EnterFullscreen(); + void ExitFullscreen(); + + // Text track related methods exposed to components handling closed captions. + void ToggleTextTrackList(); + void ShowTextTrackAtIndex(unsigned); + void DisableShowingTextTracks(); + + // Toggle the overflow menu visibility. + void ToggleOverflowMenu(); + void ShowOverlayCastButtonIfNeeded(); DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp index 9850df1..d54964c 100644 --- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp +++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
@@ -22,6 +22,7 @@ #include "core/loader/EmptyClients.h" #include "core/testing/DummyPageHolder.h" #include "modules/media_controls/elements/MediaControlCurrentTimeDisplayElement.h" +#include "modules/media_controls/elements/MediaControlDownloadButtonElement.h" #include "platform/heap/Handle.h" #include "platform/testing/EmptyWebMediaPlayer.h" #include "platform/testing/HistogramTester.h"
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsWindowEventListener.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsWindowEventListener.cpp index f8c2506..23ec9772 100644 --- a/third_party/WebKit/Source/modules/media_controls/MediaControlsWindowEventListener.cpp +++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsWindowEventListener.cpp
@@ -8,6 +8,7 @@ #include "core/frame/LocalDOMWindow.h" #include "core/html/shadow/MediaControlElements.h" #include "modules/media_controls/MediaControlsImpl.h" +#include "modules/media_controls/elements/MediaControlCastButtonElement.h" #include "modules/media_controls/elements/MediaControlPanelElement.h" namespace blink {
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp new file mode 100644 index 0000000..2e0c50d99 --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp
@@ -0,0 +1,131 @@ +// 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 "modules/media_controls/elements/MediaControlCastButtonElement.h" + +#include "core/InputTypeNames.h" +#include "core/dom/ClientRect.h" +#include "core/events/Event.h" +#include "core/html/HTMLMediaElement.h" +#include "modules/media_controls/MediaControlsImpl.h" +#include "modules/media_controls/elements/MediaControlElementsHelper.h" +#include "public/platform/Platform.h" + +namespace blink { + +namespace { + +Element* ElementFromCenter(Element& element) { + ClientRect* client_rect = element.getBoundingClientRect(); + int center_x = + static_cast<int>((client_rect->left() + client_rect->right()) / 2); + int center_y = + static_cast<int>((client_rect->top() + client_rect->bottom()) / 2); + + return element.GetDocument().ElementFromPoint(center_x, center_y); +} + +} // anonymous namespace + +MediaControlCastButtonElement::MediaControlCastButtonElement( + MediaControlsImpl& media_controls, + bool is_overlay_button) + : MediaControlInputElement(media_controls, kMediaCastOnButton), + is_overlay_button_(is_overlay_button) { + EnsureUserAgentShadowRoot(); + SetShadowPseudoId(is_overlay_button + ? "-internal-media-controls-overlay-cast-button" + : "-internal-media-controls-cast-button"); + setType(InputTypeNames::button); + + if (is_overlay_button_) + RecordMetrics(CastOverlayMetrics::kCreated); + SetIsPlayingRemotely(false); +} + +void MediaControlCastButtonElement::TryShowOverlay() { + DCHECK(is_overlay_button_); + + SetIsWanted(true); + if (ElementFromCenter(*this) != &MediaElement()) { + SetIsWanted(false); + return; + } + + DCHECK(IsWanted()); + if (!show_use_counted_) { + show_use_counted_ = true; + RecordMetrics(CastOverlayMetrics::kShown); + } +} + +void MediaControlCastButtonElement::SetIsPlayingRemotely( + bool is_playing_remotely) { + if (is_playing_remotely) { + if (is_overlay_button_) { + SetDisplayType(kMediaOverlayCastOnButton); + } else { + SetDisplayType(kMediaCastOnButton); + } + } else { + if (is_overlay_button_) { + SetDisplayType(kMediaOverlayCastOffButton); + } else { + SetDisplayType(kMediaCastOffButton); + } + } + UpdateOverflowString(); +} + +bool MediaControlCastButtonElement::WillRespondToMouseClickEvents() { + return true; +} + +WebLocalizedString::Name +MediaControlCastButtonElement::GetOverflowStringName() { + if (MediaElement().IsPlayingRemotely()) + return WebLocalizedString::kOverflowMenuStopCast; + return WebLocalizedString::kOverflowMenuCast; +} + +bool MediaControlCastButtonElement::HasOverflowButton() { + return true; +} + +void MediaControlCastButtonElement::DefaultEventHandler(Event* event) { + if (event->type() == EventTypeNames::click) { + if (is_overlay_button_) { + Platform::Current()->RecordAction( + UserMetricsAction("Media.Controls.CastOverlay")); + } else { + Platform::Current()->RecordAction( + UserMetricsAction("Media.Controls.Cast")); + } + + if (is_overlay_button_ && !click_use_counted_) { + click_use_counted_ = true; + RecordMetrics(CastOverlayMetrics::kClicked); + } + if (MediaElement().IsPlayingRemotely()) { + MediaElement().RequestRemotePlaybackControl(); + } else { + MediaElement().RequestRemotePlayback(); + } + } + MediaControlInputElement::DefaultEventHandler(event); +} + +bool MediaControlCastButtonElement::KeepEventInNode(Event* event) { + return MediaControlElementsHelper::IsUserInteractionEvent(event); +} + +void MediaControlCastButtonElement::RecordMetrics(CastOverlayMetrics metric) { + DCHECK(is_overlay_button_); + DEFINE_STATIC_LOCAL( + EnumerationHistogram, overlay_histogram, + ("Cast.Sender.Overlay", static_cast<int>(CastOverlayMetrics::kCount))); + overlay_histogram.Count(static_cast<int>(metric)); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.h new file mode 100644 index 0000000..c640a8e --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.h
@@ -0,0 +1,55 @@ +// 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 MediaControlCastButtonElement_h +#define MediaControlCastButtonElement_h + +#include "core/html/shadow/MediaControlElementTypes.h" + +namespace blink { + +class Event; +class MediaControlsImpl; + +class MediaControlCastButtonElement final : public MediaControlInputElement { + public: + MediaControlCastButtonElement(MediaControlsImpl&, bool is_overlay_button); + + // This will show a cast button if it is not covered by another element. + // This MUST be called for cast button elements that are overlay elements. + void TryShowOverlay(); + + void SetIsPlayingRemotely(bool); + + // MediaControlInputElement overrides. + bool WillRespondToMouseClickEvents() override; + WebLocalizedString::Name GetOverflowStringName() override; + bool HasOverflowButton() override; + + private: + // This is used for UMA histogram (Cast.Sender.Overlay). New values should + // be appended only and must be added before |Count|. + enum class CastOverlayMetrics { + kCreated = 0, + kShown, + kClicked, + kCount // Keep last. + }; + + void DefaultEventHandler(Event*) override; + bool KeepEventInNode(Event*) override; + + void RecordMetrics(CastOverlayMetrics); + + bool is_overlay_button_; + + // UMA related boolean. They are used to prevent counting something twice + // for the same media element. + bool click_use_counted_ = false; + bool show_use_counted_ = false; +}; + +} // namespace blink + +#endif // MediaControlCastButtonElement_h
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.cpp new file mode 100644 index 0000000..fb1cbdba --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.cpp
@@ -0,0 +1,134 @@ +// 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 "modules/media_controls/elements/MediaControlDownloadButtonElement.h" + +#include "core/InputTypeNames.h" +#include "core/events/Event.h" +#include "core/frame/Settings.h" +#include "core/html/HTMLAnchorElement.h" +#include "core/html/HTMLMediaElement.h" +#include "core/html/media/HTMLMediaElementControlsList.h" +#include "core/html/media/HTMLMediaSource.h" +#include "core/page/Page.h" +#include "modules/media_controls/MediaControlsImpl.h" +#include "public/platform/Platform.h" + +namespace blink { + +MediaControlDownloadButtonElement::MediaControlDownloadButtonElement( + MediaControlsImpl& media_controls) + : MediaControlInputElement(media_controls, kMediaDownloadButton) { + EnsureUserAgentShadowRoot(); + setType(InputTypeNames::button); + SetShadowPseudoId(AtomicString("-internal-media-controls-download-button")); + SetIsWanted(false); +} + +bool MediaControlDownloadButtonElement::ShouldDisplayDownloadButton() { + const KURL& url = MediaElement().currentSrc(); + + // Check page settings to see if download is disabled. + if (GetDocument().GetPage() && + GetDocument().GetPage()->GetSettings().GetHideDownloadUI()) + return false; + + // URLs that lead to nowhere are ignored. + if (url.IsNull() || url.IsEmpty()) + return false; + + // If we have no source, we can't download. + if (MediaElement().getNetworkState() == HTMLMediaElement::kNetworkEmpty || + MediaElement().getNetworkState() == HTMLMediaElement::kNetworkNoSource) { + return false; + } + + // Local files and blobs (including MSE) should not have a download button. + if (url.IsLocalFile() || url.ProtocolIs("blob")) + return false; + + // MediaStream can't be downloaded. + if (HTMLMediaElement::IsMediaStreamURL(url.GetString())) + return false; + + // MediaSource can't be downloaded. + if (HTMLMediaSource::Lookup(url)) + return false; + + // HLS stream shouldn't have a download button. + if (HTMLMediaElement::IsHLSURL(url)) + return false; + + // Infinite streams don't have a clear end at which to finish the download + // (would require adding UI to prompt for the duration to download). + if (MediaElement().duration() == std::numeric_limits<double>::infinity()) + return false; + + // The attribute disables the download button. + if (MediaElement().ControlsListInternal()->ShouldHideDownload()) { + UseCounter::Count(MediaElement().GetDocument(), + UseCounter::kHTMLMediaElementControlsListNoDownload); + return false; + } + + return true; +} + +WebLocalizedString::Name +MediaControlDownloadButtonElement::GetOverflowStringName() { + return WebLocalizedString::kOverflowMenuDownload; +} + +bool MediaControlDownloadButtonElement::HasOverflowButton() { + return true; +} + +void MediaControlDownloadButtonElement::SetIsWanted(bool wanted) { + MediaControlElement::SetIsWanted(wanted); + + if (!IsWanted()) + return; + + DCHECK(IsWanted()); + if (!show_use_counted_) { + show_use_counted_ = true; + RecordMetrics(DownloadActionMetrics::kShown); + } +} + +DEFINE_TRACE(MediaControlDownloadButtonElement) { + visitor->Trace(anchor_); + MediaControlInputElement::Trace(visitor); +} + +void MediaControlDownloadButtonElement::DefaultEventHandler(Event* event) { + const KURL& url = MediaElement().currentSrc(); + if (event->type() == EventTypeNames::click && + !(url.IsNull() || url.IsEmpty())) { + Platform::Current()->RecordAction( + UserMetricsAction("Media.Controls.Download")); + if (!click_use_counted_) { + click_use_counted_ = true; + RecordMetrics(DownloadActionMetrics::kClicked); + } + if (!anchor_) { + HTMLAnchorElement* anchor = HTMLAnchorElement::Create(GetDocument()); + anchor->setAttribute(HTMLNames::downloadAttr, ""); + anchor_ = anchor; + } + anchor_->SetURL(url); + anchor_->DispatchSimulatedClick(event); + } + MediaControlInputElement::DefaultEventHandler(event); +} + +void MediaControlDownloadButtonElement::RecordMetrics( + DownloadActionMetrics metric) { + DEFINE_STATIC_LOCAL(EnumerationHistogram, download_action_histogram, + ("Media.Controls.Download", + static_cast<int>(DownloadActionMetrics::kCount))); + download_action_histogram.Count(static_cast<int>(metric)); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.h new file mode 100644 index 0000000..da1f7e08 --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDownloadButtonElement.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 MediaControlDownloadButtonElement_h +#define MediaControlDownloadButtonElement_h + +#include "core/html/shadow/MediaControlElementTypes.h" + +namespace blink { + +class Event; +class MediaControlsImpl; + +class MediaControlDownloadButtonElement final + : public MediaControlInputElement { + public: + explicit MediaControlDownloadButtonElement(MediaControlsImpl&); + + // Returns true if the download button should be shown. We should + // show the button for only non-MSE, non-EME, and non-MediaStream content. + bool ShouldDisplayDownloadButton(); + + // MediaControlInputElement overrides. + // TODO(mlamouri): add WillRespondToMouseClickEvents + WebLocalizedString::Name GetOverflowStringName() override; + bool HasOverflowButton() override; + void SetIsWanted(bool) override; + + DECLARE_VIRTUAL_TRACE(); + + private: + // This is used for UMA histogram (Media.Controls.Download). New values should + // be appended only and must be added before |Count|. + enum class DownloadActionMetrics { + kShown = 0, + kClicked, + kCount // Keep last. + }; + + void DefaultEventHandler(Event*) override; + + void RecordMetrics(DownloadActionMetrics); + + // Points to an anchor element that contains the URL of the media file. + Member<HTMLAnchorElement> anchor_; + + // UMA related boolean. They are used to prevent counting something twice + // for the same media element. + bool click_use_counted_ = false; + bool show_use_counted_ = false; +}; + +} // namespace blink + +#endif // MediaControlDownloadButtonElement_h
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.cpp new file mode 100644 index 0000000..d47c72f --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.cpp
@@ -0,0 +1,80 @@ +// 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 "modules/media_controls/elements/MediaControlFullscreenButtonElement.h" + +#include "core/InputTypeNames.h" +#include "core/events/Event.h" +#include "core/frame/Settings.h" +#include "core/html/HTMLMediaElement.h" +#include "modules/media_controls/MediaControlsImpl.h" +#include "public/platform/Platform.h" + +namespace blink { + +MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement( + MediaControlsImpl& media_controls) + : MediaControlInputElement(media_controls, kMediaEnterFullscreenButton) { + EnsureUserAgentShadowRoot(); + setType(InputTypeNames::button); + SetShadowPseudoId(AtomicString("-webkit-media-controls-fullscreen-button")); + SetIsFullscreen(MediaElement().IsFullscreen()); + SetIsWanted(false); +} + +void MediaControlFullscreenButtonElement::SetIsFullscreen(bool is_fullscreen) { + SetDisplayType(is_fullscreen ? kMediaExitFullscreenButton + : kMediaEnterFullscreenButton); +} + +bool MediaControlFullscreenButtonElement::WillRespondToMouseClickEvents() { + return true; +} + +WebLocalizedString::Name +MediaControlFullscreenButtonElement::GetOverflowStringName() { + if (MediaElement().IsFullscreen()) + return WebLocalizedString::kOverflowMenuExitFullscreen; + return WebLocalizedString::kOverflowMenuEnterFullscreen; +} + +bool MediaControlFullscreenButtonElement::HasOverflowButton() { + return true; +} + +void MediaControlFullscreenButtonElement::DefaultEventHandler(Event* event) { + if (event->type() == EventTypeNames::click) { + RecordClickMetrics(); + if (MediaElement().IsFullscreen()) + static_cast<MediaControlsImpl&>(GetMediaControls()).ExitFullscreen(); + else + static_cast<MediaControlsImpl&>(GetMediaControls()).EnterFullscreen(); + event->SetDefaultHandled(); + } + MediaControlInputElement::DefaultEventHandler(event); +} + +void MediaControlFullscreenButtonElement::RecordClickMetrics() { + bool is_embedded_experience_enabled = + GetDocument().GetSettings() && + GetDocument().GetSettings()->GetEmbeddedMediaExperienceEnabled(); + + if (MediaElement().IsFullscreen()) { + Platform::Current()->RecordAction( + UserMetricsAction("Media.Controls.ExitFullscreen")); + if (is_embedded_experience_enabled) { + Platform::Current()->RecordAction(UserMetricsAction( + "Media.Controls.ExitFullscreen.EmbeddedExperience")); + } + } else { + Platform::Current()->RecordAction( + UserMetricsAction("Media.Controls.EnterFullscreen")); + if (is_embedded_experience_enabled) { + Platform::Current()->RecordAction(UserMetricsAction( + "Media.Controls.EnterFullscreen.EmbeddedExperience")); + } + } +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.h new file mode 100644 index 0000000..ca4d990 --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlFullscreenButtonElement.h
@@ -0,0 +1,35 @@ +// 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 MediaControlFullscreenButtonElement_h +#define MediaControlFullscreenButtonElement_h + +#include "core/html/shadow/MediaControlElementTypes.h" + +namespace blink { + +class Event; +class MediaControlsImpl; + +class MediaControlFullscreenButtonElement final + : public MediaControlInputElement { + public: + explicit MediaControlFullscreenButtonElement(MediaControlsImpl&); + + // TODO(mlamouri): this should be changed to UpdateDisplayType(). + void SetIsFullscreen(bool); + + // MediaControlInputElement overrides. + bool WillRespondToMouseClickEvents() override; + WebLocalizedString::Name GetOverflowStringName() override; + bool HasOverflowButton() override; + + private: + void DefaultEventHandler(Event*) override; + void RecordClickMetrics(); +}; + +} // namespace blink + +#endif // MediaControlFullscreenButtonElement_h
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverflowMenuButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverflowMenuButtonElement.cpp new file mode 100644 index 0000000..08f93a3 --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverflowMenuButtonElement.cpp
@@ -0,0 +1,44 @@ +// 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 "modules/media_controls/elements/MediaControlOverflowMenuButtonElement.h" + +#include "core/InputTypeNames.h" +#include "core/events/Event.h" +#include "modules/media_controls/MediaControlsImpl.h" +#include "public/platform/Platform.h" + +namespace blink { + +MediaControlOverflowMenuButtonElement::MediaControlOverflowMenuButtonElement( + MediaControlsImpl& media_controls) + : MediaControlInputElement(media_controls, kMediaOverflowButton) { + EnsureUserAgentShadowRoot(); + setType(InputTypeNames::button); + SetShadowPseudoId(AtomicString("-internal-media-controls-overflow-button")); + SetIsWanted(false); +} + +bool MediaControlOverflowMenuButtonElement::WillRespondToMouseClickEvents() { + return true; +} + +void MediaControlOverflowMenuButtonElement::DefaultEventHandler(Event* event) { + if (event->type() == EventTypeNames::click) { + if (GetMediaControls().OverflowMenuVisible()) { + Platform::Current()->RecordAction( + UserMetricsAction("Media.Controls.OverflowClose")); + } else { + Platform::Current()->RecordAction( + UserMetricsAction("Media.Controls.OverflowOpen")); + } + + static_cast<MediaControlsImpl&>(GetMediaControls()).ToggleOverflowMenu(); + event->SetDefaultHandled(); + } + + MediaControlInputElement::DefaultEventHandler(event); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverflowMenuButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverflowMenuButtonElement.h new file mode 100644 index 0000000..846e4f7 --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverflowMenuButtonElement.h
@@ -0,0 +1,31 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MediaControlOverflowMenuButtonElement_h +#define MediaControlOverflowMenuButtonElement_h + +#include "core/html/shadow/MediaControlElementTypes.h" + +namespace blink { + +class Event; +class MediaControlsImpl; + +// Represents the overflow menu which is displayed when the width of the media +// player is small enough that at least two buttons are no longer visible. +class MediaControlOverflowMenuButtonElement final + : public MediaControlInputElement { + public: + explicit MediaControlOverflowMenuButtonElement(MediaControlsImpl&); + + // MediaControlInputElement overrides. + bool WillRespondToMouseClickEvents() override; + + private: + void DefaultEventHandler(Event*) override; +}; + +} // namespace blink + +#endif // MediaControlOverflowMenuButtonElement_h
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp new file mode 100644 index 0000000..b9a5e90 --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
@@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h" + +#include "core/InputTypeNames.h" +#include "core/events/Event.h" +#include "core/html/HTMLMediaElement.h" +#include "modules/media_controls/MediaControlsImpl.h" +#include "modules/media_controls/elements/MediaControlElementsHelper.h" +#include "public/platform/Platform.h" + +namespace blink { + +MediaControlOverlayPlayButtonElement::MediaControlOverlayPlayButtonElement( + MediaControlsImpl& media_controls) + : MediaControlInputElement(media_controls, kMediaOverlayPlayButton) { + EnsureUserAgentShadowRoot(); + setType(InputTypeNames::button); + SetShadowPseudoId(AtomicString("-webkit-media-controls-overlay-play-button")); +} + +void MediaControlOverlayPlayButtonElement::UpdateDisplayType() { + SetIsWanted(MediaElement().ShouldShowControls() && MediaElement().paused()); +} + +void MediaControlOverlayPlayButtonElement::DefaultEventHandler(Event* event) { + if (event->type() == EventTypeNames::click && MediaElement().paused()) { + Platform::Current()->RecordAction( + UserMetricsAction("Media.Controls.PlayOverlay")); + MediaElement().Play(); + UpdateDisplayType(); + event->SetDefaultHandled(); + } + // TODO(mlamouri): should call MediaControlInputElement::DefaultEventHandler. +} + +bool MediaControlOverlayPlayButtonElement::KeepEventInNode(Event* event) { + return MediaControlElementsHelper::IsUserInteractionEvent(event); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h new file mode 100644 index 0000000..0e6b35f --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h
@@ -0,0 +1,30 @@ +// 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 MediaControlOverlayPlayButtonElement_h +#define MediaControlOverlayPlayButtonElement_h + +#include "core/html/shadow/MediaControlElementTypes.h" + +namespace blink { + +class Event; +class MediaControlsImpl; + +class MediaControlOverlayPlayButtonElement final + : public MediaControlInputElement { + public: + explicit MediaControlOverlayPlayButtonElement(MediaControlsImpl&); + + // MediaControlInputElement overrides. + void UpdateDisplayType() override; + + private: + void DefaultEventHandler(Event*) override; + bool KeepEventInNode(Event*) override; +}; + +} // namespace blink + +#endif // MediaControlOverlayPlayButtonElement_h
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.cpp new file mode 100644 index 0000000..d7e14b7 --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.cpp
@@ -0,0 +1,70 @@ +// 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 "modules/media_controls/elements/MediaControlPlayButtonElement.h" + +#include "core/InputTypeNames.h" +#include "core/events/Event.h" +#include "core/html/HTMLMediaElement.h" +#include "core/html/media/HTMLMediaSource.h" +#include "modules/media_controls/MediaControlsImpl.h" +#include "public/platform/Platform.h" + +namespace blink { + +MediaControlPlayButtonElement::MediaControlPlayButtonElement( + MediaControlsImpl& media_controls) + : MediaControlInputElement(media_controls, kMediaPlayButton) { + EnsureUserAgentShadowRoot(); + setType(InputTypeNames::button); + SetShadowPseudoId(AtomicString("-webkit-media-controls-play-button")); +} + +bool MediaControlPlayButtonElement::WillRespondToMouseClickEvents() { + return true; +} + +void MediaControlPlayButtonElement::UpdateDisplayType() { + SetDisplayType(MediaElement().paused() ? kMediaPlayButton + : kMediaPauseButton); + UpdateOverflowString(); +} + +WebLocalizedString::Name +MediaControlPlayButtonElement::GetOverflowStringName() { + if (MediaElement().paused()) + return WebLocalizedString::kOverflowMenuPlay; + return WebLocalizedString::kOverflowMenuPause; +} + +bool MediaControlPlayButtonElement::HasOverflowButton() { + return true; +} + +void MediaControlPlayButtonElement::DefaultEventHandler(Event* event) { + if (event->type() == EventTypeNames::click) { + if (MediaElement().paused()) { + Platform::Current()->RecordAction( + UserMetricsAction("Media.Controls.Play")); + } else { + Platform::Current()->RecordAction( + UserMetricsAction("Media.Controls.Pause")); + } + + // Allow play attempts for plain src= media to force a reload in the error + // state. This allows potential recovery for transient network and decoder + // resource issues. + const String& url = MediaElement().currentSrc().GetString(); + if (MediaElement().error() && !HTMLMediaElement::IsMediaStreamURL(url) && + !HTMLMediaSource::Lookup(url)) + MediaElement().load(); + + MediaElement().TogglePlayState(); + UpdateDisplayType(); + event->SetDefaultHandled(); + } + MediaControlInputElement::DefaultEventHandler(event); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.h new file mode 100644 index 0000000..b9e75df --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPlayButtonElement.h
@@ -0,0 +1,31 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MediaControlPlayButtonElement_h +#define MediaControlPlayButtonElement_h + +#include "core/html/shadow/MediaControlElementTypes.h" + +namespace blink { + +class Event; +class MediaControlsImpl; + +class MediaControlPlayButtonElement final : public MediaControlInputElement { + public: + explicit MediaControlPlayButtonElement(MediaControlsImpl&); + + // MediaControlInputElement overrides. + bool WillRespondToMouseClickEvents() override; + void UpdateDisplayType() override; + WebLocalizedString::Name GetOverflowStringName() override; + bool HasOverflowButton() override; + + private: + void DefaultEventHandler(Event*) override; +}; + +} // namespace blink + +#endif // MediaControlPlayButtonElement_h
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.cpp new file mode 100644 index 0000000..e774df1 --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.cpp
@@ -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 "modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.h" + +#include "core/InputTypeNames.h" +#include "core/events/Event.h" +#include "core/html/HTMLMediaElement.h" +#include "core/html/track/TextTrackList.h" +#include "modules/media_controls/MediaControlsImpl.h" + +namespace blink { + +MediaControlToggleClosedCaptionsButtonElement:: + MediaControlToggleClosedCaptionsButtonElement( + MediaControlsImpl& media_controls) + : MediaControlInputElement(media_controls, kMediaShowClosedCaptionsButton) { + EnsureUserAgentShadowRoot(); + setType(InputTypeNames::button); + SetShadowPseudoId( + AtomicString("-webkit-media-controls-toggle-closed-captions-button")); +} + +bool MediaControlToggleClosedCaptionsButtonElement:: + WillRespondToMouseClickEvents() { + return true; +} + +void MediaControlToggleClosedCaptionsButtonElement::UpdateDisplayType() { + bool captions_visible = MediaElement().TextTracksVisible(); + SetDisplayType(captions_visible ? kMediaHideClosedCaptionsButton + : kMediaShowClosedCaptionsButton); +} + +WebLocalizedString::Name +MediaControlToggleClosedCaptionsButtonElement::GetOverflowStringName() { + return WebLocalizedString::kOverflowMenuCaptions; +} + +bool MediaControlToggleClosedCaptionsButtonElement::HasOverflowButton() { + return true; +} + +void MediaControlToggleClosedCaptionsButtonElement::DefaultEventHandler( + Event* event) { + if (event->type() == EventTypeNames::click) { + if (MediaElement().textTracks()->length() == 1) { + // If only one track exists, toggle it on/off + if (MediaElement().textTracks()->HasShowingTracks()) { + static_cast<MediaControlsImpl&>(GetMediaControls()) + .DisableShowingTextTracks(); + } else { + static_cast<MediaControlsImpl&>(GetMediaControls()) + .ShowTextTrackAtIndex(0); + } + } else { + static_cast<MediaControlsImpl&>(GetMediaControls()).ToggleTextTrackList(); + } + + UpdateDisplayType(); + event->SetDefaultHandled(); + } + + MediaControlInputElement::DefaultEventHandler(event); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.h new file mode 100644 index 0000000..e648a95 --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlToggleClosedCaptionsButtonElement.h
@@ -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. + +#ifndef MediaControlToggleClosedCaptionsButtonElement_h +#define MediaControlToggleClosedCaptionsButtonElement_h + +#include "core/html/shadow/MediaControlElementTypes.h" + +namespace blink { + +class Event; +class MediaControlsImpl; + +class MediaControlToggleClosedCaptionsButtonElement final + : public MediaControlInputElement { + public: + explicit MediaControlToggleClosedCaptionsButtonElement(MediaControlsImpl&); + + // MediaControlInputElement overrides. + bool WillRespondToMouseClickEvents() override; + void UpdateDisplayType() override; + WebLocalizedString::Name GetOverflowStringName() override; + bool HasOverflowButton() override; + + private: + void DefaultEventHandler(Event*) override; +}; + +} // namespace blink + +#endif // MediaControlToggleClosedCaptionsButtonElement_h
diff --git a/third_party/WebKit/Source/modules/mediasource/MediaSource.idl b/third_party/WebKit/Source/modules/mediasource/MediaSource.idl index 8b23fd3..28f118d1 100644 --- a/third_party/WebKit/Source/modules/mediasource/MediaSource.idl +++ b/third_party/WebKit/Source/modules/mediasource/MediaSource.idl
@@ -28,7 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// https://www.w3.org/TR/media-source/#idl-def-MediaSource +// https://w3c.github.io/media-source/#idl-def-mediasource enum EndOfStreamError { "network",
diff --git a/third_party/WebKit/Source/modules/mediasource/SourceBuffer.idl b/third_party/WebKit/Source/modules/mediasource/SourceBuffer.idl index 193360b..07f46e03 100644 --- a/third_party/WebKit/Source/modules/mediasource/SourceBuffer.idl +++ b/third_party/WebKit/Source/modules/mediasource/SourceBuffer.idl
@@ -28,7 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// https://www.w3.org/TR/media-source/#idl-def-SourceBuffer +// https://w3c.github.io/media-source/#idl-def-sourcebuffer enum AppendMode { "segments",
diff --git a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.idl b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.idl index 03b43ee..49e3fcb 100644 --- a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.idl +++ b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.idl
@@ -18,7 +18,8 @@ Boston, MA 02110-1301, USA. */ -// https://www.w3.org/TR/html5/webappapis.html#navigatorcontentutils +// https://html.spec.whatwg.org/multipage/webappapis.html#custom-handlers + partial interface Navigator { [RuntimeEnabled=NavigatorContentUtils, RaisesException] void registerProtocolHandler(DOMString scheme, DOMString url, DOMString title); [RuntimeEnabled=CustomSchemeHandler, RaisesException] DOMString isProtocolHandlerRegistered(DOMString scheme, DOMString url);
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEvent.idl b/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEvent.idl index 15b64ac..d3a24c44 100644 --- a/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEvent.idl +++ b/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEvent.idl
@@ -23,7 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// http://www.w3.org/TR/webrtc/#rtcdtmftonechangeevent +// https://w3c.github.io/webrtc-pc/#rtcdtmftonechangeevent [ NoInterfaceObject,
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEventInit.idl b/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEventInit.idl index a070229..82b8213 100644 --- a/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEventInit.idl +++ b/third_party/WebKit/Source/modules/peerconnection/RTCDTMFToneChangeEventInit.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// http://www.w3.org/TR/webrtc/#rtcdtmftonechangeevent +// https://w3c.github.io/webrtc-pc/#rtcdtmftonechangeevent dictionary RTCDTMFToneChangeEventInit : EventInit { DOMString tone;
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCIceCandidateInit.idl b/third_party/WebKit/Source/modules/peerconnection/RTCIceCandidateInit.idl index e5a883e7..76c5bc19 100644 --- a/third_party/WebKit/Source/modules/peerconnection/RTCIceCandidateInit.idl +++ b/third_party/WebKit/Source/modules/peerconnection/RTCIceCandidateInit.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// http://www.w3.org/TR/webrtc/#idl-def-RTCIceCandidateInit +// https://w3c.github.io/webrtc-pc/#idl-def-rtcicecandidateinit dictionary RTCIceCandidateInit { DOMString candidate;
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp index a215a535..75f9fdd2 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp
@@ -23,12 +23,11 @@ list->AppendClipPathItem(clip_path_, true); } -int BeginClipPathDisplayItem::NumberOfSlowPaths() const { +void BeginClipPathDisplayItem::AnalyzeForGpuRasterization( + SkPictureGpuAnalyzer& analyzer) const { // Temporarily disabled (pref regressions due to GPU veto stickiness: // http://crbug.com/603969). // analyzer.analyzeClipPath(m_clipPath, SkRegion::kIntersect_Op, true); - // TODO(enne): fixup this code to return an int. - return 0; } void EndClipPathDisplayItem::Replay(GraphicsContext& context) const {
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h index 3952c87..42434ae 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h
@@ -24,7 +24,7 @@ void AppendToWebDisplayItemList(const IntRect&, WebDisplayItemList*) const override; - int NumberOfSlowPaths() const override; + void AnalyzeForGpuRasterization(SkPictureGpuAnalyzer&) const override; private: #ifndef NDEBUG
diff --git a/third_party/WebKit/Source/platform/graphics/paint/CompositingRecorder.cpp b/third_party/WebKit/Source/platform/graphics/paint/CompositingRecorder.cpp index 7eac3491..cdcd8fd 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/CompositingRecorder.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/CompositingRecorder.cpp
@@ -29,8 +29,58 @@ CompositingRecorder::~CompositingRecorder() { if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) return; - graphics_context_.GetPaintController().EndItem<EndCompositingDisplayItem>( - client_); + // If the end of the current display list is of the form + // [BeginCompositingDisplayItem] [DrawingDisplayItem], then fold the + // BeginCompositingDisplayItem into a new DrawingDisplayItem that replaces + // them both. This allows Skia to optimize for the case when the + // BeginCompositingDisplayItem represents a simple opacity/color that can be + // merged into the opacity/color of the drawing. See crbug.com/628831 for more + // details. + PaintController& paint_controller = graphics_context_.GetPaintController(); + const DisplayItem* last_display_item = paint_controller.LastDisplayItem(0); + const DisplayItem* second_to_last_display_item = + paint_controller.LastDisplayItem(1); + // TODO(chrishtr): remove the call to LastDisplayItemIsSubsequenceEnd when + // https://codereview.chromium.org/2768143002 lands. + if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && last_display_item && + second_to_last_display_item && last_display_item->DrawsContent() && + second_to_last_display_item->GetType() == + DisplayItem::kBeginCompositing && + !paint_controller.LastDisplayItemIsSubsequenceEnd()) { + FloatRect cull_rect( + ((DrawingDisplayItem*)last_display_item)->GetPaintRecord()->cullRect()); + const DisplayItemClient& display_item_client = last_display_item->Client(); + DisplayItem::Type display_item_type = last_display_item->GetType(); + + // Re-record the last two DisplayItems into a new drawing. The new item + // cannot be cached, because it is a mutation of the DisplayItem the client + // thought it was painting. + paint_controller.BeginSkippingCache(); + { +#if DCHECK_IS_ON() + // In the recorder's scope we remove the last two display items which + // are combined into a new drawing. + DisableListModificationCheck disabler; +#endif + DrawingRecorder new_recorder(graphics_context_, display_item_client, + display_item_type, cull_rect); + DCHECK(!DrawingRecorder::UseCachedDrawingIfPossible( + graphics_context_, display_item_client, display_item_type)); + + second_to_last_display_item->Replay(graphics_context_); + last_display_item->Replay(graphics_context_); + EndCompositingDisplayItem(client_).Replay(graphics_context_); + + // Remove the DrawingDisplayItem. + paint_controller.RemoveLastDisplayItem(); + // Remove the BeginCompositingDisplayItem. + paint_controller.RemoveLastDisplayItem(); + } + paint_controller.EndSkippingCache(); + } else { + graphics_context_.GetPaintController().EndItem<EndCompositingDisplayItem>( + client_); + } } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h index d5f344e6..a9afcd1 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
@@ -17,6 +17,8 @@ #include "platform/wtf/text/WTFString.h" #endif +class SkPictureGpuAnalyzer; + namespace blink { class GraphicsContext; @@ -335,7 +337,7 @@ virtual bool DrawsContent() const { return false; } // Override to implement specific analysis strategies. - virtual int NumberOfSlowPaths() const { return 0; } + virtual void AnalyzeForGpuRasterization(SkPictureGpuAnalyzer&) const {} #ifndef NDEBUG static WTF::String TypeAsDebugString(DisplayItem::Type);
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp index 4fe7853..474a7d12 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
@@ -7,6 +7,7 @@ #include "platform/graphics/LoggingCanvas.h" #include "platform/graphics/paint/DrawingDisplayItem.h" #include "platform/graphics/paint/PaintChunk.h" +#include "third_party/skia/include/core/SkPictureAnalyzer.h" #ifndef NDEBUG #include "platform/wtf/text/WTFString.h"
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp index 7c14717..2a17f3d 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp
@@ -10,6 +10,7 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkData.h" +#include "third_party/skia/include/core/SkPictureAnalyzer.h" namespace blink { @@ -29,8 +30,14 @@ return record_.get(); } -int DrawingDisplayItem::NumberOfSlowPaths() const { - return record_ ? record_->numSlowPaths() : 0; +void DrawingDisplayItem::AnalyzeForGpuRasterization( + SkPictureGpuAnalyzer& analyzer) const { + // TODO(enne): Need an SkPictureGpuAnalyzer on PictureRecord. + // This is a bit overkill to ToSkPicture a record just to get + // numSlowPaths. + if (!record_) + return; + analyzer.analyzePicture(ToSkPicture(record_).get()); } #ifndef NDEBUG
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h index 3dedbcbd..e5f989f8 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h
@@ -41,7 +41,7 @@ return known_to_be_opaque_; } - int NumberOfSlowPaths() const override; + void AnalyzeForGpuRasterization(SkPictureGpuAnalyzer&) const override; private: #ifndef NDEBUG
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp index d3b7553..e26681df 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
@@ -16,8 +16,6 @@ #include <stdio.h> #endif -static constexpr int kMaxNumberOfSlowPathsBeforeVeto = 5; - namespace blink { void PaintController::SetTracksRasterInvalidations(bool value) { @@ -537,7 +535,7 @@ !new_display_item_list_.IsEmpty()) GenerateChunkRasterInvalidationRects(new_paint_chunks_.LastChunk()); - int num_slow_paths = 0; + SkPictureGpuAnalyzer gpu_analyzer; current_cache_generation_ = DisplayItemClient::CacheGenerationOrInvalidationReason::Next(); @@ -556,8 +554,8 @@ Vector<const DisplayItemClient*> skipped_cache_clients; for (const auto& item : new_display_item_list_) { // No reason to continue the analysis once we have a veto. - if (num_slow_paths <= kMaxNumberOfSlowPathsBeforeVeto) - num_slow_paths += item.NumberOfSlowPaths(); + if (gpu_analyzer.suitableForGpuRasterization()) + item.AnalyzeForGpuRasterization(gpu_analyzer); // TODO(wkorman): Only compute and append visual rect for drawings. new_display_item_list_.AppendVisualRect( @@ -595,7 +593,7 @@ new_display_item_list_.ShrinkToFit(); current_paint_artifact_ = PaintArtifact( std::move(new_display_item_list_), new_paint_chunks_.ReleasePaintChunks(), - num_slow_paths <= kMaxNumberOfSlowPathsBeforeVeto); + gpu_analyzer.suitableForGpuRasterization()); ResetCurrentListIndices(); out_of_order_item_indices_.Clear(); out_of_order_chunk_indices_.Clear();
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp index 038f0bd..f4e0aae 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
@@ -2273,10 +2273,44 @@ DisplayItemClient::EndShouldKeepAliveAllClients(); #endif } + + void TestFoldCompositingDrawingInSubsequence() { + FakeDisplayItemClient container("container"); + FakeDisplayItemClient content("content"); + GraphicsContext context(GetPaintController()); + + { + SubsequenceRecorder subsequence(context, container); + CompositingRecorder compositing(context, content, SkBlendMode::kSrc, 0.5); + DrawRect(context, content, kBackgroundDrawingType, + FloatRect(100, 100, 300, 300)); + } + GetPaintController().CommitNewDisplayItems(); + EXPECT_EQ( + 1u, + GetPaintController().GetPaintArtifact().GetDisplayItemList().size()); + + { + EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible( + context, container)); + SubsequenceRecorder subsequence(context, container); + CompositingRecorder compositing(context, content, SkBlendMode::kSrc, 0.5); + DrawRect(context, content, kBackgroundDrawingType, + FloatRect(100, 100, 300, 300)); + } + GetPaintController().CommitNewDisplayItems(); + EXPECT_EQ( + 1u, + GetPaintController().GetPaintArtifact().GetDisplayItemList().size()); + +#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS + DisplayItemClient::EndShouldKeepAliveAllClients(); +#endif + } }; TEST_F(PaintControllerUnderInvalidationTest, ChangeDrawing) { - EXPECT_DEATH(TestChangeDrawing(), "under-invalidation: display item changed"); + EXPECT_DEATH(TestChangeDrawing(), ""); } TEST_F(PaintControllerUnderInvalidationTest, MoreDrawing) { @@ -2297,29 +2331,22 @@ } TEST_F(PaintControllerUnderInvalidationTest, ChangeDrawingInSubsequence) { - EXPECT_DEATH(TestChangeDrawingInSubsequence(), - "\"\\(In cached subsequence of first\\)\" under-invalidation: " - "display item changed"); + EXPECT_DEATH(TestChangeDrawingInSubsequence(), ""); } TEST_F(PaintControllerUnderInvalidationTest, MoreDrawingInSubsequence) { - EXPECT_DEATH(TestMoreDrawingInSubsequence(), - "Check failed: false. Can't find cached display item"); + EXPECT_DEATH(TestMoreDrawingInSubsequence(), ""); } TEST_F(PaintControllerUnderInvalidationTest, LessDrawingInSubsequence) { // We allow invalidated display item clients as long as they would produce the // same display items. The cases of changed display items are tested by other // test cases. - EXPECT_DEATH(TestLessDrawingInSubsequence(), - "\"\\(In cached subsequence of first\\)\" under-invalidation: " - "new subsequence wrong length"); + EXPECT_DEATH(TestLessDrawingInSubsequence(), ""); } TEST_F(PaintControllerUnderInvalidationTest, ChangeNonCacheableInSubsequence) { - EXPECT_DEATH(TestChangeNonCacheableInSubsequence(), - "\"\\(In cached subsequence of container\\)\" " - "under-invalidation: display item changed"); + EXPECT_DEATH(TestChangeNonCacheableInSubsequence(), ""); } TEST_F(PaintControllerUnderInvalidationTest, InvalidationInSubsequence) { @@ -2329,6 +2356,11 @@ TestInvalidationInSubsequence(); } +TEST_F(PaintControllerUnderInvalidationTest, + FoldCompositingDrawingInSubsequence) { + TestFoldCompositingDrawingInSubsequence(); +} + #endif // defined(GTEST_HAS_DEATH_TEST) && !OS(ANDROID) } // namespace blink
diff --git a/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm b/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm index e3eada5..6379d6a 100644 --- a/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm +++ b/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm
@@ -24,7 +24,6 @@ #include "platform/graphics/paint/PaintCanvas.h" #include "platform/mac/ThemeMac.h" #include "platform_canvas.h" -#include "third_party/skia/include/core/SkRegion.h" namespace blink {
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath index 16e16cc..f3f4661 100644 --- a/tools/android/eclipse/.classpath +++ b/tools/android/eclipse/.classpath
@@ -122,6 +122,7 @@ <classpathentry kind="src" path="third_party/mockito/src/src/main/java"/> <classpathentry kind="src" path="third_party/robolectric/robolectric/robolectric-annotations/src/main/java"/> <classpathentry kind="src" path="third_party/robolectric/robolectric/robolectric-resources/src/main/java"/> + <classpathentry kind="src" path="third_party/robolectric/robolectric/robolectric-shadows/shadows-multidex/src/main/java"/> <classpathentry kind="src" path="tools/android/findbugs_plugin/src"/> <classpathentry kind="src" path="tools/android/findbugs_plugin/test/java/src"/> <classpathentry kind="src" path="tools/android/memconsumer/java/src"/>
diff --git a/tools/battor_agent/BUILD.gn b/tools/battor_agent/BUILD.gn index 065ee03..fe2ce233 100644 --- a/tools/battor_agent/BUILD.gn +++ b/tools/battor_agent/BUILD.gn
@@ -14,6 +14,7 @@ deps = [ ":battor_agent_lib", "//base", + "//build/config/sanitizers:deps", "//build/win:default_exe_manifest", "//device/serial", ]
diff --git a/tools/bisect-builds.py b/tools/bisect-builds.py index 442f399..2586814 100755 --- a/tools/bisect-builds.py +++ b/tools/bisect-builds.py
@@ -1001,6 +1001,11 @@ print (' ' + CHANGELOG_URL % (GetGitHashFromSVNRevision(min_chromium_rev), GetGitHashFromSVNRevision(max_chromium_rev))) +def error_internal_option(option, opt, value, parser): + raise optparse.OptionValueError( + 'The -o and -r options are only\navailable in the internal version of ' + 'this script. Google\nemployees should visit http://go/bisect-builds ' + 'for\nconfiguration instructions.') def main(): usage = ('%prog [options] [-- chromium-options]\n' @@ -1086,6 +1091,8 @@ default=False, help='Test the first and last revisions in the range ' + 'before proceeding with the bisect.') + parser.add_option("-r", action="callback", callback=error_internal_option) + parser.add_option("-o", action="callback", callback=error_internal_option) (opts, args) = parser.parse_args()
diff --git a/tools/gn/visual_studio_writer.cc b/tools/gn/visual_studio_writer.cc index 76ebc562..aa01d821 100644 --- a/tools/gn/visual_studio_writer.cc +++ b/tools/gn/visual_studio_writer.cc
@@ -37,41 +37,9 @@ namespace { -std::string EscapeString(const std::string& value) { - std::string result; - for (char c : value) { - switch (c) { - case '\n': - result += " "; - break; - case '\r': - result += " "; - break; - case '\t': - result += "	"; - break; - case '"': - result += """; - break; - case '<': - result += "<"; - break; - case '>': - result += ">"; - break; - case '&': - result += "&"; - break; - default: - result += c; - } - } - return result; -} - struct SemicolonSeparatedWriter { void operator()(const std::string& value, std::ostream& out) const { - out << EscapeString(value) + ';'; + out << XmlEscape(value) + ';'; } };
diff --git a/tools/gn/xml_element_writer.cc b/tools/gn/xml_element_writer.cc index fcf34b28..bb0d232 100644 --- a/tools/gn/xml_element_writer.cc +++ b/tools/gn/xml_element_writer.cc
@@ -81,3 +81,35 @@ return out_; } + +std::string XmlEscape(const std::string& value) { + std::string result; + for (char c : value) { + switch (c) { + case '\n': + result += " "; + break; + case '\r': + result += " "; + break; + case '\t': + result += "	"; + break; + case '"': + result += """; + break; + case '<': + result += "<"; + break; + case '>': + result += ">"; + break; + case '&': + result += "&"; + break; + default: + result += c; + } + } + return result; +}
diff --git a/tools/gn/xml_element_writer.h b/tools/gn/xml_element_writer.h index 8a83df0a..01346d23 100644 --- a/tools/gn/xml_element_writer.h +++ b/tools/gn/xml_element_writer.h
@@ -120,4 +120,6 @@ out_, tag, attribute_name, attribute_value_writer, indent_ + 2)); } +std::string XmlEscape(const std::string& value); + #endif // TOOLS_GN_XML_ELEMENT_WRITER_H_
diff --git a/tools/gn/xml_element_writer_unittest.cc b/tools/gn/xml_element_writer_unittest.cc index 93dfd47..cc21c4bb 100644 --- a/tools/gn/xml_element_writer_unittest.cc +++ b/tools/gn/xml_element_writer_unittest.cc
@@ -84,3 +84,10 @@ } EXPECT_EQ("<foo bar=\"baz\">Hello world!</foo>\n", out.str()); } + +TEST(XmlElementWriter, TestXmlEscape) { + std::string input = "\r \n \t & < > \""; + std::string output = XmlEscape(input); + std::string expected = " 	 & < > ""; + EXPECT_EQ(expected, output); +}
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 4b5f27c4..4ac7a30 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -92947,6 +92947,8 @@ <int value="1168" label="NETWORKINGCASTPRIVATE_GETWIFITDLSSTATUS"/> <int value="1169" label="ACCESSIBILITY_PRIVATE_DARKENSCREEN"/> <int value="1170" label="WEBRTC_AUDIO_PRIVATE_SET_AUDIO_EXPERIMENTS"/> + <int value="1171" label="AUTOTESTPRIVATE_GETPLAYSTORESTATE"/> + <int value="1172" label="AUTOTESTPRIVATE_SETPLAYSTOREENABLED"/> </enum> <enum name="ExtensionIconState" type="int">
diff --git a/ui/base/template_expressions.cc b/ui/base/template_expressions.cc index c8d49a9..14b638e 100644 --- a/ui/base/template_expressions.cc +++ b/ui/base/template_expressions.cc
@@ -31,6 +31,9 @@ case '"': out.append("\\\""); break; + case ',': + out.append("\\,"); + break; default: out += c; }
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc index d56eb1d..d517f07 100644 --- a/ui/keyboard/keyboard_controller.cc +++ b/ui/keyboard/keyboard_controller.cc
@@ -411,8 +411,9 @@ } void KeyboardController::ShowKeyboardInternal(int64_t display_id) { - if (!container_.get()) - return; + // The container window should have been created already when + // |Shell::CreateKeyboard| is called. + DCHECK(container_.get()); if (container_->children().empty()) { keyboard::MarkKeyboardLoadStarted();
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc index bf3df7e..1a3ae27 100644 --- a/ui/views/bubble/bubble_frame_view.cc +++ b/ui/views/bubble/bubble_frame_view.cc
@@ -257,7 +257,8 @@ const int title_height = std::max(icon_height, label_height) + title_padding; const int close_height = GetWidget()->widget_delegate()->ShouldShowCloseButton() - ? close_->height() + ? close_->height() + LayoutProvider::Get()->GetDistanceMetric( + DISTANCE_CLOSE_BUTTON_MARGIN) : 0; insets += gfx::Insets(std::max(title_height, close_height), 0, 0, 0); return insets;
diff --git a/ui/views/bubble/bubble_frame_view_unittest.cc b/ui/views/bubble/bubble_frame_view_unittest.cc index bf955dd..3474899 100644 --- a/ui/views/bubble/bubble_frame_view_unittest.cc +++ b/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -145,12 +145,12 @@ EXPECT_EQ(kArrow, frame.bubble_border()->arrow()); EXPECT_EQ(kColor, frame.bubble_border()->background_color()); - int margin_x = frame.content_margins().left(); - int margin_y = frame.content_margins().top() + - frame.GetCloseButtonForTest()->height(); - gfx::Insets insets = frame.bubble_border()->GetInsets(); - EXPECT_EQ(insets.left() + margin_x, frame.GetBoundsForClientView().x()); - EXPECT_EQ(insets.top() + margin_y, frame.GetBoundsForClientView().y()); + gfx::Insets frame_insets = frame.GetInsets(); + gfx::Insets border_insets = frame.bubble_border()->GetInsets(); + EXPECT_EQ(border_insets.left() + frame_insets.left(), + frame.GetBoundsForClientView().x()); + EXPECT_EQ(border_insets.top() + frame_insets.top(), + frame.GetBoundsForClientView().y()); } // Tests that the arrow is mirrored as needed to better fit the screen.
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm index ce75522..c77bdf4 100644 --- a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm +++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
@@ -5,7 +5,6 @@ #import "ui/views/controls/scrollbar/cocoa_scroll_bar.h" #import "base/mac/sdk_forward_declarations.h" -#include "cc/paint/paint_shader.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/effects/SkGradientShader.h" #include "ui/compositor/layer.h"
diff --git a/ui/views/window/dialog_delegate_unittest.cc b/ui/views/window/dialog_delegate_unittest.cc index d11cfddd..3cfa829 100644 --- a/ui/views/window/dialog_delegate_unittest.cc +++ b/ui/views/window/dialog_delegate_unittest.cc
@@ -28,15 +28,7 @@ class TestDialog : public DialogDelegateView { public: - TestDialog() - : input_(new views::Textfield()), - canceled_(false), - accepted_(false), - closed_(false), - closeable_(false), - should_handle_escape_(false) { - AddChildView(input_); - } + TestDialog() : input_(new views::Textfield()) { AddChildView(input_); } ~TestDialog() override {} void Init() { @@ -51,6 +43,7 @@ bool ShouldShowWindowTitle() const override { return !title_.empty(); } + bool ShouldShowCloseButton() const override { return show_close_button_; } // DialogDelegateView overrides: bool Cancel() override { @@ -66,7 +59,6 @@ return closeable_; } - // DialogDelegateView overrides: gfx::Size GetPreferredSize() const override { return gfx::Size(200, 200); } bool AcceleratorPressed(const ui::Accelerator& accelerator) override { return should_handle_escape_; @@ -92,6 +84,9 @@ } void set_title(const base::string16& title) { title_ = title; } + void set_show_close_button(bool show_close) { + show_close_button_ = show_close; + } void set_should_handle_escape(bool should_handle_escape) { should_handle_escape_ = should_handle_escape; } @@ -100,13 +95,14 @@ private: views::Textfield* input_; - bool canceled_; - bool accepted_; - bool closed_; + bool canceled_ = false; + bool accepted_ = false; + bool closed_ = false; // Prevent the dialog from closing, for repeated ok and cancel button clicks. bool closeable_; base::string16 title_; - bool should_handle_escape_; + bool show_close_button_ = true; + bool should_handle_escape_ = false; DISALLOW_COPY_AND_ASSIGN(TestDialog); }; @@ -118,9 +114,8 @@ void SetUp() override { ViewsTestBase::SetUp(); - dialog_ = new TestDialog(); - dialog_->Init(); - DialogDelegate::CreateDialogWidget(dialog_, GetContext(), nullptr)->Show(); + InitializeDialog(); + ShowDialog(); } void TearDown() override { @@ -128,6 +123,18 @@ ViewsTestBase::TearDown(); } + void InitializeDialog() { + if (dialog_) + dialog_->TearDown(); + + dialog_ = new TestDialog(); + dialog_->Init(); + } + + void ShowDialog() { + DialogDelegate::CreateDialogWidget(dialog_, GetContext(), nullptr)->Show(); + } + void SimulateKeyEvent(const ui::KeyEvent& event) { ui::KeyEvent event_copy = event; if (dialog()->GetFocusManager()->OnKeyEvent(event_copy)) @@ -208,12 +215,38 @@ const int point; const int hit; } cases[] = { - { border, HTSYSMENU }, - { border + 10, HTSYSMENU }, - { border + 20, HTCLIENT }, - { border + 50, HTCLIENT }, - { border + 60, HTCLIENT }, - { 1000, HTNOWHERE }, + {border, HTSYSMENU}, + {border + 10, HTSYSMENU}, + {border + 20, HTNOWHERE}, + {border + 50, HTCLIENT /* Space is reserved for the close button. */}, + {border + 60, HTCLIENT}, + {1000, HTNOWHERE}, + }; + + for (size_t i = 0; i < arraysize(cases); ++i) { + gfx::Point point(cases[i].point, cases[i].point); + EXPECT_EQ(cases[i].hit, frame->NonClientHitTest(point)) + << " case " << i << " with border: " << border << ", at point " + << cases[i].point; + } +} + +TEST_F(DialogTest, HitTest_HiddenTitleNoCloseButton) { + InitializeDialog(); + dialog()->set_show_close_button(false); + ShowDialog(); + + const NonClientView* view = dialog()->GetWidget()->non_client_view(); + BubbleFrameView* frame = static_cast<BubbleFrameView*>(view->frame_view()); + const int border = frame->bubble_border()->GetBorderThickness(); + + struct { + const int point; + const int hit; + } cases[] = { + {border, HTSYSMENU}, {border + 10, HTSYSMENU}, + {border + 20, HTCLIENT}, {border + 50, HTCLIENT}, + {border + 60, HTCLIENT}, {1000, HTNOWHERE}, }; for (size_t i = 0; i < arraysize(cases); ++i) {